1 november 2026 · forskning

Hur värmer man upp ett backtest utan att räkna lookbacken som resultat?

Hur värmer man upp ett backtest utan att räkna lookbacken som resultat?

En 20-dagars Donchian ser harmlös ut i en spec. Agenten skriver ett rullande 20-bars max, backtestet startar på rad ett i parquet-filen, och under de första två veckorna är "20-dagars high" bara löpande max av de bars som råkar finnas. På dag fyra är det en fyradagars high. Strategin du trodde att du testade är inte den som producerade de första dussinet fills.

Jag har en notebook med dagliga ETHUSDT-bars där Sharpe för hela urvalet är 1.4. Klipp bort de första 20 sessionerna och den faller till 0.6. Behåll de 20 och släng resten av år ett, och den skriver 3.1. Ingen läckte morgondagen. Strategin använde det förflutna, bara inte tillräckligt av det, och rapporten behandlade de halvfärdiga affärerna som evidens.

1.4Sharpe för hela urvalet, ofullständigt fönster inräknat
0.6samma kod efter 20 färdiga sessioner
3.1Sharpe om du bara behåller burn-in-affärerna

Låt fönstret handla medan det fortfarande fylls

Den vanliga förödelsen är min_periods=1. Pandas räknar ett rullande medel på en enda bar om du låter det. Agenter gör det här hela tiden, för en NaN högst upp i framen känns som en bugg, och att fylla den gör att unit testet blir grönt.

Ett 20-dagars realized-vol-mål med två avkastningsobservationer är en size-explosion. Variansen av två tal är ett myntkast, du inverterar den, och den första positionen är flera gånger den avsedda risken. En z-score mot en standardavvikelse nära noll gör samma trick med ett tecken: strategin verkar ha en knivskarp entry som aldrig dyker upp igen när fönstret är ärligt.

Breakouts är värre, för de ser ut som den riktiga regeln. En 20-bars kanal på bar sex är en sex-bars kanal. Du får ett kluster av affärer precis i starten, ofta i en stilla period som inte skulle ha triggat den färdiga indikatorn. Stilla marknader driver lite. En tight kanal triggar. Equity-kurvan får ett försprång som inget senare år upprepar.

Zero-fill och forward-fill hittar på en annan lögn. RSI på 0 läses som översåld. En saknad ATR på 0 spränger unit size, och backtestet köper plikttroget ett lager. Jag tar hellre att en NaN dödar ordern än att en 0 hittar på en.

Jag ertappar mig fortfarande med att plotta från rad 0 eftersom en tom månad till vänster i diagrammet ser ofärdig ut. Den tomma månaden är den ärliga delen.

Beskär equity-kurvan, behåll positionen

Den här överlever code review. Du beräknar 20-dagars features korrekt, slänger de första 20 raderna från den plottade kurvan och publicerar från 21 januari. Positionen den 21 januari öppnades den 14 januari. Trailing stopens high-water, pyramidantalet, kassan efter de burn-in-affärerna: alltihopa vandrade in i det "rena" urvalet.

Förödelsen är en paper-strategi som inte kan startas på datumet i artikeln. Starta om från flat vid den rapporterade starten och den första veckans ordrar stämmer inte överens. Ibland är backtestet redan inne i en affär som papersystemet inte har någon anledning att gå in i. Ibland går papersystemet in för att dess lookback är kall, och backtestet sitter utanför för att dess dolda månad redan tog breakouten. Två öppningsböcker, ett publicerat startdatum.

Walk-forward-fold gör det här i tysthet. Varje testfönster har en lookback-svans som du inte plottar. Hoppa över att simulera den svansen och de första testaffärerna är återigen affärer från ofullständiga fönster. Simulera den och rapportera bara testdagarna, och testdagens position är villkorad av fills du inte visar. Den andra versionen kan vara ett legitimt forskningsval. Att kalla foldens första morgon för en kallstart, medan en trailing stop redan är live från svansen, är hur två forskare får två Sharpe ur en config.

Om omstart från flat vid det publicerade startdatumet ändrar P&L, sitter warmupen i track record. Lookback-datan får finnas. Lookback-affärerna får inte.

Värm upp i kalenderdagar när featuren inte är en dag

"Ge den 30 dagar" lämnar featuren underspecificerad. Trettio kalenderdagar på en 5-minuters Donchian är tusentals bars förbi en 20-periods lookback. Trettio dagar på en daglig feature som behöver 20 sessioner är antingen tjock eller tunn, beroende på helger och hål.

En funding-rate z-score på en av våra perp-venues fick en 30-dagars warmup för att specen sa 30 perioder och någon översatte perioder till kalender. Funding där printas var åttonde timme. Trettio dagar är ungefär 90 settlements. Trettio perioder är tio dagar. De extra två månaderna av burn-in råkade innehålla en depeg-vecka. Att slänga den gjorde att live-fönstret såg lugnare ut än strategins verkliga historik. Folk skyllde på startdatumskänslighet. Warmupen hade ätit regimen.

Och krypto kontra aktier gör att samma siffra byter betydelse utan att någon redigerar en parameter. Tjugo "dagar" av ETH inkluderar lördagar. Tjugo aktiesessioner är nästan en kalendermånad. Kopiera en 20-dagars lookback från en aktie-notebook till timvisa perpetual-candles och du har en 20-timmars kanal med ett 20-dagars namn. Den första giltiga baren är då antingen 20 timmar in, eller 20 dagar in om någon senare funktion resamplar, och jag har sett båda i samma agent-diff.

Spika den första handelsbara timestampen

Warmupen är ett datakrav, inte ett bonusurval. Varje feature anger antalet färdiga observationer den behöver, i de enheter den beräknas i. Den första handelsbara timestampen är den första baren där allt det är sant och ett flat konto skulle ha fått skicka en order.

FeatureVad specen vanligtvis sägerVad som faktiskt måste finnasTyst substitut
20-dagars Donchian20 dagliga highs20 avslutade sessionerRullande max med min_periods=1
30-dagars realized vol30-dagars fönster30 close-to-close-avkastningarTvådagars varians, inverterad till size
20-print funding z-score20 dagar20 funding-settlements20 kalenderdagar (~90 prints), eller 20 bars av fel tidsram
14-periods RSI på 5m14 perioder14 stängda femminutersbars14 dagar, eller 14 bars med luckor forward-fillade

P&L före den timestampen stannar utanför track record. Tillståndet före den timestampen kan fortfarande behöva simuleras, så en trailing stop eller en cooldown är verklig när klockan når den första handelsbara baren, men de fills går inte in i Sharpe, trade count eller capacity-matten. Kör sedan den fula kontrollen: starta om från flat vid den timestampen, med lookbacken tillgänglig bara som data. Om ordrarna ändras skeppade du dolda affärer.

Paper trading startar på samma kontrakt. Det gör varje walk-forward-testfönster också. Om diagrammet ser ut som att det saknas en månad, låt den saknas.

backtestingdata engineeringwalk-forwardAI-agenterpaper trading
← Alla inlägg