Det finns en fråga som varje backtest smiter ifrån: skulle samma kod, matad med samma marknad live, ha gjort samma sak? Den går inte att besvara med mer backtesting. Den besvaras bara genom att köra strategin mot livedata med verklig exekveringssemantik och sedan kontrollera — affär för affär — att de två världarna är överens. Vi gör den kontrollen varje dag, automatiskt, och den har varit den enskilt mest produktiva buggjägaren i hela plattformen.
Dag ett: bygg spegeln
Varje befordrad strategi kör i sin egen isolerade live-nod och konsumerar riktiga börsströmmar: live-quotes för fills, verkliga spreadar, verkliga handelstider. Inget delat tillstånd mellan strategier (den läxan fick vi den hårda vägen — i en delad nod läckte en strategis positionsförfrågningar in i en annans). Varje fill registreras tillsammans med signalvärdet som gav upphov till den.
Varje morgon: replay och diff
Ett dagligt jobb tar varje strategis paper-fönster, kör identisk kod genom backtest-motorn över samma period på katalogdata och matchar fills en-till-en: samma sida, samma tidsstämpeltolerans, samma storlek. Utdatan är ingen korrelation och ingen magkänsla. Det är en tabell: matchade, endast paper, endast replay. En frisk strategi ligger på 54 av 55 matchade. En sjuk talar om exakt vilken affär som avvek, och när.
Vad som gick sönder, i den ordning det gick sönder
- Fills under uppvärmning. Live-noden matade in historik för att värma upp indikatorer — och strategier med egna bar-hanterare handlade glatt på den. Backtesterna såg aldrig de fantomingångarna. Fixen låg i inlämningslagret, inte i strategin, eftersom varje strategi annars ärver buggen.
- Sekventiell uppvärmning med flera ben. En tvärsnittsstrategi värmde upp ett instrument i taget; varje ben såg tomma syskon och ankaret initierades aldrig. Live handlade den ingenting; i replay handlade den utan problem. Noll matchade affärer — men bara diffen sa det rakt ut.
- Kraschloopar på tick-precision. Live-aggTrade-tickar kommer in med en annan precision än sandbox-instrumentet förväntade sig. Noden kraschloopade på ett assertion som backtesten aldrig kunde utlösa, eftersom katalogbarer redan är normaliserade.
- Omstartsamnesi. Processomstarter körde ingångslogiken igen på positioner som redan fanns — för en rebalanseringsstrategi blev en omstart i tysthet en rebalansering. I live-handel är det ingen fotnot om paritet; det är en varningsflagga med pengar knutna till sig.
Lägg märke till mönstret: inte en enda av dem är en signalbugg. Alla är buggar vid exekveringsgränsen — uppvärmning, tillstånd, precision, omstarter. Det är precis den klass av fel som backtester är strukturellt blinda för, eftersom backtest-motorn är exekveringsgränsen i en backtest.
Asymmetrierna vi behåller med flit
De två världarna är avsiktligt inte identiska. Backtesten debiterar en modellerad halv spread plus kvadratrotsimpact inuti PnL; paper betalar den verkliga spreaden i fill-priset och har ingen impact-modell. Att lägga den modellerade spreaden på paper (eller den verkliga på backtester) skulle dubbelräkna. Paritet betyder samma beslut, samma fills inom tolerans — inte bitidentisk PnL. Att veta vilka skillnader som är principiella och vilka som är buggar utgör större delen av disciplinen.
En backtest är en hypotes. Paper trading är experimentet. Replay-paritet är labbjournalen som avslöjar när du lurar dig själv.
Om du kör strategier och inte diffar live-beteende mot replay-beteende enligt schema, så har du en hel buggkategori du aldrig sett. Vi hittar en ungefär varannan vecka, och var och en av dem var osynlig inifrån backtesten.
← Alla inlägg
