Egy ügylet felénél újraindítottunk egy papírkereskedési stratégiát, és az újraindítás előtti megbízássorozattól eltérőt kaptunk. Ugyanazok a piaci adatok, ugyanaz a stratégiaverzió, ugyanaz az egyenleg. A jelzésszámítás egyezett. A stratégia viszont nem jól emlékezett a pozíciójára és a függő megbízásaira.
Egy napnyi újrajátszás során követtük végig az eltérést. A tanulság egyszerű volt: a szoftver számára az újraindítás piaci esemény. Ha nem teszteled, hogyan építi fel újra az állapotát a stratégia, egy tiszta visszateszt elfedheti, hogy a papírszámlás rendszer elfelejti, mije van.
09:10 — Egy eseménytelen pozíciót választottunk
A tesztstratégia egy likvid perpetual kontraktussal kereskedett: long pozíciót nyitott, amikor a rövid mozgóátlag a hosszú fölé keresztezett, majd a fordított kereszteződésnél zárt. Az újrajátszást egy már nyitott, kis méretű pozícióval kezdtük, amelyhez egy reduce-only limitmegbízás tartozott a pozíció csökkentésére. A helyreállítás során így két dolgot kellett rekonstruálni: mink volt, és mit kértünk már a piactól.
Az ellenőrzőpontnál a számlán 0.04 kontraktus volt. A 0.01-es megbízás nyitva állt. A stratégiafolyamat mindkét értéket a memóriában tárolta, az indulási folyamat azonban csak a pozíciót kérte le. Úgy kezelte a gyorsítótárban lévő megbízást, mintha már nem létezne.
09:25 — Megjelent az első duplikált megbízás
Újraindítás után a stratégia észlelte a meglévő long pozíciót, lefuttatta a jelzési logikát, majd beadott egy újabb, 0.01-es csökkentő megbízást. A papírkereskedési piactéren így már két aktív megbízás volt. Külön-külön egyik sem volt hibás. Együtt azonban a tervezett mennyiség kétszeresét adhatták el, ha mindkettő teljesül.
Először a jelzési ciklust hibáztattuk. Nem a ciklus volt a gond, hanem a hiányos állapotfelvétel. A stratégia megkérdezte: „Milyen pozícióm van?”, de azt nem: „Melyik megbízások vannak még érvényben?”
| Állapot az újraindítás után | A folyamat szerint | A számlán valójában |
|---|---|---|
| Pozíció | Long 0.04 | Long 0.04 |
| Nyitott csökkentő megbízások | Nincs | Kettő, egyenként 0.01-es |
| Tervezett kitettség egy teljesülés után | Long 0.03 | Akár long 0.02 is lehet |
10:00 — Javítottuk a helyreállítást, majd találtunk egy időzítési rést
Úgy módosítottuk az indulást, hogy az új döntések engedélyezése előtt a számla pozícióiból és nyitott megbízásaiból építse fel újra az állapotot. Ezzel megszűnt a duplikálás. Ezután kevésbé simára vettük a kapcsolat megszakadását: az egyik megbízás teljesült, miközben a stratégia offline volt, az erről szóló értesítés pedig csak újracsatlakozás után érkezett meg.
A számla pillanatfelvétele már tartalmazta a teljesülést. A késve érkező értesítés ezután még egyszer csökkentette a helyi pozíciót. Néhány másodpercig a stratégia úgy hitte, hogy 0.02 kontraktust tart, miközben a számlán 0.03 volt. A következő újraegyensúlyozását így egy nem létező hiány alapján végezte volna.
Egyeztetési szabályokat vezettünk be: a számla pillanatfelvételét tekintjük kiindulópontnak, eseményazonosítókkal hagyjuk figyelmen kívül azokat a teljesüléseket, amelyek már szerepelnek benne, és az első szinkronizálás befejezéséig nem adunk be megbízást. Egy értesítés késhet vagy kétszer is megérkezhet. A helyreállításnak mindkettőt kezelnie kell.
13:40 — Az újrajátszás egy rejtett eltérést is elkapott
Ugyanazt az árfolyampályát játszottuk újra az eredeti és az újraindított futás során. A végeredményként kapott P&L összehasonlítása nem mutatta volna ki a problémát: a piac fordulása után mindkét változat ugyanazzal a pozícióval zárt. A megbízási események összevetése viszont feltárta az eltérést.
Minden döntést a felhasznált állapottal együtt naplóztunk: pozíció, nyitott megbízások, utoljára feldolgozott teljesülésazonosító, jelzésérték és stratégiaverzió. Így meg tudtuk magyarázni az első eltérő eseményt. Az egyik futásban volt érvényben lévő megbízás, a másikban üres volt a lista. Később az egyik futás kétszer dolgozott fel egy teljesülést.
Az egyező záró egyenleg nem bizonyítja, hogy a működés is egyezett. Hasonlítsd össze a döntések és megbízások sorozatát, különösen a helyreállítás körüli szakaszokon.
16:20 — Mit csinálnánk másképp legközelebb
Túl sok időt töltöttünk az árfolyamadatok újrajátszásával, mielőtt ellenőriztük volna a számlaállapot változásait. Legközelebb először a hibás eseteket idéznénk elő, és szinte változatlanul hagynánk az árfolyampályát. Így könnyebb észrevenni a szoftverhibát, mert egy volatilis elmozdulás nem zavarja meg a diagnózist.
- Indítsd újra a rendszert nyitott pozícióval és részben teljesült megbízással.
- Szakítsd meg a kapcsolatot a megbízás beadása után, majd csatlakozz újra az értesítés megérkezése előtt.
- Küldd el kétszer ugyanazt a teljesülési eseményt, és ellenőrizd, hogy az állapot csak egyszer változik-e.
- A pozíciók és a nyitott megbízások egyeztetéséig tiltsd le az új megbízásokat.
- Hasonlítsd össze a döntési és megbízási naplókat a megszakítás nélküli és az újraindított futások között.
Azt is megtanultuk, hogy a helyreállítási pillanatfelvételt a stratégiaverzió és az eseménynapló mellé kell menteni. Így percek alatt reprodukálhatóvá vált a hiba, és nem kellett valakinek emlékeznie a pontos újracsatlakozási sorrendre.
Egy papírkereskedési stratégia, amely csak addig működik helyesen, amíg a folyamata életben marad, még nem ment át a teljes főpróbán. Indítsd újra pozíció közben, késleltesd a teljesülések érkezését, és vizsgáld meg minden ezután beadott megbízását. Nem az a cél, hogy bebizonyítsd: soha nem hibázik. Tedd láthatóvá a helyreállítás működését, mielőtt a papírszámla váratlanul ugyanarra a tanulságra kényszerít.
← Összes bejegyzés


