Does the dealer-gamma state rescue short 0DTE premium?

Five structures, three entry times, every threshold — 34 sessions, honest fills

Published 2026-08-24 · Sample SPX, 2026-05-01 to 2026-07-31, 34 sessions, entries at 10:00, 11:30 and 13:00 ET held to the 16:00 settlement · Data licensed ThetaData SPXW tick tape and 5-minute full-chain quotes · Status measurement, not a signal

The most common thing anyone does with a dealer-gamma dashboard is sell 0DTE premium with it. The claim is old and specific: when the measured dealer book is long gamma, hedging flow leans against the move, the session pins, and the option that was sold expires worthless more often than its price implies. So the dashboard is supposed to select the days — not to find an edge in options, but to tell you which of the days on which you would sell anyway are the good ones.

Stated precisely, that is the rule tested here. On each session the measured dealer book's net gamma is scored against a pool of the prior ≤20 sessions, giving a state z-score. Premium is sold only when z is at or above a threshold, at a fixed entry time, held to expiry with no stops and no management. The question is not whether short 0DTE premium makes money. It is whether conditioning on the gamma state makes it better than not conditioning.

The verdict

No. On 34 sessions — 28 of which carry the walk-forward forecast the second family of rules needs — conditioning premium selling on the dealer-gamma state does not rescue it, does not beat selling unconditionally on the same days, and is not distinguishable from a random selection of the same size. That holds across five structures, three entry times and every threshold tested.

The distinction that matters, and the one this sample forces: the comparative result is what 34 sessions can settle, and the absolute level of short 0DTE premium is not. Selling the straddle unconditionally on every one of those sessions returned -$284 per session, with a 95% bootstrap confidence interval of [-$991, +$342]. The sample cannot even sign it. Nothing below should be read as "short 0DTE premium loses money"; every number below is a statement about selection, measured against the same days traded without a filter.

What was tested

Five structures, each entered at 10:00, 11:30 and 13:00 ET. Fills are honest: sell the bid on every short leg, pay the ask on every long leg, at the 5-minute chain snapshot stamped exactly at the entry time, fees $1.25 per contract per leg entered. Mid fills are computed alongside and never used for a conclusion. Settlement is the official SPX closing index value, which is what PM-settled SPXW cash-settles to; the reconstructed parity spot is used only to pick the strike, and is worth 0.53 pt mean absolute error against the official close (max 1.60), well inside the 5-point strike grid.

structuremid credit $ @11:30honest credit $spread cost $spread % of miduncond. mean $ / cellwin%
straddle (ATM)27522736170.6%-28458%
strangle_025 (shorts 0.25% OTM)13781366120.9%-24169%
strangle_050 (shorts 0.50% OTM)68467591.3%-14081%
condor_025_25 (0.25% shorts, 25-pt wings)819798212.6%-14654%
condor_050_25 (0.50% shorts, 25-pt wings)381365164.1%-13075%

Credits are the 11:30 entry, 34 sessions. "Uncond. mean $ / cell" pools all three entry times, 102 session × entry cells, honest fills with fees.

Three rule families were run over that grid. A is the gamma state alone — sell if z ≥ q, at q = -1.0, -0.5, 0.0 and +0.5, with no reference to the option price at all. B is disagreement: sell when the honest credit exceeds what the structure is expected to pay out under a gamma-tilted, walk-forward-calibrated forecast of the to-close move, at thresholds of 0.0, 0.5, 1.0, 2.0 and 3.0 index points. C is the same as B with the gamma tilt removed — trailing realised vol only — which is the control that isolates what the gamma term contributes. No threshold was tuned; the whole surface is printed.

One microstructure note, because it is the usual escape hatch. On the ATM 0DTE straddle the bid/ask is 0.6–0.7% of the mid credit — $18 on $2,739 — which is about 6% of the mean loss. The spread is emphatically not the whole story on this structure. It becomes material only on the defined-risk wings: the 0.50% iron condor pays 4.6% of its premium in spread ($18 on $370), and there the spread is roughly 14% of the loss.

The whole threshold surface, on the straddle

These 84 cells are the 28 sessions that carry a forecast, so all rules are comparable to each other and to the unconditional row at the top. "Perm pctile" is where the rule's mean sits in the permutation null described in the next section; below about 50 means the selection did worse than picking the same number of cells at random.

