Risk Regime Dashboard Contract
Updated: 2026-06-02 07:48 CEST
ibkr regime reports the broad-market stress lifecycle: quiet, early_warning, confirmed_stress, panic, stabilization, opportunity, or data_quality. It is an evidence-balance read, not a prediction, trading system, portfolio planner, or investment recommendation.
Use it to answer one question: are several independent market-risk indicators confirming each other, or is the market still broadly calm?
Canary may consume this output, but canary owns account and portfolio action. A portfolio concentration problem can be real even while the broad market regime is calm.
Output Shape
Each row should show:
- current value;
- band:
green,yellow,red, or unranked; - status:
ok,stale,computing,unavailable, orerror; - source and as-of information;
- a short band reason;
- the threshold set used for that row.
The top-level envelope should also show:
lifecycle: scope (marketfor regime), stage, severity, readiness, timing, confidence, evidence,
confirmed sources, unconfirmed sources, a semantic lifecycle fingerprint, and an explicit no-execution statement;
source_health: per-clusteras_of, status, age/freshness, confidence, and
fingerprint-stability semantics;
fingerprint: semantic identity for the classified broad-market state.
Missing, stale, computing, and degraded data must stay visible. A quiet reading with missing critical inputs is not the same thing as a confirmed calm regime.
Indicator Sources
Each row must identify the concrete data source and actual symbol or series behind the reading. The live dashboard uses these sources; historical replays may substitute point-in-time equivalents, but the row meaning should stay the same.
| Row | Actual symbols or series | Live source |
|---|---|---|
| VIX/VIX3M | VIX and VIX3M, Cboe equity-volatility indexes | IBKR index market data for Cboe VIX and VIX3M; backtests use Cboe official historical CSVs. |
| VVIX | VVIX, Cboe's VIX-of-VIX index | Cboe official daily VVIX time series. |
| HYG/SPY | HYG, a high-yield corporate bond ETF, and SPY, an S&P 500 ETF | IBKR HYG/SPY quotes plus HMDS daily bars; SPY 52-week high uses IBKR Misc Stats tick 165 when available and daily-bar fallback otherwise. Backtests use Nasdaq public ETF history. |
| HY OAS | FRED BAMLH0A0HYM2 for high-yield OAS and BAMLC0A0CM for investment-grade corporate OAS | FRED/St. Louis Fed CSVs for ICE BofA option-adjusted spread series. |
| CP 90-day AA financial minus 13-week T-bill | Federal Reserve RIFSPPFAAD90_N.B and U.S. Treasury ROUND_B1_CLOSE_13WK_2; cached under legacy series keys RIFSPPFAAD90NB / DTB3 for wire compatibility | Federal Reserve Commercial Paper Data Download Program plus U.S. Treasury Daily Treasury Bill Rates. |
| USD/JPY weekly change | USD.JPY, routed as IBKR CASH on IDEALPRO with currency JPY | IBKR FX tick plus HMDS midpoint history for the seven-trading-day comparison; Tier 1 historical replay uses FRED DEXJPUS. |
| SPX-canonical dealer gamma | SPX/SPXW index options with SPY ETF options as context | IBKR option chains, open interest, option quotes/model-computation ticks, and the daemon's gamma cache. |
| S&P 500 breadth | Current S&P 500 constituent stock tickers; there is no single breadth symbol used live | Local daemon compute from IBKR HMDS constituent daily bars and the generated S&P 500 membership list. |
Clusters
A cluster is a group of related indicators. The composite regime counts clusters, not raw rows, so one market theme cannot vote twice.
Within each cluster, the worst ranked row wins: red beats yellow, yellow beats green. Unavailable, computing, and error rows are unranked.
Equity Volatility
This cluster watches option-market fear. VIX/VIX3M asks whether near-term fear is priced above longer-term fear. VVIX asks whether traders are paying up for large volatility moves. When both worsen, equity stress is usually becoming more urgent.
VIX is Cboe's 30-day implied-volatility index for the S&P 500. VIX3M is the same idea over roughly three months, and VVIX measures how volatile VIX itself is expected to be.
VIX/VIX3M backwardation is stress-level evidence by itself. An isolated VVIX red between 110 and 120 is noisier: the VVIX row remains red and visible, but the equity-volatility cluster counts as yellow unless VVIX is at least 120, VIX is up at least 20% on the day, SPY is down at least 1% on the day, or another independent cluster is red. This keeps volatility warnings visible without letting a standalone vol-of-vol pop dominate the broad-market read.
| Row | Green | Yellow | Red |
|---|---|---|---|
| VIX/VIX3M | < 0.92 | 0.92-1.00 | > 1.00 |
| VVIX | < 90 | 90-110 | > 110 |
Credit
This cluster watches whether corporate credit is weakening before or alongside stocks. HYG is an ETF holding high-yield corporate bonds, meaning lower-rated company debt that behaves more like risk assets than Treasuries. SPY is the large S&P 500 ETF used here as the stock-market comparison.
HYG/SPY is the faster market proxy. HY/IG OAS is the slower official cash-credit read: it compares high-yield and investment-grade corporate bond spreads, where OAS means the extra yield investors demand over Treasuries after adjusting for bond options. Credit stress matters because equity rallies are less sturdy when lenders are already demanding more compensation for risk.
HYG/SPY can still show a red row by itself. For the cluster count, that single proxy red is treated as a yellow watch unless cash credit is also red or another independent cluster is red. The row stays visible; it just does not get to call broad stress alone.
| Row | Green | Yellow | Red |
|---|---|---|---|
| HYG/SPY | HYG healthy | HYG below 50-DMA | HYG weak while SPY is near highs |
| HY OAS | < 4.0 and not widening | 4.0-5.5 or widening > 0.50 pp | > 5.5 or widening > 1.00 pp |
Funding
This cluster watches whether short-term money markets are becoming stressed. The spread between 90-day AA financial commercial paper and 3-month T-bills is a simple check on whether financial borrowers are paying unusually high short- term funding costs.
Commercial paper is short-term company borrowing; T-bills are short-term U.S. Treasury borrowing. A wider spread means financial firms are paying noticeably more than the government to borrow for a similar short horizon.
| Row | Green | Yellow | Red |
|---|---|---|---|
| CP 90-day AA financial minus 3-month T-bill | < 25 bp | 25-75 bp | > 75 bp |
FX Carry
This cluster watches USD/JPY as a proxy for global carry-trade pressure. When the yen strengthens quickly, leveraged risk trades can unwind at the same time. That does not predict every selloff, but it is useful confirmation when other clusters are also deteriorating.
USD/JPY is quoted as yen per U.S. dollar. A falling USD/JPY means the yen is strengthening, which is the direction that can pressure yen-funded carry trades.
USD/JPY can still show a red row by itself. For the cluster count, an isolated FX red is treated as a yellow watch until another independent cluster confirms stress. Canary may still act on a fast carry unwind when direct SPY/VIX tape or breadth confirms the move.
| Row | Green | Yellow | Red |
|---|---|---|---|
| USD/JPY weekly change | yen move < 1% | yen strengthens 1-2% | yen strengthens > 2% |
Dealer Gamma
This cluster watches whether dealer hedging is more likely to dampen or amplify index moves. Above zero-gamma, hedging flows are usually more stabilizing. Below zero-gamma, hedging can chase the market lower or higher and make moves sharper. Treat this as a regime hint, not a precise tradable level.
SPX/SPXW index options are the canonical production signal for S&P 500 dealer gamma. SPY is the exchange-traded S&P 500 ETF; its option book trades separately and is used as corroborating context when fresh and high quality. Missing or throttled SPY does not downgrade an otherwise fresh, rankable SPX gamma result. SPY-only gamma is a proxy, not the canonical S&P dealer-gamma row.
| Row | Green | Yellow | Red |
|---|---|---|---|
| SPX zero-gamma | spot > 2% above zero-gamma | within +/-2% | spot below zero-gamma |
Gamma is ranked only when gamma_zero.envelope.result.quality.rankability is rankable. Non-rankable gamma remains visible in the row/envelope, but it does not become the active gamma market-structure read:
| Rankability | Meaning |
|---|---|
rankable | Fresh and covered enough to treat as the active market-structure signal. Rankable SPX is stable and production-ready even when SPY is unavailable and disclosed as context. |
context_only | Awareness-only market-structure context. |
blocked | Payload exists but a freshness, coverage, OI, model, cache, farm, entitlement, pacing, or partial-chain gate blocks ranking. |
unavailable | No usable OI-weighted gamma payload exists. |
Missing 0DTE is disclosed in the horizon coverage and warning details, but it does not by itself make an otherwise healthy SPX read context-only when the 1-7DTE and term buckets are present. After the expiring SPXW series closes, the 0DTE bucket can be absent while the broader SPX surface remains usable.
Model-quality gates judge per slice, never pooled. Each underlying's derived-IV share, top-strike concentration, and median per-expiry skew-fit R² are judged on that underlying's own slice. The skew bars are preferred ≥ 0.75 SPX, ≥ 0.70 SPY, with a hard block below 0.50; a median between the block and preferred bars still ranks, with the gate's reason disclosing the sub-preferred fit — median R² is amplitude-relative and tracks intraday smile noise rather than coverage health, so it is disclosure-worthy but not rank-blocking on its own. The combined node carries no pooled model gates: the pooled derived-IV share is leg-count weighted across both chains and the cross-book concentration ratio matches no per-slice calibration, so gating them there would let a present-but-degraded SPY downgrade a rankable SPX (the same posture violation as the absent-SPY rule above forbids). The pooled numbers stay visible in quality.coverage as diagnostics, and the SPX slice's own verdict reaches the combined node through the spx_coverage gate. One consequence: a SPY slice ranking inside the disclosed skew window votes in the combined band weighting. Every successful compute appends per-slice skew diagnostics (per-expiry R² and residual RMS, coverage, rankability) to $XDG_STATE_HOME/ibkr/gamma-skew-diagnostics.jsonl — offline calibration input for these heuristic bars; nothing reads it at runtime and it is safe to delete.
Breadth
This cluster watches how many S&P 500 stocks are participating. A rally led by many stocks is healthier than a rally carried by a few mega-caps. Weak breadth near index highs warns that the headline index may be hiding fragility.
There is no single live IBKR symbol for this row. The daemon computes it from daily bars for the individual S&P 500 member stocks and caches the post-close result.
| Row | Green | Yellow | Red |
|---|---|---|---|
| S&P 500 breadth | > 55% above 50-DMA | 40-55%, or weakening near highs | < 40%, especially while SPX is near highs |
Confirmation Eligibility and Severity Governance
A red row may CONFIRM stress only when its evidence is deep, persistent, and cadence-fresh. Otherwise it is PROVISIONAL: visible on the row, listed in lifecycle.unconfirmed, able to drive early_warning — but it never counts toward confirmed_stress/panic, never rescues another cluster from its isolated-red downgrade, and never reaches confirmed_by. This policy exists because of the 2026-06-12 false positive, where a 7 bps HYG break (one session old, thin pre-open tick) and a prior-evening gamma cache mutually confirmed "Broad stress regime / act" against a green tape (docs/design/regime-calibration.md).
Eligibility gates per indicator (heuristic noise floors, pending_backtest like the band thresholds; values live in internal/rpc/regime_policy.go):
| Indicator | Min depth for eligible red | Fast path (eligible day 1) | Min streak (NY trading sessions) | Cadence freshness | Exit hysteresis (leave red) |
|---|---|---|---|---|---|
| VIX/VIX3M | ratio >= 1.00 | ratio >= 1.05 | 2 | same-session tick | ratio < 0.98 |
| VVIX | >= 110 | >= 120 | 2 | latest official daily close (<= 4d) | < 105 |
| HYG/SPY | HYG >= 0.25% below 50DMA | >= 1.0% below | 2 | RTH tick or latest official close (off-hours banding input is the close, never a thin pre/post print) | HYG closes back above 50DMA |
| HY OAS | band is the gate | n/a | 1 | series <= 7d | < 5.25 and widening < 0.85 pp |
| Funding | band is the gate | n/a | 1 | series <= 7d | < 65 bp |
| USD/JPY | band is the gate (speed is depth) | n/a | 1 | same-day tick/close | yen move < 1.5% |
| Dealer gamma | gap <= -0.5% below gamma-zero | gap <= -2.0% or wholly-short profile | 1 | compute within current NY trading date (prior-date cache = stale, warns only) | gap > +0.5% |
| Breadth | <= 38% | <= 30% | 2 | last completed session's compute | > 45% |
Eligibility latches for the life of the red streak (a depth wobble back inside the floor does not flip it); freshness is never latched — overdue data drops eligibility immediately. Streaks count NY trading days; a weekend or holiday poll keys to the most recent trading day.
Severity governance, applied after stage selection and disclosed in lifecycle.governors[]:
- While a confirming cluster's threshold set carries
pending_backtest, heuristic evidence without a fresh tape co-sign (SPY <= -1.5%, VIX +10%, or a same-session term inversion) reads one severity rung down:confirmed_stress-> watch, 3-redpanic-> act. Pure-tape panic (SPY <= -4%/-7%) always reaches urgent. Promotion out ofpending_backtesthappens per versioned threshold-set label via the backtest plan. - If a confirming cluster's source health is stale/partial/degraded, severity caps at watch (evidence-keyed: an unrelated dead feed does not mute a fresh confirmation).
Display tone follows governed severity, not just stage: confirmed_stress with severity: watch remains an amber/watch headline, preserving red for act-grade stress and risk_off for full risk-off conditions. The condition label still stays "Confirmed stress regime" so the evidence balance is not watered down.
Composite Logic
The headline label is a single wording table shared by composite.verdict and posture.label (rpc.RegimeHeadline); CLI, MCP, and SPA render the served string:
| Cluster state | Regime label |
|---|---|
| 0 red and 0-2 yellow | Normal regime |
| 0 red and 3+ yellow | Elevated stress watch |
| any visible red (eligible or provisional) below confirmation | Stress signal present |
stage confirmed_stress/panic (2 eligible reds, or 1 + tape) | Confirmed stress regime |
| 3+ eligible red | Broad stress regime |
| all ranked clusters eligible red | Full risk-off conditions |
The output may also show raw indicator counts for transparency. Cluster counts are the primary signal because related rows, such as VIX and VVIX, are not fully independent votes; cluster_eligible_red_count and cluster_provisional_red_count split the reds by confirmation eligibility.
Lifecycle is a second layer on top of the row and cluster evidence:
| Lifecycle stage | Broad-market meaning |
|---|---|
quiet | Enough data is ranked and no material stress or recovery/opportunity evidence is present. |
early_warning | Weak, isolated, provisional, or forward-looking evidence is visible, but eligible independent confirmation is not yet present. |
confirmed_stress | At least two ELIGIBLE stress clusters, or one eligible cluster plus confirming SPY/VIX tape, are active. |
panic | Three or more eligible stress clusters, or tape severe enough (SPY <= -4%/-7%) that the regime should be treated as acute. |
stabilization | Stress evidence is easing, but this is not yet a deployable opportunity by itself. |
opportunity | Constructive tape and low stress evidence are present; this is broad-market context only, not a trade instruction. |
data_quality | Missing, stale, computing, or degraded inputs prevent a confident lifecycle read. |
The lifecycle layer must keep unconfirmed red evidence visible without letting a single fragile or stale proxy dominate the trigger. readiness should be blocked or degraded when critical source health is stale, partial, computing, or degraded; the severity governor additionally caps the demanded response when the CONFIRMING clusters themselves are impaired.
An unconfirmed HYG/SPY-only red or USD/JPY-only red remains visible in the row details, but it is counted as yellow at the cluster level; the independence rescue that waives this downgrade counts ELIGIBLE reds only, so two marginal reds can no longer confirm each other.
The expanded Tier 1 backtest shows that isolated red equity-volatility clusters are also the main source of repeated false alarms. They should not be deleted: major stress often starts in volatility before credit, funding, or FX confirms. The live rule therefore keeps VIX/VIX3M inversion as stress, but downgrades an isolated moderate VVIX-only red to yellow unless the already-visible SPY/VIX tape or another cluster confirms it.
Method Notes
Breadth is computed locally from S&P 500 constituent daily bars because the retail IBKR feed does not provide the official S&P breadth series directly. The daemon caches the post-close result; reads should not trigger a 500-name fanout.
Dealer gamma is an SPX/SPXW-canonical zero-gamma estimate from IBKR option chain data, with SPY used as additive context when usable. The live sweep uses the nearest 80 listed strikes per expiry inside the +/-10% candidate window to keep the IBKR fan-out bounded, especially for SPX/SPXW. Historical backtests should exclude gamma unless the row has a trusted point-in-time gamma snapshot with method, source, coverage, and timestamp.
Open interest is a required input for OI-weighted dealer GEX, but missing OI is unknown, never zero. Priced legs without observed OI may still fit the IV/skew surface, but they must be omitted from OI-weighted GEX and surfaced through warning_details / data_quality. SPY option OI can be absent outside regular U.S. option hours. SPX option OI should normally be stable across session phases; missing SPX OI is unexpected data-quality evidence even pre-market, after-hours, overnight, or on closed-session cache reads.
MOVE/rates-vol is outside the live surface until a verified IBKR contract or licensed official connector exists. Do not proxy it with ETFs or futures.
Decisions Journal
Every decision-relevant regime snapshot appends one line to $XDG_STATE_HOME/ibkr/regime-decisions.jsonl: raw values, bands, depth metrics, streaks, freshness, eligibility, cluster tallies, lifecycle decision, and governor records. Lines dedupe on the snapshot's semantic fingerprint with an hourly heartbeat. The file is append-only, never read at runtime, and safe to delete — the same contract as gamma-skew-diagnostics.jsonl. It is the forward-collection corpus that makes the pending_backtest thresholds calibratable: a threshold set drops pending_backtest only with months of journal coverage, measured false-alarm/recall rates against labeled episodes, and a version-label bump documented here. Disable via ibkr settings set regime.journal.enabled=false.
Backtesting
The active backtest sequence, tuning gates, and source-data backlog live in Regime and Canary Backtest Runbook. Keep this file as the product contract for ibkr regime; do not use it as a second tuning backlog.