Data Sources
Last verified
Eighteen external feeds drive the platform. Each is registered as a DataSource subclass in app/sources/ and pulled by engine.py:fetch_all_sources() on the cadence dictated by the active collection profile.
The full inventory
| Source | What it provides | Cadence | Required |
|---|---|---|---|
market (primary brokerage feed + public market-data fallback) |
SPY/QQQ/IWM/DIA closes, VIX, MOVE, chain net-Γ + gamma walls/ZGL/PCR, BTC, RSI, IVR | Per profile | Yes (core) |
fred |
Fed liquidity, HY OAS, 2s10s, breakevens, yields, real yield | Per profile | Yes |
credit |
High-yield credit spread series, NFCI | Per profile | Yes |
liquidity |
Net Fed liquidity (WALCL − TGA − RRP) | Per profile | Yes |
darkpool |
Dealer-gamma analytics vendor DIX + GEX daily CSV | Daily post-close | Yes |
news |
FXStreet RSS + Iran International liveblog + Hormuz tanker monitor | Per profile | Yes |
sentiment |
Third-party news-sentiment feed (retired 2026-06) | Per profile | Optional (25 req/day budget) |
seasonality |
Historical SPY seasonality lookup | Per profile | Optional |
vol_structure |
VIX term structure (VIX9D/VIX/VIX3M/VIX6M ratios) | Per profile | Yes |
eps |
Forward EPS revision deltas | Per profile | Optional |
breadth |
S&P 500 % above 50/200 SMA, sector breadth | Per profile | Yes |
energy |
WTI, Brent, USO, XLE, crack spread | Per profile | Yes |
inflation |
Breakeven inflation series (5Y, 10Y, 5Y5Y) | Per profile | Yes |
macro_indicators |
Composite macro health proxies | Per profile | Optional |
cot |
CFTC Commitments of Traders speculator net positioning | Weekly (Fri ~15:30 ET) | Optional |
aaii |
AAII bull-bear sentiment spread | Weekly (Thu) | Optional |
ebp |
Fed Excess Bond Premium + GZ credit spread + model recession probability | Monthly (FEDS Notes CSV) | Optional |
fred_macro |
Free FRED macro-state + financial-stress / funding series (Kim-Wright 10Y term premium, EFFR, SOFR, jobless claims, STLFSI4, KCFSI, unemployment, Core PCE); all data_only carriers, not yet scored |
Per profile (full / extended) |
Optional |
cboe |
Free CBOE CDN no-key CSVs — options put/call ratios (equity / total / index) + VIX term-structure front/back points (VIX9D, VIX6M); all data_only carriers, not yet scored |
Daily (full / extended) |
Optional |
ofr |
Free OFR (US Treasury) no-key daily CSV — Financial Stress Index composite + 5 subindices (credit / equity-valuation / safe-assets / funding / volatility); all data_only carriers, not yet scored |
Daily (full / extended) |
Optional |
naaim |
Free NAAIM weekly page-scrape — NAAIM Exposure Index (active-manager equity exposure); data_only carrier, not yet scored |
Weekly (rides full / extended) |
Optional |
options-analytics-live |
Live options-analytics dealer-risk + levels for SPY — settled/live net dealer gamma + delta (billions), intraday flow-shift, the categorical flow direction, and the gamma-flip / call-wall / put-wall / max-pain levels; all fa_* data_only carriers, not yet scored. Captured forward as a hedge against the subscription lapsing |
Intraday (4×/trading day, full) |
Optional |
edgar_xbrl |
Free, no-key SEC EDGAR audited quarterly financial facts for a fixed 6-name entity set (NVDA inventory + revenue; MSFT/GOOGL/AMZN/META/ORCL capex + operating cash flow). Feeds the AI Capital Cycle T13 auto trigger + T10’s capex/OCF companion read; persisted to its own table, not daily_signals |
Daily (overnight / full) |
Optional |
Three auxiliary fetches run alongside the registered sources and stash results under underscore-prefixed keys (_gamma_levels, _fed_watch, _correlations) so format_report can find them without colliding with per-source dicts:
- Gamma profile — Brokerage option-chain pull for the per-strike
gamma_levelsAPI path. Requires brokerage auth; logs and continues on token failure. - Fed Watch — CME rate-cut probability surface for the next FOMC meeting.
- Correlations — rolling SPY/VIX, SPY/DXY, SPY/TNX, SPY/Oil pair correlations computed post-hoc from the persisted
daily_signalshistory. Not an external fetch — it’s a SQL query against our own history.
Provider mix and fallback posture
markettries the brokerage market-data feed first, falls back to the public market-data fallback when the brokerage returns None/empty. The chain-computed quantities (chain net-Γ, gamma walls, ZGL, PCR — not the dealer-gamma analytics GEX aggregate, which arrives viadarkpool) require brokerage option chains and have no fallback. VIX uses volume-weighting since the brokerage reports no OI for index options. TNX and DXY have no option chains.- The brokerage feed is optional. Missing or expired tokens log CRITICAL but the platform continues on the public market-data fallback / FRED / other sources. See source health for how token status surfaces on
/api/v1/status. - The third-party news-sentiment feed was rate-limited at 25 requests/day and retired 2026-06 (DOCTRINE D22);
/api/v1/source-healthsurfaces remaining budget for active rate-limited sources. - News fan-out — the
newssource merges three feeds: FXStreet financial headlines, Iran International liveblog (for geopolitical risk), and the Hormuz Strait tanker monitor (for oil-supply tail risk). ebppulls the Federal Reserve’s monthly FEDS Notes Excess Bond Premium CSV. EBP is the residual of the Gilchrist-Zakrajšek corporate credit spread after stripping out compensation for expected default risk — the credit-market literature’s premier forward leading indicator, with a 50-year multi-regime history back to 1973. The source persists three fields per cycle:ebp(the excess premium, % points, can be negative),gz_spread(the parent GZ spread, % points), andebp_recession_prob(the model’s recession probability, a 0-1 fraction; renamed from the upstreamest_probcolumn). Cadence is monthly — the Fed refreshes the file roughly once a month, last row datedYYYY-MM-01, so only the low-frequency profiles (overnight,extended,full) earn a fresh row. Ingested + persisted only: the three fields land ondaily_signalsfor future scoring / matcher use but are not yet wired into the health score or alignment — that is a later, separately-gated step.cboepulls free, no-key CBOE CDN CSVs (daily cadence,full/extendedprofiles). Fivedata_onlycarriers for the drawdown-risk / state lane: three options put/call ratios —cboe_equity_pc(equity-only),cboe_total_pc(equity + index),cboe_index_pc(index-only) — and two VIX term-structure points,vix9d_close(9-day, front of the curve) andvix6m_close(6-month, back). The intermediate VIX3M and the derived VIX term slope / ratio are already persisted elsewhere (Law 3 — not re-emitted here). Each CSV leg is fetched independently throughsafe_fetch, so a single dead file degrades that one field tonulland leaves the others intact. Ingested + persisted only — not yet wired into the health score or alignment.ofrpulls the OFR (US Treasury Office of Financial Research) Financial Stress Index from a free, no-key daily CSV (financialresearch.gov, daily T-2,full/extendedprofiles). Sixdata_onlycarriers for the drawdown-risk / state lane: the compositeofr_fsi(>0 = above-average stress) plus five subindices —ofr_fsi_credit,ofr_fsi_equity_valuation,ofr_fsi_safe_assets,ofr_fsi_funding,ofr_fsi_volatility. The three geographic split columns (US / other-advanced / emerging) are deliberately dropped. It is a second, model-independent stress read alongside the FRED STLFSI4 / KCFSI legs. The single CSV routes throughsafe_fetch; a dead URL or unparseable file degrades the whole dict to empty without raising. Ingested + persisted only — not yet wired into the health score or alignment.naaimpulls the NAAIM Exposure Index via a free, two-step weekly page-scrape (naaim.org). The data-file XLSX href rotates each week, so the source scrapes the program page for the current link, then parses the workbook (viaopenpyxl) and reads the latest row’s “NAAIM Number” intonaaim_exposure— the average equity exposure NAAIM-member active managers report running (~-200 leveraged short to +200 leveraged long). Adata_onlypositioning / contrarian carrier for the squeeze-setup and drawdown-risk lane. The source is fragile by design: a non-matching href regex, an empty page, or a missingopenpyxlall degrade to empty without raising, and a latest row older than ~14 days still returns the value but logs a staleness warning. Browser-like request headers are sent to avoid bot-filtering. Ingested + persisted only — not yet wired into the health score or alignment.options-analytics-livepulls the live options-analytics dealer-risk + levels archive for SPY from two REST endpoints. It persists afa_*-prefixed family: settled vs live aggregate net dealer gamma + delta (normalized to billions to share the dealer-gamma analytics GEX scale), the intraday flow-shift fractions, a categoricalfa_flow_direction(amplifying / dampening / neutral / no_flow / regime_flip), the live gamma-flip / call-wall / put-wall / max-pain price levels, and anfa_as_ofvintage stamp. This is a SECOND vendor’s positioning read, deliberately kept distinct from the dealer-gamma analytics GEX and the option-chain gamma walls. Each endpoint is fetched independently throughsafe_fetch, so a 5xx / timeout / null on one endpoint degrades only its fields and never poisons the other or the cycle; with no API key the source returns empty and logs a warning. Captured forward as a hedge — alldata_onlycarriers, not yet wired into the health score or alignment (forward-accruing until graded).edgar_xbrlpulls SEC EDGAR’s freecompanyfactsAPI for a fixed six-name entity set — no key, no rate concern (six requests per cycle against SEC’s ~10 req/s ceiling). Unlike every other source in this table it does NOT feeddaily_signals: it persists directly to its own append-only table, because the data is per-company audited history, not a daily macro reading. The interesting engineering is the extraction, not the fetch — EDGAR reports cash-flow and income figures as fiscal-year-to-date cumulative totals, not clean quarterly numbers, so the source derives genuine quarterly deltas (and correctly handles a company’s underlying reporting tag changing over the years) before writing anything. See the AI capital cycle framework page for how the derived reads feed the T13/T10 triggers.
Macro calendar — what’s filled, what isn’t
The platform seeds a forward macro-event calendar (calendar_events) that powers the air-pocket flag’s catalyst leg and the AI brief’s calendar_lookahead. The three high-impact monthly prints — Employment Situation (NFP), CPI, PPI — are seeded from FRED’s free release/dates endpoint, plus FOMC decisions and the weekly FRED release projections.
Each macro-event row carries consensus and actual columns. The two behave differently:
consensusis NULL by constraint. The market’s prior-expectation survey for these releases has no free, terms-of-service-clean source. FRED’s release endpoint serves the schedule only — the published date, never the street’s forecast. Consensus figures live behind paid econ-calendar vendors, which the platform deliberately avoids. So the print-vs-consensus surprise read (the thing the calendar would unlock) stays blocked until a free consensus source appears or a paid one is sanctioned. This is an honest data gap, not a bug — the column exists, waiting for a source that does not yet exist.actualis wired for the unambiguous prints. The realized headline figure is free from FRED (the underlying series themselves), so after a print lands the backfill fillsactualfor the releases whose series → quoted-headline mapping is unambiguous:- NFP →
PAYEMS(Total Nonfarm Payrolls); headline = month-over-month change in the level, in thousands (e.g.+139K). - CPI →
CPIAUCSL(CPI-U, All Items, SA); headline = month-over-month percent change (e.g.+0.2% m/m). - PPI is deliberately left NULL. PPI has two competing “headline” series in common quotation (final-demand vs all-commodities) and the quoted figure isn’t unambiguously one of them — so per the rule that a wrong
actualis worse than an empty one, PPI stays unfilled until a canonical mapping is settled.
- NFP →
Constraint: no free consensus survey for NFP/CPI/PPI; no canonical headline mapping for PPI. Falsifier: a free, ToS-clean consensus feed (or a sanctioned paid one) becomes available, or PPI’s quoted-headline series is settled. Unblock: wire consensus into
_emit_fred_release_calendar(consensus=) and the surprise framing follows; add the PPI entry toRELEASE_ACTUAL_MAPand itsactualwires automatically.
Execution order
Fast HTTP sources run first (FRED, liquidity, darkpool, news, sentiment) so the heavy market-data fallback sources (market, eps, breadth) don’t gate the report on slow network paths. Breadth specifically downloads in batches of 50 tickers with 2-second delays to stay under the market-data fallback feed’s rate limits.
Every fetch routes through DataSource.safe_fetch() in app/sources/base.py — uniform retry with exponential backoff, WARNING on transient failure, logger.exception() on fatal, returns a default on terminal failure. New sources must use it.
See also
- Schedule — when each profile fires, which sources each profile pulls.
- Lifecycle — what happens to fetched data inside a report cycle.
- Source health — how
source_runstracks ok/fail and the 95%/80% escalation rules. - DIX and GEX — the two signals that flow through the
darkpoolsource. - Source code:
app/sources/(one file per source). Inventory + provider table also inapp/sources/README.md.