21. september 2026 · teknik

Genstart din strategi midt i backtesten. Kan den huske, hvad den ejer?

Genstart din strategi midt i backtesten. Kan den huske, hvad den ejer?

En nyttig backtesttest handler ikke om at finde en bedre parameter: Stop processen halvvejs, gendan den, og fuldfør den samme afspilning. Med identiske input og en kontrolleret eksekveringssimulator bør dens beslutninger, ordrer og egenkapital stemme overens med en uafbrudt kørsel.

Hvis de ikke gør det, har du fundet et problem med tilstandshåndteringen. Strategien afhænger af noget, du ikke har gemt eller ikke kunne genskabe. Den afhængighed er vigtig, når researchkørsler genoptages, workers udskiftes, eller en papertradingtjeneste udruller ny kode.

Jeg kan godt lide denne test, fordi det forventede svar er usædvanligt klart. Der er ingen diskussion om, hvorvidt markedet har ændret sig. Begge kørsler får det samme marked.

Her er tre forkerte måder at genstarte på. Tallene er illustrative; hver fejl kan opstå i et ellers deterministisk system.

1. Genindlæs nogle få candles, og kald indikatorerne opvarmede

Antag, at en strategi bruger et eksponentielt glidende gennemsnit over 100 perioder. Opdateringen er:

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

Den uafbrudte proces viderefører den akkumulerede EMA. Den genstartede proces henter 100 candles, initialiserer EMA'en med den første lukkekurs og antager, at en indikator over 100 perioder kræver 100 observationer.

Den antagelse forveksler indikatorens udjævningsparameter med et vindue med begrænset hukommelse. En EMA bevarer et gradvist aftagende bidrag fra sin starttilstand. Hvis to versioner starter med en forskel på 10 prisenheder mellem deres EMA-værdier, mindsker efterfølgende identiske priser forskellen sådan her:

Opdateringer siden initialiseringResterende forskelAndel af den oprindelige fejl
1001.35313.53%
2500.06740.674%
5000.0004540.00454%

Beregningen er 10 * (99 / 101)^k. Hvis du henter 100 candles, får du kun 99 opdateringer, når den første observation bruges som startværdi.

Problemet viser sig som regel tæt på en beslutningsgrænse. Den ene kørsel ser prisen over EMA'en; den anden ser den under. En lille numerisk forskel skaber en hel ekstra handel. Når det sker, kan afkølingsperioder, tilgængelige midler og senere beslutninger også begynde at afvige.

Gem indikatorens rekursive tilstand, dens initialiseringsstatus og den senest behandlede hændelse. Alternativt kan du afspille fra en kendt starttilstand. En længere opvarmningsperiode kan give en acceptabel tilnærmelse, men vælg længden ud fra en eksplicit fejltolerance, og undersøg, om tolerancen kan ændre beslutninger. “Fem gange perioden” er en konvention, ikke et bevis.

Og indikatorer udgør ikke hele historikken. En rullende percentil kræver sit vindue. En online model kan have brug for sin optimizer-tilstand. En regel, der venter 3 candles efter et tab, skal huske tabet og tælleren.

2. Gem positionerne, og glem ordrerne undervejs

Din målposition er 10 enheder. En købsordre på 10 er blevet udført for 4, så 6 stadig afventer. Du gemmer positionen som 4, genstarter og indsender endnu en købsordre på de manglende 6.

Hvis både den oprindelige rest og erstatningsordren bliver udført, ejer du 16.

I backtests forbliver denne fejl ofte skjult, fordi en genstart af fill-motoren lydløst sletter aktive ordrer. I papertrading kan simulatoren eller den eksterne tjeneste stadig have dem. Den samme gendannelseskode giver dermed forskellig eksponering alt efter, hvilken komponent der overlevede.

Ved genstartFaktisk tilstandHvad gendannelse baseret kun på positionen ser
Målposition1010
Udført position44
Afventende købsmængde60
Yderligere nødvendig mængde06

Problemet viser sig som et uforklarligt ryk af ordrer umiddelbart efter gendannelsen. Nogle gange fordobles eksponeringen. Andre gange lukkes en position, mens dens beskyttelsesordre stadig er aktiv, så den senere kan åbne en ny position.

