Skip to content

KB / framework

Drawdown-Risk Lens (20-day, transparent z-score composite)

Last verified

A probabilistic drawdown-risk gauge over the seven credit / inflation / rate LEVELS the full-history study flagged for the platform’s multi-week drawdown lane. Renders as the “Drawdown-Risk Lens · 20d” block in the regime card with a 0–100 score, a low / elevated / high band, and the top contributing legs.

This is not a directional predictor, not a timing trigger, and not the validated logistic from the research. It is a transparent equal-weight composite, chosen deliberately for explainability and graceful degradation over fitted accuracy.

What it measures

Each of the seven levels is standardized against its trailing baseline (default ~2 trading years), oriented by economic risk-direction, and averaged into a single number. Higher = more macro stress relative to the recent norm; lower = calmer.

Why this shape, not a fitted model

The full-history study (.research/SYNTHESIS.md) validated the multi-week drawdown signal as a parsimonious L2 logistic over the same seven features. That model is sklearn-based, and the platform’s prod image deliberately ships no machine-learning runtimescikit-learn and its peers live in requirements-dev.txt and the no-Dockerfile-reference lint (verify-docs.sh:27) blocks them from ever being COPYed into a production container.

The deployable shape is therefore the transparent composite. Trade-offs, on the record:

The seven inputs + risk-orientation

The orientation table lives in app/signals/drawdown_risk.py:_FEATURE_ORIENTATION and is documented inline with the rationale. Summary:

FeatureOrientationReading
hy_oas+1High-yield credit-spread widening = credit stress
ebp+1Excess bond premium = above-fundamentals default-risk compensation
nfci+1Positive NFCI = tighter-than-average financial conditions
real_yield_10y+1Higher real yields = tighter policy / valuation pressure
t10y3m_spread−1Curve inversion (low/negative) precedes recessions
breakeven_5y+1Elevated inflation expectations → tightening risk (regime-specific)
breakeven_10y+1Same — long-end inflation expectations

A +1 feature contributes +1·z to the mean (positive z = up = more risk). A −1 feature contributes −1·z (so a deeply inverted curve, where z is very negative, still pushes risk up).

How the gauge is computed

For each available feature with a non-zero baseline standard deviation:

  1. z = (level − trailing_mean) / trailing_std
  2. oriented_z = z × orientation

Then:

  1. mean_z = average(oriented_z over available legs)
  2. score = 100 / (1 + exp(−mean_z)) — a logistic squash with steepness 1.0, so mean_z = 0 maps to 50, +1σ to ~73, +2σ to ~88, −1σ to ~27.
  3. Band: low under +0.5σ, elevated between +0.5σ and +1.25σ, high at or above +1.25σ.

If fewer than four legs are populated the gauge returns status: insufficient_data and the dashboard suppresses the block.

Caveats — read these before you act on it

Where it lives in the code