Simplify Analytics

Regime Monitor

US market · as of 2026-09-18

regime
uptrend, calm · code 1 · 2026-09-18
flags
none

Bitmask: 1 narrow (an uptrend carried by three sectors or fewer), 2 credit-stress (HY OAS at its 3y 90th percentile), 4 correlated (sector correlation at its 3y 90th). 0 is none; NULL when the label is unknown. A CODE, NOT A STATISTIC.

The nine axes

The readings worker/app/core/regime.py labels from, in its own order, each against its own three years, or its whole history where that is shorter (window all (<3y)). They are collected whether or not the label is: this table is the same whether the strip above says a regime or says pending. Their dates differ — the Cboe pair, ICE's spread and the Fed's reserves are knowable a session late, the other five the evening of their own session — which is why each row carries one and no single date sits above the table.

trendpx_vs_200dmaSPY6.91%2026-09-183y29.5%752
realized_volrealized_vol_21dSPY9.4%2026-09-183y17.6%752
vixvixUS15.44002026-09-173y35.3%774
vix_termvix_term_ratioUS0.83232026-09-173y13.8%752
breadthsector_breadth_200dmaUS50.0%2026-09-183y7.8%752
correlationsector_corr_63dUS0.04922026-09-183y2.9%752
dispersionsector_dispersion_21dUS3.72%2026-09-183y50.6%752
credithy_oasUS2.70002026-09-173y10.6%787
liquidityreservesUS$3,013,794m2026-09-163y21.3%157

core.metric_context() for the nine (metric, entity) pairs in one statement. hy_oas is ICE BofA through FRED and the Cboe pair is Cboe: neither is exportable, so this page offers no CSV.

Timeline

100 spells over the window, 37 of them a single session — that count is the statement's own, not a filter over the rows. A one-session interruption ends a spell and starts another, so the thin bands are real and are drawn at their true width. The label of each band is the one today's rule gives that day's point-in-time axes — see the note below.

$761.692026-09-18
uptrend, calm2026-07-312026-09-1835
uptrend, stressed2026-07-302026-07-301
uptrend, calm2026-06-252026-07-2924
uptrend, stressed2026-06-242026-06-241
uptrend, calm2026-06-152026-06-236
uptrend, stressed2026-06-102026-06-123
uptrend, calm2026-06-092026-06-091
uptrend, stressed2026-06-082026-06-081
uptrend, calm2026-04-232026-06-0531
uptrend, stressed2026-04-222026-04-221
uptrend, calm2026-04-132026-04-217
uptrend, stressed2026-04-082026-04-103
downtrend, stressed2026-03-202026-04-0712
uptrend, stressed2026-03-022026-03-1914
uptrend, calm2026-02-262026-02-272
uptrend, stressed2026-02-242026-02-252
uptrend, calm2026-02-232026-02-231
uptrend, stressed2026-02-132026-02-205
uptrend, calm2026-02-092026-02-124
uptrend, stressed2026-02-062026-02-061
uptrend, calm2026-01-222026-02-0511
uptrend, stressed2026-01-212026-01-211
uptrend, calm2025-11-262026-01-2036

Every materialiser run recomputes regime_code over the whole history, so a past spell carries TODAY'S thresholds applied to that day's readings - not the label anyone saw at the time. Relabelling re-derives every historical statistic on this page with it.

What followed each prior occurrence

SPY's forward 20-session return from the first session of every earlier spell of uptrend, calm, from every session carrying that label, and from every labelled session as the baseline. The current spell began 2026-07-31 and has run 35 sessions. A label that flickers produces many occurrences a few sessions apart whose windows overlap, which is what the non-overlapping count exists to say.

SPY's 20-session return, measured from the close of the session each reading became knowable (its own close: this metric is knowable the evening of its session). A window whose last close falls after this page's as-of date is not counted.
conditiondateswindowsp25medianp75upspan
the first session of each prior spell
each prior occurrence
6537-1.5%+2.1%+3.4%65%2016-09-01
2026-06-25
every session carrying this label
uptrend, calm
1,813105-0.5%+1.7%+3.2%71%2016-09-01
2026-08-20
every labelled session
the baseline
2,505126-0.7%+1.8%+3.7%70%2016-09-01
2026-08-20
2026-07-312026-09-1835+3.0%
2026-06-252026-07-2924+0.6%
2026-06-152026-06-236+0.3%
2026-06-092026-06-091+2.3%
2026-04-232026-06-0531+4.8%
2026-04-132026-04-217+7.8%
2026-02-262026-02-272-6.2%
2026-02-232026-02-231-3.7%
2026-02-092026-02-124-2.4%
2026-01-222026-02-0511+0.1%
2025-11-262026-01-2036+1.9%
2025-10-212025-11-1720-1.7%
2025-10-142025-10-141+3.1%
2025-05-122025-10-10106+3.4%
2025-03-242025-03-252-8.2%
2024-12-202025-03-0347+3.1%
2024-11-072024-12-1829+2.0%
2024-11-042024-11-041+6.0%
2024-10-092024-10-3117+2.4%
2024-08-092024-10-0741+2.5%
2023-11-012024-08-02189+8.0%
2023-03-162023-10-24154+4.5%
2023-03-142023-03-141+4.6%

