Every 2026 monthly options expiration date
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-09-20, from Options Expiration Calendar 2026: All 12 Dates.
| expiration_date | expiry_label | weekday | day_of_month | expiry_class | calendar_check |
|---|---|---|---|---|---|
| 2026-01-16 | Jan 16 | Fri | 16 | monthly | already traded |
| 2026-02-20 | Feb 20 | Fri | 20 | monthly | already traded |
| 2026-03-20 | Mar 20 | Fri | 20 | quarterly | already traded |
| 2026-04-17 | Apr 17 | Fri | 17 | monthly | already traded |
| 2026-05-15 | May 15 | Fri | 15 | monthly | already traded |
| 2026-06-19 | Jun 19 | Fri | 19 | quarterly | already traded |
| 2026-07-17 | Jul 17 | Fri | 17 | monthly | already traded |
| 2026-08-21 | Aug 21 | Fri | 21 | monthly | already traded |
| 2026-09-18 | Sep 18 | Fri | 18 | quarterly | already traded |
| 2026-10-16 | Oct 16 | Fri | 16 | monthly | no closure scheduled |
| 2026-11-20 | Nov 20 | Fri | 20 | monthly | no closure scheduled |
| 2026-12-18 | Dec 18 | Fri | 18 | quarterly | no closure scheduled |
- Rows × columns
- 12 × 6
- 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 |
|---|---|---|---|
expiration_date |
date | 2026-01-16 to 2026-12-18 | |
expiry_label |
text | 12 distinct values (Apr 17, Aug 21, Dec 18…) | |
weekday |
text | 1 distinct value (Fri) | |
day_of_month |
number | 15 to 21 | |
expiry_class |
text | 2 distinct values (monthly, quarterly) | |
calendar_check |
text | 2 distinct values (already traded, no closure scheduled) |
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.
SELECT
toString(cal.exp_date) AS expiration_date,
concat(formatDateTime(cal.exp_date, '%b '), toString(toDayOfMonth(cal.exp_date))) AS expiry_label,
formatDateTime(cal.exp_date, '%a') AS weekday,
toDayOfMonth(cal.exp_date) AS day_of_month,
if(toMonth(cal.exp_date) IN (3, 6, 9, 12), 'quarterly', 'monthly') AS expiry_class,
multiIf(cal.exp_date < today(), 'already traded',
hol.holiday != '', concat('scheduled closure: ', hol.holiday),
'no closure scheduled') AS calendar_check
FROM
(
SELECT
toDate('2026-01-01') + toIntervalMonth(arrayJoin(range(12))) AS month_start,
month_start + ((12 - toDayOfWeek(month_start)) % 7) + 14 AS exp_date
) AS cal
LEFT JOIN
(
SELECT
date AS d,
any(name) AS holiday
FROM global_markets.stocks_market_holidays
GROUP BY date
) AS hol ON hol.d = cal.exp_date
ORDER BY cal.exp_date