Financial Stress Composite

Integrates credit spreads, yield-curve inversion, and systemic stress to assess market stress levels.

Abstract

The Financial Stress Composite blends three independent indicators of financial strain: the St. Louis Fed Financial Stress Index (STLFSI4), high-yield option-adjusted spreads (HY OAS), and the yield-curve slope (T10Y2Y). Higher stress corresponds to elevated STLFSI4, wider credit spreads, and deeper yield-curve inversion. A robust z‑scored average yields a continuous composite regime indicator: High_Stress, Neutral, or Low_Stress.

1. Data

Resample all inputs to a common monthly frequency (month‑end).

2. Transformation

Because stress increases with higher STLFSI4 and HY spreads but decreases with a steeper yield curve, we invert the curve slope:

Stress\_Curve_t = −T10Y2Y_t

This makes positive z‑scores represent more inversion, hence higher stress.

3. Normalisation

z\_{rob}(X)_t = \dfrac{X_t − \mathrm{median}(X)_{t,w}}{1.4826·\mathrm{MAD}(X)_{t,w}}
with rolling window w = 60 months (minimum 24). Median absolute deviation scaling reduces outlier bias.

4. Composite Construction

Fin\_{Stress,t} = \tfrac{1}{3}\big(z(STLFSI4_t) + z(HY\_OAS_t) + z(−T10Y2Y_t)\big)

5. Regime Mapping

If\ C_t > 0.75 → High\_Stress;\quad |C_t| ≤ 0.75 → Neutral;\quad C_t < −0.75 → Low\_Stress

6. Implementation (Python)

import pandas as pd
import numpy as np

def robust_z(s, win=60, min_win=24):
    x = pd.to_numeric(s, errors="coerce").astype(float)
    w = max(min_win, min(win, x.dropna().size))
    med = x.rolling(w, min_periods=min_win).median()
    mad = (x - med).abs().rolling(w, min_periods=min_win).median()
    return (x - med) / (1.4826 * mad.replace(0, np.nan))

f = df_fin_stress.copy()
f["Z_STL"] = robust_z(f["STLFSI4"])
f["Z_HY"]  = robust_z(f["HY_OAS"])
f["Z_INV"] = robust_z(-f["T10Y2Y"])

f["Fin_Stress"] = f[["Z_STL","Z_HY","Z_INV"]].mean(axis=1)

hi, lo = 0.75, -0.75

def _regime(v):
    if pd.isna(v): return np.nan
    return "High_Stress" if v > hi else ("Low_Stress" if v < lo else "Neutral")

f["Fin_Stress_Regime"] = f["Fin_Stress"].apply(_regime)

df_sig_fin_stress = f
display(df_sig_fin_stress.tail())

7. Interpretation

8. Limitations