1. november 2026 · forskning

Hvordan varmer du en backtest op uden at tælle lookback med som performance?

Hvordan varmer du en backtest op uden at tælle lookback med som performance?

En 20-dages Donchian ser harmløs ud i en spec. Agenten skriver et 20-bar rullende maksimum, backtesten starter på første række i parquet-filen, og i de første to uger er "20-dages high" bare det løbende maksimum af de bars, der findes. På dag fire er det en fire-dages high. Strategien, du troede du testede, er ikke den, der producerede de første dusin fills.

Jeg har en notebook med daglige ETHUSDT-bars, hvor Sharpe på hele stikprøven er 1.4. Skær de første 20 sessioner fra, og den falder til 0.6. Behold de 20 og smid resten af det første år væk, og den printer 3.1. Ingen lækkede i morgen. Strategien brugte fortiden, bare ikke nok af den, og rapporten behandlede de halvfærdige handler som evidens.

1.4Sharpe på hele stikprøven, ufærdigt vindue medregnet
0.6samme kode efter 20 afsluttede sessioner
3.1Sharpe, hvis du kun beholder burn-in-handlerne

Lad vinduet handle, mens det stadig fyldes

Den sædvanlige ulykke er min_periods=1. Pandas beregner et rullende gennemsnit på en enkelt bar, hvis du lader den. Agenter gør det konstant, fordi en NaN øverst i framen føles som en bug, og at fylde den får unit testen til at lyse grønt.

Et 20-dages realized-vol-mål med to observationer af afkast er en size-eksplosion. Variansen af to tal er et møntkast, du inverterer den, og den første position er flere gange den tilsigtede risiko. En z-score mod en standardafvigelse tæt på nul gør det samme trick med et fortegn: strategien ser ud til at have en knivskarp entry, der aldrig viser sig igen, når vinduet er ærligt.

Breakouts er værre, fordi de ligner den rigtige regel. En 20-bar kanal på bar seks er en seks-bar kanal. Du får en klynge af handler lige i starten, ofte i en stille periode, der ikke ville have udløst den færdige indikator. Stille markeder driver lidt. En stram kanal fyrer. Equity-kurven får et forspring, som intet senere år gentager.

Zero-fill og forward-fill opfinder en anden løgn. RSI på 0 læses som oversolgt. En manglende ATR på 0 sprænger enhedsstørrelsen, og backtesten køber pligtskyldigt et lagerhus. Jeg vil hellere have, at en NaN slår ordren ihjel, end at et 0 opfinder én.

Jeg tager stadig mig selv i at plotte fra række 0, fordi en blank måned til venstre på chartet ser ufærdig ud. Den blanke måned er den ærlige del.

Beskær equity-kurven, behold positionen

Den her overlever code review. Du beregner 20-dages-features korrekt, fjerner de første 20 rækker fra den plottede kurve og publicerer fra 21. januar. Positionen den 21. januar blev åbnet den 14. januar. Trailing stoppets high-water, pyramideantallet, cash efter de burns: det hele gik med ind i den "rene" stikprøve.

Ulykken er en papirstrategi, der ikke kan startes på datoen i indlægget. Genstart fra flat ved den rapporterede start, og den første uges ordrer stemmer ikke overens. Nogle gange er backtesten allerede i en handel, som papirsystemet ikke har nogen grund til at gå ind i. Nogle gange går papirsystemet ind, fordi dets lookback er koldt, og backtesten står over, fordi dens skjulte måned allerede tog breakoutet. To åbningsbøger, én publiceret startdato.

Walk-forward-folds gør det i al stilhed. Hvert testvindue har en lookback-hale, du ikke plotter. Spring simuleringen af den hale over, og de første testhandler er igen handler med ufærdigt vindue. Simuler den og rapportér kun testdagene, og testdagens position er betinget af fills, du ikke viser. Den anden version kan være et legitimt forskningsvalg. At kalde foldens første morgen en kold start, mens en trailing stop allerede er live fra halen, er hvordan to forskere får to Sharpes ud af én config.

Hvis genstart fra flat på den publicerede startdato ændrer P&L, sidder opvarmningen i track record. Lookback-dataene må gerne være der. Lookback-handlerne må ikke.

Varm op i kalenderdage, når featuren ikke er en dag

"Giv den 30 dage" lader featuren være underspecificeret. Tredive kalenderdage på en 5-minutters Donchian er tusindvis af bars forbi et 20-perioders lookback. Tredive dage på en daglig feature, der har brug for 20 sessioner, er enten fed eller tynd, afhængigt af weekender og huller.

En funding-rate z-score på en af vores perp-venues fik en 30-dages opvarmning, fordi spec'en sagde 30 perioder, og nogen oversatte perioder til kalender. Funding printer der hver ottende time. Tredive dage er omkring 90 settlements. Tredive perioder er ti dage. De ekstra to måneders burn-in ramte tilfældigvis en depeg-uge. At droppe den fik det live vindue til at se roligere ud end strategiets reelle historik. Folk bebrejdede startdato-sensitivitet. Opvarmningen havde spist regimet.

Og krypto versus aktier får det samme tal til at skifte betydning uden at nogen redigerer en parameter. Tyve "dage" med ETH inkluderer lørdage. Tyve aktiesessioner er næsten en kalendermåned. Kopiér et 20-dages lookback fra en aktie-notebook over på timebaserede perpetual-candles, og du har en 20-timers kanal med et 20-dages navn. Den første gyldige bar er så enten 20 timer inde, eller 20 dage inde, hvis en senere funktion resampler, og jeg har set begge i samme agent-diff.

Fastlæg det første handelbare tidsstempel

Opvarmningen er et datakrav, ikke en bonus-stikprøve. Hver feature angiver det antal færdige observationer, den har brug for, i de enheder den beregnes i. Det første handelbare tidsstempel er den første bar, hvor alle de er sande, og en flat konto ville have fået lov til at sende en ordre.

FeatureHvad spec'en plejer at sigeHvad der faktisk skal findesStille erstatning
20-dages Donchian20 daglige highs20 afsluttede sessionerLøbende maksimum med min_periods=1
30-dages realized vol30-dages vindue30 close-to-close-afkastTo-dages varians, inverteret til size
20-print funding z-score20 dage20 funding-settlements20 kalenderdage (~90 prints), eller 20 bars i den forkerte timeframe
14-perioders RSI på 5m14 perioder14 lukkede fem-minutters bars14 dage, eller 14 bars med huller forward-filled

P&L før det tidsstempel hører ikke med i track record. State før det tidsstempel kan stadig skulle simuleres, så en trailing stop eller en cooldown er ægte, når uret rammer den første handelbare bar, men de fills kommer ikke med i Sharpe, antallet af handler eller kapacitetsregnestykket. Kør så det grimme tjek: genstart fra flat ved det tidsstempel, med lookback tilgængelig kun som data. Hvis ordrerne ændrer sig, sendte du skjulte handler.

Papirhandel starter på samme kontrakt. Det samme gør hvert walk-forward-testvindue. Hvis chartet ser ud til at mangle en måned, så lad den mangle.

backtestingdata engineeringwalk-forwardai-agenterpapirhandel
← Alle indlæg