Skip to content

KB / operations

FinRep-AI — how the dashboard's AI Read card works

Last verified

The AI Read card at the top of the dashboard is generated by Claude Opus 4.8. Every few hours the platform hands the model a curated snapshot of its current market view and asks for a directional read on SPY (1-day / 3-day / 5-day) plus a specific options play that fits the setup.

This article walks through what the AI is looking at, what it’s asked to produce, and shows a real example end-to-end.

How it operates

Five scheduled briefs per trading day, plus event-driven triggers on breaking news:

SlotEastern TimePurpose
pre_market08:30Overnight setup + futures read before the bell
open_snap09:35First-five-minutes confirmation or fakeout
midday12:00Lunch-hour drift check
pre_close15:30Last 30 minutes — position-into-close call
close_recap16:15Day-over recap + setup for the next session

Event-driven triggers fire when breaking news lands (Iran, energy disruption, Fed surprise, etc.), capped at 3 per day with a 30-minute minimum gap between fires so a noisy news cycle doesn’t burn through the budget.

Every brief carries the last 3 days of prior briefs along with it. The AI is building a rolling narrative — it knows what it said yesterday, why, and whether the market followed through. When its view shifts, it surfaces a view_change_note explaining what changed.

What the AI sees (the signal pack)

The signal pack is built by app/signals/ai_context.py:build_signal_pack(db) and pulled from the same store the dashboard reads. ~50 fields covering today’s market state plus the last 7 trading days:

Price + structure

Volatility

Positioning + flow

Macro + regime

Energy + cross-asset

Recent news (last 24h)

Historical analogues

What it’s asked to produce

The system prompt asks for plain English, minimal jargon, and a strict JSON output schema:

{
  "headline": "One sentence — the read in a sentence.",
  "direction": {
    "1d": {"bias": "up | down | sideways", "confidence": 1-5},
    "3d": {"bias": "...", "confidence": 1-5},
    "5d": {"bias": "...", "confidence": 1-5}
  },
  "play": {
    "strategy": "Specific options trade, 2DTE to 2W DTE.",
    "thesis": "Why this trade fits the setup.",
    "invalidation": "What kills the trade.",
    "max_risk_pct": 0.5-3.0
  },
  "news_read": "How news is moving the tape.",
  "view_change_note": "Optional — only if the AI shifted from yesterday.",
  "watch": ["Specific levels or prints to monitor."]
}

The voice rules are blunt: no hedging, no academic language, no “could potentially,” no “it’s worth noting.” Pick a direction and a play. The platform tracks how often the call was right via the brief-accuracy backtest.

Example end-to-end

Trigger: pre_close slot, 2026-05-22 15:30 ET.

Signal-pack highlights handed to the AI:

{
  "as_of": "2026-05-22T15:30:00-04:00",
  "latest_daily": {
    "trade_date": "2026-05-22",
    "spy_close": 748.40,
    "spy_3d_return": -0.012,
    "vix_close": 18.4,
    "dix": 0.378,
    "gex": -2.8,
    "regime": "CAUTIOUS",
    "regime_reason": "Negative gamma + below-average DIX + elevated 0DTE PCR",
    "spy_dist_to_call_pct": 0.6,
    "spy_dist_to_put_pct": -2.1,
    "alignment_label": "MIXED",
    "health_score": 58,
    "energy_regime": "RISING"
  },
  "news": {
    "window_hours": 24,
    "count": 47,
    "items": [
      {
        "source": "iran",
        "title": "US and Iran reach preliminary nuclear framework — tanker traffic normalizes.",
        "finrep_ai_score": 0.62,
        "finrep_ai_label": "positive"
      }
    ]
  },
  "analogues": [
    "2024-02-13", "2024-09-18", "2025-03-04",
    "2025-07-22", "2025-11-08"
  ]
}

What the AI produced (parsed brief):

{
  "headline": "Risk-on news fights negative gamma — close near call wall favors a tight upside fade.",
  "direction": {
    "1d": {"bias": "sideways", "confidence": 3},
    "3d": {"bias": "up", "confidence": 4},
    "5d": {"bias": "up", "confidence": 3}
  },
  "play": {
    "strategy": "SPY 745/752 call debit spread, 7 DTE",
    "thesis": "Iran deal removes the energy-shock tail. DIX is recovering off the lows and the analogues that share this signal mix were positive 3d/5d 70% of the time. Negative gamma keeps the 1d range pinned, so a tight spread above the call wall plays the swing without paying for the chop.",
    "invalidation": "SPY closes below 744 on the next session, or VIX prints above 22.",
    "max_risk_pct": 1.0
  },
  "news_read": "Iran deal is the dominant tape mover; energy regime should flip from RISING back to NORMAL within 48h.",
  "view_change_note": "Yesterday's brief was bearish into close on the energy-shock thesis. The framework news erases that — the cautious posture is no longer the operative read.",
  "watch": ["SPY 752 call wall", "VIX < 17", "Crack spread normalization"]
}

That entire round-trip — from signal pack to parsed brief — takes ~4 seconds and costs about $0.16 once the prompt cache is warm.

Why we run it this way

Three principles shape the design:

  1. The AI reads the same surface external agents do. The signal pack pulls from /api/v1/signals/latest, the analogues come through the compare_to_history MCP tool, the news comes from the same news_items table the comparison surface exposes. If a third-party agent subscribed to the API tomorrow, it would see the exact same inputs and could write its own competing brief generator.

  2. The AI sees yesterday. Most LLM market commentary is a snapshot — fresh prompt every time, no memory. FinRep-AI sees the last 3 days of its own briefs along with the live signal pack, so when the view changes there’s a documented reason and a view_change_note field for the user.

  3. The brief generation is internal, but the data is public. The dashboard AI burns the operator’s Anthropic credit on a fixed schedule. The platform doesn’t expose a “generate a brief on demand” endpoint — anyone wanting to run their own briefs uses their own AI subscription against the public API + MCP. That keeps the cost predictable and the data layer accessible.