{"slug":"msft-decline-from-peak","qid":"drawdown_episodes","label":"drawdown_episodes","post_title":"msft-decline-from-peak","post_url":"/blog/lang/zh-hant/msft-decline-from-peak#q-drawdown_episodes","columns":["peak_on","trough_on","depth_pct","sessions_below_peak","days_to_recover"],"rows":[{"peak_on":"2021/11/19","trough_on":"2022/11/03","depth_pct":37.6,"sessions_below_peak":392,"days_to_recover":573},{"peak_on":"2025/10/28","trough_on":"2026/06/25","depth_pct":34.9,"sessions_below_peak":228,"days_to_recover":0},{"peak_on":"2020/02/10","trough_on":"2020/03/16","depth_pct":28.2,"sessions_below_peak":82,"days_to_recover":120},{"peak_on":"2024/07/05","trough_on":"2025/04/08","depth_pct":24.2,"sessions_below_peak":229,"days_to_recover":335},{"peak_on":"2018/10/01","trough_on":"2018/12/24","depth_pct":18.6,"sessions_below_peak":112,"days_to_recover":165},{"peak_on":"2015/04/28","trough_on":"2015/08/25","depth_pct":17.7,"sessions_below_peak":124,"days_to_recover":178},{"peak_on":"2015/01/08","trough_on":"2015/04/02","depth_pct":15.3,"sessions_below_peak":72,"days_to_recover":106},{"peak_on":"2015/12/29","trough_on":"2016/06/27","depth_pct":14.4,"sessions_below_peak":141,"days_to_recover":206},{"peak_on":"2020/09/02","trough_on":"2020/09/18","depth_pct":13.5,"sessions_below_peak":98,"days_to_recover":146},{"peak_on":"2023/07/18","trough_on":"2023/09/26","depth_pct":13.2,"sessions_below_peak":78,"days_to_recover":112},{"peak_on":"2018/01/31","trough_on":"2018/02/08","depth_pct":10.5,"sessions_below_peak":16,"days_to_recover":26}],"shape":"table","sql":"WITH daily AS\n(\n    SELECT\n        date,\n        toFloat64(max(close)) AS close\n    FROM global_markets.stocks_daily_aggs\n    WHERE ticker = 'MSFT'\n      AND date >= '2015-01-01'\n    GROUP BY date\n),\nmarked AS\n(\n    SELECT\n        date,\n        close,\n        max(close)          OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS peak_close,\n        argMax(date, close) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS peak_date\n    FROM daily\n),\nnext_session AS\n(\n    SELECT\n        date,\n        any(date) OVER (ORDER BY date ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING) AS next_date\n    FROM daily\n),\nepisodes AS\n(\n    SELECT\n        peak_date,\n        any(peak_close)     AS peak_level,\n        min(close)          AS trough_level,\n        argMin(date, close) AS trough_date,\n        max(date)           AS last_below_date,\n        count()             AS sessions_below\n    FROM marked\n    WHERE close < peak_close\n    GROUP BY peak_date\n    HAVING min(close) / any(peak_close) <= 0.90\n)\nSELECT\n    formatDateTime(e.peak_date, '%Y/%m/%d')             AS peak_on,\n    formatDateTime(e.trough_date, '%Y/%m/%d')           AS trough_on,\n    round((1 - e.trough_level / e.peak_level) * 100, 1) AS depth_pct,\n    toUInt32(e.sessions_below)                          AS sessions_below_peak,\n    if(n.next_date > e.peak_date,\n       toUInt32(dateDiff('day', e.peak_date, n.next_date)),\n       toUInt32(0))                                     AS days_to_recover\nFROM episodes AS e\nLEFT JOIN next_session AS n ON n.date = e.last_below_date\nORDER BY depth_pct DESC","computed_at":"2026-09-25T15:28:12.671491+00:00","elapsed":0.004679494}