Liquidity

reserves, own 3y 21.3% · n=157 · 2026-09-16

DESIGN's liquidity panel is five legs — reserves, TGA, RRP, SOFR−EFFR and dealer positions. Four of them are metrics: reserve balances, which is also the "liquidity" axis in the table above, and tga, rrp and sofr_effr_spread_bp, which the worker added once its ALFRED pulls were windowed for series too long to fetch in one request. All four carry a reading below, each with its own value date. The fifth, primary dealer positions, is not collected at all: no collector reads the NY Fed's series and no table in this warehouse holds it. It is named below rather than drawn, because an empty frame says something this warehouse does not know.

$3,013,794m2026-09-16
Reserve balances at the Fedreserves$3,013,794m2026-09-163y21.3%157
Treasury General Accounttga$877,028m2026-09-163y82.5%157
Overnight reverse reporrp$0.3bn2026-09-173y2.9%748
SOFR minus EFFRsofr_effr_spread_bp-1.0 bp2026-09-163y36.4%747
  • Primary dealer positions· not collected — no collector reads the NY Fed's series and no table in this warehouse holds it

All four legs come from FRED first-published vintages - WRESBAL, WTREGEN, RRPONTSYD, and SOFR minus EFFR - knowable a session late and registered exportable, though this page builds no CSV link. Their units differ because the registry registered them differently: millions, millions, billions, basis points. No net-liquidity composite is drawn: WALCL is not a registered metric, and DATA_SOURCES.md:134 refuses a composite with a term missing.

Yield curve

10-year minus 2-year, own 3y 45.2% · n=748 · 2026-09-16

Two spreads, not a curve, and deliberately: core.fred_observations holds the constant-maturity yields, but an unregistered FRED series has no knowable lag, no n_min and no core.metric_context() row, so nothing here reads one directly. What is registered is the two differences the worker derives — curve_10y_2y and curve_10y_3m — and those are drawn, dated, with their own-history percentiles and nothing implied between them. Negative is an inverted curve, which is curve_10y_2y's own registered description and not a threshold this page chose. 10-year minus 2-year +0.27 pp on 2026-09-16 and 10-year minus 3-month +0.87 pp on 2026-09-16.

10-year minus 2-year+0.27 pp2026-09-1610-year minus 3-month+0.87 pp
10-year minus 2-yearcurve_10y_2y+0.27 pp2026-09-163y45.2%748
10-year minus 3-monthcurve_10y_3m+0.87 pp2026-09-163y98.1%748

FRED DGS10 minus DGS2 and DGS10 minus DGS3MO, first-published vintages, knowable a session late. Both are registered exportable; this page builds no CSV link.

Not yet built

One of DESIGN's five parts for this page has no module at all yet. It is listed here so the page states its own coverage: nothing above is standing in for it.

  • Risk-appetite composite, scored across 8 assets· no module computes this

The label and its flags are worker/app/core/regime.py's, stored as the codes regime_code and regime_flags. Neither is a statistic, so neither carries a percentile here or anywhere. web/src/lib/regime.ts mirrors the axis table and the code and flag names; its test reads the Python and fails if the mirror drifts.

The n beside every percentile on this page — in the headers, the axis table and the leg tables — is core.metric_context()'s n_3y: the readings in the three years that percentile is ranked against, not the metric's whole history. The headers and the tables' window column take their window from windowPercentile() in src/lib/metrics.ts, and a window reading “all (<3y)” is a metric whose every reading on record lies inside those three years, so there are not three years of it.

Forward returns use core.prices_asof for SPY on the as-of date's adjustment basis. Overlapping 20-session windows are de-overlapped before counting, and the floor of 20 non-overlapping windows is applied to that smaller count.