Education
Concepts and mechanics behind every page on the dashboard. Skim the table of contents and jump to whatever you're curious about.
Sector Rotation (Stovall)
A top-down framework that rotates capital between economic sectors as the business cycle turns. It is the strongest-performing strategy our backtests have surfaced (see /backtest/stovall), and the live read-out is on /market-stage.
The core idea: different sectors lead at different points in the cycle. Early-cycle cyclicals (financials, technology, consumer discretionary) lead coming out of a recession; late-cycle inflation plays (energy, materials, staples) lead into the top; defensives (health care, utilities, staples) lead through the downturn. Rotate with the cycle and you ride each sector's best window.
The crucial subtlety: the stock market leads the economy by ~6-9 months because investors price in expected conditions, not current ones. So the market cycle (when sectors actually move) runs ahead of the economic cycle (when GDP and production confirm it). Our classifier reads the market cycle from weekly sector money-flow, which is why it can flag a stage turn before the macro data does.
Market cycle vs economic cycle
The market curve (solid) leads the economy (dotted). Labels follow the Way2Wealth / Stovall cycle-position framework — education only, not a live signal.
Concept inspired by Sam Stovall / Way2Wealth TIME TO KNOWLEDGE cycle-position education (market leads economy); rebuilt for MRT (not a copy of any publisher chart).
The four economic stages
Stovall characterizes each economic stage by the state of four macro series. These are the conditions the market positions around one to two quarters before they show up in the data.
| Economic stage | Consumer exp. | Ind. production | Interest rates | Yield curve |
|---|---|---|---|---|
| Full Recession | Reviving | Bottoming out | Falling | Normal |
| Early Recovery | Rising | Rising | Bottoming out | Normal (steep) |
| Full Recovery | Declining | Flat | Rising rapidly | Flattening |
| Early Recession | Falling sharply | Falling | Peaking | Flat / inverted |
Sector leadership by stage
Our classifier maps the market cycle into five stages. For each, the leaders are the sectors the model goes long; the laggards are the textbook underperformers to avoid or underweight.
Rates have fallen, credit is loosening, and the market anticipates recovery before the data confirms it. Interest-sensitive cyclicals begin accumulating first.
Industrial production turns up and capex resumes; capital goods plus raw-materials demand lead. Defensives lag as risk appetite broadens.
The economy runs hot, inflation and rates climb, and the late-cycle inflation trade leads while early-cycle growth starts to roll over.
Demand falls and earnings estimates get cut. Defensives with inelastic demand and still-elevated Energy hold up while cyclicals sell off.
The deepest part of the downturn. Rate-sensitive defensives lead, and Financials begin to base in anticipation of the next easing cycle.
Macro signals at each turn
The cycle transitions don't announce themselves — these are the macro tells that historically precede each hand-off, most of which the dashboard already tracks (yield curve, HY spreads, PMI, breadth). The live Market Stage page reads them against the current stage in real time.
- Yield curve steepening off the lows as the Fed cuts
- Credit spreads (HY OAS) peaking and beginning to narrow
- ISM Manufacturing PMI troughing below 50 but ticking up
- Initial jobless claims rolling over from the peak
- PMI back above 50, new-orders sub-index leading
- Copper / gold ratio rising (cyclical demand)
- Breadth thrust — % of stocks above 200dma expanding fast
- Credit spreads firmly tightening
- Yield curve flattening as the Fed hikes into strength
- Core inflation / breakevens rising
- Energy and materials taking relative-strength leadership
- Tech / discretionary momentum fading vs the tape
- Yield curve flat or inverted
- Credit spreads widening from the tights
- Defensives (staples, health care, utilities) outperforming
- Breadth deteriorating — fewer stocks above 50/200dma
Strengths and pitfalls
- Works: aligns positioning with the business cycle instead of fighting it; top-down and rules-based with a handful of liquid sector ETFs; empirically strong (+53pp cumulative alpha vs SPY over 4.5y, Sharpe 1.12 vs 0.75 in our backtest); leadership rotation is a leading signal of the turn.
- Breaks: entry/exit timing matters a lot at the turns; a contrarian misread of the stage leaves you in the wrong sectors; over-trading the transitions racks up costs and whipsaw; stage boundaries are fuzzy in real time (the classifier emits
unknownand falls back to neutral weights when no signature fires).
References
- Sam Stovall, Standard & Poor's Guide to Sector Investing (1995) and Sector Investing (1996) — the original framework.
- Way2wealth, “Sector Rotation” research note — applies the Stovall model to the economic cycle (source of the four-stage indicator table).
What this dashboard does
A single composite score (−100 to +100) that classifies the current equity-market regime as Strong Bull / Bull / Neutral / Bear / Strong Bear, plus a Pozsar-style plumbing kill switch that overrides everything when liquidity infrastructure breaks.
The score is built from six weighted lenses (Macro, Credit, Breadth, Volatility, Cross-asset, Sentiment) each containing 5–8 indicators, plus a seventh lens (Plumbing) that doesn't add to the composite weight but can force the regime label to Defensive — Plumbing Stress.
Indicator data is persisted in Postgres and re-fetched daily. A 15-year backtest runs in ~30 s warm. Every page on the site is a different read-out of that same underlying data.
Financial plumbing
“Plumbing” is the financial-system equivalent of what plumbing means in a building: the boring infrastructure that nobody pays attention to until something breaks. The term was popularised by Zoltan Pozsar (ex-Credit Suisse, ex-NY Fed) — he literally calls it that because it's pipes through which dollars flow between banks, the Fed, and the Treasury.
When the plumbing works, no one notices. When it breaks, forced selling dominates everything else — sentiment, technicals, fundamentals all get overridden because dealers can't hedge, banks can't lend, and someone with leverage has to liquidate. That's why this dashboard treats it as a kill switch, not a regular lens.
What we actually track in the plumbing lens
| Indicator | Why it matters | Stress condition |
|---|---|---|
| SOFR − IORB spread | Banks would rather borrow in repo than from the Fed → reserves are scarce | Persistent > +5 bps |
| RRP balance | The Fed's "shock-absorber" cash pile — when drained, QT bites real reserves | Rapid drain toward zero |
| Bank reserves / GDP | Pozsar's "LCLOR" thesis — system breaks below ~10% of GDP | < 10% of GDP |
| MOVE index | Treasury rates volatility — when bonds get jumpy, dealers can't make markets | Sustained > 140 |
| SRF usage | Standing Repo Facility taps mean open-market repo isn't working | Any non-trivial usage |
| 10Y swap spread proxy | Persistently negative = collateral / duration stress | Persistently negative |
Each emits a 0→1 stress reading. The lens combines them into a plumbing stress score. When the score crosses 0.5, the headline regime label gets force-overridden to “Defensive — Plumbing Stress” regardless of what the bullish lenses say.
Three famous plumbing-breakdown events
- Sept 2019 repo spike — SOFR jumped to ~10% intraday. Corporate tax payments + Treasury settlements drained reserves below LCLOR. Fed had to restart balance-sheet expansion (“not-QE”).
- March 2020 Treasury market dislocation — 10Y bid-ask widened to multiples of normal as foreign sellers dumped USTs. Fed had to buy $1T of Treasuries in three weeks.
- March 2023 SVB / regional banks — duration losses on bank HTM portfolios → deposit run → KRE/KBE ratio collapsed → Fed launched BTFP. The
kre_kbe_ratioindicator was specifically built for this pattern.
Why it's the only strategy that pays
Per /strategy on 10y prod data: a strategy that is long SPY by default, cash when the kill switch trips has Sharpe 0.91 vs buy-and-hold's 0.80, with a max drawdown of −9.6% vs −33.9%. The reason: plumbing breaks are step-change events. By the time the equity market has fully priced it in, you've already lost 15-30%. By the time SOFR breaks IORB, everyone is selling because their hedges aren't working — but the kill switch fires before the equity market has repriced. So you exit a few days early, sit out the worst, and get back in once the Fed responds.
Composite & lens system
The composite score is a weighted sum of six lens scores, scaled to [−100, +100]:
composite = Σ (lens_score × lens_weight) × 100
with default lens weights:
macro 0.20
credit 0.20
breadth 0.15
volatility 0.20
crossasset 0.10
sentiment 0.15
(sums to 1.0)Each lens score is itself a weighted average of its indicators' regime contributions in [−1, +1]. An indicator's regime contribution is its percentile rank within a 3-year lookback, mapped to [−1, +1] via its Direction:
HIGHER_IS_BULLISH— high percentile → +1 (bullish); e.g. high HY OAS, high VIX (after our May 2026 polarity flip).LOWER_IS_BULLISH— low percentile → +1; e.g. falling DXY.HIGHER_IS_BEARISH_CONTRARIAN— high percentile → −1; e.g. AAII bull-bear at extreme highs (crowded long is bearish input).LOWER_IS_BEARISH_CONTRARIAN— low → −1; capitulation = bullish input (the framework already inverts contrarian indicators internally so "positive contribution = bullish" is always the convention).
Regime classification thresholds
composite >= +60 → Strong Bull composite >= +20 → Bull composite >= -20 → Neutral composite >= -60 → Bear composite < -60 → Strong Bear plumbing trip → Defensive — Plumbing Stress (overrides all of above)
The headline label is then run through hysteresis: a flip only sticks if the new label has held for at least 3 consecutive raw classifications. This stops the regime label from oscillating on noise. Plumbing trips bypass hysteresis (they're step-changes that demand action immediately).
Information Coefficient (IC)
IC is Spearman rank correlation between an indicator's reading and forward S&P returns. It answers: “does this signal predict anything?”
We compute IC at three horizons: 5d (week-ahead), 20d (month-ahead), 60d (quarter-ahead). For equity-index forward returns the industry-standard thresholds are:
| |IC| | Verdict | Action |
|---|---|---|
| ≥ 0.10 | Real signal | Keep, weight up |
| ≥ 0.05 | Marginal | Borderline; depends on stability |
| < 0.05 | Noise | Drop or down-weight |
Sign matters too. Positive IC = indicator predicts forward returns directionally. Negative IC = indicator is a contrarian signal (high reading → low forward return). The May 2026 indicator polarity audit found that 19 of our 36 actionable indicators had their Direction declared opposite to what the data said — those got flipped at the source.
Where to see this: /validation shows composite IC, per-lens IC, and per-indicator IC with polarity verdicts.
Validation framework
Six interlocking analytics, all run against the cached backtest. No look-ahead — each backtest point uses only data available on that day; forward returns are pulled after the fact for the analytics layer only.
- Composite IC. Does the headline score predict forward returns? At 5/20/60d.
- Per-lens IC. Which lens does the work? Which is noise? Sorted by 20d magnitude.
- Per-indicator IC + polarity. For each indicator, does its
Directionmatch what the data says? Outputs a keep / flip / drop recommendation per indicator. - Quintile bucketing. Sort backtest points into 5 buckets by composite score. Compute mean forward return per bucket. If the model works, top quintile beats bottom quintile monotonically.
- Plumbing kill-switch validation. Forward returns when plumbing tripped vs clear, with the edge in bps and hit rate for each.
- Walk-forward + out-of-sample. IC computed year-by-year, with a regression-slope trend (stable / decaying / improving). Plus a single 60/40 in-sample / out-of-sample split with a sign-flip-aware verdict.
The whole thing lives at /validation and runs in ~30-90 s on a 10y window once the cache is warm.
Strategy concepts
The /strategy page converts the composite score into actual P&L. Four strategies, all rebalanced on the backtest cadence (default weekly), with configurable transaction cost, no look-ahead:
- Directional — long SPY when composite ≥ +20, cash otherwise.
- Contrarian — long SPY when composite ≤ −20, cash otherwise.
- Plumbing-defensive — long SPY always except when the kill switch trips.
- Buy-and-hold — the benchmark.
Stats explained
- CAGR — compound annual growth rate. The single number for “how fast did it grow.”
- Sharpe ratio — risk-adjusted return. mean(daily_return) / std(daily_return) × √252. Higher is better; 0.5 is mediocre, 1.0 is good, 2.0 is exceptional.
- Max drawdown — biggest peak-to-trough loss along the equity curve. A higher CAGR with a worse drawdown isn't obviously better; allocators care about both.
- Time in market — fraction of days with non-zero position. A 100% in-market strategy has no opportunity cost from cash; a 30% in-market strategy is mostly sitting out.
- Hit rate — fraction of closed entry-to-exit trade pairs that finished profitable. Watch out for small samples (a 100% hit rate over 2 trades is not the same signal as 60% over 50).
Yield curve concepts
The yield curve is the term structure of US Treasury rates from 1 month to 30 years. It carries more macro information per data point than almost anything else.
- Slope — long minus short.
2s10sis the classic. Negative = inverted = recession warning. Re-steepening from inversion is historically the actual recession trigger, not the inversion itself. - Real yield = Nominal − Breakeven. The 10y nominal yield (DGS10) decomposes into 10y real yield (DFII10, a TIPS yield) and 10y breakeven inflation (T10YIE, the difference). When 10y nominal moves, look at the decomposition: rising real yields (restrictive Fed) hurt risk multiples; rising breakevens (inflation expectations breaking out) hurt bonds without helping equities.
- Curve regimes — /yield classifies the last month's move as:
- Bull steepener: rates falling, curve steeper (cuts priced)
- Bull flattener: rates falling, curve flatter (growth scare)
- Bear steepener: rates rising, curve steeper (reflation)
- Bear flattener: rates rising, curve flatter (Fed hiking)
- Inverted: 2s10s < 0 (recession armed)
- Steepening from inversion: re-normalisation (recession trigger)
- Why TIPS don't exist at 2Y — Treasury doesn't issue 2-year Treasury Inflation-Protected Securities, so there's no 2Y real yield or breakeven on FRED. The 2Y row on the breakevens panel shows nominal-only with
—for real / breakeven.
Persistence & caching
Every indicator's daily reading is persisted to a Postgres table (indicator_observations). Every backtest reads from there instead of re-fetching from Yahoo / FRED on every request. That's why a 15-year backtest runs in ~30 s warm and a 1-year backtest in ~9 s.
- Cache fill: a one-time admin endpoint
POST /api/v1/admin/backfill?years=15seeds 15 years of every indicator. - Live edge: when a request reaches up to today, the cache layer fetches only the last ~7 days from upstream and merges. Backtest historical part comes straight from DB.
- Resilience: if a source 403s (CBOE, AAII), the cache returns the most recent persisted reading instead of dropping the indicator. CBOE total P/C falls back to a SPY chain-derived ratio when the CDN blocks us.
- SP500 closes: 500 individual constituent close series are persisted in
daily_closes. Breadth indicators read from there instead of yfinance-bulk on every call.
Multi-ticker overlay on /compare
The /compare page overlays up to 10 stocks or ETFs on a single chart so you can see how they've moved against each other over time. Different from the correlation view — that one tells you statistical relationship; this one tells you actual relative performance.
The three views (Rebased / Return % / Price)
- Rebased (default) — every line anchored to
100at the start of the window. Reads as a normalised index: a line at200means +100% from start,50means −50%. Best for seeing which tickers led / lagged regardless of price level. - Return % — same data, but the y-axis is in percent return (start = 0%). Clearer when you want to read magnitudes off the axis directly.
- Price — raw dollars. Only useful when the tickers are similarly priced (e.g. comparing two ETFs at $50 vs $60). With mixed-price names, one expensive ticker dominates the y-axis.
Time horizons
1M / 3M / 6M / YTD / 1Y / 3Y / 5Y / 10Y. Use the same structural-vs-tactical framework as the correlations page — short windows show recent leadership, long windows show whether the recent picture is normal or a regime change. A 10Y overlay of the Mag 7 vs SPY is a quick way to see how concentrated the index leadership has been.
Load top 10 of any ETF
Click 📊 Load top 10 of an ETF, pick from the searchable catalog of 41+ cached ETFs (sectors, themes, ARK funds, semis baskets, defense, energy, etc.), and the chart replaces its tickers with that ETF's top 10 holdings. The benchmark also switches from SPY to the parent ETF — which is the right comparison: you want to see how each constituent has moved versus the basket itself, not vs the broad index. Click “reset to SPY” to restore the default if you want both views.
Same holdings file the /rotation Holdings drilldown uses; refreshes quarterly. Useful for spotting concentration risk (e.g. SMH's top 10 are ~75% of the ETF — if NVDA drops 15%, the whole basket follows).
Built-in presets
Eight one-click loaders that drop the right basket onto the chart:
- Mag 7 — AAPL, MSFT, GOOGL, AMZN, META, NVDA, TSLA
- AI capex chain — NVDA, AVGO, MU, ANET, VRT, CEG, AMAT (the bottleneck stack from /themes)
- Sector ETFs — all 9 cyclical / defensive sector SPDRs
- Risk-on / risk-off — SPY, TLT, GLD, DXY, HYG, VIXY (the macro asset palette)
- Themes — SMH, ARKK, CIBR, ICLN, BOTZ, FINX, URA
- Defensives — XLP, XLU, XLV, GLD, TLT (late-cycle hideouts)
- Reshoring — CAT, DE, URI, MTZ, ROK, ETN, EMR
- Energy security — CEG, VST, GEV, LNG, KMI, CCJ, URA
Legend = leaderboard
Below the chart, every ticker is listed with total return, annualised return, max drawdown, peak / trough range, and last price — sorted by total return descending. Click any row to toggle the line on or off, useful when one outlier is compressing the y-axis (e.g. NVDA over 5Y dominates everything else; toggle it off to see the rest).
Optional SPY benchmark
Toggle Show SPY benchmark to add SPY as a dashed reference line. Anything visibly above SPY beat the index over the window; anything below underperformed. The dashed style makes it easy to read "alpha" off the chart at a glance.
Compare vs Correlations — when to use which
| Question | Use |
|---|---|
| Did A and B move together? | /rotation → Correlations rolling chart |
| Which of these 7 stocks won the year? | /compare with rebased view |
| How concentrated was the rally? | /compare with Mag 7 preset + SPY benchmark on |
| When did relationship X break? | /rotation → Correlations rolling at progressively shorter windows |
Math
rebased(t) = price(t) / price(start) × 100. Anchor is the first trading day in the requested window. Tickers with no data in the window (e.g. an ETF launched after the rebase date in a 5Y window) are dropped silently with a notice. Max drawdown is computed peak-to-trough within the window. All fetches reuse the existing rotation panel cache, so a typical comparison is one bulk yfinance call cached for the rest of the day.
Historical correlations on /rotation
The Correlations tab on /rotation shows two complementary views of how sectors / themes move together:
- Matrix heatmap — pairwise correlation of daily log returns over a rolling window. Cells coloured green-to-red on the level view, or indigo-to-amber on the shift view (latest window correlation − same window 30 days ago).
- Rolling correlation chart — pick any two tickers, see how their correlation has evolved. Reference lines at ±1, ±0.5, 0.
Time horizons: 20d → 10Y
Both views support multiple windows. They're not redundant — each one tells you a different story:
| Window | What it shows | Best for |
|---|---|---|
| 20d / 60d / 120d | Tactical — recent regime | Short-term pair trading, risk-on / risk-off reads |
| 1Y | Cyclical — current cycle | Where the relationship sits in the present economic regime |
| 3Y | Multi-cycle — last full economic phase | Smooths cycle noise, exposes regime shifts |
| 5Y | Strategic — long-run trend | Confirms structural relationships |
| 10Y | Structural — pre-COVID baseline | Anchor: what the “normal” correlation has been |
The matrix supports all windows up to 10Y. The rolling chart caps at 5Y because a 10Y rolling correlation is so smoothed it's effectively a single number — no trajectory to plot.
The structural-vs-tactical framework
Long windows tell you what's structural — the baseline relationship that has held across cycles. Short windows tell you what's tactical — where the relationship sits today. The interesting trade isn't the level of either one; it's the gap between them.
Worked example — XLK / TLT over three windows on the same day:
| Window | Mean | Latest | Read |
|---|---|---|---|
| 5Y rolling | −0.19 | +0.05 | Decade-long inverse relationship is decaying |
| 1Y rolling | +0.07 | +0.08 | Cyclical regime: now slightly positive |
| 60d rolling | +0.02 | +0.42 | Tactical break is sharply accelerating |
Three windows, three different stories of the same pair. The 5Y mean (−0.19) tells you what the relationship used to be — textbook “rates-up = tech-down.” The 1Y mean (+0.07) tells you that's already broken at the cycle level. The 60d latest (+0.42) tells you the break is now sharply accelerating. Without the long windows you can't tell whether the +0.42 today is normal or a regime change — they give you the anchor against which the tactical reading is evaluated.
When the matrix views diverge
On the matrix view, each pair has a 10Y structural number and a 60d-by-default tactical number. When they agree (XLK / XLY at +0.83 over 10Y, ~+0.7 today) the relationship is stable. When they disagree by 0.4+ points, treat that pair as a regime change candidate — drill into it on the rolling chart at progressively shorter windows to see when the break started.
Why shifts matter more than levels
Two sectors being correlated +0.8 isn't inherently informative — if they've been +0.8 for years (e.g. XLK vs XLY), that's just structure. What's informative is when a long-stable relationship breaks. The shift column on the matrix surfaces the recent break for every pair at once; the rolling chart shows the full trajectory of any single pair.
Pre-set pairs worth watching
- XLK / TLT — tech vs long bonds. 5Y mean historically inverse; recent regime has flipped to positive. Worked example above.
- XLE / TLT — commodity inflation vs duration; typically inverse. Decoupling = inflation regime resolving.
- XLY / XLP — cyclicals vs defensives. Deep negative = clear risk-on/off split; decoupling = transition.
- IWM / SPY — small caps vs large caps. Persistent decoupling marks narrow-leadership / breadth-deterioration, the standard late-cycle pattern.
- XLF / XLRE — banks vs REITs. Both rate-sensitive but in opposite directions on the curve. Decoupling = curve regime change.
- GLD / DXY — textbook inverse. When gold rallies with a strong dollar, something macro-structural has shifted.
Math
Both views use Pearson correlation on daily log returns (more numerically stable than simple returns around extreme moves). The window length is in trading days (1Y = 252, 5Y = 1260, 10Y = 2520) but the underlying fetch is in calendar days, so the engine pulls ~1.6× the trading-day window to make sure the correlation has full samples.
On the themes universe, ETFs launched within the last few years (e.g. some clean-energy or AI funds from 2020+) will have shorter histories than the requested 10Y window. Pandas handles this with pairwise complete observations — the cell value reflects whatever overlap each pair actually has, so you'll see lower-confidence numbers for newer themes rather than NaN.
How the macro-theme engine works
The /themes page implements a 5-step inference chain: (1) macro / geopolitical situation → (2) sectors disrupted or advanced → (3) bottlenecks within those sectors → (4) companies fulfilling the bottlenecks → (5) best stock pick within the company set. The chain has two distinct halves with different feasibility profiles, and the engine handles them differently:
Steps 1–3: human-curated catalog
Steps 1–3 are qualitative and require domain knowledge that a purely quantitative engine can't generate. They live in a human-authored YAML catalog (backend/app/data/themes.yaml) covering 6 active themes:
- AI Infrastructure & Compute
- Energy Security & Dispatchable Power
- US Reshoring & Industrial Renaissance
- Defense & Geopolitical Tension
- Healthcare Innovation: GLP-1 & Beyond
- Deglobalization & Supply Chain Re-routing
Each theme bundles: a thesis paragraph, a list of macro indicators with the direction the theme prefers, a list of sector ETFs it touches, and a list of bottlenecks each with 2–4 candidate company tickers.
Steps 4–5: pure quant scoring
Steps 4–5 are quantitative. The engine scores activation and ranks companies entirely from market data:
| Component | Weight | What it measures |
|---|---|---|
| Theme activation (0–100) | ||
| Macro match | 40% | How the live indicator readings align with the theme's preferred direction |
| Sector strength | 35% | Weighted RS-Ratio + RS-Mom + RS-Accel of the theme's sector ETFs |
| Money flow | 25% | Weighted flow_intensity of the theme's sector ETFs |
| Best-pick score per company (0–100) | ||
| RS vs SPY 60d | 35% | Outperformance over 60 trading days, in pp |
| 20d return | 25% | Recent month price action |
| 20d acceleration | 25% | 2nd-order RoC: is the move speeding up or fading? |
| 5d return | 15% | Recency / confirmation |
What the system does not do
- No live news feed. The macro/geopolitical situation is inferred from market indicators (yields, oil, dollar, credit spreads), not from headlines.
- No fundamental analysis. Best-pick scoring is pure technical / momentum. PE, growth, margins, balance-sheet quality are not in the score.
- No theme auto-discovery. Themes are human-curated; novel macro themes need to be added to the catalog by hand.
- Not a recommendation. A high-scoring stock on this screen is a candidate worth deeper diligence, nothing more.
Worked example
When AI Infrastructure scores 60.9/100 and the best pick is MU at score 98, the chain looked like:
- Macro match 49 — neutral; macro is mixed but not hostile to capex.
- Sector strength 77 — XLK is in Leading with rising RS-Accel.
- Flow 57 — money positive into the theme's ETFs.
- Bottleneck = HBM memory & advanced packaging — MU sits here as the dedicated US pure-play.
- MU score 98 — 20d return +51%, 60d RS vs SPY +72.5pp, and momentum is ▲ confirming (still accelerating).
Each link in the chain is independently verifiable on the dashboard: the macro composite on /, sector strength on /rotation, the company's setup on its rotation row.
Acceleration in sector / theme rotation
The 2nd-order RoC also lights up on equity prices — sector ETFs, themes, individual stocks. Rotation in particular is where it shines: a sector that's leading and still accelerating is structurally different from one that's leading but decelerating, even though both sit in the same RRG quadrant.
Where it's surfaced on /rotation
- Performance heatmap — every cell now carries a momentum glyph next to the return:
- ▲ confirming — positive return that's also accelerating (this period outpaced the prior one).
- △ fading — positive return that's decelerating; the up-move is losing steam even before it rolls over.
- ▽ improving — negative return whose decline is decelerating; an early bottoming signal.
- ▼ worsening — negative return whose decline is accelerating.
- RRG table — new
RS-Accelcolumn (2nd-order RoC of RS-Ratio, centred 100). Above 100 = the sector's relative-strength momentum is still rising (gaining ground vs the benchmark). Below 100 = momentum is fading even if the sector is still in Leading. - Money flow + holdings drilldowns —
return_5d_accel_ppandreturn_20d_accel_ppon each reading, available via the API. Future UI surfacing as needed.
The four states matter
Two sectors can both be Leading and have +5% returns over a month, but if one is ▲ confirming (this month +5%, last month +3%) and the other is △ fading (this month +5%, last month +9%), they're not the same trade. The fading one is closer to a top; the confirming one is still adding capital in the right direction.
Same goes the other way — a Lagging sector that's ▽ improving (down 8% this month, was down 12% last month) is a much better setup for a contrarian add than a ▼ worsening one (down 8% this month, was down 4% last month).
2nd-order RoC: catching inflections before the level moves
The 2nd-order rate of change — “RoC of RoC”, or acceleration — is one of the most useful tools for monitoring flows. It catches inflections before the underlying level peaks/troughs, because the rate of change peaks first.
The math
Given a daily series X (price, yield, spread, liquidity level), with a window of n days:
- 1st-order RoC:
ROC₁(t,n) = (X_t / X_{t-n} − 1) × 100(in %) - 2nd-order RoC:
ROC₂(t,n) = ROC₁(t,n) − ROC₁(t-n,n)(in pp)
We use the additive form (differences of differences) rather than the ratio of ratios, because the ratio blows up when the 1st-order RoC crosses zero — which is exactly when the interesting inflections happen.
Why it leads
Levels move because flows happen. Flows accelerate before they peak. So:
- Acceleration positive → flow speeding up. Trend gaining momentum.
- Acceleration crosses zero (down) → flow decelerating. Trend losing steam — early topping signal even while the 1st-order RoC is still positive.
- Acceleration negative and falling → flow in outright reversal. Levels follow with a lag.
May 2026 experiment results
Built 7 acceleration variants across 5 underlying series, all launched at weight=0 for IC measurement. After one month of data: 4 of 7 carry signal at the 60d horizon — a much higher hit rate than the 1st-order flow experiment (0/3) that immediately preceded it.
| Indicator | Lens | IC60d | Direction | Weight |
|---|---|---|---|---|
| net_liquidity_accel_12w | macro | −0.143 | LOWER=BULL (flipped) | 10% |
| net_liquidity_accel_8w | macro | +0.089 | HIGHER=BULL | 5% |
| hy_oas_accel_20d | credit | −0.077 | LOWER=BULL (flipped) | 5% |
| real_yield_accel_20d | macro | −0.074 | LOWER=BULL | 5% |
| net_liquidity_accel_4w | macro | +0.045 | — hold — | 0% |
| dxy_accel_20d | macro | −0.024 | — noise — | 0% |
| vix_accel_20d | volatility | +0.012 | — noise — | 0% |
Headline finding: net_liquidity_accel_12w
The 12-week 2nd-order RoC of net liquidity scored IC60d = −0.143 — same magnitude as the level itself. The hypothesis was positive acceleration → flow speeding up → bullish; the data inverted it. Decelerating quarterly liquidity flow (Fed drain intensifying / liquidity-cycle troughs) precedes higher forward returns. That's the classic "max liquidity pessimism marks the bottom" pattern showing up empirically at the macro tier — when the flow is falling fastest, that's when forward returns are best.
Why the credit-cycle hypothesis flipped
We expected accelerating widening of HY OAS to be a capitulation signal (forward bullish at medium horizons). Data says otherwise: at all measured horizons (5d, 20d, 60d), accelerating widening is the leading edge of a credit cycle and continues bearish. The capitulation rebound presumably plays out at >90d horizons we don't measure. For a 5–60d strategy, accelerating HY widening is bearish — which is what the live indicator now reports.
Result: macro lens grew from 5 active indicators to 8 (+3 accel), credit from 8 to 9 (+1 accel). The total promoted weight is 25% (3×5% + 1×10%). The lens-level renormaliser handles the redistribution; the level signals all keep their original weights.
Tactical vs strategic composite (20d vs 60d)
The dashboard reports two composite scores, both built from the same lens scores but with different weights:
- Tactical (20d-tilted) — original weights tuned for monthly entry/exit timing. Sentiment, volatility, breadth dominate (these are the lenses with the strongest 20d-horizon IC).
- Strategic (60d-tilted) — weights proportional to per-lens IC at 60d, the quarterly horizon. Macro, credit, cross-asset dominate (these are the lenses that operate at economic-cycle timeframes).
Why two scores
The validation work showed that lenses don't all predict at the same horizon. Sentiment and volatility predict the next month well; macro and credit predict the next quarter much better than the next month. A single composite has to pick a horizon, and either one under-uses the other lenses.
Per-lens IC at each horizon (10y prod data, post-polarity audit):
| Lens | IC 5d | IC 20d | IC 60d | 20d wt | 60d wt |
|---|---|---|---|---|---|
| credit | +0.096 | +0.216 | +0.329 | 20% | 27% |
| macro | +0.067 | +0.083 | +0.303 | 20% | 25% |
| crossasset | +0.116 | +0.113 | +0.222 | 10% | 18% |
| volatility | +0.121 | +0.179 | +0.160 | 20% | 13% |
| breadth | +0.089 | +0.155 | +0.116 | 15% | 9% |
| sentiment | +0.076 | +0.129 | +0.093 | 15% | 8% |
When they disagree
The disagreement is the signal. If tactical is +30 (Bull) and strategic is −10 (Neutral), the short-term picture is bullish but the quarterly drivers (macro, credit) are softer — late-cycle momentum chase. Reverse case (tactical Neutral, strategic Bull): the macro setup is supportive but sentiment / vol haven't confirmed yet — the constructive case for adding risk is building, not yet active.
The overview gauge (/) draws both needles on the same dial — 20d as the solid needle, 60d as the dashed one. If they're ≥20 points apart, a small footnote calls out the direction of disagreement.
Why macro is the hardest lens
After the May 2026 polarity audit, every lens except macro showed clean positive 20d IC. Macro stayed near zero. The reason: macro signals operate at quarterly horizons (60d), not monthly (20d).
Per-indicator IC for the macro lens on 10y prod data:
| Indicator | IC 5d | IC 20d | IC 60d |
|---|---|---|---|
yield_curve_2s10s | +0.054 | +0.105 | +0.229 |
real_yield_10y | +0.076 | +0.083 | +0.141 |
dxy | +0.094 | +0.077 | +0.161 |
net_liquidity | −0.005 | −0.090 | −0.143 |
breakeven_5y5y | −0.028 | −0.086 | −0.206 |
Every indicator's 60d IC is 1.5–2.5× larger than its 20d IC. The 2s10s spread alone has an IC of +0.229 at 60d — a strong signal that's diluted at 20d.
Why? Short-term equity moves are dominated by sentiment, vol regimes, and price-momentum effects. Macro liquidity flows take a quarter or more to fully feed through into asset prices — bank-reserve changes flow into deposit growth → loan growth → corporate spending; rate moves flow through duration, into multiples, into earnings. The 20d horizon catches mostly noise; 60d catches the economic-cycle signal.
Levels vs flows: the Druckenmiller distinction
The original framework treated net_liquidity (WALCL − TGA − RRP) as “rising = bullish.” That's Druckenmiller paraphrased — but his actual thesis is about changes (the Fed adding or draining), not the level. The 10y data agrees: high levels of liquidity coincide with cycle peaks (mean reversion); the flow direction is what predicts.
Two changes in May 2026:
net_liquiditylevel direction inverted (LOWER = bullish because high levels are late-cycle).- New
net_liquidity_change_4windicator added to the lens at 5% weight — this captures the actual flow signal Druckenmiller meant. It will be evaluated against the level on the next /validation cycle.
Practical takeaway
When using the dashboard's composite for tactical (1–2 week) decisions, the macro lens is mostly noise. When using it for strategic (1–3 month) regime calls, the macro lens dominates. The /validation page's composite IC at 60d (currently +0.256, GREEN) is the right number for macro-tilted positioning; the 20d IC (+0.23) is better for everything else.
May 2026 polarity audit
The biggest research finding of the project so far. Per-indicator IC analysis on 10 years of cached data showed 19 of 36 actionable indicators had their Direction declared opposite to what the data said. Specifically:
- Credit lens (8 of 8 inverted, all flipped). Tight spreads / strong credit ETFs / strong KRE-KBE all preceded LOWER forward returns, not higher. This is the late-cycle / crowded-credit pattern: tight spreads mark complacency, not opportunity. The framework's “tight = risk-on” framing was empirically wrong over 10y.
- Volatility lens (4 of 7 inverted, all flipped). Low VIX / contango term structure / low VVIX are crowded-short-vol complacency that mean-reverts. High VIX (panic) marks the actionable bottom. Skew and MOVE were noise (dropped to weight 0).
- Breadth lens (3 of 6 inverted, all flipped). Stretched breadth (high % above MA, small-cap leadership) is crowded longs that mean-revert. Depressed breadth marks the entry.
- Cross-asset lens (4 of 5 inverted, all flipped). Stretched copper/gold, AUD/JPY, oil, and gold-vs-real-yield richness are late-cycle euphoria signals; safety-bid moves coincide with bottoms.
- Sentiment lens (6 of 6 correctly oriented). The only lens that worked as built. AAII, NAAIM, SPY-200dma deviation, VIX complacency, global breadth, HYG appetite all score
OK / keep. - Macro lens (mostly noise). Net liquidity, NFCI, real yields, breakevens — most scored below the noise threshold. Yield curve 2s10s and DXY were the survivors.
The full per-indicator table with current IC / polarity / weight is at /validation (scroll to “Per-indicator IC”). Weight changes are documented in docs/INDICATORS.md with 0.0 ⚠ markers for zero-weighted indicators.
Where to find it on the dashboard
Start with the daily loop: regime read → Today's Trades → journal → scorecard. Everything else is supporting context. The list below is every dashboard route, grouped as the nav presents them.
- Overview
- / — Dashboard
- /terminal — Terminal
- /velaworkspace — VelaWorkspace
- /market-stage — Market Stage
- /optics — Macro Optics
- /market-trend — Market Trend
- /hmm — Hidden Markov Model
- /spreads — Spreads
- /halts — Market Halts
- /calendar — Calendar
- /news — News
- Flows
- /vol — Options & Vol
- /positioning — Positioning — CFTC COT Lev Funds net vs price — research only, not a composite input
- /movers — Movers
- /matrix — Matrix
- /themes — Stock Baskets
- /compare — Relative Performance
- /fragility — Market Fragility
- /correlations — Rolling Correlations
- /rotation — Sector Rotation — Descriptive; no measured selection edge
- /rotation-clock — Rotation Clock — Octants are descriptive; 0 of 89 tuned variants beat buy-and-hold
- /breadth — Breadth / BPI — Internals map — where participation has been, not a forecast
- /map — Map
- /dark-pool — Dark Pool
- /dispersion — Dispersion
- /capital-flows — Capital Flows
- Macro
- /macro-superchart — Macro SuperChart
- /yield — Yield Curve
- /commodities — Commodities
- /lenses — Lenses
- /macro — Macro Pulse
- /labor — Labor & CPI
- /econ — Econ Data
- /valuation — Valuation Avg — Four-metric proxy of Advisor Perspectives; weight 0 pending IC
- Signals
- /fear-greed — Fear & Greed
- /psychology — Psychology — Cycle emotion diagrams — research only, not a composite input
- /cycles — Cycles — Fractals & cycle theory — research only, not a composite input
- /capital-rotation — Capital Rotation — Cross-asset positioning map
- /political — Politicians Trades
- /smart-money — Smart Money
- /insiders — Insiders
- /email-feed — Email Feed
- Crypto
- /crypto — Market Overview
- /crypto/btc — BTC On-Chain
- /crypto/derivatives — Derivatives
- /crypto/funding — Funding
- /crypto/options — Options
- /crypto/order-book — Order Book Depth
- /crypto/etf-flows — ETF Flows
- /crypto/btc-flows-positioning — BTC Flows
- Predictions
- /predictions — Predictions
- Screener / SuperChart / Watchlist
- /screener — Screener
- /chart — SuperChart
- /watchlists — Watchlist
- Portfolio — nav menu next to Watchlist, live results, not backtests
- /journal — Trade Journal — What you actually traded, vs the plan
- /journal/risk — Portfolio Risk — Open book vs the credit gate
- /rebalance — Rebalance — Trades to reach the live stovall_credit_bonds target
- Strategy — nav menu next to Watchlist
- /strategy-lab — Strategy Lab — Chart-native TA markers · equity/DD · conditions · regime/rotation
- /luxalgo — Market Trackers + Edge Stats
- /kronos — Kronos Lab — Sample-spread OHLCV fan — not a trade signal
- /scorecard — Live Pick Scorecard — Realized returns of the picks this app published
- /funnel — Funnel — Macro→RS→themes→screener shortlist — research workflow, not a composite input
- /strategy — Score · Backtest
- /optimize — Score · Weight Sweep
- /optimizer — Score · Saved Optimizer Runs
- /backtest/strategy — TA Strategy · Backtest
- /backtest/optimize — TA Strategy · Optimizer
- /backtest — Composite Backtest
- /backtest/stovall — Sector Rotation Backtest
- /should-i-trade/backtest — Should I Trade? Backtest
- /indicators — Indicators
- /education — Education
- /validation — Validation — Indicator IC and stability over time
- Pages not in the nav tree
- /vela — child of /velaworkspace
- /optics/backtest — child of /optics
- /dark-pool/backtest — child of /dark-pool
/indicators/[id]— child of /indicators/stock/[ticker]— reached from ticker search- /markets — child of /terminal
- /should-i-trade — child of /terminal
- /derivatives — child of /terminal
- /index-board — child of /terminal
- /chart-board — child of /terminal
- /positioning/cta-us-equities — child of /positioning
- /margin — child of /positioning
- /operator — deep-link reachable (not in primary nav)