Architecture at a Glance
- Language/Runtime: Python 3.11
- Scheduler: APScheduler (cron-like jobs)
- Fetch: requests + beautifulsoup4 (for pages without APIs) or official/data APIs when available
- Storage: SQLite (local) or Postgres (cloud)
- Rules/AI layer: simple rules + optional classifier to detect “capitulation/complacency”
- Alerts: Slack webhook, email (SMTP), or SMS (Twilio)
- Dashboard (optional): FastAPI + lightweight HTML (or push to Notion/Google Sheets)
Update Cadence
- CNN Fear & Greed Index (FGI): daily (usually updates after market close)
- AAII Sentiment: weekly on Thursdays (U.S. market week)
- VIX: intraday capable; for practical alerts, poll every 15–30 minutes during market hours
Signal Model (normalized 0–100)
- FGI: already 0–100
- AAII: use %bulls, %bears (and bull-bear spread). Map “extreme bear” toward 0, “extreme bull” toward 100
Simple Composite & Alert Rules
- Composite: average of available scores (e.g., mean([FGI, AAII_score, VIX_score]))
- Capitulation (BUY setup):
- FGI <= 20 and/or
- AAII bears >= 50% and
- VIX >= 30
- Complacency (TAKE PROFITS / tighten stops):
- FGI >= 80 and/or
- AAII bulls >= 50% and
- VIX <= 15
def aaii_to_score(bulls: float, bears: float) -> int:
# Map extremes: 60% bears ~ score 10, 60% bulls ~ score 90; neutral ~ 50
spread = bulls - bears # positive = greed, negative = fear
# Clamp a linear map into 0..100
score = int(max(0, min(100, 50 + spread * 1.2))) # tune multiplier w/ backtests
return score
def vix_to_score(vix: float) -> int:
# Example bands: 12 (very calm) -> 90; 35 (panic) -> 10
# Linear map between 12..35 into 90..10 (then clamp 0..100)
lo, hi = 12, 35
if vix <= lo: return 90 if vix >= hi: return 10
frac = (vix - lo) / (hi - lo)
return int(90 - frac * 80)