rulethrcellssessionsmean $twin%perm pctilefirst 60%last 40%
UNCONDITIONAL (same cells)8428-364-1.3558%n/a-63 (51)-830 (33)
A: sell if z ≥ -1.0-1.08128-376-1.3458%54-63 (51)-908 (30)
A: sell if z ≥ -0.5-0.56023-130-0.4663%85-110 (50)-231 (10)
A: sell if z ≥ +0.00.0169-8-0.0181%72-8 (16)— (0)
A: sell if z ≥ +0.50.586+825+7.31100%95+825 (8)— (0)
B: sell if edge_gam ≥ 0.0pt0.04022-482-1.1162%36-386 (31)-813 (9)
B: sell if edge_gam ≥ 0.5pt0.53821-398-0.8963%50-256 (30)-931 (8)
B: sell if edge_gam ≥ 1.0pt1.03721-465-1.0362%41-336 (29)-931 (8)
B: sell if edge_gam ≥ 2.0pt2.03520-610-1.3160%26-387 (28)-1501 (7)
B: sell if edge_gam ≥ 3.0pt3.03117-540-1.1758%35-517 (26)-660 (5)
C: sell if edge_rv ≥ 0.0pt0.03822-423-0.9563%43-302 (29)-813 (9)
C: sell if edge_rv ≥ 0.5pt0.53722-491-1.0962%36-387 (28)-813 (9)
C: sell if edge_rv ≥ 1.0pt1.03622-546-1.1961%35-457 (27)-813 (9)
C: sell if edge_rv ≥ 2.0pt2.03420-532-1.0965%37-431 (25)-813 (9)
C: sell if edge_rv ≥ 3.0pt3.02816-610-1.0764%28-432 (21)-1146 (7)

Read the B block first, because it is the cleanest. Every disagreement threshold loses more than selling every day: -$482 at a threshold of zero against -$364 unconditional, and monotonically worse as the threshold tightens — -$610 at 2 points. Removing the gamma tilt (the C block) gives the same answer, which is the useful part of the control: the gamma term is not what is failing. The whole forecast-versus-price comparison is.

The A block, the pure gamma state, does not lose more — it loses less as the threshold rises, right up to a cell that looks like an edge. That cell is the whole story of this post's failure mode, so it gets its own section.

The one cell that looks like an edge, and why it is not

sell if z ≥ +0.5 on the straddle: 8 cells over 6 sessions, mean +$825, t = +7.31, 100% win, permutation percentile 95. On its own that is the kind of number a dashboard gets marketed with. All 6 of those sessions are in May, and none is in the last 40% of the sample. High-gamma-z days simply did not occur after May here, and May was the quiet month: mean realised move 19.6 pt against a 22.9 pt straddle, where June ran 48.8 against 33.9. The rule is a calendar, not a state.

The way to tell those apart is to split z at its median inside each period, so the comparison never crosses the regime break, and to give each session one number rather than three:

periodhigh zlow z
first 60% (20 sessions)+$141/session+$380/session
last 40% (13 sessions)-$1,944/session-$875/session

High gamma is the worse half in both periods. Whatever the +$825 cell was, it was the month.

The permutation control

A conditional rule that loses less than unconditional has done two things at once: picked particular days, and picked fewer days. Only the first is a signal. The second changes the mean by sampling noise alone, and on 34 sessions that effect is large — which is exactly the gap a small-sample selection result hides in. The right null is therefore not "zero" and not the unconditional mean. It is: a random selection of the same number of sessions.

So the condition is shuffled at session level — a day's three entry times move together, because they are near-duplicates of each other — 1000 times against the unchanged outcomes, and the reported percentile is where the real mean sits in that null distribution. Above 50 the selection beat a coin flip of the same size; below 50 it did worse than random. Re-running the headline rules day-clustered, one number per session, against that null:

rule (day-clustered)sessionsmean $/sessiontperm pctile
unconditional28-364-0.90n/a
A: z ≥ 09-575-0.5534
B: edge_gam ≥ 022-418-0.7546
B: edge_gam ≥ 2pt20-725-1.168
C: edge_rv ≥ 022-503-0.8430

Every headline rule sits below the middle of its own null. The gamma-state rule at z ≥ 0, which looked like it halved the loss in the cell-level table, is at the 34th percentile of a random selection of nine sessions and loses more per session than selling every day. The selection is not adding information; it is subtracting sample.

Why it fails, diagnosed rather than guessed

The B and C families were supposed to trade the disagreement between a forecast of the to-close move and what the market charges for it. That fails for a reason the data states directly. Regress the realised to-close move on the ATM straddle mid and on the forecast together, both standardised:

termbetaset
const+32.302.67+12.09
ATM mid (SD)+17.755.02+3.54
our forecast (SD)+0.135.02+0.03

