Signing the SPX 0DTE tape against exchange truth

One labelled session, 13,648 matched prints — what the quote rule gets right, what it inverts, and why the dealer ends flat anyway

Published 2026-09-11 · Sample SPXW 0DTE, 2025-03-28, Cboe's free Trade-by-Trade sample (3% of trades, carries execution capacity), 13,648 prints matched 1:1 to our own tape, 8,671 of them signable · Truth Cboe capacity and open/close labels, plus two unsampled intraday Open-Close files for the same session · Status measurement, not a signal

Key finding. Every tape-built dealer book rests on a quote rule that decides who bought. Scored against Cboe's participant-tagged trade data, the standard rule is right on 52.3% of volume — a coin flip. The mechanism is exact, the correction is one clause and worth 22 points, and the deeper finding survives both: the market maker's net position change is a rounding error on its own turnover.

Every dealer-gamma product in existence — this one included — is built on an inference the tape does not contain. OPRA prints a price, a size and a timestamp. It does not print who bought. So a rule is applied: compare the print to the prevailing quote, call it a customer buy if it went off at the ask and a customer sell if it went off at the bid, and mirror the result to get the dealer's position. Every level any of these services publishes is downstream of that one step.

The step is testable. Cboe publishes a free trade-by-trade sample that carries the execution capacity of each side — market maker, customer, professional customer, firm, broker-dealer — plus whether the trade opened or closed a position, and the NBBO at the time of the trade. One session of it, 2025-03-28, overlaps our archive. This is what happens when the rule is scored against it.

The rule is right on 52.3% of volume

Our production signer is a mid-band Lee-Ready variant: at or above the ask, customer buy; at or below the bid, customer sell; inside a 20% band around the mid, unsigned; otherwise the side of the mid decides. Joined to Cboe's labelled prints on (second, strike, right, price, size), keeping keys unique on both sides, it gives 13,648 clean one-to-one matches, of which 8,671 carry a non-zero sign.

signing ruleper printvolume-weighted
mid-band quote rule (production)52.5%52.3%
+ the correction below76.7%74.5%
gradient-boosted ceiling, 15 features, out-of-fold79.3%79.8%

52.3% is a coin flip with a limp. An earlier, narrower pass over simple single-leg 0DTE trades in the same file put it at 47.6% on 14,679 trades and 53,990 contracts — below chance. That is not noise, and the reason it is not noise is the most useful thing on this page.

The mechanism is exact, not statistical

Accuracy equals the market maker's passive share, to the decimal. The quote rule does not identify who bought; it identifies who crossed the spread. When the dealer is the resting side, aggressor and customer are the same party and the rule is right. When the dealer takes liquidity — which on 0DTE SPX it does on 62.8% of the prints where the role is stated — the customer was resting, and the rule returns exactly the wrong side.

Splitting Cboe's own trade-type labels makes this arithmetic rather than inference. On prints that went off at the bid or the ask:

Cboe trade typewhat it meansquote rule correctshare of volume
Simple Removecustomer crossed the spread100.0%
Simple Addcustomer was resting; dealer crossed0.0%27%

Not "poor on the second group" — zero. Twenty-seven percent of volume was signed exactly backwards, every print, by construction.

The obvious fix is to flip whenever the customer looks passive, and the obvious fix is wrong. On prints that executed inside the spread the customer is passive 99.6% of the time, and yet leaving those alone is the correct action 66.9% of the time. Inside the spread the above-or-below-mid test is no longer measuring who crossed; it is measuring where a price-improved fill landed, and that tracks the customer's own direction. Flip that group and the score gets worse. This is the trap the first version of this analysis fell into: an earlier rule of ours that flipped the inside-the-spread group scored 64.5% volume-weighted, ten points below the rule that leaves it alone.

The correction, and what it is worth

An exhaustive search over 318 interpretable variants, with a gradient-boosted model run alongside to bound what is achievable, lands on one clause:

pythonreproduce
# flip the sign iff all three hold
at_touch  = (price <= bid) or (price >= ask)      # the print took a posted side
crossed   = size / resting_size_at_that_side >= 0.5   # it consumed the posted size
flip      = at_touch and crossed and condition != 95

The size-to-resting ratio is the whole idea: a print that eats half or more of what was posted is unlikely to be the passive side of its own execution. That ratio carries about 40% of the model's total gain; nothing else exceeds 8%. The threshold is flat anywhere between 0.25 and 0.5, which is what a real effect looks like rather than a fitted one.

The gain is +22.3 percentage points volume-weighted, bootstrap 95% confidence interval [+17.9, +27.3], fold standard deviation 1.9 across a grouped five-fold cross-validation by intraday block. Quote-to-trade lag, absolute trade size and the extended condition fields carry nothing.

Cboe's own researchers get the same answer

This is not a defect of one implementation. Amaya, Garcia-Ares, Pearson and Vasquez (2025), writing from a Cboe data grant covering four exchanges from January 2020 to June 2023, report that the version of the quote rule in common use "misclassifies 42.4% of trades and 42.6% of trading volume" on the trades they could label. Different sample, different years, same order of magnitude. The rule is not broken by our use of it; it answers a different question from the one everyone asks it.

