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.
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.
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.
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.
Get new posts by email
Occasional essays on engineering, AI, and building for the people technology leaves behind.
Subscribe with RSS