{"slug":"when-a-spread-expires-between-the-strikes","qid":"final_hour_travel_spy","label":"How far SPY travels between 3:00 p.m. ET and the Friday close","post_title":"When a Spread Expires Between the Strikes","post_url":"/blog/when-a-spread-expires-between-the-strikes#q-final_hour_travel_spy","columns":["year","expiration_count","median_final_hour_move_pct","p90_final_hour_move_pct"],"rows":[{"year":"2022","expiration_count":50,"median_final_hour_move_pct":0.353,"p90_final_hour_move_pct":0.779},{"year":"2023","expiration_count":50,"median_final_hour_move_pct":0.141,"p90_final_hour_move_pct":0.388},{"year":"2024","expiration_count":50,"median_final_hour_move_pct":0.115,"p90_final_hour_move_pct":0.294},{"year":"2025","expiration_count":49,"median_final_hour_move_pct":0.103,"p90_final_hour_move_pct":0.399},{"year":"2026","expiration_count":32,"median_final_hour_move_pct":0.124,"p90_final_hour_move_pct":0.306}],"shape":"ranking","sql":"WITH bars AS (\n    SELECT\n        toDate(toTimeZone(window_start, 'America/New_York'))        AS session_date,\n        toHour(toTimeZone(window_start, 'America/New_York')) * 60\n          + toMinute(toTimeZone(window_start, 'America/New_York'))  AS et_minute,\n        toFloat64(close)                                            AS px\n    FROM global_markets.delayed_stocks_minute_aggs\n    WHERE ticker = 'SPY'\n      AND window_start >= '2022-01-01 00:00:00'\n      AND window_start <  '2026-09-01 00:00:00'\n),\nday_marks AS (\n    SELECT\n        session_date,\n        anyIf(px, et_minute = 900) AS px_3pm,\n        argMax(px, et_minute)      AS px_close\n    FROM bars\n    WHERE et_minute >= 570\n      AND et_minute <= 959\n    GROUP BY session_date\n    HAVING px_3pm > 0\n       AND px_close > 0\n       AND max(et_minute) >= 955\n)\nSELECT\n    toString(toYear(session_date)) AS year,\n    count()                        AS expiration_count,\n    round(quantileDeterministic(0.5)(100 * abs(px_close - px_3pm) / px_3pm, toUInt32(toUnixTimestamp(session_date))), 3) AS median_final_hour_move_pct,\n    round(quantileDeterministic(0.9)(100 * abs(px_close - px_3pm) / px_3pm, toUInt32(toUnixTimestamp(session_date))), 3) AS p90_final_hour_move_pct\nFROM day_marks\nWHERE toDayOfWeek(session_date) = 5\nGROUP BY year\nORDER BY year","computed_at":"2026-09-27T15:36:11.251840+00:00","elapsed":0.153123158}