{"slug":"bullish-vs-bearish-meaning","qid":"streaks","label":"streaks","post_title":"bullish-vs-bearish-meaning","post_url":"/blog/lang/pcm/bullish-vs-bearish-meaning#q-streaks","columns":["streak","direction","days","started","ended","move_pct"],"rows":[{"streak":"Up run, Feb 2010","direction":"Up streak","days":14,"started":"Feb 26, 2010","ended":"Mar 17, 2010","move_pct":5.8},{"streak":"Up run, May 2024","direction":"Up streak","days":10,"started":"May 2, 2024","ended":"May 15, 2024","move_pct":5.9},{"streak":"Up run, Apr 2025","direction":"Up streak","days":9,"started":"Apr 22, 2025","ended":"May 2, 2025","move_pct":10.3},{"streak":"Up run, Mar 2004","direction":"Up streak","days":9,"started":"Mar 24, 2004","ended":"Apr 5, 2004","move_pct":5.3},{"streak":"Up run, Nov 2006","direction":"Up streak","days":9,"started":"Nov 10, 2006","ended":"Nov 22, 2006","move_pct":2},{"streak":"Down run, Dec 2007","direction":"Down streak","days":8,"started":"Dec 27, 2007","ended":"Jan 8, 2008","move_pct":-7.1},{"streak":"Down run, Dec 2018","direction":"Down streak","days":8,"started":"Dec 13, 2018","ended":"Dec 24, 2018","move_pct":-11.7},{"streak":"Down run, Feb 2020","direction":"Down streak","days":7,"started":"Feb 20, 2020","ended":"Feb 28, 2020","move_pct":-12.4},{"streak":"Down run, Jul 2011","direction":"Down streak","days":7,"started":"Jul 25, 2011","ended":"Aug 2, 2011","move_pct":-6.8},{"streak":"Down run, Jun 2006","direction":"Down streak","days":7,"started":"Jun 5, 2006","ended":"Jun 13, 2006","move_pct":-5}],"shape":"table","sql":"WITH bars AS\n(\n    SELECT\n        date,\n        toFloat64(any(close)) AS close_price\n    FROM global_markets.stocks_daily_aggs\n    WHERE ticker = 'SPY'\n      AND close > 0\n    GROUP BY date\n),\nmoves AS\n(\n    SELECT\n        date,\n        close_price,\n        lagInFrame(close_price, 1) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS prev_close\n    FROM bars\n),\nsigns AS\n(\n    SELECT\n        date,\n        close_price,\n        prev_close,\n        sign(close_price - prev_close) AS dir\n    FROM moves\n    WHERE prev_close > 0\n),\nflags AS\n(\n    SELECT\n        date,\n        close_price,\n        prev_close,\n        dir,\n        if(dir != lagInFrame(dir, 1) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), 1, 0) AS run_break\n    FROM signs\n),\nruns AS\n(\n    SELECT\n        date,\n        close_price,\n        prev_close,\n        dir,\n        sum(run_break) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS run_id\n    FROM flags\n),\nrun_stats AS\n(\n    SELECT\n        run_id,\n        any(dir)                                                                      AS run_dir,\n        count()                                                                       AS days,\n        min(date)                                                                     AS run_start,\n        max(date)                                                                     AS run_end,\n        round(100 * (argMax(close_price, date) / argMin(prev_close, date) - 1), 1)    AS move_pct\n    FROM runs\n    WHERE dir != 0\n    GROUP BY run_id\n)\nSELECT\n    concat(if(run_dir = 1, 'Up run, ', 'Down run, '), formatDateTime(run_start, '%b %Y'))                          AS streak,\n    if(run_dir = 1, 'Up streak', 'Down streak')                                                                     AS direction,\n    days,\n    concat(formatDateTime(run_start, '%b '), toString(toDayOfMonth(run_start)), ', ', toString(toYear(run_start))) AS started,\n    concat(formatDateTime(run_end, '%b '), toString(toDayOfMonth(run_end)), ', ', toString(toYear(run_end)))       AS ended,\n    move_pct\nFROM run_stats\nORDER BY direction DESC, days DESC, streak ASC\nLIMIT 5 BY direction","computed_at":"2026-09-20T15:27:30.544661+00:00","elapsed":0.004797605}