Where SPXW 0DTE prints actually land in the quote
13,147,178 prints, 36,766,451 contracts, 38 sampled sessions, 2022-2026
Muravyev and Pearson report that option executions cluster well inside the NBBO, so the effective spread a trader really pays is far below the quoted one: the average effective spread is one quarter smaller than conventional estimates, and for traders who time their executions it is less than 40% of the conventional measure. If that held on SPXW 0DTE, a long list of results on this site would deserve a second look, because the assumed transaction cost is the single parameter that has killed almost every one of them. It does not hold here. On 13,147,178 prints, 92.56% execute exactly on the bid or exactly on the ask, and the effective-to-quoted half-spread ratio is 0.9619 per print and 1.0697 per contract — volume-weighted, SPXW 0DTE prints pay slightly more than the full quoted half-spread, not less.
This is not a refutation of their paper. It is a failure to transfer, and the reason is mechanical rather than behavioural: on 71.91% of prints the quote is one tick wide, and a one-tick quote has no price inside it.
Why this was worth running
The companion measurement on this site prices a round trip in the ATM 0DTE SPX straddle at $34.72 / $35.14 / $36.30 per 1-lot at horizons of 15 / 30 / 60 minutes, charged as the full two-sided quoted spread plus $5.00 of fees (what a 0DTE straddle round trip costs). That cost line, or one like it, appears in every strategy post here, and it is usually the difference between a positive pre-cost number and a negative post-cost one. The honest reason to run this study was the hope that the line was too harsh — that real prints land inside the quote and the charged spread is a caricature. The result runs the other way, which is why it is worth publishing.
The measurement
For every single-leg 0DTE SPXW print in regular hours, with the NBBO prevailing at that print — carried with the print by the data source, not joined approximately from a separate quote file — two numbers:
loc = (price - bid) / (ask - bid) # where the print sits in the quote eff = |price - mid| / (0.5 * (ask - bid)) # effective half-spread / quoted half-spread
eff = 1 means the print paid the full quoted half-spread. eff = 0
means it executed at the mid. loc = 0 is the bid, loc = 1 is the ask,
loc = 0.5 is the mid. Both are reported per print and per contract
(volume-weighted). Nothing is tuned: every bucket edge below was fixed before the run.
Where the prints land
| location in the quote | share of prints | share of contracts |
|---|---|---|
| at or below the bid | 47.19% | 46.51% |
| … exactly at the bid | 46.68% | |
| … strictly through the bid | 0.52% | 1.15% |
| at or above the ask | 46.41% | 48.66% |
| … exactly at the ask | 45.88% | |
| … strictly through the ask | 0.53% | 1.24% |
| at the mid | 4.71% | 3.43% |
| strictly inside the quote | 6.40% | 4.83% |
"At the mid" is |loc − 0.5| ≤ 0.02. The bid and ask rows overlap the strictly-through rows by construction: at-or-below = exactly-at plus strictly-through.
The headline follows directly. Per print the mean of eff is
0.9619; per contract it is 1.0697. Its deciles per print run
0.9991 / 0.9995 / 0.9999 / 1.0001 / 1.0003 / 1.0004 / 1.0006 / 1.0007 / 1.0009 — every decile
sits on 1. (Those are read off a histogram with 0.001-wide bins, so the atom at exactly 1.000
reports as 1.0003; the true value is 1.000.) Only 1.05% of prints and 2.40% of contracts have
eff > 1, i.e. traded through the quote. In dollars: the mean quoted half-spread
is $0.05721 per print against a mean effective half-spread of
$0.05240, a ratio of 0.916; contract-weighted it is $0.05506 quoted against
$0.06373 effective, a ratio of 1.1574.
The interior of the spread is not a distribution — it is one point. Restricted to the
841,360 prints that land strictly inside (0 < loc < 1), the deciles of loc
are 0.3338 / 0.4993 / 0.4997 / 0.5001 / 0.5003 / 0.5005 / 0.5007 / 0.5009 / 0.6662. Seven of
the nine sit between 0.4993 and 0.5009. When an SPXW 0DTE print does land inside the quote,
it lands at the mid and nowhere else.
The mechanism: the quote is one tick wide
This is the part worth reading. Price improvement on SPXW 0DTE is not rare because traders are impatient. It is rare because there is no room.
| quoted spread, ticks | prints | % of prints | contracts | % of contracts |
|---|---|---|---|---|
| 1 | 9,454,427 | 71.91% | 27,561,525 | 74.96% |
| 2 | 2,891,608 | 21.99% | 7,146,389 | 19.44% |
| 3 | 458,565 | 3.49% | 1,135,148 | 3.09% |
| 4 | 151,012 | 1.15% | 360,347 | 0.98% |
| 5 | 71,147 | 0.54% | 197,011 | 0.54% |
| 6-10 | 90,514 | 0.69% | 265,441 | 0.72% |
| >10 | 29,905 | 0.23% | 100,590 | 0.27% |
A tick is $0.05 below a $3 mid and $0.10 above it.
A one-tick quote has no price inside it. Improvement is not merely unlikely on 71.91% of prints and 74.96% of contracts — it is arithmetically impossible. So the fair test is the restriction to quotes with room in them: on the 3,692,751 prints (9,204,926 contracts) whose quote is at least two ticks wide, the at-mid share rises to 16.78% per print and 13.72% per contract, against 4.71% overall. The behaviour Muravyev and Pearson describe does exist on this tape. It simply has almost nowhere to happen.
The two cuts their mechanism predicts, both running the wrong way
A headline number failing is weak evidence: samples differ, definitions differ, and a single mean can miss for uninteresting reasons. A mechanism failing on its own predicted cuts is stronger. Their story says improvement is captured by traders with discretion over timing, which predicts a time-of-day pattern and a size pattern. Neither appears.
Time of day is flat. Seven hourly buckets, no open effect, no close effect:
| hour (ET) | prints | contracts | eff, per print | at the mid |
|---|---|---|---|---|
| 09:30-09:59 | 1,436,475 | 3,795,242 | 0.9638 | 4.72% |
| 10 | 2,568,758 | 7,024,950 | 0.9654 | 4.51% |
| 11 | 1,829,259 | 5,057,214 | 0.9587 | 4.91% |
| 12 | 1,583,682 | 4,524,298 | 0.9596 | 4.82% |
| 13 | 1,504,610 | 4,397,799 | 0.9583 | 5.13% |
| 14 | 1,931,912 | 5,631,444 | 0.9628 | 4.76% |
| 15 | 2,292,482 | 6,335,504 | 0.9626 | 4.40% |
The whole range is 0.9583 to 0.9654 — seven hundredths of one percent of the half-spread between the best and worst hour of the day.
Size runs backwards. If large traders were the patient ones capturing the
mid, eff would fall with size. It rises, steeply, and it rises the same way at
the money:
| trade size, contracts | prints | contracts | eff, all strikes | eff, ATM only |
|---|---|---|---|---|
| 1 | 8,481,520 | 8,481,520 | 0.9466 | 0.9425 |
| 2-5 | 3,392,259 | 10,101,099 | 0.9740 | 0.9753 |
| 6-20 | 1,113,558 | 10,945,679 | 1.0136 | 1.0167 |
| 21-100 | 153,368 | 5,912,413 | 1.1383 | 1.1855 |
| 101-500 | 6,239 | 1,116,048 | 1.5804 | 2.1199 |
| >500 | 234 | 209,692 | 4.4851 | 4.1192 |
ATM is |K − F|/F < 0.25%, F from per-minute put-call parity on the tape's own quotes. The ATM print counts run 4,314,432 / 1,928,358 / 570,215 / 45,152 / 1,316 / 33 down the same buckets.
The 1-lot is the only bucket that beats the quoted half-spread, at 0.9466, and it beats it by five percent. Everything above 20 contracts pays more than the full half-spread, and above 500 contracts a print pays 4.49 times it. Large SPXW 0DTE trades print through the quote; they do not capture improvement. That is the opposite of the size gradient the improvement story requires, and it holds on the ATM subsample where the liquidity is.
Stability
Nothing here is a property of one year or one session.
| year | prints | contracts | eff, per print | at the mid |
|---|---|---|---|---|
| 2022 | 954,354 | 3,216,298 | 0.9214 | 6.27% |
| 2023 | 1,536,438 | 4,779,814 | 0.9580 | 5.38% |
| 2024 | 2,373,360 | 7,366,030 | 0.9597 | 5.11% |
| 2025 | 4,013,507 | 10,657,708 | 0.9640 | 4.63% |
| 2026 | 4,269,519 | 10,746,601 | 0.9717 | 3.98% |
The ratio drifts, and it drifts up toward 1 as quotes tighten and the one-tick share grows: the at-mid share falls from 6.27% in 2022 to 3.98% in 2026. Across the 38 individual sessions the per-print ratio runs from 0.877 (2022-04-01) to 1.0109 (2025-02-03) — a band that never approaches the 0.75, let alone the 0.40, that the paper's effect sizes would imply.
Translating it back into the round trip
The companion study charges the full two-sided quoted spread. Replace that with the
measured one. At the ATM cell — 6,859,506 prints, 17,346,952 contracts — the mean quoted
half-spread is $0.06183 per contract against a mean effective half-spread of
$0.06347, so the contract-weighted ratio is r = 1.0265. The
round-trip cost is $5.00 of fees plus a spread component S; the improvement-adjusted version
is $5.00 + r × S.
| horizon | full-spread cost | spread component S | r | adjusted cost | change |
|---|---|---|---|---|---|
| 15 minutes | $34.72 | $29.72 | 1.0265 | $35.51 | −$0.79 |
| 30 minutes | $35.14 | $30.14 | 1.0265 | $35.94 | −$0.80 |
| 60 minutes | $36.30 | $31.30 | 1.0265 | $37.13 | −$0.83 |
"Change" is negative because the adjustment makes the trade more expensive: 79 to 83 cents worse per 1-lot. As a share of the mean absolute mid-to-mid P&L the cost goes from 21.8% to 22.3%, 13.1% to 13.4%, and 7.8% to 8.0%.
An independent cross-check that the two studies are measuring the same market: a straddle round trip crosses four half-spreads (call and put, in and out), so at the measured ATM quote that is 4 × $0.06183 × 100 = $24.73 per 1-lot, against the companion study's implied spread component of $29.72 / $30.14 / $31.30. Same order, the companion slightly larger, which is what a slightly wider ATM definition and a different sample window should produce.
One assumption would have been needed for any relief, and it is worth stating even though
the sign makes it moot. eff measures where the average print lands. A
backtest fill is not an average print: the measured population contains patient limit orders
resting inside the spread and dealer-to-dealer prints, and a taker who must trade at a
specific moment — which is what every signal backtest on this site requires — has no claim on
their improvement. The adjusted column is therefore a lower bound on cost and an upper bound
on relief. Here the adjustment is negative to begin with, so the caveat only makes the
conclusion firmer: the cost line in the companion study was slightly generous, not too
harsh.
Sampling and exclusions
This is a print-level study over 20 million rows, so the archive is sampled rather than swept, and the rule was fixed before anything was run. For each year 2022-2026, take the first available session on or after the 1st of each of eight months — January, February, April, May, July, August, October, November. The four skipped months are the quarter-end ones, whose triple-witching sessions carry atypical 0DTE flow. The calendar is the SPXW expiration list (1,129 dates in the window), not the archive's session list, because a 0DTE study can only run on a day that is itself an expiry. A session that failed to load or yielded fewer than 1,000 usable prints would have been replaced by the next in the calendar and the replacement reported: 38 sessions, zero replacements.
Of 20,709,094 raw prints, 7,559,103 were multi-leg legs (a condition code counts as multi-leg when at least 80% of its prints share an exact timestamp with two or more distinct contracts), 2,807 carried a zero-width quote, and 6 fell outside regular hours. No crossed quotes, no non-finite quotes, no non-positive asks. 13,147,178 prints and 36,766,451 contracts retained.
Stale quotes would bias this study toward more apparent improvement, not less: if
the NBBO recorded with a print is old, a print at the true mid can look like it beat the
quote. Restricting to prints whose quote is under one second old leaves 12,945,798 prints and
35,415,585 contracts, and changes nothing — mean eff 0.9616 per print and 1.0722
per contract against 0.9619 and 1.0697 on the full set.
What it does not say
It does not refute Muravyev and Pearson. Their paper is about a broad cross-section of equity and index options over a long window; this is SPXW 0DTE only, on 38 sampled sessions, in a contract that barely existed when their data was collected. The correct reading is that their result does not transfer to this instrument, and the tick table says why: their mechanism needs a quote with room inside it, and SPXW 0DTE mostly does not have one. On their own data, on their own universe, nothing here speaks to their finding at all.
It is 38 sessions, not the full archive — the reason is cost, not convenience: each session is roughly half a million usable prints and the study reads over 20 million rows. The sample is spread across five years and every year gives the same answer, but a rule fixed on the 1st of eight months is still a rule, and a different rule would give slightly different decimals. The moneyness cut uses a forward from per-minute put-call parity on the tape's own quotes, because no independent SPX spot series exists on disk for the sampled sessions. And nothing here says anything about what a specific order would have been filled at — only about where the population of prints landed. Nothing on this page is investment advice; see the Terms.
Reproduce it
This one is honestly not free, and there is no free path to it. Measuring where a print
lands inside the quote requires the trade tape with the prevailing NBBO attached to each
print — not a quote file joined to a trade file after the fact, which introduces exactly the
staleness this study has to rule out. The tape behind this post is licensed: ThetaData
(thetadata.net), at the subscription tier
that serves /v3/option/history/trade_quote for SPXW. That endpoint returns
price, size, condition, bid,
ask, bid_size, ask_size and a
quote_timestamp per print, which is the whole input. With that subscription the
study is an afternoon's work:
import numpy as np, pandas as pd # one session of SPXW 0DTE prints from /v3/option/history/trade_quote, # columns: price, size, condition, bid, ask, quote_timestamp, trade_timestamp t = pd.read_parquet("spxw_2026-08-03.parquet") t = t[(t.ask > t.bid) & np.isfinite(t.bid) & np.isfinite(t.ask)] # drop zero-width, crossed t = t[(t.trade_timestamp >= 34200000) & (t.trade_timestamp < 57600000)] # 09:30-16:00 ET # drop multi-leg: a condition is multi-leg if >= 80% of its prints share an exact # timestamp with 2+ distinct contracts -- tag it once per session, then filter t = t[~t.condition.isin(multileg_conditions(t))] mid = 0.5 * (t.bid + t.ask) half = 0.5 * (t.ask - t.bid) loc = (t.price - t.bid) / (t.ask - t.bid) # 0 = bid, 0.5 = mid, 1 = ask eff = (t.price - mid).abs() / half # 1 = paid the full quoted half-spread print(np.average(eff), np.average(eff, weights=t["size"])) # 0.9619, 1.0697 print(((loc <= 0) | (loc >= 1)).mean()) # 0.9256 of prints ticks = np.where(mid < 3, 0.05, 0.10) print(((t.ask - t.bid) / ticks).round().eq(1).mean()) # 0.7191 one tick wide
What is free on our side is everything the cost translation is applied to. The
finished sessions are listed at /sessions, and each one's per-minute
series is in its JSON at https://gex.live/snapshots/YYYY-MM-DD.json — including
straddle, the ATM 0DTE straddle mid in index points, which is the premium the
$34.72 / $35.51 above is charged against. Those files carry mids, not quotes, so they can
reproduce the premium and the P&L of the companion study but not the spread: this post's
entire subject is the one thing a mid-only file cannot see.
Part of gex.live research. Measured on the free session archive; every session is free to replay.