Crack the Sky
Warehouse → math chain
CLI usage
python -m pricing.from_market --date YYYY-MM-DD [--asof-ns N] [--r 0.04]
— --r is optional; without it the landed Treasury curve
interpolates per contract.
As-of load
- Loads last
option_snapshotsandforwardsat or before that instant.
Own IV
- Inverts own IV from last/close (no NBBO mid).
-
Every price is a traded price. Option NBBO is 403 on this
tier —
/v3/quotesand thequotes_v1flat file both — so there is no bid, no ask and no spread anywhere in the warehouse, andQuote.market_priceis the last trade else the session close. This is a modelling assumption, not just an ingest limitation, and it propagates into every IV and greek derived from it:- A trade may print at the bid, at the ask, or inside the spread, so inverted IV carries an offset from the mid that is unknown without NBBO — bounded in the worst case by about half the spread in vol terms, and not safe to assume averages out over a series. The bound is widest exactly where spreads are widest: the OTM wings the skew is made of.
- No spread means no width-based liquidity screen. Volume and open interest are the substitutes the snapshot carries.
- A last trade can be arbitrarily stale.
Quotecarries the trade's own stamp inlast_trade_asof_ns(fromoption_snapshots.last_trade_sip_timestamp_ns) alongsideasof_ns— which still prefersunderlying_last_updated_ns, the right clock for spot and rates — andgreeks_asofskips last-priced rows whose trade is older than--max-trade-age-min(default 60), counting them asstalein the canary report. There is noday_closefallback: the reprice identity needs a contemporaneous market price and a stale one is not one.
Own greeks
- Computes own Greeks. SPX/SPXW → European BSM; SPY → American CRR (default 51 tree steps on the chain).
--spy-atm-pctCRR-prices only ATM SPY and European-prices the rest.--max-rowscaps American CRR rows only so an SPX-first concat cannot starve SPY.- Vendor
greeks_*/implied_volatilitycopied as diagnostics with signed diffs (own − vendor). Theta × 365 and vega × 100 for unit alignment. Never inputs. - T is ACT/365 from as-of to the settlement instant (not UTC midnight of the expiry date): SPY/SPXW 16:00 ET, SPX monthlies and VIX/VIXW 09:30 ET.
--rpins a scalar rate; default is the landed Treasury curve viarate_for, interpolated to each maturity.- SPX has no snapshot spot: parity forward → Black-76 via synthetic
S = F e^{-rT}. - Exit nonzero on foreign roots, mixed underlyings, required-nulls, empty allowlisted root, schema drift, or (unless
--skip-uninvertible) a price outside bounds.--euro-ivpins every invert back to closed-form BSM for an A/B against the American solver.
Skip counts
Rows are omitted rather than written as NaN.
ChainCounts is what the canary report echoes.
None of these is a FAIL by itself; an empty result after skips is a
ChainError.
| Count | Omitted because |
|---|---|
| n_expired | T ≤ 0 at the as-of (settlement instant already passed). |
| n_no_price | No last and no day close — nothing to invert. |
| n_stale | Last print older than --max-trade-age-min (default 60). No day_close fallback. Rows priced off close, and lasts with no trade stamp, are not age-filtered. |
| n_uninvertible | Price outside no-arbitrage bounds. Default is raise (--skip-uninvertible counts and drops). The below-intrinsic subset is also n_below_intrinsic. |
| n_below_intrinsic | Inside uninvertible: a traded price below the style's intrinsic floor. Issue #44's stale-print tail, now mostly caught as n_stale first. |
| n_no_asof | Quote has no snapshot clock — cannot form T. |
| n_otm | Only when a moneyness filter is set; far-from-the-money names dropped before invert. |
What a nonzero exit means
| Symptom | What it actually is |
|---|---|
| foreign root / mixed underlyings / empty allowlisted root | The parquet is not this desk's universe, or --roots asked for a name that produced zero rows. Absence is failure. |
| SchemaError | Extra, missing, or mistyped column vs ingest.schemas. The warehouse moved without the reader. |
| AsOfError | No snapshot/forward file at or before the instant, or an unstamped filename. Wrong --date / --asof-ns, or the sweep never ran. |
| ValueError / ChainError on invert | A price outside bounds with the default raise policy — not a NaN. Pass --skip-uninvertible only to survey the tail. |
| empty table | Everything was skipped. Look at the counts above before assuming the partition is missing. |