Market making has a simple pitch: quote both sides, capture the spread, repeat. It is the one strategy whose edge is supposed to come from arithmetic rather than prediction.
So we did the arithmetic on our own systems. Six of them, every closed round trip, 7,919 order rows. The strategy does earn — the fleet came out at +4.8 basis points of turnover. But almost nothing about *where* the money went matched the pitch.
The number that frames everything
On the venue we measured, the spread of the ETH/USDT order book was 0.04 basis points. Maker fee: 10 bp per side, 20 bp for a round trip.
| pair | book spread | maker fee | needed per round trip | book spread is smaller by |
|---|---|---|---|---|
| ETH/USDT | 0.04 bp | 10 bp | 20 bp | 500× |
| XRP/USDT | 0.74 bp | 10 bp | 20 bp | 27× |
| LINK/USDT | 1.78 bp | 10 bp | 20 bp | 11× |
| OP/USDT | 7.38 bp | 10 bp | 20 bp | 2.7× |
Quoting at the touch on a retail fee schedule is a guaranteed loss on every round trip. Professional market makers do not live on these terms — they live on VIP tiers with rebates, where the fee is near zero or negative.
Our own engine already refuses to quote inside that limit, which means it forces the quote to stand at least maker + 0.05% from mid. On ETH that is 15 bp against a book best of 0.02 bp — 750 times further out.
A quote standing 750× further from mid than the best bid is not providing liquidity at the touch. It fills only when price travels all the way to it — which is to say, only when the market moves against you.
The measured fill rates say exactly that: 3.5–6.6 % on ETH and LINK, against 29–32 % on the more volatile OP.
What we measured
An instrument (audit:mm) that reads the order ledger only — no exchange call needed. Six systems, all of them on a demo venue, $3,441 of closed round-trip turnover.
The useful part is not the total. It is that a closed round trip decomposes exactly, by algebra rather than by model. A limit bid sits at mid × (1 − s) and a limit ask at mid × (1 + s), so the mid at the moment of each fill can be reconstructed from the fill price itself:
realized = q × (sell − avgCost)
= q × (sell − midSell) + q × (midBuy − avgCost) ← SPREAD: what we quoted
+ q × (midSell − midBuy) ← DRIFT: where the market went while we heldThe identity is exact. Its single premise — that a limit order filled at our own price — is true for a maker by construction.
And it carries its own sanity check: the "spread" term must reproduce the half-spread the system was configured with. It does, to within 0.3 bp on every system (±0.2 % configured → +40.0 and +39.8 bp measured; ±0.35 % → +70.1; ±0.4 % → +79.8). Had it not reproduced, the decomposition would be invalid and every verdict below withdrawn.
Finding 1: drift is twice the cost of fees
| system | pair | half-spread | turnover | spread | drift | fees | net |
|---|---|---|---|---|---|---|---|
| LINK, spot | LINK | ±0.4 % | $167 | +79.8 | −142.6 | −15.9 | −78.8 bp |
| ETH #1 | ETH | ±0.2 % | $1,138 | +40.0 | −28.4 | −16.1 | −4.5 bp |
| ETH #2 | ETH | ±0.2 % | $922 | +39.8 | −15.6 | −15.9 | +8.3 bp |
| OP | OP | ±0.35 % | $1,215 | +70.1 | −31.1 | −16.7 | +22.3 bp |
| fleet | $3,442 | +52.5 | −31.5 | −16.3 | +4.8 bp |
Read the fleet row. The systems quoted 52.5 bp of spread. Fees took 16.3. Drift took 31.5 — sixty percent of everything quoted, and about twice what fees cost.
Every discussion of market-making economics we have seen — including our own product's warnings — is about the fee column. The larger column is the one nobody guards.
Finding 2: the one economic guard stands on the smaller cost
Our engine refuses to quote when the captured spread does not clear maker fees on both legs plus a margin. That is a correct *necessary* condition. It is not a sufficient one, and the reason is precise: ask − bid is a property of the quote, while the money is a property of the round trip — and between placing the quote and closing the round trip, mid moves.
One system passed that floor comfortably (half-spread 0.2 % against a 0.08 % maker fee) and still closed at −$0.51 after costs. The guard was not missing and not broken. It was measuring the smaller of two costs, because the smaller one is the one visible at the moment the order is placed.
Finding 3: it is not adverse selection either
The obvious suspect for a market maker's losses is toxic flow: you get filled precisely when the informed side is trading, and price keeps going. That is measurable — markout, where mid stood 1, 3 and 10 ticks after each fill, signed by side:
| system | +1 tick | +3 ticks | +10 ticks |
|---|---|---|---|
| ETH #1 | +9.6 | +8.4 | +10.1 |
| ETH #2 | +9.7 | +10.6 | +10.6 |
| OP | −7.7 | −12.1 | −12.5 |
| LINK | −4.5 | +1.2 | +1.1 |
On ETH the flow was not toxic — after our fills, price came back our way. So the money was not lost in the seconds around the fill. It was lost while holding inventory afterwards.
That distinction changes the fix. Toxic flow is treated by widening the spread. Inventory loss is treated by managing inventory — skewing quotes, capping the bag, cutting it. Widening the spread when the problem is inventory just makes you fill less often at the same underlying risk.
Note also the OP row: the most toxic flow of the four, and the most profitable system of the four. Its 0.35 % half-spread covered the toxicity. A single metric, read alone, would have condemned the winner.
Finding 4: the ask does not know what the inventory cost
The sell quote is computed from mid. It has no idea what the inventory it is selling was bought for.
In a sell-off, the nearest sell line sits below our own average cost, and the system sells into it anyway: 78 such sales, −$6.93, against a fleet result of +$1.65. Four times everything earned, given back by selling below cost.
We fixed exactly this class in our range grid — closes are floored at average entry × (1 + round-trip fee). For a market maker the answer is genuinely less obvious, because turnover *is* the job, and a floor that blocks selling turns a market maker into a bag holder. That one went to a human decision rather than a default.
What this means if you are considering it
Three questions, answerable before you fund anything:
- What is the book spread on your pair, in basis points, and what is your maker fee? If the fee is larger — and at retail it will be by one or two orders of magnitude — you are not making markets. Your quote will stand far outside the book.
- What is the amplitude of the pair on your timeframe? Since the quote only fills when price comes to it, the strategy earns when price oscillates around a level and loses when it trends. Our measurement: +22.3 bp on the volatile pair, −78.8 bp on the trending one.
- Where does your inventory cap actually bind? Ours did not: the guard asked "is inventory still below the cap?" and then placed a full-size quote, so a system with seven cents of headroom bought twelve dollars more — up to 120 % of deposit in inventory.
The honest summary is that on retail terms this is not a liquidity-provision strategy at all. It is a mean-reversion strategy expressed through limit orders — and it should be selected, sized and judged as one. Pick the pair by amplitude against your fee floor, not by how deep the book is.
Limits of this measurement
- •Six systems, one venue, demo accounts, $3,442 of closed turnover. Small. The decomposition is exact arithmetic on real order rows, but the totals are not a market-wide claim.
- •Fee schedule is ours. At a VIP tier with rebates every number above changes, and the conclusion may invert — that is the whole point of the fee comparison.
- •Demo fills are optimistic. A demo venue does not model queue position: in production a resting quote also has to be *reached in the queue*, which lowers fill rates further and never raises them.
- •Markout uses our own reconstructed mid, valid under the same premise as the decomposition.
- •This is not investment advice, and none of the above is a recommendation to trade.
What we changed
The fee floor now has a single owner asked by the engine, the paper path and the form — it had been three numbers under one name, and in the band between them the form said "the engine will pause" while the engine quoted happily.
The bid is now cut by remaining headroom rather than placed at full size. And quote skew by inventory — leaning the quote against the bag you already hold — was judged by replaying both policies over the same price path rather than by argument: three systems in favour, none against, with one verdict the instrument withdrew itself because the reconstructed mid did not match the candles.
That last part matters more than the result. A market maker that only counts closed round trips is scoring itself on the trades it chose to finish, while the unfinished bag sits off the scoreboard. Any comparison of two policies has to price the inventory still held, or the policy that holds its losers longest wins on paper.