A Python bot that scans for US Technology stocks with significant daily losses and sends email alerts via Gmail.
-
Primary Data Source: Financial Modeling Prep (FMP) API
- Biggest losers feed for candidate universe
- Company profiles for market cap, sector, and industry
-
Secondary Data Source: Twelve Data (optional)
- Verification of percent changes
- Built-in credit tracking (8/min, 800/day limits)
-
Email Alerts: Gmail SMTP (App Password)
- No OAuth required
- HTML-formatted emails with summary tables
- CSV attachment with raw data
-
Smart Caching: SQLite-based profile cache
- Reduces API calls to stay within free tiers
- Configurable cache duration (default: 7 days)
- Daily % Change: <= -5% (close-to-close)
- Sector: Technology (exact match)
- Industry Override: include if industry contains keywords (default:
software), even if sector is not Technology - Market Cap: >= $1,000,000,000 (1 billion USD)
Optional overrides:
INCLUDE_INDUSTRY_KEYWORDS: comma-separated industry keywords to include (default:software)EXTRA_SYMBOLS: comma-separated extra symbols to scan (added to the 544-universe)FORCE_INCLUDE_SYMBOLS: comma-separated symbols that bypass the sector/industry check (still must meet % change + market cap)
Results are sorted by market cap (descending).
# Clone or download the project
cd tech_losers_bot
# Create virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txtcp .env.example .envEdit .env with your API keys:
# Required
FMP_API_KEY=your_fmp_api_key_here
GMAIL_SENDER=your_email@gmail.com
EMAIL_RECIPIENTS=recipient@example.com
# Optional (for verification)
TWELVE_DATA_API_KEY=your_twelve_data_key_here
# Optional settings
PROFILE_CACHE_DAYS=7
TWELVE_DATA_DAILY_LIMIT=800
TWELVE_DATA_REQUEST_TIMEOUT=8
TWELVE_DATA_MAX_RETRIES=2
TWELVE_DATA_WORKERS_PER_KEY=1
TWELVE_DATA_API_KEYS_CSV=
INCLUDE_INDUSTRY_KEYWORDS=software
EXTRA_SYMBOLS=
FORCE_INCLUDE_SYMBOLS=
# SMTP (App Password)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@gmail.com
SMTP_PASSWORD=your_app_password_here
SMTP_USE_TLS=true
# Optional AI summary (NVIDIA)
NVIDIA_API_KEY=your_nvidia_api_key_here
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- Sign up at financialmodelingprep.com
- Verify your email
- Use the "Free Plan Access" API key from your dashboard
- Create account at twelvedata.com
- Get your API key from the dashboard
- Note: Free tier has 8 credits/min and 800 credits/day
This project now sends email via SMTP using a Gmail App Password (no OAuth).
- Enable 2‑Step Verification on your Google account
- Create an App Password for “Mail”
- Set these in your
.env:SMTP_USER(your Gmail address)SMTP_PASSWORD(the app password)SMTP_HOST/SMTP_PORTif you want to change defaults
python main.pypython main.py --dry-runpython main.py --dry-run --sample-size 50python main.py --scan-source fmppython main.py --scan-source fmp-quotespython main.py --verifypython main.py --statuspython main.py --clear-cacheUS Technology Losers <= -5% (Close-to-Close), mcap >= $1B — YYYY-MM-DD
- Run timestamp with timezone
- Summary counts:
- Total scanned
- Candidates from losers feed
- After -5% filter
- After sector + mcap filter
- Results table:
- Rank
- Symbol
- Company
- Daily % change
- Price (USD)
- Market cap (USD)
- Sector ("Technology")
- Industry
- Reason (latest news summary)
losers_tech_over1b_YYYY-MM-DD.csvwith the same columns
# Run Tue–Sat at 5:00 PM SGT (after market close)
0 17 * * 2-6 cd /path/to/tech_losers_bot && ./venv/bin/python main.pyCreate ~/Library/LaunchAgents/com.techlosers.bot.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.techlosers.bot</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/tech_losers_bot/venv/bin/python</string>
<string>/path/to/tech_losers_bot/main.py</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>17</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>WorkingDirectory</key>
<string>/path/to/tech_losers_bot</string>
</dict>
</plist>Load with:
launchctl load ~/Library/LaunchAgents/com.techlosers.bot.plistThe project includes a GitHub Actions workflow at .github/workflows/daily_scan.yml that runs automatically.
Schedule: Tue–Sat at 08:00 SGT (Mon–Fri US Market Close).
Manual trigger: Go to Actions → "Daily Tech Losers Scan" → "Run workflow".
Go to Settings → Secrets and variables → Actions → New repository secret and add:
| Secret Name | Description |
|---|---|
FMP_API_KEY |
Financial Modeling Prep API key |
TWELVE_DATA_API_KEYS_CSV |
Comma-separated Twelve Data keys |
TWELVE_DATA_API_KEY |
Primary Twelve Data key |
GMAIL_SENDER |
Sender email address |
EMAIL_RECIPIENTS |
Comma-separated recipient emails |
SMTP_USER |
Gmail address for SMTP auth |
SMTP_PASSWORD |
Gmail App Password |
NVIDIA_API_KEY |
(Optional) NVIDIA NIM API key |
- Copy values from your local
.envfile - Each
.envvariable maps to a secret with the same name TWELVE_DATA_API_KEYS_CSVis a single comma-separated string of all Twelve Data keys
| Feature | Local | GitHub Actions |
|---|---|---|
| Trigger | python main.py |
Automatic (cron) or manual |
| Secrets | .env file |
Repository secrets |
| Network wait | Default 5-min polling | --no-wait flag |
| Data output | Local data/ dir |
Downloadable artifact |
| Logs | Terminal stdout | Actions run logs |
tech_losers_bot/
├── .github/
│ └── workflows/
│ └── daily_scan.yml # GitHub Actions workflow (daily cron)
├── main.py # Entry point
├── requirements.txt # Dependencies
├── .env.example # Environment template
├── .env # Your configuration (create this)
├── README.md # This file
├── src/
│ ├── __init__.py # Package exports
│ ├── config.py # Configuration loader
│ ├── cache.py # SQLite profile cache
│ ├── credit_tracker.py # Twelve Data credit tracking
│ ├── fmp_client.py # FMP API client
│ ├── twelve_data_client.py # Twelve Data API client
│ ├── provider_router.py # Multi-source routing
│ └── gmail_sender.py # SMTP email sender
├── data/ # Generated data (auto-created)
│ ├── profile_cache.db # SQLite cache
│ ├── credit_tracker.json
│ └── *.csv # Generated reports
└── credentials/ # (unused) OAuth files no longer required
| Service | Limit | How Bot Stays Within |
|---|---|---|
| FMP Free | 250 requests/day | Profile caching (7-30 days) |
| Twelve Data | 800 credits/day, 8/min | Credit tracker + throttling |
| Gmail SMTP | Varies by account | One report per run |
Make sure your .env file exists and contains a valid FMP API key.
- Ensure
SMTP_USERandSMTP_PASSWORDare set correctly - Confirm 2‑Step Verification is enabled and App Password is valid
The bot will automatically skip verification if credits are exhausted. Credits reset daily.
This is normal on days without significant tech sector losses. The bot will send a "no stocks" notification.
MIT License - feel free to use and modify.