The parity gap
A backtest is a clean room. A paper-trading account is a slightly dirtier clean room. Live trading is the street. The reason a strategy that prints money in sim can bleed in production is rarely the signal logic. It is the silent set of assumptions your simulator makes that the real market refuses to honor.
Almost every simulator quietly assumes some combination of the following. None of them are true live:
- →You are always filled, at the price you wanted, for the full size.
- →Your fill happens the instant the bar closes or the signal fires.
- →There is no spread between bid and ask; you trade at the mid or the last print.
- →The broker or exchange never rejects, throttles, or goes into maintenance.
- →Fees and funding are an afterthought, deducted at the end if at all.
- →Your process never crashes and your connection never drops.
Each assumption is a small loan from reality that live trading calls in. The sum of those loans is the parity gap, and it is what turns a +0.4R/trade backtest into a break-even or losing system. The work is not to eliminate the gap; it is to make it small enough, and known enough, that you can trust your numbers.
Fills and liquidity
The single largest source of divergence is the fill model. Paper trading hands you the mid price instantly. Live, your order has to interact with a real order book that has a spread, finite depth, and other participants ahead of you.
A market order crosses the spread and walks the book. On a liquid pair that is a few basis points. On a thin altcoin or an illiquid futures contract, a single order can move the price against you before it finishes filling. A limit order avoids the spread but introduces a different problem: queue position. You sit behind everyone who posted at your price first, and if the market never trades through your level, you simply do not get filled. The trade your backtest counted as a winner never happened.
Then there are partial fills. You ask for 2 BTC and get 1.3 before the liquidity at your price is gone. Now your position size is wrong, your average entry is worse than planned, and your stop and target math is based on a fill you did not fully get. A simulator that assumes full fills hides every one of these cases.
Latency and timing
Sim treats time as instantaneous. Live has three distinct delays stacked on top of each other, and each one moves the price you actually trade away from the price your backtest recorded.
- →Data feed lag: the market has already moved by the time the tick reaches you
- →Signal-to-order delay: computing the signal and constructing the order takes real milliseconds
- →Order-to-exchange latency: network round-trip and matching-engine processing before you are in the book
The most common and most dangerous timing lie is the bar-close trade. A strategy computed on the 1-minute close cannot actually trade at that close. The close price only exists once the minute is over, and by the time your bot sees it, computes the signal, and submits the order, the next bar is already moving. Your backtest filled you at the close. Live, you fill somewhere in the next bar, often at a meaningfully different price. For mean-reversion and fast strategies, this single effect can flip the sign of your edge.
Broker and exchange reality
Paper trading talks to a fiction that always cooperates. The real exchange is an adversarial, rate-limited, occasionally offline system with its own rules about rounding, margin, and uptime. These are the live failure modes a simulator almost never reproduces:
Live failure modes paper never shows
REJECT order refused: insufficient margin / risk limit
429 rate limit hit, order dropped or delayed
MAINT exchange maintenance window, API unavailable
FUNDING perp funding charged every 8h while position is open
LIQ margin call / forced liquidation before your stop
MIN_QTY size below lot minimum, order rejected
TICK price rounded to tick size, not your exact level
STEP quantity rounded to step size, fill size shifts
Lot and tick rounding deserve special mention because they are deterministic and still routinely ignored. If the exchange tick size is $0.50 and your model wants a stop at $98,317.30, your real stop is at $98,317.00 or $98,317.50. Multiply small rounding across thousands of trades and the drift is not noise. Funding is the other quiet killer: a perpetual held across funding periods pays a fee your price-only backtest never subtracted, and over a multi-day hold it can dwarf the commission.
State and reconnection
In sim, the process never dies and the socket never drops. Live, both happen routinely: a VPS reboots after a kernel update, the OOM killer takes your process, the WebSocket silently stalls. Your open positions do not vanish when your code does. They sit on the exchange, exposed, while your bot is blind.
The failure that costs real money is naive state recovery. A bot that trusts its own last-known state on restart can re-enter a position it already holds (doubling size) or behave as if flat when it is not. The only safe design treats the exchange as the source of truth. On startup, before doing anything else, the bot queries the exchange for actual open positions and open orders and reconciles its internal state to match.
This requires idempotency. Every order carries a client-generated ID so that a retry after a dropped acknowledgement does not place a second order. Reconnection logic re-subscribes, detects gaps in the data stream, and refuses to trade until state is confirmed. A simulator that never disconnects gives you no reason to build any of this, which is exactly why first live deployments are so fragile.
A big chunk of the gap is fees and funding you never modeled →
Before you blame the fill model, quantify the costs your sim ignored. The Trading Fee Calculator shows what commissions and funding actually take out of a round trip on Bybit, Binance, Hyperliquid, or any exchange, in dollars and in R.
How to actually measure parity
You cannot close a gap you do not measure. Parity is not a feeling; it is a number you track over time. The method is to run sim and live side by side on the same signals, then compare what each one did with them.
Drive both environments from a single signal stream so that any divergence is attributable to execution, not to the strategy seeing different data. For every trade, record the intended price, the sim fill, and the live fill, then compute the slippage in basis points relative to intent.
Per-trade parity metric
slippage_bps = (live_fill − intended) / intended × 10,000
Intended entry: 100,000.00
Sim fill: 100,000.00 (0.0 bps)
Live fill: 100,012.00 (1.2 bps)
Parity gap: 1.2 bps per side, ~2.4 bps round trip
Track the distribution, not just the mean. A 2 bps average can hide a fat tail of 20 bps fills on thin liquidity, and those tail trades usually drive most of the damage. Plot live PnL against sim PnL over the same period; a stable, small, predictable offset means your fill model is trustworthy. A widening or erratic gap means your model is wrong and you should not be scaling size on its numbers.
An engineering checklist for parity before scaling size
Closing the gap is mostly engineering discipline, applied before real capital is at risk. The order matters: shared code first, realistic costs second, live verification last.
One code path for sim and live
The strategy and order logic must be identical in both modes, with only the execution adapter swapped behind an interface. If sim runs different code than live, you are testing the wrong thing, and the bugs live where the code paths diverge.
A realistic fill model
Model the spread, a conservative slippage assumption, queue behavior for limit orders, and the possibility of no fill and partial fills. Pessimistic is safer than optimistic: a model that overstates costs simply makes live a pleasant surprise.
Replayed market data, not synthetic
Test against recorded tick or order-book data, including the messy days: gaps, spikes, low-liquidity sessions, and exchange outages. Smooth synthetic data hides exactly the conditions that break live execution.
Fees and funding in the model
Subtract commissions and funding per trade as the trade happens, not as a lump sum at the end. This is the cheapest part of the gap to close and the most often skipped.
A live canary with tiny size
Before scaling, run the real system live with the smallest size the exchange allows. Compare its fills and PnL against sim in bps. Only when the residual gap is small, stable, and explained do you increase size.
Summary
- Sim assumes instant full fills, zero latency, and a cooperative broker; live honors none of these
- The fill model is the largest source of divergence: spread, queue position, partials, and no-fills
- A strategy computed on the bar close cannot actually trade the close; latency moves your real price
- Model fees and funding per trade, plus tick and lot rounding, before blaming anything else
- On crash or disconnect, reconcile against the exchange as source of truth; use idempotent orders
- Measure parity in bps by running sim and live on the same signals, and track the distribution
- Before scaling size: shared code path, realistic fills, replayed data, and a tiny live canary
Frequently asked questions
Why are my live trading results worse than my paper trading?
Paper trading and most backtesters fill you at the mid or last price instantly, with no spread, no queue, no rejection, and no latency. Live, you pay the spread, you wait in the order book queue, you sometimes do not get filled at all, and your signal-to-order path takes tens to hundreds of milliseconds. Each of these costs you basis points the simulator never charged. The difference is real and measurable, not bad luck.
What is sim-to-live parity?
Sim-to-live parity is the discipline of making your simulation environment behave as close to live as possible: realistic fill modeling, modeled latency, modeled fees and funding, the same code path for both modes, and reconciliation against the exchange. The goal is not a perfect simulator; it is a simulator whose lies are small and known, so that a number you trust in sim survives contact with live.
How do you measure slippage between sim and live?
Run sim and live on the same signals at the same time, then compare fill price and realized PnL per trade. Express the gap in basis points relative to the intended price. Track the distribution, not just the average, because the tail trades (thin liquidity, fast moves) usually drive most of the divergence. A stable, small bps gap means your fill model is trustworthy.
Can a backtest ever match live results?
Not exactly, and you should not expect it to. Live has queue position, partial fills, rejections, and latency jitter that no offline simulation reproduces perfectly. The realistic target is a known, bounded gap: you model fees, funding, spread, and a conservative slippage assumption, then verify in a small live canary that the residual divergence is within tolerance before scaling size.
What happens to my positions if my trading bot crashes?
Your positions keep existing on the exchange; the exchange does not care that your process died. The danger is state: on restart the bot must reconcile against the exchange as the source of truth, not trust its own last-known state, or it can double a position or trade as if flat when it is not. Idempotent order handling and startup reconciliation are what make a crash a non-event instead of a loss.
Quantify the part of the gap that is just costs
A large share of the sim-to-live gap is fees and funding you never modeled. Use our free Trading Fee Calculator to measure exactly what a round trip costs you on Bybit, Binance, Hyperliquid, or any other exchange, in dollars and in R.