n = 84. R² with the market price alone 0.353; adding the forecast, 0.353 — a change of +0.000.

The forecast carries zero incremental information over the straddle price itself. So the disagreement between the two is not the market's mispricing; it is the forecast's error. Selecting on it is noise at best, and empirically it is slightly anti-selective — which is what the monotone worsening in the B and C blocks is.

And the underlying relation is not absent, only far too small to survive the payoff's variance. Higher dealer gamma really does show up with the right sign in the P&L: corr(z, short-straddle P&L) = +0.082 pooled, worth +$192 per standard deviation of z, t = +0.81; at the 13:00 entry the correlation is +0.233, t = +1.33. Nowhere near significance at this n, and nowhere near large enough to matter next to a straddle whose loss distribution has a -$991 lower confidence bound.

What it does not say

It does not say short 0DTE premium is a losing trade. The unconditional straddle is -$284 per session with a 95% bootstrap interval of [-$991, +$342]; the sample cannot sign that number, and neither can this post. The absolute level is unsettled here. Only the comparison is settled.

A null on 34 sessions is a null on 34 sessions. It rules out a large, robust selection effect over this window and these specifications. It does not rule out a small one, and it cannot rule out one that lives in a regime this window does not contain — the sample spans a vol break, a quiet May, a June vol event and a mid-vol July, and almost every difference between the halves of this document is that break rather than anything about gamma.

It does not test the many things people also do with a gamma dashboard: intraday exits, stops, delta management, ratios, longer expiries, or the level-based reading the hold-rate study covers. Entries are 10:00, 11:30 and 13:00 only, held to expiry, unmanaged. The three entries of one session are near-duplicates, so every cell-level t above over-counts; the day-clustered table is the honest one, and it is weaker, not stronger.

Fills are 1 lot at the touch. The ATM legs quote a median of 11 contracts on the bid (5th percentile 2), and 27 of 102 entry cells had at least one leg with fewer than 5 on the bid. Size beyond roughly 10 lots would have to work the spread, and that is not modelled. Nothing on this page is investment advice; see the Terms.

Reproduce it

The gamma state is free; the payoff is not. Every finished session's JSON at https://gex.live/snapshots/YYYY-MM-DD.json carries the state this rule reads — gpct, the net-gamma percentile against the trailing pool, as a per-minute series aligned with minutes (index 30 is 10:00 ET), and straddle, the ATM straddle mid in index points, on the same clock. now.sessions_in_pool reports how many prior sessions the pool held. The dates are the ones listed at /sessions. That is enough to rank sessions by dealer-gamma state and to see what the market was charging at each entry minute.

It is not enough to settle a P&L. Reproducing the payoff needs licensed data: a ThetaData subscription covering the SPXW trade and NBBO tick feed, from which the 5-minute full-chain quote snapshots and the honest fills are built, plus the index endpoint for the official close. Reproducible does not mean free.

pythonreproduce
# FREE -- the per-session gamma state and what the market charged
import json, urllib.request
d = json.load(urllib.request.urlopen("https://gex.live/snapshots/2026-05-01.json"))
i = 30                                # index 30 = 10:00 ET (minutes start 09:30)
g = d["gpct"][i]                      # net-gamma percentile vs the trailing pool
s = d["straddle"][i]                  # ATM straddle mid, index points
n = d["now"]["sessions_in_pool"]      # how many prior sessions that pool held
# The rule's z is this same state as a z-score against a pool of the prior <= 20
# sessions; gpct is its percentile form. Rank the sessions, cut at a threshold.

# LICENSED -- the payoff. ThetaData (https://thetadata.net):
#   SPXW option trade + NBBO tick feed  -> 5-minute full-chain quote snapshots
#   /v3/index/history/eod               -> official SPX close = PM settlement
# entry  sell the bid on every short leg, pay the ask on every long leg, at the
#        snapshot stamped exactly at 10:00 / 11:30 / 13:00 ET
# fees   $1.25 per contract per leg entered
# exit   cash settlement against the official close; no stops, no management
# strike picked off the parity spot (0.53 pt mean abs error vs the close), never
#        used to settle

# THE NULL -- what makes a conditional mean readable at this n
# shuffle the condition across sessions (a day's three entries move together),
# 1000 times, against the unchanged outcomes; report the percentile of the real
# mean in that distribution. Below 50 = worse than picking that many days at random.

The per-session dealer books these states come from, minute by minute, are in the session archive, and the pre-registered touch-probability test is the same question asked of price rather than of premium — with the same answer for the gamma regime.

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