KB / indicators
Health Score (19-component composite)
Last verified
Composite 0–100 measure of structural market health — not direction. A high score means the plumbing is intact (liquidity flowing, credit calm, institutions buying). Normal markets score 55–60.
Components (19, sum to 100)
| Component | Max | What it measures | Metric |
|---|---|---|---|
| Energy | 10 | Energy regime (WTI, crack spread, XLE) | energy_regime |
| HY OAS | 8 | High-yield credit spreads | hy_oas |
| Stagflation | 8 | Weighted breakevens (5Y 40%, 10Y 20%, 5Y5Y 20%, 5Y-10Y inversion 20%) | stagflation |
| DIX | 7 | Institutional dark-pool buying activity | dix |
| GEX | 7 | Options dealer gamma exposure | gex |
| Breadth | 7 | % of S&P 500 above 50-day SMA | breadth_50d |
| Liquidity | 7 | Fed net liquidity direction | net_liquidity |
| Breakeven | 6 | 5Y breakeven inflation expectations (lower is better) | breakeven_5y |
| Vol Term | 5 | VIX term structure (contango/backwardation) | vix_regime |
| SPY/ZGL | 5 | Price vs zero gamma level | spy_vs_zgl |
| 0DTE PCR | 5 | Same-day options put/call ratio | zero_dte_pcr |
| Sectors | 5 | Sector breadth favorability | sectors |
| Correlations | 5 | Weighted per-pair health (SPY/VIX, SPY/Oil, SPY/DXY, SPY/TNX) | correlations |
| BTC | 3 | Bitcoin as liquidity proxy | btc |
| SKEW/VIX | 3 | Tail-risk hedging activity | skew_vix |
| Real Yield | 3 | 10Y TIPS real yield level | real_yield |
| Copper/Gold | 2 | Growth expectation proxy ratio | copper_gold |
| USD/JPY | 2 | Carry trade unwind risk | usdjpy |
| HYG | 2 | Credit ETF selling pressure confirmation | hyg_confirmation |
Pure additive sum. Each band-classifier maps the raw value to a per-component points award between 0 and the listed max. Logic lives in app/signals/score.py — pure, FastAPI-free, directly unit-testable.
Score ranges
Score-range readings
The 50–60 band is where most days live.
Regime-conditional rebalancing
score_weights.json → regime_overrides lets any regime declare scaling factors per component. Currently configured:
- energy_shock (energy_regime in SHOCK/CRISIS/SHOCK_UP/RISING): Correlations doubles 5→10 (cross-asset transmission dominates), BTC drops to 0, Sectors scales 0.6× (5→3). Total stays at 100.
- energy_relief (FALLING/SHOCK_DOWN): Correlations 0.6× (5→3), Breadth boosted 1.43× (7→10).
Adding an override: {trigger: {field, in|eq}, scales: {component: factor}}. Factors must sum-offset so the post-override max stays at 100.
Score vs regime — when they disagree
The dashboard’s bridge text (italicized line under the regime name) labels the divergence:
| Score | Regime | Label | Meaning |
|---|---|---|---|
| 70+ | RISK-ON | Favorable | Score and regime agree |
| 70+ | Not RISK-ON | Favorable, with caution | Score high but a lagging signal holds the regime back |
| 50-70 | Any | Mixed | Some supports intact, others not |
| 50-70 | RISK-OFF/PANIC | Mixed, deteriorating | Mid-range score but conditions worsening |
| 30-50 | Any | Cautionary | Multiple supports weakening |
| < 30 | PANIC/RISK-OFF | Adverse | Structural supports broken |
| < 30 | Other | Adverse, holding | Score very low but regime hasn’t caught up yet |
Scale headroom
A May 2026 regime-quantile audit confirmed the 0-100 scale spans cleanly without saturation:
| Regime | n | p5 | p50 | p95 | max |
|---|---|---|---|---|---|
| PANIC | 18 | 23 | 28 | 39 | 40 |
| RISK-OFF | 289 | 28 | 37 | 49 | 57 |
| TRANSITIONAL | 308 | 20 | 47 | 55 | 77 |
| CAUTIOUS | 467 | 42 | 50 | 58 | 74 |
| RISK-ON | 205 | 48 | 55 | 82 | 87 |
See also
- Regimes — the 5-tier orthogonal axis the score reconciles against.
- GEX — dealer gamma exposure (7 pts; reduced from 10 in the 2026.05 rebalance).
- DIX — dark-pool institutional flow (7 pts; reduced from 10 in the 2026.05 rebalance).
- 5Y Breakeven — inflation-expectation component added in the 2026.05 rebalance (6 pts).
- Component code:
app/signals/score.py. Weights config:app/signals/config/score_weights.json.