Een perfect reproduceerbare backtest is soms minder betrouwbaar dan een backtest die een beetje schommelt. Herhaalbaarheid bewijst dat je twee keer hetzelfde antwoord kunt krijgen; ze zegt niets over de vraag of dat antwoord afhangt van één willekeurige datasnapshot, een eigenaardigheid van een library of een verborgen standaardinstelling.
Dat klinkt als een pleidooi tegen reproduceerbaarheid, maar dat is het niet. Zet de run vast, zodat je hem kunt verklaren. Varieer vervolgens bewust de aannames die de uitkomst niet zouden moeten bepalen. De eerste stap maakt een resultaat controleerbaar; de tweede vertelt je of het iets betekent.
Wat toont een reproduceerbare backtest nu eigenlijk aan?
Als dezelfde code, data, configuratie en random seed dezelfde trades en metrics opleveren, heb je een belangrijke bron van verwarring onder controle gebracht. Je kunt de “verbetering” van een agent vergelijken met de bovenliggende run. Je kunt een bugfix onderscheiden van een gewijzigde kostenstructuur. Een collega kan hetzelfde grootboek inspecteren en dezelfde fills vinden.
Maar het resultaat geldt onder de voorwaarde dat alles wat je hebt vastgezet gelijk blijft. Neem een cryptostrategie waarvan het historische bestand candles van één minuut bevat. Je slaat de hash van het bestand op, legt de code vast en krijgt bij elke nieuwe run een Sharpe van 1.4. Als de leverancier later enkele candles corrigeert, beschrijft die nette reproduceerbaarheid nog steeds het oude bestand. Ze vertelt je niet of het signaal overeind blijft met de gecorrigeerde historie, of dat die candles destijds in die vorm beschikbaar waren.
De hash is nuttig: hij maakt de afhankelijkheid zichtbaar. Hij bewijst niet dat die afhankelijkheid onschadelijk is.
Zet de run vast; stel de bevinding op de proef
Ik maak graag onderscheid tussen twee vragen. Kunnen we deze exacte run reconstrueren? En blijft de onderzoeksconclusie overeind bij redelijke wijzigingen? De eerste vraag vraagt om een onveranderlijk verslag; de tweede om gecontroleerde aanpassingen, één tegelijk.
| Wat je vastlegt | Wat je daarna varieert | Wat het kan aantonen |
|---|---|---|
| Versie van ruwe data en checksums | Revisie van de leverancier of een tweede bron | Afhankelijkheid van gecorrigeerde of leveranciersspecifieke waarden |
| Codecommit en pakketversies | Numeriek equivalente implementatie | Gevoeligheid voor volgorde, afronding of library |
| Kosten, funding en aannames over fills | Een verdedigbare kostenmarge | Of een kleine edge uitzonderlijk gunstige uitvoering vereist |
| Universum en samenstelling op het betreffende tijdstip | Alternatieve regels voor in aanmerking komende markten | Afhankelijkheid van beslissingen over opname of uitsluiting |
Stel bijvoorbeeld dat een futuresstrategie in een basissimulatie 8% geannualiseerd extra rendement laat zien. Voer de simulatie opnieuw uit met takerkosten die 25% hoger zijn, funding die verschuift naar de eerstvolgende waargenomen afrekening en waarbij je de twee grootste bijdragers elk afzonderlijk verwijdert. Dat zijn geen drie manieren om het model te verbeteren. Het zijn toetsen: elke toets vraagt of een aannemelijk detail de hoofdconclusie draagt.
Houd elke toets afzonderlijk. Als je data, kostenstructuur en uitvoeringstiming tegelijk wijzigt, zegt een slechter resultaat je weinig over de oorzaak. En als een toets onwaarschijnlijk is, benoem die dan als stresstest in plaats van als de meest waarschijnlijke uitkomst.
Verwar byte-voor-byte-overeenkomst niet met numerieke waarheid
Sommige berekeningen zijn gevoelig voor de volgorde. Optellen met floating-pointgetallen is niet associatief, dus als je veel kleine P&L-waarden in een andere volgorde optelt, kunnen de laatste cijfers veranderen. Parallelle reducties, hardware en libraryversies kunnen allemaal de exacte uitvoer beïnvloeden. Meestal is dat onschadelijk; soms zorgt een kleine numerieke verandering ervoor dat een drempel wordt overschreden, een positie verandert en de rest van de simulatie een ander pad volgt.
Daarom zou ik zowel de exacte artefacten als toleranties voor vergelijkingen bewaren. Leg het handelsgrootboek vast, niet alleen de uiteindelijke Sharpe. Vergelijk eerst beslissingen en kasstromen, en vergelijk daarna de metrics binnen een vastgelegde tolerantie. Als een verschil van één cent bepaalt of er een order wordt ingediend, onderzoek die grens dan expliciet.
Een bruikbaar runverslag bevat de identiteit van de data en code, de configuratie, random seed, uitvoeringsomgeving en voldoende tussenresultaten om een metric terug te volgen tot aan de fills en kasstromen. Alleen een eindscore is geen reproduceerbaar onderzoeksartefact.
Wanneer variatie ruis is en wanneer ze een bevinding oplevert
Niet elk gewijzigd getal is reden tot zorg. Een kleine afwijking in een metric door een andere optelvolgorde kan samengaan met ongewijzigde trades. Een gewijzigde trade vlak bij een drempel kan nader onderzoek verdienen. Een strategie die het grootste deel van haar resultaat verliest wanneer een leverancier een klein stukje historie herziet, heeft iets geleerd over haar eigen kwetsbaarheid, ook als de oorspronkelijke run perfect reproduceerbaar blijft.
Critici van robuustheidstoetsen hebben op één punt gelijk: je kunt aannames blijven veranderen tot een strategie er veerkrachtig uitziet, of een deugdelijk resultaat afwijzen omdat een bewust extreem scenario het onderuit haalt. Bepaal vooraf welke variaties aannemelijk zijn, rapporteer de volledige reeks en maak onderscheid tussen gewone alternatieven en stresstests. Bewaar vervolgens de basisrun, zodat een andere onderzoeker exact kan reproduceren wat jij zag.
Reproduceerbaarheid geeft je een betrouwbaar vertrekpunt. Daarna komt de nuttige vraag: welke onderdelen van het antwoord blijven overeind wanneer de wereld rond die run verandert op manieren die je redelijkerwijs kunt verwachten?
← Alle artikelen


