roll_cycle
Answered against 22 years of US equities and 12 years of US options data and published with the query that produced it. This result is stored as of 2026-10-01, from when-do-vix-futures-expire.
| settlement_date | vix_contract | days_since_prior_settlement |
|---|---|---|
| 2026-01-21 | VX Jan 2026 | 35 |
| 2026-02-18 | VX Feb 2026 | 28 |
| 2026-03-18 | VX Mar 2026 | 28 |
| 2026-04-15 | VX Apr 2026 | 28 |
| 2026-05-19 | VX May 2026 | 34 |
| 2026-06-17 | VX Jun 2026 | 29 |
| 2026-07-22 | VX Jul 2026 | 35 |
| 2026-08-19 | VX Aug 2026 | 28 |
| 2026-09-16 | VX Sep 2026 | 28 |
| 2026-10-21 | VX Oct 2026 | 35 |
| 2026-11-18 | VX Nov 2026 | 28 |
| 2026-12-16 | VX Dec 2026 | 28 |
- Rows × columns
- 12 × 3
- Period covered
- to
- Computed
- Completeness
- No missing values
- Source
- US exchange, SIP and OPRA market data
- Licence
- Strasmore terms · free, no signup
What each column holds
| Column | Type | Range | Notes |
|---|---|---|---|
settlement_date |
date | 2026-01-21 to 2026-12-16 | |
vix_contract |
text | 12 distinct values (VX Apr 2026, VX Aug 2026, VX Dec 2026…) | |
days_since_prior_settlement |
number | 28 to 35 |
Computed from Strasmore's warehouse of US exchange, SIP and OPRA market data. Equity prices are delayed; options greeks and implied volatility are end-of-day. This result is stored, not recomputed on load — it is exactly the numbers that were returned on , and the query below is what returned them.
Run it yourself
This is the exact query behind the result above. Change a ticker, a date or a column and run it against the warehouse — no account, no key. The no-signup tier is smaller than the one this page was computed on; a query that reaches past it comes back saying which plan runs it.
WITH
traded AS
(
SELECT groupArray(session_day) AS session_days
FROM
(
SELECT date AS session_day
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= toDate('2014-11-01')
GROUP BY session_day
)
),
closures_ahead AS
(
SELECT groupArray(date) AS closed_days
FROM global_markets.stocks_market_holidays
WHERE status = 'closed'
)
SELECT
toString(settlement) AS settlement_date,
concat('VX ', formatDateTime(contract_month, '%b %Y')) AS vix_contract,
toInt32(dateDiff('day', prior_settlement, settlement)) AS days_since_prior_settlement
FROM
(
SELECT
contract_month,
settlement,
lagInFrame(settlement) OVER (ORDER BY settlement ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_settlement
FROM
(
SELECT
a.contract_month AS contract_month,
if(((a.ref_friday <= toDate(arrayMax(t.session_days))) AND (NOT has(t.session_days, a.ref_friday)))
OR has(h.closed_days, a.ref_friday),
addDays(a.ref_friday, -1),
a.ref_friday) AS spx_anchor,
addDays(spx_anchor, -30) AS wednesday_target,
if(((wednesday_target <= toDate(arrayMax(t.session_days))) AND (NOT has(t.session_days, wednesday_target)))
OR has(h.closed_days, wednesday_target),
addDays(wednesday_target, -1),
wednesday_target) AS settlement
FROM
(
SELECT
contract_month,
addMonths(contract_month, 1) AS ref_month,
addDays(ref_month, ((5 - toInt32(toDayOfWeek(ref_month)) + 7) % 7) + 14) AS ref_friday
FROM
(
SELECT addMonths(toDate('2025-12-01'), toInt32(arrayJoin(range(13)))) AS contract_month
)
) AS a
CROSS JOIN traded AS t
CROSS JOIN closures_ahead AS h
)
)
WHERE prior_settlement >= toDate('2025-12-01')
ORDER BY settlement ASC
Work with this data in your AI assistant
Opens ready to query, with this page's data. Free, no account.