Vi startade om en pappershandelsstrategi mitt i en affär och fick en annan ordersekvens än den som hade skapats före omstarten. Samma marknadsdata, samma strategiversion, samma kontosaldo. Signalen beräknades likadant. Strategins minne av positionen och de väntande ordrarna gjorde det inte.
Vi spårade avvikelsen under en dags replayarbete. Lärdomen var enkel: en omstart är en marknadshändelse för din programvara. Om du inte testar hur strategin återställer sitt tillstånd kan ett rent backtest dölja ett pappershandelssystem som glömmer vad det har.
09:10 — Vi valde en händelselös position
Teststrategin handlade en likvid perpetual: gå lång när ett kort glidande medelvärde korsade upp över ett längre, och stäng sedan positionen vid den omvända korsningen. Vi startade uppspelningen med en liten öppen position och en vilande reduce-only-limitorder för att minska den. Då behövde återställningen återskapa två saker: vad vi ägde och vad vi redan hade bett handelsplatsen göra.
Vid kontrollpunkten hade kontot 0.04 kontrakt. Ordern låg öppen på 0.01. Strategiprocessen hade cachat båda värdena i minnet, men vid uppstart hämtades bara positionen. Den utgick från att den cachade ordern inte längre fanns.
09:25 — Den första dubbla ordern dök upp
Efter omstart såg strategin den befintliga långpositionen, körde signallogiken och skickade ytterligare en trimorder på 0.01. Pappershandelsplatsen hade nu två aktiva ordrar. Ingen av dem var dålig i sig. Tillsammans kunde de sälja dubbelt så mycket som avsett om båda gick till avslut.
Först skyllde vi på signalloopen. Det var inte loopen, utan den ofullständiga ögonblicksbilden. Strategin frågade: ”Vilken position har jag?” men aldrig: ”Vilka ordrar är fortfarande aktiva?”
| Tillstånd efter omstart | Vad processen trodde | Vad kontot hade |
|---|---|---|
| Position | Lång 0.04 | Lång 0.04 |
| Öppna trimordrar | Inga | Två på 0.01 vardera |
| Avsedd exponering efter ett avslut | Lång 0.03 | Kan bli lång 0.02 |
10:00 — Vi fixade återställningen och hittade sedan en timingkant
Vi ändrade uppstarten så att tillståndet återskapas från kontots positioner och öppna ordrar innan nya beslut får fattas. Det tog bort dubbelordern. Sedan gjorde vi frånkopplingen mindre prydlig: en order gick till avslut medan strategin var offline, och avslutsnotisen kom efter återanslutningen.
Kontots ögonblicksbild visade redan avslutet. Den fördröjda notisen minskade sedan den lokala positionen en gång till. Under några sekunder trodde strategin att den hade 0.02 kontrakt när kontot hade 0.03. Nästa ombalansering byggde på en påhittad positionbrist.
Vi lade till regler för avstämning: utgå från kontots ögonblicksbild, använd händelseidentifierare för att ignorera avslut som redan ingår där, och skicka inga ordrar förrän den första synkroniseringen är klar. En notis kan komma sent eller två gånger. Återställningen måste tåla båda fallen.
13:40 — Uppspelningen fångade en diskret avvikelse
Vi spelade upp samma prisförlopp för den ursprungliga körningen och körningen efter omstart. En jämförelse av slutlig P&L hade missat problemet: båda versionerna slutade med samma position efter att marknaden vänt. Jämförelsen av orderhändelser avslöjade det.
Vi loggade varje beslut tillsammans med tillståndet det läste: position, öppna ordrar, senast behandlade avslutsidentifierare, signalvärde och strategiversion. Då gick den första avvikande händelsen att förklara. Den ena körningen såg en aktiv order; den andra såg en tom lista. Senare tillämpade den ena ett avslut två gånger.
Ett matchande slutsaldo bevisar inte att beteendet varit detsamma. Jämför sekvensen av beslut och ordrar, särskilt kring återställningen.
16:20 — Vad vi skulle göra annorlunda nästa gång
Vi lade för mycket tid på att spela upp prisdata innan vi kontrollerade kontots tillståndsövergångar. Nästa gång skulle vi börja med att injicera felfallen och hålla marknadsförloppet nästan plant. Då syns programvarufelet tydligt, utan att en volatil prisrörelse försvårar felsökningen.
- Starta om med en position och en delvis avslutad order.
- Koppla från efter orderläggningen och återanslut innan avslutsnotisen kommer.
- Skicka samma avslutshändelse två gånger och kontrollera att den bara ändrar tillståndet en gång.
- Blockera nya ordrar tills både positioner och öppna ordrar har stämts av.
- Jämför besluts- och orderloggar mellan oavbrutna körningar och körningar efter omstart.
Vi lärde oss också att spara en återställningsögonblicksbild tillsammans med strategiversionen och händelseloggen. Det gjorde felet möjligt att återskapa på några minuter, i stället för att förlita sig på att någon kom ihåg den exakta sekvensen vid återanslutningen.
En pappershandelsstrategi som bara beter sig korrekt så länge processen är igång har inte klarat en fullständig övning. Starta om den mitt i en position, låt avslut komma sent och granska varje order den skickar efteråt. Poängen är inte att bevisa att den aldrig fallerar. Poängen är att göra återställningen synlig innan pappershandelskontot tvingas lära dig samma sak genom en överraskning.
← Alla inlägg


