Skip to content

Daily Tech Losers Scan #29

Daily Tech Losers Scan

Daily Tech Losers Scan #29

Workflow file for this run

# ──────────────────────────────────────────────────────────────
# Daily Tech Losers Scan
# Scans US Tech stocks for ≥5% daily losses, emails a report.
# Runs Tue–Sat at 00:00 UTC (8:00 AM SGT — after US market close).
# ──────────────────────────────────────────────────────────────
name: Daily Tech Losers Scan
on:
# Manual trigger from Actions tab
workflow_dispatch:
# Automated daily schedule (must be on default branch to fire)
schedule:
# 00:00 UTC = 08:00 SGT — well after US market close
- cron: "0 0 * * 2-6" # Tue–Sat SGT (Mon–Fri US)
# Cancel any in-progress run if a new one triggers (idempotency guard)
concurrency:
group: tech-losers-scan
cancel-in-progress: true
jobs:
scan:
runs-on: ubuntu-latest
timeout-minutes: 30
# ── All secrets & config as env vars (job level) ──────────
env:
# Secrets (stored in Settings → Secrets → Actions)
FMP_API_KEY: ${{ secrets.FMP_API_KEY }}
TWELVE_DATA_API_KEYS_CSV: ${{ secrets.TWELVE_DATA_API_KEYS_CSV }}
TWELVE_DATA_API_KEY: ${{ secrets.TWELVE_DATA_API_KEY }}
GMAIL_SENDER: ${{ secrets.GMAIL_SENDER }}
EMAIL_RECIPIENTS: ${{ secrets.EMAIL_RECIPIENTS }}
SMTP_USER: ${{ secrets.SMTP_USER }}
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }}
# Non-secret config (safe to hardcode)
SMTP_HOST: smtp.gmail.com
SMTP_PORT: "587"
SMTP_USE_TLS: "true"
NVIDIA_MODEL: stockmark/stockmark-2-100b-instruct
NVIDIA_API_BASE_URL: https://integrate.api.nvidia.com
AI_SUMMARY_ENABLED: "true"
AI_SUMMARY_MAX_TOKENS: "220"
AI_SUMMARY_TEMPERATURE: "0.2"
PROFILE_CACHE_DAYS: "7"
TWELVE_DATA_DAILY_LIMIT: "800"
TWELVE_DATA_REQUEST_TIMEOUT: "8"
TWELVE_DATA_MAX_RETRIES: "2"
TWELVE_DATA_WORKERS_PER_KEY: "2"
INCLUDE_INDUSTRY_KEYWORDS: software
EXTRA_SYMBOLS: IREN
FORCE_INCLUDE_SYMBOLS: IREN
steps:
# ── 1. Checkout code ────────────────────────────────────
- name: Checkout repository
uses: actions/checkout@v4
# ── 2. Set up Python ────────────────────────────────────
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip # built-in pip caching
# ── 3. Install dependencies ─────────────────────────────
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
# ── 4. Verify critical secrets are set ──────────────────
- name: Verify secrets
run: |
missing=0
for secret_name in FMP_API_KEY SMTP_USER SMTP_PASSWORD GMAIL_SENDER EMAIL_RECIPIENTS; do
val=$(eval echo "\$$secret_name")
if [ -z "$val" ]; then
echo "::error::Missing required secret: $secret_name"
missing=1
else
echo "✓ $secret_name is set"
fi
done
if [ "$missing" -eq 1 ]; then
echo "::error::One or more required secrets are missing. Go to Settings → Secrets → Actions to add them."
exit 1
fi
# ── 5. Create data directory ────────────────────────────
- name: Prepare data directory
run: mkdir -p data
# ── 6. Run the bot ──────────────────────────────────────
- name: Run Tech Losers Scan
run: python main.py --no-wait --scan-source td
# ── 7. Upload report artifacts (optional, for debugging) ─
- name: Upload reports
if: always()
uses: actions/upload-artifact@v4
with:
name: scan-reports-${{ github.run_id }}
path: data/
retention-days: 14
if-no-files-found: ignore