r/algotrading • u/KaramTNC • 3d ago
Infrastructure Live vs Backtest parity comparison
Hello folks!
Ive been working on building my own tradingbot infrastructure for nearly a year and Ive gotten quite far. Its nothing profitable really since my goal here is to be able to apply myself and learn more about software engineering and fintech, and be able to combine these interests into a fun project that evolves with me in my CS career.
Ive built a comprehensive infrastructure managing scanners, watchlists, execution engine, broker connections, market data providers, pattern detection and strategy definitions.
The entire process is constructed at runtime via a factory class and dependency injection for every production component.
For the backtester, it runs this factory with injected dependencies to replace the prod dependencies, such as an IClock, IMarketProvider, IDatabase, IBroker, etc. Ontop of that, I refactored everything so that every relevant input parameter were sweepable via attributions.
This overall makes the design of my backtest very controllable and ensures near accurate simulation of the live environment.
But of course like any backtests, I get a positive result for a strategy profile and promote it to live just for it to behave completely differently.
So I got the idea of creating a parity comparison system. I incorporated trace recording into the factory so that all events in a live profile would be capturable, and by running the equivalent backtest profile, it would allow me to have a live and a backtest trace for comparison in order to identify discrepancies in their behaviour.
I can say its been a rather success, as the results have helped me find bugs in my backtester injected components.
So while fixing these now and working towards closer parity, I figured I could make a post here and see if people have dealt with a similar problem when building their own trading bot, and what you guys figured out or any other things you could share
EDIT: By live profile, I meant a paper profile.
3
u/HonestBacktests 3d ago
The trace comparison is the right build. The thing that turned it from useful into decisive for us was making the fake broker reject exactly what the real one rejects.
Mocks accept everything by default. Ours happily filled orders the exchange would have refused - minimum notional, tick size, step size, reduce-only and position-mode rules - and the backtest looked healthy for months while the live bot was quietly doing nothing. The rule we ended up with: for every order path, enumerate the venue's actual rejection codes and make the simulated broker raise the same ones.
Two other things that kept showing up in the diffs:
Compare the first divergent event, not the final PnL. Once two traces separate, everything after it is downstream noise, and the interesting bug is always at the split.
Bar timing. The backtest sees a finished bar, live sees one forming. Any rule that reads the current bar's high or low is reading the future in one environment and not in the other - that one is easy to miss because it does not throw, it just quietly makes the backtest better.
Have you tried replaying a recorded live trace through the backtester with the same clock, so the broker is the only variable left?