21 september 2026 · engineering

Herstart je strategie halverwege de backtest. Weet die nog wat hij bezit?

Herstart je strategie halverwege de backtest. Weet die nog wat hij bezit?

Een nuttige backtesttest draait niet om het vinden van een betere parameter: stop het proces halverwege, herstel het en voltooi dezelfde replay. Bij identieke invoer en een gecontroleerde uitvoeringssimulator moeten de beslissingen, orders en het vermogen overeenkomen met een ononderbroken uitvoering.

Is dat niet zo, dan heb je een probleem met het statusbeheer gevonden. De strategie is afhankelijk van iets wat je niet hebt opgeslagen of niet kon reconstrueren. Die afhankelijkheid is van belang wanneer onderzoeksruns worden hervat, workers worden vervangen of een paper-tradingservice nieuwe code uitrolt.

Ik vind deze test prettig omdat het verwachte antwoord ongewoon duidelijk is. Er valt niet over te discussiëren of de markt is veranderd. Beide runs krijgen dezelfde markt.

Hier zijn drie manieren waarop een herstart misgaat. De cijfers zijn illustratief; elk probleem kan optreden in een verder deterministisch systeem.

1. Laad een paar candles opnieuw in en beschouw de indicatoren als opgewarmd

Stel dat een strategie een exponentieel voortschrijdend gemiddelde van 100 perioden gebruikt. De update is:

alpha = 2 / 101
ema_next = alpha * close + (1 - alpha) * ema_previous

Het ononderbroken proces neemt de opgebouwde EMA-waarde mee. Het herstartte proces haalt 100 candles op, initialiseert de EMA met de eerste slotkoers en gaat ervan uit dat een indicator van 100 perioden 100 waarnemingen nodig heeft.

Die aanname verwart de afvlakkingsparameter van de indicator met een venster met eindige geheugenduur. Een EMA behoudt een afnemende bijdrage van zijn beginwaarde. Als twee versies beginnen met een verschil van 10 prijseenheden in de EMA, neemt dat verschil bij identieke vervolgprijzen als volgt af:

Updates sinds initialisatieResterend verschilFractie van de aanvankelijke fout
1001.35313.53%
2500.06740.674%
5000.0004540.00454%

De berekening is 10 * (99 / 101)^k. Met 100 opgehaalde candles krijg je slechts 99 updates als de eerste waarneming als beginwaarde dient.

De problemen worden meestal zichtbaar rond een beslissingsgrens. De ene run ziet de prijs boven de EMA; de andere ziet hem eronder. Een klein numeriek verschil leidt tot een extra transactie. Daarna kunnen ook de afkoelperiode, het beschikbare geld en latere beslissingen uiteenlopen.

Sla de recursieve indicatorstatus, de initialisatiestatus en de laatst verwerkte gebeurtenis op. Je kunt ook opnieuw afspelen vanaf een bekende beginstatus. Een langere opwarmperiode kan een acceptabele benadering opleveren, maar kies de lengte op basis van een expliciete fouttolerantie en controleer of die tolerantie beslissingen kan veranderen. “Vijf keer de periode” is een vuistregel, geen bewijs.

En indicatoren vormen niet de hele historie. Een voortschrijdend percentiel heeft zijn venster nodig. Een online model kan zijn optimizerstatus nodig hebben. Een regel die na een verlies 3 candles wacht, moet dat verlies en de teller onthouden.

2. Sla posities op en vergeet de orders die nog lopen

Je doelpositie is 10 eenheden. Een kooporder voor 10 is voor 4 uitgevoerd, waardoor er nog 6 openstaan. Je maakt een checkpoint met positie 4, start opnieuw en plaatst nog een kooporder voor de ontbrekende 6.

Als zowel het oorspronkelijke restant als de vervangende order worden uitgevoerd, bezit je 16 eenheden.

In backtests blijft deze fout vaak verborgen omdat het opnieuw starten van de fill-engine openstaande orders stilzwijgend wist. Bij paper trading kunnen de simulator of een externe service die orders behouden. Dezelfde herstelcode leidt dan tot een andere blootstelling, afhankelijk van welk onderdeel de herstart heeft overleefd.

Bij herstartWerkelijke statusWat herstel op basis van alleen de positie ziet
Doelpositie1010
Uitgevoerde positie44
Hoeveelheid openstaande kooporders60
Nog benodigde hoeveelheid06

