{"slug":"when-do-vix-futures-expire","qid":"walk_back","label":"walk_back","post_title":"when-do-vix-futures-expire","post_url":"/blog/when-do-vix-futures-expire#q-walk_back","columns":["vix_contract","next_month_third_friday","friday_status","counted_back_from","thirty_days_earlier","that_day_status","final_settlement_date"],"rows":[{"vix_contract":"VX Jan 2026","next_month_third_friday":"Fri Feb 20, 2026","friday_status":"trading day","counted_back_from":"Fri Feb 20, 2026","thirty_days_earlier":"Wed Jan 21, 2026","that_day_status":"trading day","final_settlement_date":"Wed Jan 21, 2026"},{"vix_contract":"VX Dec 2026","next_month_third_friday":"Fri Jan 15, 2027","friday_status":"trading day","counted_back_from":"Fri Jan 15, 2027","thirty_days_earlier":"Wed Dec 16, 2026","that_day_status":"trading day","final_settlement_date":"Wed Dec 16, 2026"},{"vix_contract":"VX May 2026","next_month_third_friday":"Fri Jun 19, 2026","friday_status":"exchange holiday","counted_back_from":"Thu Jun 18, 2026","thirty_days_earlier":"Tue May 19, 2026","that_day_status":"trading day","final_settlement_date":"Tue May 19, 2026"},{"vix_contract":"VX Jun 2024","next_month_third_friday":"Fri Jul 19, 2024","friday_status":"trading day","counted_back_from":"Fri Jul 19, 2024","thirty_days_earlier":"Wed Jun 19, 2024","that_day_status":"exchange holiday","final_settlement_date":"Tue Jun 18, 2024"}],"shape":"table","sql":"WITH\n    traded AS\n    (\n        SELECT groupArray(session_day) AS session_days\n        FROM\n        (\n            SELECT date AS session_day\n            FROM global_markets.stocks_daily_aggs\n            WHERE ticker = 'SPY'\n              AND date >= toDate('2014-11-01')\n            GROUP BY session_day\n        )\n    ),\n    closures_ahead AS\n    (\n        SELECT groupArray(date) AS closed_days\n        FROM global_markets.stocks_market_holidays\n        WHERE status = 'closed'\n    )\nSELECT\n    concat('VX ', formatDateTime(contract_month, '%b %Y'))  AS vix_contract,\n    formatDateTime(ref_friday, '%a %b %e, %Y')              AS next_month_third_friday,\n    if(friday_closed, 'exchange holiday', 'trading day')    AS friday_status,\n    formatDateTime(spx_anchor, '%a %b %e, %Y')              AS counted_back_from,\n    formatDateTime(wednesday_target, '%a %b %e, %Y')        AS thirty_days_earlier,\n    if(target_closed, 'exchange holiday', 'trading day')    AS that_day_status,\n    formatDateTime(settlement, '%a %b %e, %Y')              AS final_settlement_date\nFROM\n(\n    SELECT\n        a.contract_month AS contract_month,\n        a.ref_friday     AS ref_friday,\n        ((a.ref_friday <= toDate(arrayMax(t.session_days))) AND (NOT has(t.session_days, a.ref_friday)))\n            OR has(h.closed_days, a.ref_friday)             AS friday_closed,\n        if(friday_closed, addDays(a.ref_friday, -1), a.ref_friday) AS spx_anchor,\n        addDays(spx_anchor, -30)                            AS wednesday_target,\n        ((wednesday_target <= toDate(arrayMax(t.session_days))) AND (NOT has(t.session_days, wednesday_target)))\n            OR has(h.closed_days, wednesday_target)         AS target_closed,\n        if(target_closed, addDays(wednesday_target, -1), wednesday_target) AS settlement\n    FROM\n    (\n        SELECT\n            contract_month,\n            addMonths(contract_month, 1)                                             AS ref_month,\n            addDays(ref_month, ((5 - toInt32(toDayOfWeek(ref_month)) + 7) % 7) + 14) AS ref_friday\n        FROM\n        (\n            SELECT toDate(arrayJoin(['2026-01-01', '2026-12-01', '2026-05-01', '2024-06-01'])) AS contract_month\n        )\n    ) AS a\n    CROSS JOIN traded AS t\n    CROSS JOIN closures_ahead AS h\n)\nORDER BY multiIf(contract_month = toDate('2026-01-01'), 1,\n                 contract_month = toDate('2026-12-01'), 2,\n                 contract_month = toDate('2026-05-01'), 3,\n                 4) ASC","computed_at":"2026-10-01T15:14:21.965285+00:00","elapsed":0.112020545}