Fire tall, alle målt på vår egen paper trading-stack, én strategi, 1-minute BTCUSDT perpetual-signaler, 31 dager og 1,418 ordre. Median tid fra bar close til ordren er bekreftet av børsen: 195 ms. 99-persentilen: 2,970 ms. Median i de 1% av minuttene med høyest realisert volatilitet: 840 ms. Og latencykonstanten som sto i backtest-konfigurasjonen det meste av året før: 0.
Tre av tallene er kjedelige. Alle vet at null er feil, alle bytter det før eller siden ut med noe, og dette «noe» er nesten alltid en konstant noen har valgt på gefühlen. 100 ms, 250 ms, «la oss være på den sikre siden, 500». Tallet som faktisk betyr noe, er 840, fordi det viser at latencyn din avhenger av markedstilstanden, og markedstilstandene der den skyter i været, er de samme som signalet ditt mener å ha funnet noe i.
Slik fordeler de 195 millisekundene seg
Her er hele budsjettet, målt trinn for trinn med tidsstempler fra en monoton klokke skrevet ved hvert ledd. Serveren er en AWS-instans i ap-northeast-1, samme region som endepunktene til handelsplassen. Det er omtrent så bra som et oppsett for en vanlig trader uten samlokalisering kan bli.
| Trinn | p50 | p95 | p99 |
|---|---|---|---|
| Bar close → WS kline-closed-hendelse mottatt | 128 ms | 402 ms | 1,940 ms |
| Parsing + oppdatering av feature-tilstand | 3 ms | 9 ms | 28 ms |
| Beslutning: modelevaluering + risikosjekker | 11 ms | 22 ms | 60 ms |
| Ordre sendt → bekreftelse fra børsen | 47 ms | 180 ms | 1,100 ms |
| Fra start til slutt (målt, ikke summert) | 195 ms | 690 ms | 2,970 ms |
To ting er verdt å merke seg før vi kommer til det interessante. For det første summerer ikke medianene seg: 128 + 3 + 11 + 47 = 189, mens målt median fra start til slutt er 195. Persentiler kan ikke summeres, og hvis du lager et latencyestimat ved å summere p99 for hvert trinn, får du 3,128 ms, mens den faktiske p99 er 2,970. Her er det nært nok, men når trinnene er korrelert i motsatt retning, kan det bli helt feil. Mål hele forløpet.
For det andre: se på den øverste raden. To tredeler av medianbudsjettet går med til å vente på at børsen skal fortelle deg at baren er stengt. Det skyldes ikke nettverket, koden din eller rutingen av ordren. Handelsplassen samler handler i en kline, avgjør at minuttet er over og sender oppdateringen. Den sendes gjennom en kø som deles med alle de andre abonnentene på strømmen.
De 840
Fordeler du alle de 1,418 ordrene etter realisert volatilitet i minuttet som utløste signalet, spriker fordelingen.
| Volatilitetsgruppe for signallinjen | Ordrer | p50 fra start til slutt | p99 fra start til slutt |
|---|---|---|---|
| Nederste kvartil | 201 | 141 ms | 488 ms |
| De to midterste kvartilene | 796 | 183 ms | 1,210 ms |
| Øverste kvartil | 407 | 312 ms | 2,880 ms |
| Øverste 1% av alle minutter | 14 | 840 ms | 4,100 ms |
Alle trinn blir tregere samtidig, og dermed forsterkes effekten. Handelsplassens aggregering og kringkastingskø påvirkes av belastningen på matching engine, så et minutt med 11,000 handler sendes senere enn et minutt med 600. Prosessen din håndterer flere dybdeoppdateringer og flere handler i samme tidsrom, så feature-oppdateringen som vanligvis tar 3 ms, tar 28. REST-ordrebanen konkurrerer med alle andres panikk, og du begynner å se sporadiske 503-feil og nye forsøk som hver koster et helt sekund. Korrelasjonskoeffisienten mellom antall handler i signallinjen og latency fra start til slutt var 0.41 i utvalget vårt. Ikke enormt. Nok til å ødelegge en konstant.
Og strategiene som kommer gjennom en første grovsortering, er overveldende ofte strategier som handler utbrudd, reverseringer, dislokasjoner og likvidasjonskaskader. De utløses nettopp i gruppen der latencyn er verst. Et momentumsignal som bare slår inn når minuttet har beveget seg 40 bps, er strukturelt innrettet slik at det alltid blir betjent av den tregeste utgaven av stacken din.
En gang brukte vi en hel dag på å spore en avvikende forsinkelse på 3.6 sekunder som dukket opp omtrent på samme tidspunkt hver natt. Synderen var logrotate, som kopierte og tømte en fil på 2 GB på samme EBS-volum som prosessen skrev til, og dermed stanset hendelsessløyfen. Markedet var uskyldig. Mål først, og skyld på mikrostrukturen etterpå.
Slik påvirker det en fill
Prisen beveger seg mens du venter. I et tilfeldig minutt var den gjennomsnittlige ugunstige prisbevegelsen i løpet av medianen vår på 195 ms omtrent 1.1 bps mot signalretningen. I minuttene i øverste kvartil, med 312 ms, var den 5.8 bps. I minuttene i øverste 1%, med 840 ms, var det omtrent 14 bps i ugunstig prisbevegelse før ordren i det hele tatt nådde ordreboken.
På BTC-perps spiller spreaden knapt inn her: ett tick på en kurs på 84,000 tilsvarer 0.012 bps, så tapet skyldes ugunstig prisbevegelse, ikke kostnaden ved å krysse spreaden. Flytter du samme strategi til en perp med middels markedsverdi, begynner det andre leddet å slå inn: spreaden på beste kjøps- og salgskurs i utvalget vårt økte fra 1.4 bps i rolige minutter til 6.2 bps i øverste kvartil, og dybden på disse kursene ble redusert med mer enn halvparten. Du betaler for prisbevegelsen, den bredere spreaden og den dårligere dybden samtidig, fordi alt skyldes samme forhold.
Da vi spilte av de samme 31 dagene på nytt med latency betinget av hver enkelt bar, i stedet for en flat 200 ms, ble gjennomsnittlig inngangskurs i backtesten 3.1 bps dårligere. Forskjellen var nesten helt konsentrert i 9% av handlene. Avviket mellom inngangskursen i backtesten og paper trading falt fra 4.2 bps til 0.9 bps. Sharpe i utvalget strategien ble tilpasset på, falt fra 1.7 til 1.1. Det er det ærlige tallet, og det var det hele tiden.
Hva bør du faktisk legge inn i konfigurasjonen
Ikke én enkelt verdi. Dette gjør vi nå:
- Trekk fra utvalget, ikke sett en verdi. Trekk latencyen for hver simulert ordre fra en empirisk fordeling som tar hensyn til aktiviteten i den aktuelle baren. Antall handler og absolutt avkastning holder, og begge finnes allerede i en standard kline. Tilpass fordelingen én gang per handelsplass og ordretype, og beregn den på nytt hver måned.
- Behold halen. Ikke tilpass en lognormalfordeling og tro at jobben er gjort. p99 finnes i stormer av nye forsøk og GC-pauser som ingen jevn fordeling gjenskaper. Vi bruker empiriske kvantiler og trekker nye utvalg fra halen over p95.
- Latency gjelder også kanselleringer. En erstatning av en stop-ordre eller en kansellering av en hedge er underlagt samme forsinkelse, og i raske markeder konkurrerer kanselleringen din med en fill. Hvis simulatoren din kansellerer umiddelbart, er risikomodellen din oppdiktet.
- Legg til en foreldelsessjekk, og simuler den. Vår løsning forkaster alle signaler der baren er mer enn 1.5 sekunder gammel ved ankomst. Det er en reell atferd med reelle kostnader: den fjerner handler i det stille, og de samme handlene må fjernes i backtesten.
- Kalibrer på nytt mot paper trading. Paper trading gir deg fasiten. Logg de fire tidsstemplene for hvert ledd på hver ordre, og sammenlign fordelingene med det simulatoren la til grunn hver uke.
Samme problem i andre aktivaklasser. Amerikanske aksjer: den konsoliderte kursstrømmen legger til sin egen aggregeringsforsinkelse på toppen av meglerens, og den øker når meldingstrafikken blir høy, av samme strukturelle grunn. Prediksjonsmarkeder: de fleste handelsplasser tar bare imot ordre via REST, og vi har målt medianer under 100 ms som øker til flere sekunder når en avgjørelse skal fattes og alle kommer samtidig. Kryptoopsjoner: kursen du priser ut fra, kan være 2 sekunder gammel akkurat i det minuttet det underliggende aktivumet beveget seg.
Den generelle feilen er å behandle en utførelsesparameter som en uavhengig konstant når den i virkeligheten avhenger av den samme tilstandsvariabelen som driver signalet ditt. Gebyrer oppfører seg forutsigbart; funding oppfører seg forutsigbart; latency gjør det ikke. Hvis du skal huske ett tall fra alt dette, så husk forholdstallet: p99-en vår er femten ganger medianen, og signalene våre kommer uforholdsmessig ofte nær p99.
Instrumenter de fire leddene. Det tar en ettermiddag, og det forteller deg mer om strategien din enn enda en uke med parametersøk.
← Alle innlegg


