Vol & Dealer Regime
US equity vol complex · as of 2026-09-18
Each cell places that reading in its own history by the one window rule — its trailing three years, or its whole history where that is shorter (labelled own all (<3y)), with that window's n — from core.metric_context(). All five are knowable a session late, so none of them describes 2026-09-18: the Cboe cells with a reading are dated 2026-09-17 and OCC's is 2026-09-16, which is why each cell carries its own date rather than borrowing the one in the strip.
VIX term structure
The 30D and 3M legs give 0.8323, so the curve is in contango on 2026-09-17. The percentile in the header is that ratio's own three-year standing — the window the rule in src/lib/metrics.ts reads, and the one its label names. It is the number the buckets under What followed are cut from. Days in state counts runs of the state above.
| curve | read on | 9D | 30D | 3M | 30D / 3M |
|---|---|---|---|---|---|
| now | 2026-09-17 | 13.3900 | 15.4400 | 18.5500 | 0.8323 |
| 1 week ago | 2026-09-10 | 17.7000 | 17.8400 | 19.7300 | 0.9042 |
| 1 month ago | 2026-08-18 | 13.5900 | 15.8400 | 19.2700 | 0.8220 |
| 3 months ago | 2026-06-17 | 18.6300 | 18.4400 | 20.6200 | 0.8943 |
Cboe VIX9D, VIX and VIX3M through core.metric_daily. Licence: not exportable.
Days in contango or backwardation
contango has held for 113 sessions since 2026-04-08, after 1 session of backwardation ending 2026-04-07. The state is the ratio against 1, which is where the curve's slope changes sign — a definition, not a tuned threshold, and deliberately not read from the worker's regime constants. The same ratio drawn here is the one the curve above plots as its 30D/3M pair.
Gaps-and-islands over the whole stored ratio history from 2009-09-18; each reading is one Cboe session.
What followed this reading
The condition is the curve's state and the fifth of the ratio's three-year percentile it sits in — contango, 0.0%–20.0% of the last three years, which on 2026-09-17 means a ratio between 0.7104 and 0.8402. Read the condition rows against the baseline row, not on their own: the reading that matters is the difference.
| condition | dates | windows | p25 | median | p75 | up | span |
|---|---|---|---|---|---|---|---|
same state and same percentile bucket contango, percentile 0.0%–20.0% | 972 | 108 | -0.8% | +1.2% | +2.7% | 66% | 2010-01-11 2026-08-19 |
same state, any percentile contango | 3,931 | 209 | -0.8% | +1.6% | +3.4% | 68% | 2009-09-18 2026-08-19 |
every reading on record the baseline | 4,255 | 213 | -0.8% | +1.7% | +3.5% | 69% | 2009-09-18 2026-08-19 |
Percentiles are measured against ONE window - the 752 readings in the three years ending 2026-09-17 - so "same bucket" is a band of ratio values, stated above. Each prior reading's own trailing-three-year percentile is the point-in-time version and costs 3.7 s against production: too slow for a page.
The curve's legs
The three tenors the term structure above draws, as history rather than as one day's shape. VIX carries prints on NYSE holidays that VIX9D and VIX3M do not — 773 points here against 751 for VIX3M over the same three years — so the lines do not share every session. All of them end on 2026-09-17.
Cboe, lag 1. Not exportable.
VVIX and SKEW
Two readings about the tails rather than the level: VVIX is the implied volatility of VIX options, SKEW the implied probability of a large S&P 500 fall. They are drawn in separate panes because they share no scale — and neither belongs on the term structure above, which is one measure at three maturities.
Cboe, lag 1. Not exportable.
Put/call
DESIGN asks for three put/call ratios on one axis. One is collected, and it is not the one the other two would be: OCC's ratio is OPEN INTEREST — positions outstanding — while Cboe's published total and index ratios are VOLUME. Drawing the one on an axis labelled for three would make the missing two look like zero, so they are named below instead.
- OCC equity put/call, open interest· open interest· core.occ_open_interest
- Cboe total put/call· volume· not collected: no table in this warehouse holds it
- Cboe index put/call· volume· not collected: no table in this warehouse holds it
OCC, lag 1. Not exportable.
Net market GEX
Dealer net gamma in the three funds with a 0DTE expiry every session, on the book of 2026-09-17. SPY, QQQ and IWM are not positive, and the three sum to -$14.98bn per 1%. The sum is allowed because all three carry the same unit — dollars traded per 1% move in that fund — so it is what dealers would trade if all three moved 1% together. They do not move together exactly, which is why the three are drawn beside the sum and never replaced by it.
gamma_flip_state is a category, not a measure, so it carries no percentile and none is drawn (core.metric_registry, unit state_code).
Derived from core.option_strikes by worker/app/core/chain_metrics.py; the first stored chain is 2026-06-17, so the whole history is 64 books and every net_gex percentile stands on that. Not exportable.
Per-fund readings
Every metric the two modules above draw on, per fund, with the reading's own date and its own-history percentile by the one window rule: its trailing three years, or its whole history where that is shorter (window all (<3y)). The chain metrics (net GEX, the flip, the 0DTE share) are dated by the chain book they were derived from — 2026-09-16 and 2026-09-17 here, as of 2026-09-18 — and a book appears only once its metrics have been derived; the surface metrics are knowable the evening of their own session. Dates differ down this table for that reason, which is why each row carries one.
| IWM | net_gex | -$7.39bn per 1% | 2026-09-17 | all (<3y) | 0.8% | 64 | |
| IWM | gamma_flip_state | 1 | 2026-09-17 | — | — | — | 1 found / 0 none within 25% / -1 undetermined |
| IWM | gamma_flip_level | $295.70 | 2026-09-17 | — | — | — | flip level, repriced book |
| IWM | gamma_flip_distance_atr | +2.85 ATR | 2026-09-17 | all (<3y) | 80.5% | 64 | |
| IWM | zero_dte_volume_share | 32.0% | 2026-09-17 | all (<3y) | 8.6% | 64 | |
| IWM | iv_term_regime_days | -6 | 2026-09-18 | all (<3y) | 40.0% | 241 | |
| IWM | iv_term_slope_30_90 | -1.8 pts | 2026-09-18 | all (<3y) | 11.4% | 241 | |
| IWM | vrp_30d | +5.7 pts | 2026-09-18 | all (<3y) | 79.0% | 236 | |
| IWM | realized_vol_21d | 11.9% | 2026-09-18 | 3y | 1.1% | 752 | |
| IWM | px_vs_200dma | 3.87% | 2026-09-18 | 3y | 26.7% | 752 | |
| IWM | close_adj | $284.10 | 2026-09-18 | — | — | — | close |
| QQQ | net_gex | -$731.8m per 1% | 2026-09-17 | all (<3y) | 72.7% | 64 | |
| QQQ | gamma_flip_state | -1 | 2026-09-17 | — | — | — | 1 found / 0 none within 25% / -1 undetermined |
| QQQ | gamma_flip_level | $716.98 | 2026-09-16 | — | — | — | flip level, repriced book |
| QQQ | gamma_flip_distance_atr | +1.49 ATR | 2026-09-16 | all (<3y) | 84.7% | 62 | |
| QQQ | zero_dte_volume_share | 63.0% | 2026-09-17 | all (<3y) | 2.3% | 64 | |
| QQQ | iv_term_regime_days | -35 | 2026-09-18 | all (<3y) | 1.2% | 241 | |
| QQQ | iv_term_slope_30_90 | -3.2 pts | 2026-09-18 | all (<3y) | 1.2% | 241 | |
| QQQ | vrp_30d | +7.1 pts | 2026-09-18 | all (<3y) | 90.0% | 236 | |
| QQQ | realized_vol_21d | 13.2% | 2026-09-18 | 3y | 19.6% | 752 | |
| QQQ | px_vs_200dma | 9.02% | 2026-09-18 | 3y | 37.8% | 752 | |
| QQQ | close_adj | $721.45 | 2026-09-18 | — | — | — | close |
| SPY | net_gex | -$6.86bn per 1% | 2026-09-17 | all (<3y) | 41.4% | 64 | |
| SPY | gamma_flip_state | 1 | 2026-09-17 | — | — | — | 1 found / 0 none within 25% / -1 undetermined |
| SPY | gamma_flip_level | $765.86 | 2026-09-17 | — | — | — | flip level, repriced book |
| SPY | gamma_flip_distance_atr | +0.49 ATR | 2026-09-17 | all (<3y) | 45.1% | 61 | |
| SPY | zero_dte_volume_share | 64.7% | 2026-09-17 | all (<3y) | 11.7% | 64 | |
| SPY | iv_term_regime_days | -36 | 2026-09-18 | all (<3y) | 5.8% | 241 | |
| SPY | iv_term_slope_30_90 | -2.5 pts | 2026-09-18 | all (<3y) | 3.1% | 241 | |
| SPY | vrp_30d | +3.8 pts | 2026-09-18 | all (<3y) | 67.6% | 236 | |
| SPY | realized_vol_21d | 9.4% | 2026-09-18 | 3y | 17.6% | 752 |
core.metric_context() for 33 (metric, fund) pairs in one statement. Licences differ DOWN this table, which is why no CSV is offered for it: 5 of its 11 metrics are registered exportable = false (the chain metrics, derived from core.option_strikes) and 6 exportable = true.
Sources: Cboe (VIX9D, VIX, VIX3M, VVIX, SKEW and the term ratio), OCC (equity put/call and open interest), this warehouse's own chain metrics derived from core.option_strikes, and the three funds' own surface and price metrics. 13 of the 19 metrics drawn above are registered exportable = false (ADR-0020), every market series among them; the other 6 are registered exportable = true — close_adj, iv_term_regime_days, iv_term_slope_30_90, px_vs_200dma, realized_vol_21d, vrp_30d, all of them in the per-fund grid. No CSV is offered here all the same: the table holding them holds restricted rows beside them, and a mixed table cannot be exported wholesale. Each of those metrics exports on its own from /explorer/<metric>, through the gate in /api/export that checks core.metric_registry server-side.
Every percentile on this page is read by one window rule, in src/lib/metrics.ts: the three-year percentile, “insufficient data” where those three years hold fewer than n_min readings, and the window named beside it — in the label of a cell or a header, and in the grid's window column. Every n beside a percentile is the count of that three-year window as core.metric_context() returns it — in the cells at the top, the headers and the grid alike. A window reading “all (<3y)” is a metric whose every reading on record lies inside the three years, so its n is the whole history and there are not three years of it.
Forward returns use core.prices_asof for SPY on the as-of date's adjustment basis, so every window is a total return on one basis; a window whose last close falls after the as-of date is not counted. Overlapping 20-session windows are de-overlapped before counting, and the floor of 20 non-overlapping windows is applied to that smaller count.