10 September 2026 · 5 min read

The spread that survives the fees

Most cross-venue spreads a detector flags are gross spreads. After two taker fees, two slippage terms, transfer cost and decay, the number that matters is what survives.

The first version of any arbitrage detector finds opportunities everywhere. Two venues quote the same asset a few basis points apart, the detector lights up, and the log fills with spreads that would have made money if the world had ended at the moment the quote arrived. When I built the engine behind Shayanomaly, which streams order books from five venues and looks for cross-venue anomalies, the first thing I learned was that the number the detector was computing was not the number I cared about. It was computing the gross spread. The number that decides anything is the spread that survives the deductions, and there are six of them.

Six deductions

Start with a gross spread: venue A asks 100.00, venue B bids 100.50, so buying on A and selling on B shows 50 basis points. Then take it apart.

Two taker fees. Crossing the spread on both legs means paying the taker rate at each venue, and at the base tier those rates are public. Binance charges 0.10% on spot for regular users, as does Bybit and OKX, whose base tier is 0.08% maker and 0.10% taker. Kraken's fee schedule starts higher, at 0.40% maker and 0.80% taker for the entry tier before volume and balance discounts. Two legs at 10 basis points each is 20 of the 50 gone before anything has moved.

Base-tier spot taker fee by venue Horizontal bars in basis points: Binance 10, Bybit 10, OKX 10, Kraken 80 at the entry tier. Kraken's bar is much longer than the other three. What crossing the spread costs, per leg Spot taker fee at the base tier, basis points, September 2026 Binance 10 Bybit 10 OKX 10 Kraken 80 Every tier above the base is cheaper; a detector should read the account's actual tier, not the public page.
Source: the public fee pages of Binance, Bybit, OKX and Kraken, entry tier, read in September 2026.

Two notes on those fees before moving on. First, they are taker fees, because an arbitrage that has to complete before the spread closes crosses the book on both legs; resting a maker order on one side changes the fee and adds a new risk, that the maker leg never fills while the taker leg already has. A detector that assumes maker fees is pricing a strategy it is not running. Second, the fifth venue in a five-venue terminal is often a large regulated exchange whose entry tiers sit above the 0.10% level of the three cheapest here, and a pair that includes it starts its life with a larger first deduction than the others. That is not a reason to exclude the venue. It is a reason to compute the deduction per venue rather than assume one number.

Two slippage terms. The quoted price is the best level, and the best level has a size. Buying more than the size at the ask walks the book to the next level and the one after that, so the average fill price is worse than the quote by an amount that depends on the trade size and the depth. The same happens on the sell side. A detector that reads only the top of book is pricing a trade of the smallest possible size, which is the one trade nobody wants to make.

Transfer or gas. If the two legs settle on different venues, the asset or the cash has to get from one to the other at some point, and moving it costs a withdrawal fee or an on-chain transaction. Strategies that pre-position inventory on both sides pay this less often but still pay it, amortised over the trades the inventory supports.

Decay. The quote is a snapshot and the fill is later. Between the two, the spread moves, usually against you, because the spread you saw is the same spread everyone else saw. The expected loss from that movement over the fill window is a cost, and it is the one most detectors do not even have a variable for.

A 50 basis point gross spread, taken apart One stacked bar. Of 50 basis points: 20 go to taker fees on the two legs, 12 to slippage against the depth of both books, 9 to transfer cost and decay over the fill window, and 9 survive. The surviving segment is highlighted. What is left of 50 basis points Fees from public schedules; slippage, transfer and decay are stated assumptions fees 20 slippage 12 move 9 left 9 two taker fees two slippage terms transfer and decay surviving spread basis points; the gross figure alone would have been reported as 50
Illustrative: fees from the schedules above at 10 basis points per leg; the other three terms are example values chosen to show the shape of the calculation.

The surviving spread

So the number the detector computes, for every venue pair on every book update, is the surviving spread: the gross spread minus all six deductions, with the two slippage terms computed by walking each book to the intended trade size and the fee terms read from the account's actual tier rather than the public page. Then one more rule, which is the one that keeps the strategy alive: the uncertain terms are inflated by a safety multiple before they are subtracted. Fees are exact. Slippage from the current book is exact for this instant and wrong the next. Decay is an estimate. Multiply the estimated terms by a factor, 1.5 or 2 depending on how much you trust your latency, and only a spread that is still positive after that counts as an opportunity.

The fee lookup deserves one more sentence, because it is the term people get wrong in the easy direction. Public fee pages describe the base tier, and almost no account that trades enough to arbitrage sits at the base tier. Volume discounts, token-holding discounts and negotiated rates all lower the number, and a detector that uses the public rate will discard opportunities that were real. So the fee term is read from the account, refreshed on a schedule, and logged with the spread, so that a trade that looked marginal can be checked against the fee that actually applied.

The gross number is never shown without the surviving one beside it. That is a display rule as much as a computation rule, and it matters, because a screen full of gross spreads trains the person watching it to believe in money that does not exist.

The detector pipeline, from book update to decision Two rows of boxes. First row: book update arrives, walk both books to the trade size, look up the account's fee tier. Second row: subtract the six deductions with the safety multiple applied to the estimated ones, then a threshold gate that either reports an opportunity or discards it. The surviving-spread step is highlighted. Book update both venues, timestamped Walk both books to the intended size Fee lookup the account's tier, both legs Surviving spread gross minus six terms, estimates inflated Threshold gate positive after the multiple Report or discard runs on every update, for every venue pair; gross spread logged, never shown alone
Illustrative: the shape of the calculation, not a diagram of any particular codebase.

What changes when you compute it

The first thing that changes is the count. A detector that flags gross spreads fires constantly; one that flags surviving spreads fires rarely, and the difference is the point. Most of what looked like opportunity was the market's fee structure showing through. The venues with the highest published fees produce the widest gross spreads for exactly that reason: nobody is arbitraging them away, because after fees there is nothing to arbitrage.

The second thing that changes is what you watch. Once the detector is honest, the interesting question stops being which pairs show a spread and becomes which deductions dominate for each pair. Fee-dominated pairs are dead until your tier improves. Slippage-dominated pairs are alive only at small sizes, which caps the profit at a number you can compute in advance. Decay-dominated pairs are a latency problem, not a pricing problem, and no amount of book-walking fixes them. Each dominant term points at a different piece of engineering, or at a decision to leave the pair alone.

The third thing that changes is the conversation with anyone looking over your shoulder. A gross spread is a story about money you could have made. A surviving spread is a claim you can be held to, because every term in it is either read from a public schedule or written down as an assumption with a multiple on it. When the number is wrong, and it will be, you can see which term was wrong.

The limit

The surviving spread is a per-trade number, and it says nothing about how many such trades exist or how often. A pair can survive the deductions once an hour and still not be worth the infrastructure that watches it. That is a different calculation, about capacity and frequency, and it sits on top of this one rather than inside it. What this one buys is more modest and more necessary: it stops the detector from lying, and it does so by refusing to display any spread that has not paid its way out.

ArbitrageMarket MicrostructureShayanomaly
All writing

Written by Mohd Shayan

Get new posts by email

Occasional essays on engineering, AI, and building for the people technology leaves behind.

One email per new post. Unsubscribe any time.

Subscribe with RSS