Skip to content

Options Data Pipeline — Architecture Reference


status: ACTIVE tier: 2 (design reference) last-verified: 2026-09-27 verified-against: e3ba5fd4 supersedes: Projects/_closed/Options Indicator Improvements/Options Data Concept and Architecture.md (historical source, Tier 3) governing-spec: Projects/_closed/Options Indicator Improvements/Simplify Options Flow Data Pipeline/Unified Implementation Plan v4.1.md + Decision Log (D1-D10)


2026-09-26 cutover (v4.1 — the state described below is TRANSITIONAL)

The storage root moved to ~/Dropbox/Apps/ATAS/Options (gex_lib.OPTIONS_ROOT single source; env TRADERJAN_OPTIONS_ROOT) and a Schema v4 day-file store is live: gex/{SYM}/{date}.json — one file per symbol-session (ascending UTC snapshots[] + session metadata: publish_ts/publish_detected/settled/activation). 2,629 day-files: NQ 1,692 (2020-01→), ES 937 (2023-01→), the other 5 instruments' live era backfilling. Raw layer live: raw/{SYM}/{date}/{HHMMSS}.json.gz byte-exact per poll (daemon + C#).

Binding (C# v2.10.0, single-source): ALL render/signal paths bind DayFileOptionsStore.PayloadAt (UTC-first, 4-rung ladder: carry-over → settled → morning baseline → prior-base; no day-file = honest blank). D10: static levels switch ONCE daily at the detected OI publication (publish_ts; the Morning Activation Floor = thin-day fallback only) — the session-roll switch and its ~12h lookahead retired. The legacy tiers (_ETH/_RTH/_HHMM/phase files) are write-once P-IT compat + fallback internals pending Phase 4 retirement; the readers' Tier-2 description below remains accurate for the LEGACY path only.


Purpose

How options-derived market structure (GEX levels, walls, profiles) flows from raw vendor data to the ATAS chart and the Python backtester — one canonical contract, three consumers.

CBOE delayed CDN (QQQ/SPY chains) ──┐
ThetaData EOD + 15-min parquets   ──┼──► gex_lib.py (canonical math, schema v3)
Yahoo futures closes + VIX/VXN    ──┘         │
                                              ├──► ~/Dropbox/Apps/ATAS/Options/
                                              │      gex/{NQ,ES}/{date}.json        (v4 day-files)
                                              │      nq_qqq_ratios.json / es_spy_ratios.json
                                              │
              C# GexEngine.cs (parity port) ◄─┤──► Options Flow indicator (chart/HUD)
                                              └──► manage_data.py ──► Master Parquets ──► backtest.py

Data sources

Source Content Cadence Notes
CBOE delayed CDN QQQ/SPY option chains (OI, IV, volume) ~15 min delayed Live path for collector daemon + C# in-indicator fetch
ThetaData EOD quotes+OI, 15-min intraday quotes Cached (thetadata_cache/) QQQ/SPY full history (2020–2026); IV via bisection inversion (no greeks subscription)
Yahoo Finance NQ=F/ES=F daily closes, ^VXN/^VIX On demand Ratio files + IV rank; fallback constants forbidden for archives
AlphaVantage (RETIRED) Historical EOD chains Retired 2026-09-27 Superseded by ThetaData full-history (2020–2026) EOD + intraday

Schema v3 contract (OptionsPayload)

Defined in TraderJan.Indicators/GexEngine.cs, mirrored by Backtesting/scripts/gex_lib.py. Key fields: schema_version: 3, spot_price (futures scale), etf_spot, ratio, key_levels (10 fields), term_structure (dte0/weekly/monthly tiers), regime, strike_profile (band-limited rows), source, timestamp, trade_date, chain_date, phase.

Archive tiers per session date in snapshots/{SYM}/:

File Semantics (point-in-time)
full_options_{sym}_{date}.json Base: day-T EOD chain (oracle)
…_{date}_ETH.json Overnight slot: T-1 chain
…_{date}_RTH.json RTH slot: T-1 chain (PIT); live-era = collector live chain pre-Phase 2, repaired after
…_{date}_RTH_settled.json Day-T settled EOD (ThetaData) — the oracle
…_{date}_{HHMM}.json 15-min intraday snapshot (HHMM = ET); EOD-frozen OI, IV inverted from quotes

PIT hard rule: chain_date < trade_date for _RTH/_ETH; enforced by audit_options_archives.py (0 violations = gate).

Session calendar

  • Options day rolls at 05:00 CT (OCC morning publication); RTH window 08:30–16:15 CT.
  • Weekend guard: no dated snapshots written Sat/Sun (collector + C# WriteArchive).
  • Live-era boundary: 2026-08-25 (collector v3 start); generator protects v3 collector files there.

Generators & consumers

Tool Role
Backtesting/scripts/options_collector.py 24/7 daemon (launchd, 900 s): live chains → active file + snapshots
Backtesting/scripts/generate_intraday_json.py Historical _HHMM backfill (band-limited ±4 %, D3)
Backtesting/scripts/build_gex_from_thetadata.py _RTH_settled regeneration (OI pre-check)
TraderJan.Indicators/OptionsFlow/download_all_historical.py AV offline rebuild + PIT _ETH/_RTH
Backtesting/engine/manage_data.py Master Parquet GEX columns (delegates to gex_lib since Phase 5)
Backtesting/scripts/audit_options_archives.py Quality gates: vt bounds, scale, PIT, provenance, weekend
Backtesting/scripts/verify_intraday.py / verify_engine_a_neutrality.py Parquet PIT + Engine A non-GEX byte-identity

Known limitations (documented, accepted)

  • Intraday snapshots freeze OI at day-T EOD (ThetaData carries none intraday) — historical DynamicRealTime replay is not strictly PIT for OI.
  • ES intraday history starts 2023-01 (SPY cache scope); NQ covers 2020-01-02 → present.
  • CBOE feed is ~15-min delayed; live levels lag fast markets by design.