{"slug":"falling-wedge-pattern","qid":"move_distribution","label":"move_distribution","post_title":"falling-wedge-pattern","post_url":"/blog/lang/pcm/falling-wedge-pattern#q-move_distribution","columns":["move_bucket","wedge_share_pct","base_share_pct"],"rows":[{"move_bucket":"below -10%","wedge_share_pct":8.7,"base_share_pct":5.3},{"move_bucket":"-10% to -5%","wedge_share_pct":11.5,"base_share_pct":10.8},{"move_bucket":"-5% to 0%","wedge_share_pct":25.8,"base_share_pct":26.7},{"move_bucket":"0% to +5%","wedge_share_pct":27.9,"base_share_pct":32.1},{"move_bucket":"+5% to +10%","wedge_share_pct":16,"base_share_pct":16},{"move_bucket":"above +10%","wedge_share_pct":10.1,"base_share_pct":9.1}],"shape":"ranking","sql":"WITH\nbars AS (\n    SELECT\n        ticker,\n        date,\n        toFloat64(high)  AS hi,\n        toFloat64(low)   AS lo,\n        toFloat64(close) AS px\n    FROM global_markets.stocks_daily_aggs\n    WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','META','TSLA','AVGO','JPM','BAC','WFC','GS','KO','PEP','PG','JNJ','PFE','MRK','XOM','CVX','WMT','HD','MCD','NKE','CSCO','INTC','IBM','T','VZ','DIS')\n      AND date >= '2010-01-04'\n      AND date <= '2026-09-30'\n),\nsplit_dates AS (\n    SELECT\n        ticker,\n        groupArray(execution_date) AS split_days\n    FROM\n    (\n        SELECT ticker, execution_date\n        FROM global_markets.stocks_splits\n        WHERE execution_date >= '2009-10-01'\n        GROUP BY ticker, execution_date\n    )\n    GROUP BY ticker\n),\nstepped AS (\n    SELECT\n        ticker,\n        date,\n        px,\n        hi - lo AS rng,\n        if(hi < lagInFrame(hi, 1) OVER w AND lo < lagInFrame(lo, 1) OVER w, 1, 0) AS lower_both\n    FROM bars\n    WINDOW w AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)\n),\nfeat AS (\n    SELECT\n        ticker,\n        date,\n        px,\n        sum(lower_both) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)  AS wedge_streak,\n        avg(rng)        OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 4 PRECEDING AND CURRENT ROW)  AS rng5,\n        groupArray(rng) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 64 PRECEDING AND 5 PRECEDING) AS prior_rng,\n        lagInFrame(px, 5)   OVER wf AS px_back5,\n        leadInFrame(px, 5)  OVER wf AS px_fwd5,\n        leadInFrame(px, 10) OVER wf AS px_fwd10,\n        leadInFrame(px, 20) OVER wf AS px_fwd20\n    FROM stepped\n    WINDOW wf AS (PARTITION BY ticker ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)\n),\nscored AS (\n    SELECT\n        f.px       AS px,\n        f.px_fwd20 AS px_fwd20,\n        if(f.wedge_streak = 4 AND f.rng5 < arraySort(f.prior_rng)[15], 1, 0) AS is_wedge\n    FROM feat AS f\n    LEFT JOIN split_dates AS s ON s.ticker = f.ticker\n    WHERE length(f.prior_rng) = 60\n      AND f.px_back5 > 0\n      AND f.px_fwd5  > 0\n      AND f.px_fwd10 > 0\n      AND f.px_fwd20 > 0\n      AND NOT arrayExists(d -> (d >= f.date - 10) AND (d <= f.date + 32), s.split_days)\n)\nSELECT\n    move_bucket,\n    round(100 * wedge_n / sum(wedge_n) OVER (), 1) AS wedge_share_pct,\n    round(100 * base_n  / sum(base_n)  OVER (), 1) AS base_share_pct\nFROM\n(\n    SELECT\n        multiIf(fwd20 < -10, 'below -10%',\n                fwd20 < -5,  '-10% to -5%',\n                fwd20 < 0,   '-5% to 0%',\n                fwd20 < 5,   '0% to +5%',\n                fwd20 < 10,  '+5% to +10%',\n                             'above +10%') AS move_bucket,\n        multiIf(fwd20 < -10, 1, fwd20 < -5, 2, fwd20 < 0, 3, fwd20 < 5, 4, fwd20 < 10, 5, 6) AS bucket_order,\n        countIf(is_wedge = 1) AS wedge_n,\n        count()               AS base_n\n    FROM\n    (\n        SELECT is_wedge, 100 * (px_fwd20 / px - 1) AS fwd20\n        FROM scored\n    )\n    GROUP BY move_bucket, bucket_order\n)\nORDER BY bucket_order ASC","computed_at":"2026-10-06T15:38:26.358519+00:00","elapsed":0.010161024}