What monthly expiration does to the book

53 monthly-expiration sessions against the 1,024 other sessions in the archive

Published 2026-08-24 · Sample SPX regular session, 2022-04-14 to 2026-08-21, 1,077 usable trading days · Split 53 opex, 1,024 other · Data one-minute index prints and the two dealer books from the session archive · Status measurement, not a signal

The folklore around monthly expiration is specific enough to test. Opex pins price. The book is enormous going in and gutted coming out. Dealer levels stop meaning anything for a day. Each of those is a statement about numbers this archive already holds, so the study below puts every one of them to the same 53 third-Fridays and reports all twelve comparisons it ran — not the one that worked.

Most of the folklore is simply not there. The 10:00-to-close range on opex is 47.2 points against 51.6 on other days, a difference of −4.4 ± 3.8 (t = −1.15): nothing. The book at 10:00 is not bigger in any way that survives its own error bar. The hold band is not wider. Two things do survive, and the first one is not about range at all — it is about the ratio of range to the volatility the tape was already making.

The one clean result: opex is quieter than its own volatility predicts

Points are the wrong unit for "quiet". Twenty points is a formality on a wild day and the whole session on a calm one. So the range from 10:00 to the close is divided by the move the tape was already making at 10:00 — the trailing 30-minute realised move per minute, projected over the minutes remaining (σ = rv30 × √(minutes left)), the same scaler the touch surface uses. It reads only information available at 10:00, so nothing here sees the future except the range itself, which is the outcome.

10:00 → closeopex (53)other (1,024)difference ± set
range ÷ σ1.0131.189−0.176 ± 0.065−2.72
range, points47.251.6−4.4 ± 3.8−1.15
σ at 10:00, points49.146.7+2.3 ± 3.3+0.71

An opex session travels about 15% less than its own opening volatility implies (0.176 ÷ 1.189). The medians agree in sign and size — 0.932 against 1.027 — so it is not one wild third Friday doing the work. And the reason it does not show up in points is in the third row: opex days start with slightly higher σ, 49.1 against 46.7, itself not distinguishable from zero. Higher volatility going in, ordinary range coming out: the ratio moves, the points do not.

That is the same shape as this site's other range finding — that volatility, not gamma, owns the point range. If you want to say something about a day's range, you have to say it relative to what the tape was doing when you said it. Opex is one of the few labels for which that correction is the entire effect.

The other clean result: the book does shrink, by less than advertised

Expiry removes contracts, and the archive can say exactly how many. Take the contract count of the book at 10:00, compare it with the same count on the next session, and do it twice: once for opex → next, once for every other consecutive pair as a control.

overnight change in contract countpairsmean ± semedian
opex → next session52−3.29% ± 0.52−3.86%
control: any other session → next1,018+0.34% ± 0.15−0.42%
control, also excluding the day before opex966+0.37% ± 0.15−0.41%
difference (opex − control)−3.63 ± 0.54

t = −6.72. That is the strongest statistic in the study, and dropping the day before opex from the control barely moves it. It is also small. In levels: the opex book holds 5,703 contracts at 10:00 and the day-after book holds 5,471 — a loss of about 230 contracts. A normal session carries 5,614, so the morning after monthly expiration the book sits 2.5% under ordinary size. Both halves of that have to be said together: the shrink is real and unambiguous, and most of it is replaced within a session.

The two books disagree about what expiry removed