And then the book still does not follow

A perfect per-print sign would not, by itself, produce a dealer book. The same session can be scored one level up, against Cboe's unsampled intraday Open-Close files — full exchange files, cumulative from the open, which is exactly the object our published volume block is. Our strike window covers 99.6% of the session's true 0DTE contracts, and our contract count is 0.976 of Cboe's on matched cells, with the gap fully accounted for by global-trading-hours volume (2.1%) and prints after 15:55 (1.1%). The volume layer is sound. Only the attribution fails, and here is what it fails against — the whole 0DTE book at 13:16, 352 cells, 1,838,501 contracts:

capacitynet contractsas % of contracts traded
market maker+1,764+0.10%
customer+41,167+2.24%
professional customer−51,080−2.78%
firm+6,805+0.37%
broker-dealer+1,344+0.07%

The dealer's inventory change is 0.09% of its own gross turnover. It intermediated 1.8 million contracts and ended the day flat. The day's real imbalance was customer against professional customer — a capacity a customer-versus-dealer model does not have, and whose flow such a model necessarily hands to the dealer. Our book reported −43,275 contracts for that same moment against a true +1,764, and −30,062 at 12:30 against a true −2,817.

Nor does the structure hide inside the strikes. The sum of the absolute per-strike market-maker net is 13,580 against a 1,376 aggregate — 9.9 times larger, which looks like real per-strike positioning until it is tested. A permutation that shuffles trade sides while preserving sizes and strike allocation gives a null of 13,832 ± 874: z = −0.3, p = 0.61. The apparent structure is sampling noise. That test is underpowered at a 3% sample — it shows the structure is invisible here, not that it is absent — but it is the only test the free data supports, and it does not survive it.

Three independent confirmations of the flat dealer

The near-flat intermediary is not a property of this one session.

Does the rule's input at least look the same across the archive?

The correction above is measured on one day, because one labelled day is what exists for free. Cross-day stability of the correction is untested and is the honest main risk. What can be checked for free is whether the microstructure the rule keys on is present and steady across the archive — sampling eight days per year of the near-term tape, single-leg universe:

year20222023202420252026
prints at the bid or the ask84.5%88.8%86.1%87.1%79.2%
volume the correction would flip59.3%57.6%57.1%59.5%54.1%
prints that consumed the posted size exactly41.2%41.0%40.3%43.5%35.7%

Across all sampled days the flipped share of volume is 57.1% on average, standard deviation 6.6, range 30.6 to 69.5. Stable through 2022–2026 with mild 2026 drift. A 2019 sample is a different regime entirely — only 38.9% of prints at the bid or ask — and the rule should not be trusted there. This shows the inputs exist and are steady. It does not show the correction is right on any day but the one it was measured on.

What this does not say

It does not say the levels are wrong. A level is judged by whether price respects it, and that judgement is made on price — which is why every measurement this site publishes about levels (hold rates, the touch surface, the pre-registered dealer-state test) is scored against the forward path and never against the book's own sign. It does say that the per-strike sign and the session-level direction of any tape-signed 0DTE book, ours included, should not be read as reliable, and that the correction above is not yet in our pipeline: applying it changes the sign of the measured book across the entire archive, which is a decision and not a patch.

It is one session, a 3% sample, SPXW 0DTE, customer and professional-customer legs only. The 3% sampling destroys trade reconstruction — only 1,685 of 111,333 execution ids keep a partner — so multi-leg package signing has never been validated against truth and cannot be on this data. Nothing on this page is investment advice; see the Terms.

A dead end worth publishing

Open-interest change cannot validate signing direction, and it is an attractive idea, so it is worth killing in public. Open interest rises whenever openings exceed closings regardless of direction: a customer buying 100 to open and a customer selling 100 to open both add 100. The sign of the daily open-interest change encodes open-versus-close, not buy-versus-sell. Measured anyway over 60 sessions and 124,249 strike-expiry rows, the old rule agrees with it 50.7% of the time and the corrected rule 47.2% — both exactly as meaningless as the argument predicts. Direction requires knowing who rested, and OPRA does not carry that.

Reproduce it

The truth file is free and needs no account:

pythonreproduce
curl -L https://datashop.cboe.com/download/sample/289 -o cboe_tbt_2025-03-28.zip
# per print: capacity, side, open_close, trade_type, complex_exec_id,
# and the NBBO at the time of the trade. 3% of that session's trades.

The other half — the raw SPXW tick tape with prevailing NBBO that our book is signed from — is licensed. Redoing this needs a ThetaData subscription (thetadata.net) at the tier that carries SPXW trades and quotes; there is no free substitute, and we would rather say so than pretend otherwise. The join is on (second, strike, right, price, size), keeping keys unique on both sides, which is what turns 764,886 of our prints and Cboe's sample into 13,648 unambiguous pairs.

What is free on our side is everything downstream: each finished session's published book, minute by minute, is at https://firmtape.com/snapshots/YYYY-MM-DD.json, and the dates are listed at /sessions. The OCC floor is computed from a public URL and bounds, every evening and for free, how much of any given session's tape could not have had a customer on one side and a dealer on the other.

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