{"slug":"what-happens-when-the-yield-curve-un-inverts","qid":"episodes","label":"Every 2s10s un-inversion: the crossing and the spread 3, 6 and 12 months later","post_title":"What Happens When the Yield Curve Un-Inverts","post_url":"/blog/what-happens-when-the-yield-curve-un-inverts#q-episodes","columns":["episode","crossed_on","crossed_on_label","negative_sessions_prior","trough_spread","spread_3m_later","spread_6m_later","spread_12m_later"],"rows":[{"episode":"May 1980","crossed_on":"1980-05-02","crossed_on_label":"May 2, 1980","negative_sessions_prior":423,"trough_spread":-2.41,"spread_3m_later":0.98,"spread_6m_later":-0.62,"spread_12m_later":-0.9},{"episode":"Oct 1981","crossed_on":"1981-10-28","crossed_on_label":"Oct 28, 1981","negative_sessions_prior":453,"trough_spread":-2.41,"spread_3m_later":-0.06,"spread_6m_later":-0.22,"spread_12m_later":0.88},{"episode":"Jul 1982","crossed_on":"1982-07-19","crossed_on_label":"Jul 19, 1982","negative_sessions_prior":400,"trough_spread":-1.7,"spread_3m_later":0.78,"spread_6m_later":1.11,"spread_12m_later":0.67},{"episode":"Jun 1989","crossed_on":"1989-06-30","crossed_on_label":"Jun 30, 1989","negative_sessions_prior":132,"trough_spread":-0.45,"spread_3m_later":-0.15,"spread_6m_later":0.06,"spread_12m_later":0.18},{"episode":"Dec 2000","crossed_on":"2000-12-27","crossed_on_label":"Dec 27, 2000","negative_sessions_prior":226,"trough_spread":-0.52,"spread_3m_later":0.67,"spread_6m_later":1.2,"spread_12m_later":1.94},{"episode":"Mar 2007","crossed_on":"2007-03-21","crossed_on_label":"Mar 21, 2007","negative_sessions_prior":220,"trough_spread":-0.19,"spread_3m_later":0.17,"spread_6m_later":0.53,"spread_12m_later":1.75},{"episode":"Sep 2024","crossed_on":"2024-09-04","crossed_on_label":"Sep 4, 2024","negative_sessions_prior":538,"trough_spread":-1.08,"spread_3m_later":0.06,"spread_6m_later":0.29,"spread_12m_later":0.58}],"shape":"table","sql":"WITH\ndaily AS\n(\n    SELECT\n        date,\n        dateDiff('day', toDate('1970-01-01'), date)   AS dnum,\n        ifNull(toFloat64(max(yield_2_year)), 0.)      AS y2,\n        ifNull(toFloat64(max(yield_10_year)), 0.)     AS y10,\n        y10 - y2                                      AS spread\n    FROM global_markets.treasury_yields\n    WHERE yield_2_year > 0 AND yield_10_year > 0\n    GROUP BY date\n),\nscored AS\n(\n    SELECT\n        date, dnum, y2, y10, spread,\n        count()         OVER (ORDER BY date ROWS BETWEEN 60 PRECEDING AND 1 PRECEDING) AS rows_prior,\n        sum(spread < 0) OVER (ORDER BY date ROWS BETWEEN 60 PRECEDING AND 1 PRECEDING) AS neg_prior,\n        sum(spread > 0) OVER (ORDER BY date ROWS BETWEEN CURRENT ROW AND 20 FOLLOWING) AS pos_next\n    FROM daily\n),\ncandidates AS\n(\n    SELECT\n        date, dnum, y2, y10, spread,\n        lagInFrame(dnum, 1, toInt64(-100000)) OVER (ORDER BY dnum ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS prev_dnum\n    FROM scored\n    WHERE spread > 0 AND rows_prior = 60 AND neg_prior >= 35 AND pos_next >= 19\n),\nepisodes AS\n(\n    SELECT date AS cross_date, y2, y10, spread\n    FROM candidates\n    WHERE dnum - prev_dnum > 180\n      AND date <= today() - 380\n)\nSELECT\n    formatDateTime(e.cross_date, '%b %Y')                                       AS episode,\n    toString(toDate(e.cross_date))                                              AS crossed_on,\n    concat(formatDateTime(e.cross_date, '%b '), toString(toDayOfMonth(e.cross_date)), ', ', toString(toYear(e.cross_date))) AS crossed_on_label,\n    countIf(d.spread < 0 AND d.date < e.cross_date)                             AS negative_sessions_prior,\n    round(minIf(d.spread, d.date < e.cross_date), 2)                            AS trough_spread,\n    round(argMinIf(d.spread, d.date, d.date >= addDays(e.cross_date, 91)), 2)   AS spread_3m_later,\n    round(argMinIf(d.spread, d.date, d.date >= addDays(e.cross_date, 182)), 2)  AS spread_6m_later,\n    round(argMinIf(d.spread, d.date, d.date >= addDays(e.cross_date, 365)), 2)  AS spread_12m_later\nFROM episodes AS e\nCROSS JOIN daily AS d\nWHERE d.date BETWEEN addDays(e.cross_date, -800) AND addDays(e.cross_date, 380)\nGROUP BY e.cross_date\nHAVING countIf(d.date >= addDays(e.cross_date, 365)) > 0\nORDER BY e.cross_date","computed_at":"2026-09-19T15:13:10.291307+00:00","elapsed":1.362260135}