On yksi kysymys, jota jokainen backtesti väistää: olisiko sama koodi, samaa markkinaa livenä syötettynä, tehnyt saman asian? Siihen ei voi vastata lisäbacktestauksella. Vastauksen saa vain ajamalla strategiaa live-datalla aidoilla toteutussemantiikoilla ja tarkistamalla sitten — kauppa kaupalta — että nuo kaksi maailmaa ovat yhtä mieltä. Teemme tämän tarkistuksen joka päivä automaattisesti, ja se on ollut koko alustan tuotteliain buginlöytäjä.
Päivä yksi: rakenna peilikuva
Jokainen ylennetty strategia pyörii omassa eristetyssä live-nodessaan ja kuluttaa aitoja pörssistreameja: live-noteeraukset täyttöihin, todelliset spreadit, todelliset kaupankäyntiajat. Strategioiden välillä ei ole jaettua tilaa (opimme sen kantapään kautta — jaetussa nodessa yhden strategian positiokyselyt vuosivat toisen puolelle). Jokainen täyttö kirjataan yhdessä sen tuottaneen signaaliarvon kanssa.
Joka aamu: replay ja diff
Päivittäinen ajo ottaa kunkin strategian paper-ikkunan, ajaa identtisen koodin backtest-moottorin läpi samalta ajanjaksolta katalogidatalla ja täsmää täytöt yksi yhteen: sama suunta, sama aikaleimatoleranssi, sama koko. Tuloksena ei ole korrelaatio eikä fiilis. Se on taulukko: täsmätyt, vain paperissa, vain replayssä. Terve strategia asettuu lukemaan 54/55 täsmättyä. Epäterve kertoo täsmälleen, mikä kauppa erkani ja milloin.
Mikä hajosi, siinä järjestyksessä kuin se hajosi
- Lämmittelytäytöt. Live-node syötti historiaa indikaattorien lämmittelyyn — ja strategiat, joilla oli omat bar-käsittelijät, kävivät sillä iloisesti kauppaa. Backtestit eivät nähneet noita haamusisäänmenoja koskaan. Korjaus tehtiin tilauskerrokseen eikä yksittäiseen strategiaan, koska muuten jokainen strategia perii bugin.
- Peräkkäinen monijalkainen lämmittely. Poikkileikkausstrategia lämmitteli yhden instrumentin kerrallaan; jokainen jalka näki sisarensa tyhjinä eikä ankkuria alustettu koskaan. Livenä se ei käynyt kauppaa lainkaan; replayssä se toimi hyvin. Nolla täsmättyä kauppaa — mutta vain diff sanoi sen ääneen.
- Tick-tarkkuuden kaatumissilmukat. Livenä aggTrade-tickit saapuvat eri tarkkuudella kuin sandbox-instrumentti odotti. Node kaatui silmukassa assertioon, jota backtesti ei voisi koskaan laukaista, koska katalogin barit on jo normalisoitu.
- Uudelleenkäynnistysamnesia. Prosessin uudelleenkäynnistykset laukaisivat sisäänmenologiikan uudelleen positioille, jotka olivat jo olemassa — tasapainottavalle strategialle uudelleenkäynnistyksestä tuli hiljaisesti uudelleentasapainotus. Live-kaupankäynnissä se ei ole pariteetin alaviite; se on hälytysmerkki, jossa on rahaa kiinni.
Huomaa kaava: yksikään näistä ei ole signaalibugi. Ne ovat kaikki toteutusrajapinnan bugeja — lämmittely, tila, tarkkuus, uudelleenkäynnistykset. Juuri sille vikaluokalle backtestit ovat rakenteellisesti sokeita, koska backtestissä toteutusrajapinta on backtest-moottori.
Epäsymmetriat, jotka pidämme tarkoituksella
Nuo kaksi maailmaa eivät ole tahallaan identtisiä. Backtesti veloittaa mallinnetun puolikkaan spreadin plus neliöjuurivaikutuksen PnL:n sisällä; paper maksaa todellisen spreadin täyttöhinnassa eikä mallinna vaikutusta lainkaan. Mallinnetun spreadin lisääminen paperiin (tai todellisen backtesteihin) laskisi saman kulun kahteen kertaan. Pariteetti tarkoittaa samoja päätöksiä ja samoja täyttöjä toleranssin sisällä — ei bitilleen identtistä PnL:ää. Suurin osa kurinalaisuudesta on juuri sen tietämistä, mitkä erot ovat perusteltuja ja mitkä bugeja.
Backtesti on hypoteesi. Paper trading on koe. Replay-pariteetti on se laboratoriopäiväkirja, joka nappaa sinut huijaamasta itseäsi.
Jos ajat strategioita etkä vertaa live-käyttäytymistä replay-käyttäytymiseen säännöllisellä aikataululla, sinulla on kokonainen bugiluokka, jota et ole koskaan nähnyt. Löydämme yhden suunnilleen parin viikon välein, ja jokainen niistä oli backtestin sisältä katsottuna näkymätön.
← Kaikki kirjoitukset
