Free lesson · HFT & microstructure
Event-driven backtesting and order lifecycle correctness
Open interactive lessonPractice calculationsExplore labs
Start with the idea
At short horizons, the sequence of events is part of the strategy. A correct backtest must reproduce when an order can exist, which messages it has seen, and which fills remain possible while cancellation is in flight.
Symbols, units & horizon
- q: signed inventory in shares/contracts
- u_t: signed executed quantity, positive for buy
- C: cash in currency
- P_t: fill price per unit
- f_t: currency fees, negative for net rebate if applicable
- m: reference mark per unit
- W: marked wealth
- Contract multipliers: assumed one here, otherwise multiply all price notionals consistently
When and why to use this
Use event and accounting invariants to validate the simulator before using it to tune or train an HFT policy.
Maintain separate states for desired orders, sent requests, exchange-accepted orders, partial fills, pending cancels and terminal orders. Process messages in a deterministic order using sequence numbers where available. When two timestamps tie, document the tie-break rather than choose the outcome most favourable to the strategy.
Historical replay treats your order as too small to change future events. That counterfactual assumption breaks at larger size or when your displayed order would alter other participants’ behaviour. An interactive simulator can model response, but its response rules introduce new model risk. Use both approaches for different questions.
Inventory and cash conservation are powerful tests: each fill changes inventory by its signed quantity and cash by the opposite notional less fees. Reconcile a market order, a partial passive fill and a cancel/fill race manually before benchmarking model accuracy.
Event-driven backtesting and order lifecycle correctness
- A signed fill adds u to inventory. Buying spends uP; selling has negative u and therefore increases cash.
- Subtract the fee once at the fill. Pending orders alone do not change cash or inventory in this simplified ledger.
- Mark the new holdings at the next reference price and add cash. Any unexplained wealth change is a ledger or event-timing error.
Cash 1000 and zero inventory: buy 2 at 100 with total fee .1. Cash becomes 799.9, inventory 2; at mark 100.2 wealth is 1000.3. The .3 gain is .4 markout less .1 fee.
Apply it in a strategy
- Replay a small session and inspect every request, acknowledgement, partial fill and cancel transition.
- Inject delays, sequence gaps and cancel/fill races; verify deterministic recovery and independent exposure limits.
- Compare replay outcomes with paper-execution telemetry at identical decision timestamps before interpreting performance.
Research deliverable
Maintain a reproducible event trace with cash/inventory conservation checks and explicit limitations on market-impact counterfactuals.
Python implementation
Self-contained teaching example. Python 3.10+; dependencies and input conventions are shown in the code and notation. Run in your own Python environment.
def apply_fill(cash,inventory,quantity,price,fee,next_mark):
new_cash=cash-quantity*price-fee
new_inventory=inventory+quantity
return new_cash,new_inventory,new_cash+new_inventory*next_mark
print(apply_fill(1000,0,2,100,.1,100.2))Continue learning
High-Frequency Trading: Signals, Queues & Execution — all lessons- HFT economics and the information-to-fill timeline
- Order-book features: imbalance, microprice and event flow
- Volume clocks, trade imbalance and VPIN
- Queue position, fill probabilities and adverse selection
- Inventory-aware quoting and economic edge development
- Event-driven backtesting and order lifecycle correctness
- HFT research promotion, drift and operating limits
Quantitative finance and development glossary · Python resources and libraries · Research sources and limitations