Skip to content

KB/framework

Cross-asset correlations basket

Last verified

The correlations category tracks 20-day rolling Pearson correlations between SPY and four anchor assets: VIX, the US Dollar Index, the 10-year Treasury yield, and WTI crude. Each pair carries a healthy historical range; drift outside that range is the structural break the basket flags. The category fuses into one alignment leg and one health-score component β€” the same four pair classifications drive both.

The four-pair basket

Pair weights β€” from app/signals/config/correlation_scoring.json:pair_weights

SPY / VIX1.0 (full weight)The structural-inverse anchor. Healthy regime = deep negative; correlation rising toward zero means dealer reflexivity is breaking down.
SPY / Oil1.0 (full weight)Energy-shock transmission channel. Healthy regime = near-zero; rising positive means oil is repricing equity directly.
SPY / DXY0.5 (half weight)Dollar-strength regime indicator. Secondary informational weight.
SPY / TNX0.5 (half weight)Rates-equity coupling indicator. Secondary informational weight.

SPY/VIX and SPY/Oil carry full weight because their relationships are the structural backbone β€” VIX is the canonical inverse anchor (when SPY rises VIX falls, by construction of how vol prices fear), and SPY/Oil is the primary transmission channel for energy shocks into equity pricing. SPY/DXY and SPY/TNX get half weight because their relationships are real but secondary in information content for equity direction.

Per-pair classification

Each pair’s current 20-day rolling correlation is classified into one of four levels via thresholds in correlation_scoring.json. The thresholds are pair-specific because healthy ranges differ β€” SPY/VIX is structurally negative, SPY/Oil structurally near-zero, SPY/DXY mildly negative, SPY/TNX mildly positive.

Per-pair healthy bands (from correlation_scoring.json + correlations.py:PAIR_CONFIG)

SPY / VIX normal-0.95 to -0.70Deep negative β€” structural inverse anchor intact.
SPY / DXY normal-0.40 to +0.10Mild negative to flat β€” dollar-strength regime stable.
SPY / TNX normal-0.20 to +0.40Mild positive β€” rates-equity coupling in the healthy band.
SPY / Oil normal-0.30 to +0.20Near-zero β€” equities + energy on independent narratives.

Bands stack outward through elevated β†’ stretched β†’ extreme per PAIR_CONFIG in app/signals/correlations.py. Cross-pair, the structural break direction varies β€” SPY/VIX extreme is correlation rising past -0.30 (the inverse anchor cracking), SPY/Oil extreme is correlation past +0.75 or below -0.80 (energy directly repricing equity), and so on.

Level-quality scoring

level_quality maps each classification to a quality factor used by the score component math:

level_quality β€” from correlation_scoring.json

normal1.0Pair in healthy band β€” full credit for the structural relationship being intact.
elevated0.7Soft drift outside healthy band β€” partial credit.
stretched0.3Notable break from healthy band β€” minimal credit.
extreme0.0Regime break β€” pair contributes zero to the Correlations component.

The score-layer formula at runtime: weighted average of pair qualities Γ— max_points. The Correlations component max is 5 points by default (doubles to 10 under the energy_shock regime override). A pair at normal contributes its full share of points; a pair at extreme contributes nothing.

Worked example. SPY/VIX normal (1.0), SPY/Oil elevated (0.7), SPY/DXY normal (1.0), SPY/TNX stretched (0.3). Weighted average = (1.0Γ—1.0 + 0.7Γ—1.0 + 1.0Γ—0.5 + 0.3Γ—0.5) / (1.0 + 1.0 + 0.5 + 0.5) = 2.35 / 3.0 = 0.783. Component points = 0.783 Γ— 5 β‰ˆ 3.9.

Fusion into the alignment category

The alignment layer maps each pair’s classification level to a directional implication via _CORR_LEVEL_IMPLICATION in implications.py:

Each pair becomes a leg; legs combine through the shared _fuse_legs helper using the alignment-layer basket weights (0.50/0.20/0.15/0.15). The fused verdict + per-leg breakdown surfaces on /api/v1/signals/alignment under categories.correlations.

Legacy single-pair fallback

When only corr_spy_oil is available β€” the pre-B2 contract that some backfilled rows still match β€” the fuse degrades to the legacy single-pair thresholds in implications.py:

This preserves byte-identical behaviour for pre-B2 callers and fixture rows. The 4-pair fuse takes over the moment any second pair is also populated. No silent degradation.

Where it surfaces

Regime-override interaction

The energy_shock regime override doubles the Correlations score-component max from 5 to 10. Under energy stress, correlation breakdowns become the dominant transmission channel β€” equities, oil, dollar, and rates all start moving together as the macro tape is repriced wholesale. Doubling the weight reflects that empirical observation. See regime overrides for the override schema.

See also