Et checkpoint skal gemme ordreidentitet og livscyklustilstand sammen med positionerne. Før nye handlinger genereres, skal gendannelsen afstemme disse oplysninger med eksekveringssystemet. En ordre med et ukendt udfald skal undersøges; hvis du behandler “ingen gemt kvittering” som “aldrig indsendt”, opstår der dublerede ordrer.

Stabile klientordre-id'er gør det lettere at slå op, hvad der skete. De forhindrer kun dubletter, hvis det modtagende system faktisk håndhæver de nødvendige regler for entydighed eller idempotens. Gem også id'erne på behandlede eksekveringer, så en genafspillet fill ikke øger positionen to gange.

Jeg har en svaghed for den kedelige statusskærm for ordrer. På dagen for en genstart bliver dens små rækker pludselig bygningens mest interessante brugerflade.

3. Gendan positionen, og start et nyt P&L-regnskab

Se på et gearet spoteksempel uden gebyrer. Start med $10,000 i kontanter, køb 10 enheder til $100, og gem et checkpoint, når markedsprisen når $110.

Den korrekte tilstand er $9,000 i kontanter plus en position til en værdi af $1,100: egenkapital på $10,100. Hvis gendannelsen sætter positionen på 10 enheder, men nulstiller kontantbeholdningen til de oprindelige $10,000, rapporterer den $11,100. Du har skabt $1,000 ved at genstarte en proces.

Andre varianter er mindre dramatiske. Gendannelsen bevarer egenkapitalen, men nulstiller indgangsprisen til $110. Den samlede egenkapital kan stadig være korrekt, mens fordelingen mellem realiseret og urealiseret resultat ændres. Hvis en stopregel eller exitbetingelse henviser til indgangsprisen, ændrer denne regnskabsmæssige genvej nu handelsadfærden.

Eller systemet glemmer den tidligere egenkapitaltop. Antag, at egenkapitalen toppede på $10,600, før den faldt til $10,100. Drawdown er cirka 4.72%. Nulstil high-water mark ved gendannelse, og strategien tror pludselig, at drawdown er nul. Enhver risikokontrol baseret på drawdown er netop blevet nulstillet uden tilladelse.

Problemet kan altså vise sig som et pludseligt spring i egenkapitalen, en mistænkeligt forbedret drawdown eller en risikoregel, der holder op med at slå til efter udrulninger. Bevar regnskabet og strategiens tilstand, der afhænger af det: kontantbevægelser, positioner, relevant kostprisgrundlag, påløbne omkostninger og hukommelse i risikokontrollen. Afstem den gendannede egenkapital med regnskabet på samme værdiansættelsestidspunkt.

Et checkpoint kræver en konsistent grænse. Hvis du gemmer kontantbeholdningen efter en fill og positionsmængden fra før den fill, får du en tilstand, der aldrig har eksisteret. Gem relaterede tilstandsdata samlet, eller registrer en varig hændelsessekvens, som tilstanden kan genskabes ud fra. Gem hændelsesmarkøren sammen med tilstanden, så gendannelsen hverken springer fillen over eller anvender den to gange.

Den test, jeg ville beholde i research-harnessen, kører først en uafbrudt referenceafspilning og genstarter derefter en anden kørsel på bevidst besværlige tidspunkter: under initialisering af indikatorer, efter en delvis fill og mens en risikogrænse er aktiv. Brug samme hændelsesrækkefølge, og bevar simulatorens tilfældighedstilstand, hvis den bruger en. Sammenlign den første beslutning efter gendannelsen, ordre- og fillregistreringerne samt egenkapitalkurven. En enslydende slutbalance kan skjule fejl, der udligner hinanden.

Ved et nedbrud efter indsendelse, men før kvittering, skal harnessen også bevare eksekveringstjenestens tilstand uafhængigt af strategiprocessen. Ellers sletter den netop den usikkerhed, du prøver at teste.

En strategis specifikation omfatter det, den husker. Gør den hukommelse så eksplicit, at du kan afbryde processen halvvejs gennem en afspilning og vise præcis, hvordan den kommer i gang igen.

strategitilstandbacktestinggendannelse fra checkpointpapertrading
← Alle indlæg