{"slug":"what-is-triple-witching","qid":"witching_volatility","label":"SPY on witching sessions vs. the same month's other sessions: intraday range and net move (% of the open)","post_title":"What Is Triple Witching? Volume & Volatility","post_url":"/blog/what-is-triple-witching#q-witching_volatility","columns":["witching_session","witching_range_pct","other_days_median_range_pct","witching_net_move_pct","other_days_median_net_move_pct"],"rows":[{"witching_session":"2024-09-20","witching_range_pct":0.73,"other_days_median_range_pct":0.92,"witching_net_move_pct":0.05,"other_days_median_net_move_pct":0.35},{"witching_session":"2024-12-20","witching_range_pct":2.55,"other_days_median_range_pct":0.61,"witching_net_move_pct":1.56,"other_days_median_net_move_pct":0.34},{"witching_session":"2025-03-21","witching_range_pct":1.23,"other_days_median_range_pct":1.72,"witching_net_move_pct":0.88,"other_days_median_net_move_pct":0.75},{"witching_session":"2025-06-20","witching_range_pct":1.1,"other_days_median_range_pct":0.73,"witching_net_move_pct":0.69,"other_days_median_net_move_pct":0.4},{"witching_session":"2025-09-19","witching_range_pct":0.63,"other_days_median_range_pct":0.71,"witching_net_move_pct":0.2,"other_days_median_net_move_pct":0.22},{"witching_session":"2025-12-19","witching_range_pct":0.68,"other_days_median_range_pct":0.7,"witching_net_move_pct":0.59,"other_days_median_net_move_pct":0.22},{"witching_session":"2026-03-20","witching_range_pct":1.82,"other_days_median_range_pct":1.28,"witching_net_move_pct":1.21,"other_days_median_net_move_pct":0.52},{"witching_session":"2026-06-18","witching_range_pct":0.58,"other_days_median_range_pct":1.12,"witching_net_move_pct":0.16,"other_days_median_net_move_pct":0.55}],"shape":"series","sql":"WITH daily AS (\n    SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,\n           toFloat64(max(high) - min(low)) / toFloat64(argMin(open, window_start)) * 100 AS range_pct,\n           abs(toFloat64(argMax(close, window_start)) - toFloat64(argMin(open, window_start)))\n               / toFloat64(argMin(open, window_start)) * 100 AS net_move_pct\n    FROM global_markets.delayed_stocks_minute_aggs\n    WHERE ticker = 'SPY'\n      AND window_start >= '2024-09-01 04:00:00'\n      AND window_start < '2026-07-01 04:00:00'\n      AND toMonth(toTimeZone(window_start, 'America/New_York')) IN (3, 6, 9, 12)\n      AND toHour(toTimeZone(window_start, 'America/New_York')) >= 9\n      AND toHour(toTimeZone(window_start, 'America/New_York')) < 16\n      AND NOT (toHour(toTimeZone(window_start, 'America/New_York')) = 9\n               AND toMinute(toTimeZone(window_start, 'America/New_York')) < 30)\n    GROUP BY day\n),\nwitching AS (\n    SELECT toStartOfMonth(day) AS m,\n           maxIf(day, day <= addDays(toStartOfMonth(day),\n                 ((5 - toDayOfWeek(toStartOfMonth(day)) + 7) % 7) + 14)) AS witching_day\n    FROM daily\n    GROUP BY m\n)\nSELECT toString(w.witching_day) AS witching_session,\n       round(anyIf(d.range_pct, d.day = w.witching_day), 2) AS witching_range_pct,\n       round(quantileDeterministicIf(0.5)(d.range_pct, cityHash64(toString(d.day)), d.day != w.witching_day), 2) AS other_days_median_range_pct,\n       round(anyIf(d.net_move_pct, d.day = w.witching_day), 2) AS witching_net_move_pct,\n       round(quantileDeterministicIf(0.5)(d.net_move_pct, cityHash64(toString(d.day)), d.day != w.witching_day), 2) AS other_days_median_net_move_pct\nFROM daily AS d\nINNER JOIN witching AS w ON toStartOfMonth(d.day) = w.m\nGROUP BY w.witching_day\nHAVING countIf(d.day != w.witching_day) > 0\nORDER BY w.witching_day","computed_at":"2026-08-10T14:15:56.812729+00:00","elapsed":0.005637058}