Ett användbart backtesttest handlar inte alls om att hitta en bättre parameter: stoppa processen halvvägs, återställ den och kör klart samma uppspelning. Med identiska indata och en kontrollerad exekveringssimulator bör besluten, ordrarna och kapitalutvecklingen matcha en oavbruten körning.
Om de inte gör det har du hittat ett problem med tillståndshanteringen. Strategin är beroende av något som du inte sparade eller inte kunde återskapa. Det beroendet spelar roll när forskningskörningar återupptas, arbetare byts ut eller en tjänst för pappershandel driftsätter ny kod.
Jag gillar det här testet eftersom det förväntade svaret är ovanligt tydligt. Det finns inget att diskutera om huruvida marknaden förändrades. Båda körningarna får samma marknadsdata.
Här är tre felaktiga sätt att starta om. Siffrorna är illustrativa; varje fel kan uppstå i ett i övrigt deterministiskt system.
1. Läs in några få staplar och anta att indikatorerna är uppvärmda
Anta att en strategi använder ett exponentiellt glidande medelvärde med 100 perioder. Uppdateringen ser ut så här:
alpha = 2 / 101
ema_next = alpha * close + (1 - alpha) * ema_previous
Den oavbrutna processen för vidare det ackumulerade EMA-värdet. Den omstartade processen hämtar 100 staplar, initierar EMA med den första stängningskursen och antar att en indikator med 100 perioder behöver 100 observationer.
Det antagandet blandar ihop indikatorns utjämningsparameter med ett ändligt minnesfönster. En EMA behåller ett avtagande bidrag från sitt ursprungliga tillstånd. Om två versioner börjar med en skillnad på 10 priseneheter i EMA-värdet krymper den skillnaden så här när de efterföljande priserna är identiska:
| Uppdateringar sedan initiering | Återstående skillnad | Andel av det ursprungliga felet |
|---|---|---|
| 100 | 1.353 | 13.53% |
| 250 | 0.0674 | 0.674% |
| 500 | 0.000454 | 0.00454% |
Beräkningen är 10 * (99 / 101)^k. Om du hämtar 100 staplar får du bara 99 uppdateringar om den första observationen används som startvärde.
Problemet brukar visa sig nära en beslutsgräns. I den ena körningen ligger priset över EMA-värdet, i den andra under. En liten numerisk skillnad skapar en extra affär. När det väl händer kan även karenstider, tillgängligt kapital och senare beslut börja skilja sig åt.
Spara indikatorns rekursiva tillstånd, dess initieringsstatus och den senast bearbetade händelsen. Alternativt kan du spela upp händelserna från ett känt starttillstånd. En längre uppvärmningsperiod kan ge en godtagbar approximation, men välj dess längd utifrån en uttrycklig feltolerans och kontrollera om toleransen kan ändra besluten. ”Fem gånger perioden” är en tumregel, inte ett bevis.
Och indikatorer är inte hela historiken. En rullande percentil behöver sitt fönster. En modell som lär sig löpande kan behöva sitt optimerartillstånd. En regel som väntar 3 staplar efter en förlust måste komma ihåg förlusten och räknaren.
2. Spara positionerna och glöm ordrarna som är på väg
Din målposition är 10 enheter. En köporder på 10 har fyllts till 4, så 6 återstår. Du sparar positionen som 4, startar om och lägger en ny köporder på de saknade 6.
Om både den ursprungliga återstående volymen och ersättningsordern fylls äger du 16.
I backtestversionen av det här felet förblir problemet ofta dolt, eftersom omstarten av fyllningsmotorn i tysthet raderar aktiva ordrar. Inom pappershandel kan simulatorn eller den externa tjänsten behålla dem. Samma återställningskod ger då olika exponering beroende på vilken komponent som överlevde.
| Vid omstart | Faktiskt tillstånd | Återställning med enbart positionen ser |
|---|---|---|
| Målposition | 10 | 10 |
| Fylld position | 4 | 4 |
| Utestående köpvolym | 6 | 0 |
| Ytterligare volym som behövs | 0 | 6 |
Problemet visar sig som en oförklarlig orderrusning direkt efter återställningen. Ibland fördubblas exponeringen. Ibland stängs en position fast dess skyddsorder fortfarande är aktiv, och den ordern kan senare öppna en ny position.
En kontrollpunkt behöver innehålla orderidentitet och livscykeltillstånd tillsammans med positionerna. Innan återställningen skapar nya åtgärder måste dessa uppgifter stämmas av mot exekveringssystemet. En order med okänt utfall måste undersökas; att tolka ”ingen sparad bekräftelse” som ”aldrig skickad” är så dubblettordrar uppstår.
Stabila klientorder-ID:n hjälper dig att ta reda på vad som hände. De förhindrar dubbletter bara om det mottagande systemet faktiskt upprätthåller kraven på unikhet eller idempotens. Spara även ID:n för redan behandlade exekveringar, så att en upprepad fyllning inte ökar positionen två gånger.
Jag har en svaghet för den där tråkiga skärmen med orderstatus. Dagen för en omstart blir dess små rader plötsligt byggnadens mest intressanta gränssnitt.
3. Återställ positionen och börja på nytt med en P&L-bokföring
Tänk dig ett obelånat spotexempel utan avgifter. Börja med $10,000 i kontanter, köp 10 enheter för $100 styck och spara en kontrollpunkt när marknadspriset når $110.
Det korrekta tillståndet är $9,000 i kontanter plus en position värd $1,100: ett eget kapital på $10,100. Om återställningen läser in de 10 enheterna men återställer kontanterna till ursprungliga $10,000 redovisar den $11,100. Du har skapat $1,000 genom att starta om en process.
Andra varianter är mindre dramatiska. Återställningen bevarar det egna kapitalet men återställer ingångspriset till $110. Det totala egna kapitalet kan fortfarande vara korrekt, medan fördelningen mellan realiserat och orealiserat resultat ändras. Om en stop-loss eller ett utträdesvillkor använder ingångspriset påverkar den bokföringsgenvägen nu handelsbeteendet.
Eller så glömmer systemet den tidigare högsta nivån för eget kapital. Anta att det egna kapitalet nådde en topp på $10,600 innan det föll till $10,100. Nedgången från toppen är cirka 4.72%. Om den högsta nivån återställs vid omstart tror strategin plötsligt att nedgången är noll. Alla riskkontroller som baseras på nedgång från toppen har då återställts utan tillstånd.
Problemet kan alltså visa sig som ett språng i eget kapital, en misstänkt förbättrad nedgång från toppen eller en riskregel som slutar utlösas efter driftsättningar. Bevara bokföringen och strategins tillstånd som beror på den: kapitalrörelser, positioner, relevant anskaffningsvärde, upplupna avgifter och riskkontrollernas minne. Stäm av det återställda egna kapitalet mot bokföringen vid samma värderingstidpunkt.
En kontrollpunkt behöver ha en konsekvent gräns. Om du sparar kontanterna efter en fyllning men positionsvolymen före den fyllningen får du ett tillstånd som aldrig har existerat. Spara relaterade tillstånd tillsammans eller registrera en beständig händelsesekvens som du kan bygga upp tillståndet från. Spara händelsemarkören tillsammans med det tillståndet så att återställningen varken hoppar över fyllningen eller tillämpar den två gånger.
Testet jag skulle behålla i forskningsmiljön kör först en oavbruten referensuppspelning och startar sedan om en andra körning vid avsiktligt besvärliga tillfällen: under indikatorernas initiering, efter en delfyllning och medan en riskgräns är aktiv. Använd samma händelseordning och bevara eventuell slumpstatus i simulatorn. Jämför det första beslutet efter återställningen, order- och fyllningsposterna samt kapitalutvecklingen. Ett matchande slutsaldo kan dölja fel som tar ut varandra.
Vid en krasch efter att en order skickats men före bekräftelsen måste testmiljön även bevara exekveringstjänstens tillstånd separat från strategiprocessen. Annars raderar den just den osäkerhet du försöker testa.
En strategis specifikation omfattar vad den minns. Gör det minnet tillräckligt tydligt för att du ska kunna avsluta processen mitt i en uppspelning och visa exakt hur den kommer i gång igen.
← Alla inlägg


