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
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 rule | per print | volume-weighted |
|---|---|---|
| mid-band quote rule (production) | 52.5% | 52.3% |
| + the correction below | 76.7% | 74.5% |
| gradient-boosted ceiling, 15 features, out-of-fold | 79.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 type | what it means | quote rule correct | share of volume |
|---|---|---|---|
| Simple Remove | customer crossed the spread | 100.0% | — |
| Simple Add | customer was resting; dealer crossed | 0.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:
# 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:
| capacity | net contracts | as % 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.
- Cboe's own published example: on 2023-08-15 the SPX 4440 put traded more than 100,000 contracts, and market makers ended net short about 3,000 — 52,000 bought against 55,000 sold, roughly 3% of gross volume, on a single strike on a day chosen for illustration because the flow was notable.
- Hu, Kirilova, Muravyev and Ryu, working on Cboe Open-Close data for SPX from 1996 to 2018, report mean market-maker trading volume of 415,840 against a mean delta-adjusted change in market-maker open interest of 3,466 — about one part in 120.
- Amaya et al.'s capacity matrix, rebuilt from 442 million trade records, puts customer-against-customer at 1.659% of 0DTE volume and market-maker-against-market-maker at 1.477% — trades that cannot exist at all inside a customer-versus-dealer dichotomy, and which a tape-signed book therefore records as full dealer position changes. Our own free daily floor from OCC data puts a lower bound on the same quantity, every evening, at a median of 5.3% of SPXW trades.
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:
| year | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|
| prints at the bid or the ask | 84.5% | 88.8% | 86.1% | 87.1% | 79.2% |
| volume the correction would flip | 59.3% | 57.6% | 57.1% | 59.5% | 54.1% |
| prints that consumed the posted size exactly | 41.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:
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.