We had a one-minute BTC momentum strategy that looked honest on Binance. Taker fees, funding, a square-root impact term we had already made slightly too mean. Walk-forward that didn't embarrass us. The paper account lived on Bybit, because that's where the keys were. I told myself BTC is BTC. By Friday I had a strategy that had been trading a lead-lag we couldn't fill, and a Sharpe that belonged to an exchange we didn't have an account on.
Monday: a clean Binance backtest
The agent had spat out something almost boring: 15-bar return versus a slow average, long or short the next bar's open, flatten on a stop or after twelve minutes. We forced it onto Binance USD-M BTCUSDT, 2023 through early 2026, and refused to look at anything gross of costs.
After 4.0 bps taker, hourly funding, and impact, walk-forward Sharpe sat at 1.6. Average net edge per fill was 3.4 bps. Trade count was high enough that I stopped poking the bootstrap. The latency pad we already add for our own stack (signal to order, 40 milliseconds on a good day) barely moved it. I remember being faintly annoyed it wasn't more fragile.
Tuesday: the paper account starts "slipping"
Paper went live at 09:12 UTC. Same code, same parameters, same "next open" rule, pointed at Bybit's linear BTCUSDT. First afternoon looked like a bad luck streak. We were filling two to eight bps worse than the Binance replay of the same minutes, always in the direction of the trade. The blotter said slippage. I believed the blotter until the misses clustered on the minutes Binance had already started running.
Overnight the gap didn't mean-revert in the way a noisy fill model mean-reverts. It sat there. A buy on Bybit printed at a price Binance had shown a beat earlier, then Bybit arrived, then we paid it. And the minutes the strategy wanted were the minutes the two tapes disagreed. Quiet minutes, the closes sat on top of each other and the strategy didn't care. It was selecting for divergence and calling that alpha.
Wednesday: two tapes, one clock
We pulled both last-trade feeds, aligned on exchange timestamps, and asked a rude question: when BTC moved at least two ticks, which venue printed first? In calm hours Binance led Bybit on about two thirds of those bursts, median lead around 40 milliseconds, which is inside a lot of "we added latency" conversations and outside a 1-minute bar. During the Tuesday CPI print the lead stretched into hundreds of milliseconds, and for a few ugly seconds the two last prices were $80 apart. I sat there with both ladders up, watching Bybit chase a movie Binance had already screened.
That was the flavour of the week, and it isn't in the Sharpe. You can know, intellectually, that crypto last prices are venue-local. It's different to see the same coin in two windows and realize one of them is living in the past.
Then we did the test I should have demanded on Monday. Keep the Binance signal. Fill at Bybit's next open. That's the paper account's actual information set if you peek at the liquid tape and trade elsewhere, and it is also a form of lookahead you will never get in size: you are using a price the execution venue has not printed. Edge went to 0.6 bps. Flip it (Bybit signal, Binance fill) and you mint a fantasy. Same-venue Binance stayed at 3.4. The "strategy" was mostly being on the faster book.
The 1-minute close gap on the minutes we traded had a median of 4.1 bps. Unconditional, across all minutes, it was about 1.5. Of course. The signal fires when someone has already started moving. We had been measuring edge on the selected sample, which is exactly where venue disagreement lives.
I used to think the worst venue bug was symbol mapping, BTCUSDT versus BTC-PERP, a join that silently duplicates a position. That's bookkeeping. This was watching two books during CPI and noticing I had researched a market I do not trade.
Thursday: funding, marks and fees weren't the same market either
Once you admit the last prices are different, you have to admit the rest of the market data contract is too. We had copied Binance's fee schedule into a Bybit paper account and then wondered why the cost line drifted.
| Input | Binance backtest | Bybit paper, that week |
|---|---|---|
| Last price | Binance USD-M | Bybit linear |
| Taker fee | 4.0 bps | 5.5 bps |
| Funding interval | hourly | 00 / 08 / 16 UTC |
| Mark / index | Binance basket | Bybit basket |
| Min qty / tick | 0.001 / 0.10 | 0.001 / 0.10 |
| Liquidation math | never hit, BTC | different mark, still never hit |
Tick and lot happened to match on BTC. I wouldn't generalize that. On the SOL book we peeked at Thursday night, tick size and min notional both differed, and the close gap on trade minutes was 11 bps. Funding was the slower leak. Binance was paying hourly. Bybit was still on the eight-hour clock for that linear. A position held through 01:00 UTC got a Binance charge in the research ledger and silence in paper, then a lump at 08:00 that the backtest had already dripped out. The carry matched over a week and disagreed over an afternoon, which is exactly the horizon this strategy lived on.
Fees were almost boring, and they still ate 1.5 bps of a 3.4 bps story. People treat 4.0 versus 5.5 as a footnote because it looks small next to a 2% daily move. It is not small next to a 3.4 bps edge. We already knew that. We had just applied the knowledge to the wrong venue's schedule.
Friday: a Bybit-native rerun
Rebuild the whole thing on Bybit OHLCV, Bybit funding stamps, Bybit 5.5 bps. Same code path, same walk-forward cuts, same impact function. Sharpe 0.4. Average net edge 0.9 bps, which is inside the noise of a one-minute taker strategy once you stop gifting it Binance's first look.
It was a different market, not a noisier one. Paper hadn't rejected the backtest because paper is "more realistic" in the abstract. Paper had been executing in a book the research never saw. The 1.6 was internally consistent. It was consistent about the wrong exchange.
We left the Binance version in the archive with a note on the report: do not paper this account against this tape. The Bybit version is the one that gets to keep running, at a number nobody would write a thread about. That's the correct outcome. I still miss the 1.6 a little, which is how you know it was doing work it hadn't earned.
What we'd skip next time
The shortcut was sociological. Binance is the tape every vendor, every research notebook, every agent default wants to hand you. The account is wherever you could actually open it. Those two facts feel like an operations detail. They are the backtest.
- Pick the execution venue first. Build the research tape from that venue's last prices, funding stamps, marks, ticks, and fee tier. If the vendor's default is Binance, that is not a default. It is a different strategy.
- If you cannot get history for the venue you'll paper on, don't substitute a leading tape and call the gap slippage. Either wait, or treat the foreign tape as a delayed signal and lag it until it could have been seen in the execution book.
- When you compare paper to backtest, split the drift: last-price gap on trade minutes, fee line, funding timestamps, mark used for stops. Tuesday's blotter mixed all four and labeled them slippage.
- Run the crossed test on purpose. Signal on A, fill on B. If that's where the whole edge lives, you do not have a strategy. You have a lead-lag you will not be filled on in size.
Would I still peek at Binance when I'm trading Bybit? For a discretionary sanity check, sure. For a fill, no. The paper account already told us what that peek is worth. It is worth the 4.1 bps the other room printed first, and we do not get those.
← All posts