The terminal carries two dealer books over the same chain: the conventional one (sign every contract's open interest by its type) and the measured one (sign every print by which side of the market it hit). From opex to the next session their magnitudes at spot move in opposite directions. The convention book's |net gamma| falls 17%, 236.4 to 196.4 $M in the group means. The measured book's rises 32%, 31.6 to 41.6 $M.

This study does not resolve which of them is reading the transition correctly. It can say only that they disagree, and that the disagreement is about the largest single event in the options calendar. Neither book's opex-day level differs from a normal session (t = +0.10 conventional, t = −1.59 measured); it is the step to the next morning where they part. That the same word can name two different books is the subject of a companion post published today — which book is the zero-gamma flip — and this is one more place where the choice changes the answer.

Everything else is a null

Twelve comparisons were run. Here are all of them, opex against every other session, Welch differences, no selection.

metric, read at 10:00 unless statedopexotherdifference ± set
range ÷ σ, 10:00 → close1.0131.189−0.176 ± 0.065−2.72
overnight contract change (opex vs control pairs)−3.29%+0.34%−3.63 ± 0.54−6.72
overnight flip migration, points85.364.8+20.5 ± 9.7+2.11
|move| 10:00 → close ÷ σ0.5400.650−0.110 ± 0.068−1.61
measured book |net gamma| at spot, $M31.637.2−5.6 ± 3.5−1.59
range, points47.251.6−4.4 ± 3.8−1.15
hold-band width, % of spot3.293.05+0.24 ± 0.21+1.11
|move| 10:00 → close, points24.727.8−3.1 ± 2.9−1.09
hold-band width, points179.7165.6+14.1 ± 13.7+1.03
σ at 10:00, points49.146.7+2.3 ± 3.3+0.71
book size, contracts5,7035,614+89 ± 144+0.62
convention book |net gamma| at spot, $M236.4234.2+2.3 ± 23.2+0.10

Hold-band rows rest on 50 opex and 976 other sessions (the band does not exist on every day); flip migration on 51 and 980 (a pair is used only when both flips exist and the sessions are consecutive in the archive). Every other row is the full 53 against 1,024.

The third row is the one that changed when the archive was rebuilt on the wide book, and it is worth saying so plainly: flip migration — how far the zero-gamma flip moved between one session's close and the next session's 10:00 print — is 85.3 points into opex against 64.8 otherwise, +20.5 ± 9.7, t = +2.11. On the pre-rebuild book the same comparison read +17.1 ± 9.2, t = +1.86, and this post was written calling it suggestive and nothing more. It now clears two standard errors — on 51 opex pairs, as one of twelve comparisons, which is exactly the situation in which a t of 2.1 should not be promoted to a finding. It is written here the same way it was before: the kind of number that becomes a result if the next two years of third Fridays agree, and nothing if they do not.

The neighbours

Opex is not an isolated day, so here are its two neighbours next to it. No test was run on these columns — the study compared opex with all other sessions, not with the day before or the day after — and they are printed as context, not as claims.

read at 10:00day before opexopexday after opexall other sessions
sessions5253521,024
book size, contracts5,7415,7035,4715,614
range ÷ σ, 10:00 → close1.2901.0131.0561.189
range, points55.047.243.651.6
σ at 10:00, points45.649.144.746.7
hold-band width, points165.1179.7150.6165.6
measured book |net gamma| at spot, $M30.631.641.637.2
convention book |net gamma| at spot, $M222.6236.4196.4234.2
overnight flip migration, points73.185.357.764.8

The table is worth one observation and no more: the highest range ÷ σ in it belongs to the day before opex (1.290), not to opex, and the lowest belongs to opex. Whether that is a Thursday effect, an artefact of 52 days, or noise, this study cannot say, because it did not test it.

What counts as opex, and what was thrown out

An opex session is the third Friday of the calendar month. Three months have no third Friday in the archive because the market was shut: 2022-04-15 and 2025-04-18 (Good Friday) and 2026-06-19 (Juneteenth). For those three the last archived session on or before the date is used instead — 2022-04-14, 2025-04-17 and 2026-06-18, each exactly one day earlier. No month is dropped: the archive now reaches 2026-08-21, which is August 2026's third Friday. That makes 53 opex days.

Of 1,086 contiguous archived sessions, 1,077 are usable. The nine exclusions are all half-days, which have fewer than 390 minutes and would corrupt every minutes-remaining scaler in the study: 2022-11-25, 2023-07-03, 2023-11-24, 2024-07-03, 2024-11-29, 2024-12-24, 2025-07-03, 2025-11-28, 2025-12-24. No session was dropped for bad prices and none for a missing 10:00 bar.

What it does not say

Fifty-three sessions is a small sample, and one t = −2.72 among a dozen comparisons is not much above what looking a dozen times produces. That sentence is the most important one on this page. The range ÷ σ result is the best number here, and if you ran twelve honest comparisons on data with no opex effect at all you would expect roughly one of them to land near two-and-a-half standard errors by chance. The defence offered is not statistical: it is that every comparison the study made is printed above, including the ten that found nothing, so nothing was selected after the fact. Treat the range ÷ σ shortfall as one measurement that wants another four years of third Fridays, not as a settled effect. The overnight book shrink, at t = −6.72, is on much firmer ground — and is also the least surprising thing in the study.

Nothing here is a pin claim. "Pinning" is usually a statement about closing near a strike, and no strike-distance metric was computed; the |move| rows say only that the 10:00-to-close displacement is not distinguishable from a normal day's, in points or scaled. Nothing here says the levels stop working on opex — the hold band is the same width and no hold rate was recomputed for the subset. The two-book disagreement is described, not explained. And the window is one regime-spanning stretch, 2022's bear market through 2026; every number is a statement about these sessions, not a law. Nothing on this page is investment advice; see the Terms.

Reproduce it

The spine of this post needs no licensed data. Every finished session's JSON at https://gex.live/snapshots/YYYY-MM-DD.json carries the one-minute series it is built from — minutes and spot for the range and the scaler, hold_lo / hold_hi for the band, flip for the migration, and ngv_meas / ngv_conv for the two books' net gamma value at spot in $M. The dates are the ones listed at /sessions; index 30 of the minute series is 10:00 ET. The headline statistic, in full:

pythonreproduce
import json, numpy as np, pandas as pd

d = json.load(open("2026-07-17.json"))        # https://gex.live/snapshots/YYYY-MM-DD.json
s = np.array(d["spot"], float)                # 390 one-minute prints, 09:30..15:59 ET
i = d["minutes"].index("10:00")               # 30 on a full session; skip half-days
r = np.diff(np.log(s), prepend=np.nan)
rv30 = pd.Series(r).rolling(30).std().values * s      # trailing move, points per minute
sig = rv30[i] * np.sqrt(len(s) - 1 - i)               # projected over the minutes left
fwd = s[i:]
range_scaled = (fwd.max() - fwd.min()) / sig          # the statistic
# opex = third Friday of the month; if it is not in /sessions, take the last
# session on or before it. Mean of range_scaled: 1.013 on 53 opex days,
# 1.189 on the other 1,024. Same recipe with abs(s[-1] - s[i]) gives the move rows.

One number in this post is not in the published files: the contract count behind the overnight-shrink table comes from the build's own book, and the session JSON publishes the resulting series rather than the chain. Rebuilding that book from scratch does need licensed data — the SPXW trade and NBBO tick feed from ThetaData, which is a paid subscription. Reproducible does not mean free in that one row. It does for the range ÷ σ result, the band, the flip and both net-gamma series, which is everything else on this page.

Part of gex.live research. Measured on the free session archive; every session is free to replay.