De schade uit zich in een onverklaarbare stroom orders direct na het herstel. Soms verdubbelt de blootstelling. Soms wordt een positie gesloten terwijl de beschermende order nog actief is, waardoor die order later alsnog een nieuwe positie kan openen.

Een checkpoint moet naast posities ook de orderidentiteit en de status in de levenscyclus bevatten. Tijdens het herstel moeten die gegevens met het uitvoeringssysteem worden vergeleken voordat er nieuwe acties worden gegenereerd. Een order waarvan de uitkomst onbekend is, moet worden onderzocht; “geen bevestiging opgeslagen” behandelen als “nooit ingediend” is hoe dubbele orders ontstaan.

Met stabiele clientorder-ID's kun je achterhalen wat er is gebeurd. Ze voorkomen alleen duplicaten als het ontvangende systeem de vereiste uniciteits- of idempotentieregels daadwerkelijk afdwingt. Sla ook verwerkte uitvoerings-ID's op, zodat een opnieuw afgespeelde fill de positie niet twee keer vergroot.

Ik heb een zwak voor dat saaie scherm met orderstatussen. Op de dag van een herstart blijken die kleine regels ineens de interessantste interface van het hele gebouw.

3. Herstel de positie en begin een nieuwe W&V-administratie

Neem een voorbeeld met spot zonder hefboom en zonder kosten. Begin met $10,000 cash, koop 10 eenheden voor $100 en maak een checkpoint wanneer de waardering $110 bereikt.

De juiste status is $9,000 cash plus een positie ter waarde van $1,100: een vermogen van $10,100. Als het herstel de 10 eenheden terugzet maar cash op de oorspronkelijke $10,000 instelt, rapporteert het $11,100. Door een proces opnieuw te starten heb je $1,000 gecreëerd.

Andere varianten zijn minder spectaculair. Het herstel houdt het vermogen intact, maar stelt de instapprijs opnieuw in op $110. Het totale vermogen kan dan kloppen terwijl de verdeling tussen gerealiseerde en ongerealiseerde winst verandert. Als een stop of uitstapvoorwaarde naar de instapprijs verwijst, verandert de boekhoudkundige kortere weg nu ook het handelsgedrag.

Of het systeem vergeet het vorige vermogenspiekpunt. Stel dat het vermogen piekte op $10,600 voordat het daalde naar $10,100. De drawdown is ongeveer 4.72%. Zet het hoogste vermogensniveau bij herstel terug en de strategie denkt plotseling dat de drawdown nul is. Elke risicobeperking op basis van drawdown is daarmee zonder toestemming gereset.

De schade kan dus bestaan uit een sprong in het vermogen, een verdacht verbeterde drawdown of een risicoregel die na uitrol niet meer afgaat. Bewaar de boekhouding en alle status van de strategie die daarvan afhangt: geldstromen, posities, toepasselijke kostprijs, opgebouwde kosten en het geheugen van risicobeperkingen. Vergelijk het herstelde vermogen met de boekhouding op hetzelfde waarderingstijdstip.

Een checkpoint vereist een consistente grens. Als je cash na een fill opslaat en de positiehoeveelheid van vóór die fill, ontstaat een status die nooit heeft bestaan. Leg verwante statusgegevens samen vast, of registreer een duurzame reeks gebeurtenissen waarmee je de status kunt reconstrueren. Sla de gebeurteniscursor bij die status op, zodat het herstel de fill niet overslaat of twee keer toepast.

De test die ik in de onderzoeksomgeving zou opnemen, voert eerst een ononderbroken referentiereplay uit en herstart daarna een tweede run op bewust lastige momenten: tijdens de initialisatie van een indicator, na een gedeeltelijke fill en terwijl een risicolimiet actief is. Gebruik dezelfde volgorde van gebeurtenissen en behoud eventuele willekeurige simulatorstatus. Vergelijk de eerste beslissing na herstel, de order- en fillrecords en het vermogensverloop. Alleen een gelijk eindsaldo kan fouten verbergen die elkaar opheffen.

Voor een crash na het indienen maar vóór de bevestiging moet de testomgeving ook de status van de uitvoeringsservice bewaren, los van het strategieproces. Anders wis je precies de onzekerheid die je probeert te testen.

De specificatie van een strategie omvat wat die onthoudt. Maak dat geheugen expliciet genoeg om het proces halverwege een replay te kunnen beëindigen en precies te laten zien hoe de strategie het werk hervat.

strategiestatusbacktestenherstel vanaf checkpointpaper trading
← Alle artikelen