Vi startet en paperstrategi på nytt halvveis i en handel og fikk en annen ordresekvens enn den strategien hadde produsert før omstarten. Samme markedsdata, samme strategiversjon, samme kontosaldo. Signalkalkuleringen stemte. Strategiens minne om posisjonen og de ventende ordrene gjorde det ikke.
Vi sporet avviket gjennom en dags replayarbeid. Lærdommen var enkel: En omstart er en markedshendelse for programvaren din. Hvis du ikke tester hvordan strategien bygger opp tilstanden sin på nytt, kan en ryddig backtest skjule at et paperhandelssystem glemmer hva det har.
09:10 — Vi valgte en kjedelig posisjon
Teststrategien handlet en likvid perpetual: Den gikk long når et kort glidende gjennomsnitt krysset over et lengre, og gikk ut ved motsatt kryss. Vi startet replayen med en liten, allerede åpen posisjon og en reduce-only limitordre som lå inne for å redusere den. Dermed måtte gjenopprettingen rekonstruere to ting: hva vi eide, og hva vi allerede hadde bedt handelsplattformen om å gjøre.
Ved kontrollpunktet hadde kontoen 0.04 kontrakter. Ordren var på 0.01. Strategiprosessen hadde mellomlagret begge verdiene i minnet, men oppstartsrutinen hentet bare posisjonen. Den behandlet den mellomlagrede ordren som om den var borte.
09:25 — Den første duplikatordren dukket opp
Etter omstarten så strategien den eksisterende long-posisjonen, kjørte signallogikken og sendte inn enda en trimmeordre på 0.01. Paperhandelsplattformen hadde nå to aktive ordrer. Ingen av dem var feil i seg selv. Samlet kunne de selge dobbelt så mye som planlagt hvis begge ble fylt.
Først ga vi signalløkken skylden. Det var ikke løkken, men det ufullstendige øyeblikksbildet. Strategien spurte: «Hvilken posisjon har jeg?» men aldri: «Hvilke ordrer ligger fortsatt inne?»
| Tilstand etter omstart | Dette trodde prosessen | Dette hadde kontoen |
|---|---|---|
| Posisjon | Long 0.04 | Long 0.04 |
| Åpne trimmeordrer | Ingen | To på 0.01 hver |
| Planlagt eksponering etter én fylling | Long 0.03 | Kunne bli long 0.02 |
10:00 — Vi rettet gjenopprettingen og fant så en timingkant
Vi endret oppstarten slik at den bygget opp tilstanden på nytt fra kontoens posisjoner og åpne ordrer før nye beslutninger ble aktivert. Da forsvant duplikatet. Deretter gjorde vi frakoblingen mindre ryddig: Én ordre ble fylt mens strategien var offline, og fyllingsvarslingen kom etter at forbindelsen var gjenopprettet.
Kontosnapshotet viste allerede fyllingen. Den forsinkede varslingen reduserte så den lokale posisjonen én gang til. I noen sekunder trodde strategien at den hadde 0.02 kontrakter, mens kontoen hadde 0.03. Den neste rebalanseringen bygget på en fiktiv underdekning.
Vi la til regler for avstemming: Bruk kontosnapshotet som utgangspunkt, bruk hendelsesidentifikatorer til å ignorere fyllinger som allerede er tatt med der, og ikke send inn ordrer før den første synkroniseringen er fullført. En varsling kan komme sent eller to ganger. Gjenopprettingen må tåle begge deler.
13:40 — Replayen avdekket et stille avvik
Vi spilte av det samme prisforløpet for den opprinnelige kjøringen og kjøringen etter omstart. En sammenligning av endelig P&L ville ikke ha fanget problemet: Begge versjonene endte med samme posisjon etter at markedet snudde. Det var sammenligningen av ordrehendelsene som avslørte det.
Vi logget hver beslutning sammen med tilstanden den leste: posisjon, åpne ordrer, sist behandlede fyllingsidentifikator, signalverdi og strategiversjon. Da kunne vi forklare den første hendelsen der kjøringene skilte lag. Den ene så en aktiv ordre; den andre så en tom liste. Senere behandlet den ene en fylling to ganger.
Samme saldo til slutt beviser ikke at atferden var den samme. Sammenlign sekvensen av beslutninger og ordrer, særlig rundt grensene for gjenoppretting.
16:20 — Hva vi ville gjort annerledes neste gang
Vi brukte for lang tid på å spille av prisdata før vi undersøkte tilstandsendringene på kontoen. Neste gang ville vi først injisert feiltilfellene og holdt markedsforløpet nesten flatt. Da blir programvarefeilen enkel å se, uten at en volatil kursbevegelse gjør diagnosen uklar.
- Start på nytt med en posisjon og en delvis fylt ordre.
- Koble fra etter innsending, og koble til igjen før fyllingsvarslingen kommer.
- Send den samme fyllingshendelsen to ganger, og kontroller at tilstanden bare endres én gang.
- Blokker nye ordrer til både posisjoner og åpne ordrer er avstemt.
- Sammenlign beslutnings- og ordrel logger mellom kjøringer uten avbrudd og kjøringer med omstart.
Vi lærte også å lagre et gjenopprettingssnapshot sammen med strategiversjonen og hendelsesloggen. Da kunne vi gjenskape feilen på minutter, i stedet for å være avhengige av at noen husket den nøyaktige sekvensen for gjenoppkobling.
En paperstrategi som bare oppfører seg riktig så lenge prosessen kjører, har ikke bestått en full gjennomkjøring. Start den på nytt midt i en posisjon, la fyllinger komme sent, og undersøk hver ordre den sender etterpå. Målet er ikke å bevise at den aldri feiler. Målet er å gjøre gjenopprettingen synlig før paperkontoen må lære deg den samme leksen på overraskende vis.
← Alle innlegg


