{"slug":"double-top-pattern-follow-through","qid":"signals_by_year","label":"signals_by_year","post_title":"double-top-pattern-follow-through","post_url":"/blog/lang/th/double-top-pattern-follow-through#q-signals_by_year","columns":["year","signal_count","median_depth_pct"],"rows":[{"year":2015,"signal_count":7,"median_depth_pct":7.65},{"year":2016,"signal_count":7,"median_depth_pct":8},{"year":2017,"signal_count":1,"median_depth_pct":18.04},{"year":2018,"signal_count":15,"median_depth_pct":7.9},{"year":2019,"signal_count":2,"median_depth_pct":13.36},{"year":2020,"signal_count":7,"median_depth_pct":8.07},{"year":2021,"signal_count":6,"median_depth_pct":8.33},{"year":2022,"signal_count":11,"median_depth_pct":9.92},{"year":2023,"signal_count":8,"median_depth_pct":8.02},{"year":2024,"signal_count":9,"median_depth_pct":7.8},{"year":2025,"signal_count":9,"median_depth_pct":9.72},{"year":2026,"signal_count":5,"median_depth_pct":8.68}],"shape":"ranking","sql":"WITH\npx AS (\n    SELECT ticker, date,\n           toFloat64(argMax(high, _ingest_time))  AS h,\n           toFloat64(argMax(low, _ingest_time))   AS l,\n           toFloat64(argMax(close, _ingest_time)) AS c\n    FROM global_markets.stocks_daily_aggs\n    WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','META','JPM','JNJ','KO','XOM')\n      AND date >= '2015-01-01' AND date < today()\n    GROUP BY ticker, date),\nsplits AS (\n    SELECT ticker, groupArray(execution_date) AS split_dates\n    FROM global_markets.stocks_splits\n    WHERE execution_date >= '2014-01-01'\n    GROUP BY ticker),\npivots AS (\n    SELECT ticker, date, h, l, c,\n           toUInt8(h = max(h) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 10 PRECEDING AND 10 FOLLOWING)) AS is_peak\n    FROM px),\nframed AS (\n    SELECT ticker, date, h, is_peak,\n           groupArray(h)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS h_back,\n           groupArray(l)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS l_back,\n           groupArray(is_peak) OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN 60 PRECEDING AND CURRENT ROW) AS p_back,\n           groupArray(c)       OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS c_fwd,\n           groupArray(date)    OVER (PARTITION BY ticker ORDER BY date ROWS BETWEEN CURRENT ROW AND 90 FOLLOWING) AS d_fwd\n    FROM pivots),\npaired AS (\n    SELECT ticker, date AS peak2_date, h AS peak2_high, h_back, l_back, c_fwd, d_fwd,\n           arrayFirst(g -> (p_back[61 - g] = 1)\n                       AND (abs((h_back[61 - g] / h) - 1) <= 0.03)\n                       AND (arrayMin(arraySlice(l_back, 61 - g, g + 1)) <= (0.95 * least(h_back[61 - g], h))),\n                      range(15, 61)) AS gap\n    FROM framed\n    WHERE is_peak = 1 AND length(l_back) = 61 AND length(c_fwd) = 91),\nnecked AS (\n    SELECT ticker, peak2_date, gap,\n           greatest(h_back[61 - gap], peak2_high)          AS peak_high,\n           arrayMin(arraySlice(l_back, 61 - gap, gap + 1)) AS neckline,\n           c_fwd, d_fwd\n    FROM (\n        SELECT p.ticker AS ticker, p.peak2_date AS peak2_date, p.peak2_high AS peak2_high,\n               p.h_back AS h_back, p.l_back AS l_back, p.c_fwd AS c_fwd, p.d_fwd AS d_fwd,\n               p.gap AS gap, s.split_dates AS split_dates\n        FROM paired AS p\n        LEFT JOIN splits AS s ON p.ticker = s.ticker)\n    WHERE gap > 0\n      AND arrayCount(d -> (d >= (peak2_date - 150)) AND (d <= (peak2_date + 180)), split_dates) = 0),\nconfirmed AS (\n    SELECT ticker,\n           d_fwd[k_rel + 11]                                   AS confirm_date,\n           round(100 * ((peak_high - neckline) / peak_high), 2) AS depth_pct\n    FROM (SELECT *, arrayFirstIndex(x -> x < neckline, arraySlice(c_fwd, 12, 20)) AS k_rel FROM necked)\n    WHERE k_rel > 0\n    ORDER BY ticker, confirm_date\n    LIMIT 1 BY ticker, confirm_date)\nSELECT\n    toYear(confirm_date)                    AS year,\n    count()                                 AS signal_count,\n    round(quantileExact(0.5)(depth_pct), 2) AS median_depth_pct\nFROM confirmed\nGROUP BY year\nORDER BY year","computed_at":"2026-09-28T15:42:00.390931+00:00","elapsed":72.415063918}