{"slug":"what-happens-when-the-yield-curve-un-inverts","qid":"spy_after","label":"SPY's change from the crossing-day close, 3, 6 and 12 months after each un-inversion","post_title":"What Happens When the Yield Curve Un-Inverts","post_url":"/blog/what-happens-when-the-yield-curve-un-inverts#q-spy_after","columns":["episode","spy_at_cross","spy_3m_pct","spy_6m_pct","spy_12m_pct"],"rows":[{"episode":"Mar 2007","spy_at_cross":143.29,"spy_3m_pct":5.5,"spy_6m_pct":7,"spy_12m_pct":-7.8},{"episode":"Sep 2024","spy_at_cross":550.95,"spy_3m_pct":10.3,"spy_6m_pct":5.8,"spy_12m_pct":17.8}],"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),\nspy AS\n(\n    SELECT date, max(toFloat64(close)) AS px\n    FROM global_markets.stocks_daily_aggs\n    WHERE ticker = 'SPY'\n    GROUP BY date\n)\nSELECT\n    formatDateTime(e.cross_date, '%b %Y')                                                                                        AS episode,\n    round(argMinIf(s.px, s.date, s.date >= e.cross_date), 2)                                                                     AS spy_at_cross,\n    round((argMinIf(s.px, s.date, s.date >= addDays(e.cross_date, 91))  / argMinIf(s.px, s.date, s.date >= e.cross_date) - 1) * 100, 1) AS spy_3m_pct,\n    round((argMinIf(s.px, s.date, s.date >= addDays(e.cross_date, 182)) / argMinIf(s.px, s.date, s.date >= e.cross_date) - 1) * 100, 1) AS spy_6m_pct,\n    round((argMinIf(s.px, s.date, s.date >= addDays(e.cross_date, 365)) / argMinIf(s.px, s.date, s.date >= e.cross_date) - 1) * 100, 1) AS spy_12m_pct\nFROM episodes AS e\nCROSS JOIN spy AS s\nWHERE s.date BETWEEN e.cross_date AND addDays(e.cross_date, 380)\nGROUP BY e.cross_date\nHAVING countIf(s.date <= addDays(e.cross_date, 7)) > 0\n   AND countIf(s.date >= addDays(e.cross_date, 365)) > 0\nORDER BY e.cross_date","computed_at":"2026-09-19T15:13:12.965704+00:00","elapsed":0.856488452}