Er is één vraag waar elke backtest omheen draait: zou dezelfde code, live gevoed met dezelfde markt, hetzelfde hebben gedaan? Die vraag beantwoord je niet met méér backtesten. Je beantwoordt hem alleen door de strategie op live data te draaien met echte uitvoeringssemantiek, en dan — trade voor trade — te controleren of beide werelden het eens zijn. Die controle doen we elke dag, automatisch, en het is veruit de productiefste bug-vinder in het hele platform.
Dag één: bouw de spiegel
Elke gepromoveerde strategie draait in een eigen geïsoleerde live node, gevoed door echte exchange-streams: live quotes voor fills, echte spreads, echte handelsuren. Geen gedeelde state tussen strategieën (die les hebben we op de harde manier geleerd — in een gedeelde node lekten de positie-queries van de ene strategie door naar de andere). Elke fill wordt vastgelegd samen met de signaalwaarde die hem veroorzaakte.
Elke ochtend: replay en diff
Een dagelijkse job neemt het paper-venster van elke strategie, draait exact dezelfde code door de backtest-engine over dezelfde periode op catalogusdata, en matcht de fills één-op-één: dezelfde kant, dezelfde timestamp-tolerantie, dezelfde omvang. De uitkomst is geen correlatie of onderbuikgevoel. Het is een tabel: matched, alleen-paper, alleen-replay. Een gezonde strategie zit op 54 van de 55 gematcht. Een ongezonde vertelt je precies welke trade afweek en wanneer.
Wat er stukging, in de volgorde waarin het stukging
- Warmup-fills. De live node voerde historie aan om indicatoren op te warmen — en strategieën met eigen bar-handlers handelden daar vrolijk op. Backtests zagen die spookentries nooit. De fix zat in de submissielaag, niet in de strategie, want anders erft elke strategie de bug gewoon opnieuw.
- Sequentiële multi-leg warmup. Een cross-sectionele strategie warmde één instrument tegelijk op; elke leg zag lege siblings en het anker werd nooit geïnitialiseerd. Live handelde hij niets; in replay handelde hij prima. Nul gematchte trades — maar alleen de diff zei dat hardop.
- Crash-loops door tick-precisie. Live aggTrade-ticks komen binnen met een andere precisie dan het sandbox-instrument verwachtte. De node ging in een crash-loop op een assertie die een backtest nooit kan triggeren, omdat catalogusbars al genormaliseerd zijn.
- Herstart-amnesie. Na een procesherstart vuurde de entry-logica opnieuw op posities die al bestonden — bij een rebalancing-strategie werd een herstart stilletjes een rebalance. In live trading is dat geen voetnoot over pariteit; dat is een rode vlag met geld eraan vast.
Let op het patroon: geen enkele hiervan is een signaalbug. Het zijn stuk voor stuk bugs op de uitvoeringsgrens — warmup, state, precisie, herstarts. Precies de klasse fouten waarvoor backtests structureel blind zijn, want in een backtest is de backtest-engine de uitvoeringsgrens.
De asymmetrieën die we bewust laten bestaan
De twee werelden zijn met opzet niet identiek. De backtest rekent een gemodelleerde halve spread plus wortelvormige impact door in de PnL; paper betaalt de echte spread in de fillprijs en kent geen impactmodel. De gemodelleerde spread aan paper toevoegen (of de echte aan de backtest) zou dubbeltellen. Pariteit betekent dezelfde beslissingen, dezelfde fills binnen tolerantie — niet bit-identieke PnL. Weten welke verschillen principieel zijn en welke bugs, is het grootste deel van de discipline.
Een backtest is een hypothese. Paper trading is het experiment. Replay-pariteit is het labjournaal dat je betrapt als je jezelf voor de gek houdt.
Draai je strategieën zonder live gedrag volgens een vast schema tegen replay-gedrag af te zetten, dan heb je een categorie bugs die je nog nooit hebt gezien. Wij vinden er ongeveer één per paar weken, en elk van die bugs was vanuit de backtest volstrekt onzichtbaar.
← Alle artikelen
