Crack the Sky

marketdata

Typed parquet I/O. Import submodules directly (marketdata.opra, .types, .catalog, .validate). CLI: python -m marketdata.validate (same as python -m marketdata).

OPRA allowlist
Allowlist is exactly SPY, SPX, SPXW, VIX, VIXW. The parser alternation is longest-first (SPXW before SPX, VIXW before VIX) so O:SPXW… is not captured as SPX and O:VIXW… is not VIX. A prefix match on O:SPY would admit SPYL/SPYS/SPYG, and O:VIX would admit VIXY; parse_opra does not. Raises OPRAParseError — never a partial.
Contract
Exercise style and multiplier live on the dataclass: SPY American, SPX/SPXW/VIX/VIXW European, multiplier 100. Settlement instants: SPY/SPXW 16:00 ET (PM-settled); SPX monthlies and both VIX series 09:30 ET (AM-settled to the Wednesday SOQ).
Quote
Snapshot-derived. Vendor IV/greeks copied as diagnostics (vendor_*). market_price = last if present, else day close; the trade's own stamp rides along as last_trade_asof_ns so consumers can age-filter (asof_ns stays the underlying/snapshot clock). Pricing must ignore vendor columns.
As-of
Snapshots/contracts/forwards are written many times a day. read_partition refuses those datasets (double-count). read_asof takes the last file per underlying at or before asof_ns (filename epoch-ms). Absence is an error. option_trades is multi-source: a partition can hold overlapping REST and flat-file rows, so readers must pass src. decision_log is the opposite case — append-only event history, so read_asof refuses it (last-file-wins would hide earlier events); read the whole partition via ingest.common.decision_log.read_decisions.
Fail-loud
Extra or missing parquet columns → SchemaError. Validate fails on foreign roots, mixed underlyings vs a SPY-only query, required-nulls, empty allowlisted root, empty table. --roots narrows the allowlist; it cannot extend it.