Yield Curve Slope
Abstract
The yield curve slope signal evaluates macro‑financial regimes via the shape of the Treasury term structure. Two primary spreads are used: T10Y2Y (10‑year minus 2‑year yield) and T10Y3M (10‑year minus 3‑month yield). Each is normalised using a robust rolling z‑score, then averaged to form a composite slope index. Thresholds classify curve phases as Steepening, Flat/Neutral, or Inverted. Version 1.1 adds: (i) an explicit data‑source overview for constant‑maturity yields, (ii) report‑level transparency (a required table), and (iii) a hysteresis rule to reduce “uninversion” whipsaws when the slope hovers near zero.
1. Data Sources
1.1 T10Y2Y (10‑year minus 2‑year, constant‑maturity spread)
- Series:
T10Y2Y(FRED). - Definition: Spread between the U.S. Treasury 10‑year and 2‑year constant‑maturity yields, in percentage points.
- Underlying yields: Treasury “constant‑maturity” yields are interpolated from the daily nominal Treasury yield curve (not necessarily from a single on‑the‑run security with that exact remaining maturity).
- Frequency / timing: Daily observations; this model resamples to month‑end to align with macro composites.
- Revisions / missing values: Constant‑maturity yields can be revised, and spreads may show missing values on holidays or around data/vendor transitions. Treat short gaps as missing, not interpolated.
1.2 T10Y3M (10‑year minus 3‑month, constant‑maturity spread)
- Series:
T10Y3M(FRED). - Definition: Spread between the U.S. Treasury 10‑year and 3‑month constant‑maturity yields, in percentage points.
- Why 3M matters: The 10Y–3M spread is widely used in recession‑probability models and term‑spread research, and is less sensitive to term‑premium shifts than 10Y–2Y in some frameworks.
- Frequency / timing: Daily observations; resampled to month‑end for the signal pipeline.
- Revisions / missing values: Same caveats as above (interpolation‑based yields; occasional revisions; holiday gaps).
1.3 What “constant‑maturity” means (why it matters)
“Constant‑maturity” Treasury yields are constructed by reading (interpolating) yields off a fitted Treasury yield curve at fixed maturities. This produces a synthetic 2‑year, 10‑year, etc. yield even when no outstanding security has that exact remaining maturity. Because these are estimates, they may be revised and can be influenced by liquidity/market microstructure (especially at inflection points).
- Resampling: use month‑end last observation (not a monthly average) to preserve turning points.
- Missing‑data policy: do not forward‑fill or interpolate month‑ends; publish missing‑data flags.
2. Normalisation
Robust z‑scores are used so that unusually large inversions/steepenings are comparable across different rate regimes (e.g., 2003–2007 vs. post‑2020).
3. Composite Construction
- Compute z‑scores: derive Z\_{10Y2Y} and Z\_{10Y3M} via the robust rolling method.
- Blend: arithmetic mean to reduce idiosyncratic noise:
YC\_{Composite,t} = \frac{Z\_{10Y2Y,t} + Z\_{10Y3M,t}}{2}
4. Regime Classification (with Hysteresis) — v1.1
4.1 Entry thresholds (unchanged)
4.2 Hysteresis rule (new)
To reduce false “uninversion” signals when the curve oscillates around zero, regimes are not allowed to switch immediately upon crossing the boundary. Instead, a hysteresis band and a sustained confirmation window are applied.
- Entry band: ±0.75 (as above).
- Exit band: ±0.50 (tighter band for leaving Steepening/Inverted).
- Confirmation: require k = 2 consecutive month‑ends beyond the exit band before changing state.
Practical implication: once the model declares Inverted, it will only revert to “uninverted” (Flat/Neutral or Steepening) after the composite rises above −0.50 for two consecutive month‑ends. This requires sustained steepening rather than a single‑month oscillation.
5. Report Transparency — Required Table (new)
Every published report should include the latest observation table so readers can see the raw spreads, the standardised values, and how close the signal is to regime boundaries.
| Date (month‑end) | T10Y2Y (pp) | T10Y3M (pp) | Z_T10Y2Y | Z_T10Y3M | Composite C | Regime (hysteresis) | Distance to entry (±0.75) | Distance to exit (±0.50) | Consecutive confirmations |
|---|---|---|---|---|---|---|---|---|---|
| … | … | … | … | … | … | … | … | … | … |
6. Implementation (Python) — updated for hysteresis
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))
def apply_hysteresis(c, entry=0.75, exit=0.50, k=2):
"""Return regime labels with hysteresis + sustained confirmation at month-end."""
state = None
above, below = 0, 0
out = []
for v in c:
if pd.isna(v):
out.append(np.nan)
continue
# initialise
if state is None:
state = "Steepening" if v > entry else ("Inverted" if v < -entry else "Flat/Neutral")
out.append(state)
continue
# count confirmations for exits
above = above + 1 if v > -exit else 0 # for leaving Inverted (rise above -exit)
below = below + 1 if v < exit else 0 # for leaving Steepening (fall below +exit)
if state == "Inverted":
if above >= k:
state = "Steepening" if v > entry else "Flat/Neutral"
elif state == "Steepening":
if below >= k:
state = "Inverted" if v < -entry else "Flat/Neutral"
else: # Flat/Neutral
if v > entry:
state = "Steepening"
elif v < -entry:
state = "Inverted"
out.append(state)
return pd.Series(out, index=c.index)
# Inputs are daily; resample to month-end last observation
df = df_yield_curve[["T10Y2Y","T10Y3M"]].resample("M").last()
df["Z_T10Y2Y"] = robust_z(df["T10Y2Y"])
df["Z_T10Y3M"] = robust_z(df["T10Y3M"])
df["YC_Composite"] = df[["Z_T10Y2Y","Z_T10Y3M"]].mean(axis=1)
df["YC_Regime"] = apply_hysteresis(df["YC_Composite"], entry=0.75, exit=0.50, k=2)
# Optional: distance-to-threshold fields for reporting
df["Dist_Entry_Upper"] = df["YC_Composite"] - 0.75
df["Dist_Entry_Lower"] = df["YC_Composite"] + 0.75
df["Dist_Exit_Upper"] = df["YC_Composite"] - 0.50
df["Dist_Exit_Lower"] = df["YC_Composite"] + 0.50
7. Model Interpretation (with academic anchors)
7.1 What the slope is proxying for
- Policy stance & growth expectations: In many models, the term spread embeds expectations of future short rates (policy path) and compensation for term risk (term premium).
- Recession risk: Historical work finds the 10Y–3M spread has substantial predictive content for U.S. recessions at horizons roughly 2–6 quarters ahead.
7.2 How to read the report table
- Raw spreads (pp): Use these to sanity‑check: are we near 0 (borderline), deeply negative (material inversion), or clearly positive?
- Robust z‑scores: These express how unusual the current slope is versus the last ~5 years of history in the model window. Large negative z indicates an unusually inverted curve, even if the absolute level is modest in bp terms.
- Composite C: The average of the two z‑scores. If components disagree materially, treat the regime as lower confidence and inspect which leg (2Y vs 3M) is driving the divergence.
- Distance to thresholds: Near‑zero distances imply higher flip risk; large magnitudes imply regime persistence unless there is a macro shock.
- Consecutive confirmations: If a state change is pending, this shows whether the signal has met the sustained condition (k months) or is still “probationary”.
7.3 Practical cautions when interpreting
- Don’t over‑interpret “one‑month” uninversions: brief crosses above zero are common; v1.1 hysteresis forces sustained steepening before changing regime.
- Macro distortions: QE/QT, reserve regimes, and institutional demand can influence curve shape without a classic cycle signal; treat the slope as one component in a broader regime set.
- Real‑time vs revised data: constant‑maturity yields can be revised; if you are doing backtests, document whether you use vintage data or the latest revised series.
8. Limitations
- Structural distortions (QE/QT, RRP balances) can flatten curves without classic cycle signals.
- Short‑term volatility may reflect liquidity or issuance factors rather than macro regime change.
- Thresholds are static; periodic review is recommended (publish changelog if adjusted).