På måndagen gjorde vi det ansvarsfulla. Agenten hade en momentumstrategi på en mid-cap USDT-M-perpetual, som clippade 25,000 USDT per trade, och den första backtesten utan volymfilter fyllde varje signal som om orderboken vore BTC. Så vi lade till den klassiska grinden: tjugo 1-minutersstaplar av dollarvolym måste överstiga tjugo gånger clippet innan en order fick gå ut. Tjugo minuter, en halv miljon dollar i tape. Myntet printade ungefär $40 million på en hektisk dag. Filtret släppte igenom de flesta signalerna. Equitykurvan blev mindre hackig. Vi skickade den till paper.
Elva timmar senare åt ett köp på 25,000 USDT 8,400 av bid och stannade. Volymen över tjugo staplar den minuten var $1.14 million. Filtret hade sagt ja.
Måndag: filtret som fick oss att känna oss ärliga
Agentens kommentar på pull requesten var "kapacitetskontroll tillagd, 20× notional." Jag godkände den. Jag har godkänt den meningen förut. Det är den sortens regel man skriver efter att någon visat en backtest som tradade ett $4,000-OI-mynt i $50,000-clip, och alla i rummet gör en grimas, och man lägger till en volymmultipel så att det inte kan hända igen.
På måndagen gjorde regeln det den alltid gör i en backtest. Den strök de döda timmarna. Den behöll timmarna där börsens egen volymsiffra såg högljudd ut. Omsättningen föll med ungefär en tredjedel. Genomsnittlig tradestorlek stannade på 25,000 för fill-modellen är en fegis: den tar hela clippet till last-plus-några-bps så fort grinden är öppen. Ingen frågade orderboken om 25,000 faktiskt låg där.
Jag rycker fortfarande till när ett mynts 24h-volym är ett jämnt tal bredvid tunt open interest. Det är rester från 2021, när Discords "market making"-bottar var två underkonton som tradade med varandra och klistrade in volymskärmdumpen i #brag. Tapen ser ut som en fest. Orderboken är papp. Jag sa till mig själv att ett 20×-filter på 1-minutersstaplar var hur man växer ifrån det. Det är det inte. Det är hur man medelvärdesbildar pappen till en jämnare siffra.
Tisdag: paper, sedan en rest
Paper började snällt. De första fem clippen fylldes på 2–4 hopp nerför ask. Fult, men klart. Sedan 14:07 UTC, en long-signal, 25,000 USDT, topp i orderboken 1,100, nästa nivå 2,400, sedan luft. Vi fick 8,400 fyllt som taker och 16,600 liggande. Fyrtio sekunder senare avbröts resten på vår egen time-in-force. Strategin trodde att den var long ett helt clip. Kontot var long en tredjedel av ett.
Men filtret hade sagt ja. Jag drog fram stapeln. Dollarvolymen under de tjugo minuterna fram till 14:07 var $1.14 million, bekvämt över $500k. Ungefär $380k av de $1.14 million var par av prints: samma pris, samma storlek, motsatta aggressor-flaggor, 2–8 millisekunder isär, och bid/ask-storleken på det priset rubbades inte. De traden betalade avgifter till varandra. De erbjöd oss inte ett hål på 25,000 USDT.
Onsdag: att matcha tapen mot orderboken
Onsdagen var den långsamma dagen, den jag skulle budgetera dubbelt så lång tid för nästa gång. Vi tog fem vardagar av trades och L2-snapshots på samma perp, 100ms orderboksfoton, och klassificerade varje print mot orderboken en snapshot före och en snapshot efter.
- Om storleken på tradepriset sjönk med ungefär tradestorleken rörde den orderboken. Räkna den.
- Om ett köp och en försäljning av samma storlek printade på ett pris utan förändring i orderboken, kalla det wash och släpp det från varje kapacitetssiffra.
- Om en trade vandrade genom flera nivåer och de nivåerna försvann är det en riktig taker. Räkna den, och låtsas inte att du också kan ta den likviditeten; någon har redan gjort det.
- Om traden är taggad som en likvidation är det riktig storlek, och det är den sista storleken du vill använda som bevis för att du kan clippa 25,000. Den tvingade ordern tävlar med dig.
Snapshoten ljuger lite. Allt som fylls och fylls på igen inom 100ms ser ut som ett spöke, och en del genuina market makers gör cancel-replace så snabbt. Vi samplade några minuter av 10ms-böcker senare och wash-andelen rörde sig med ett par procentenheter, inte med en faktor två. Jag kan leva med ett par procentenheter. Jag kan inte leva med att behandla börsens volymticker som en likviditetsräkning.
AggTrades slår redan ihop en taker som träffar flera makers på ett pris. De slår inte ihop två underkonton som washar. Om ditt "rena" flöde är aggregerade trades har du fortfarande det här problemet. Du har det bara med färre rader.
Och 24h-volymen på ticker-API:t är samma smutsiga summa, fördröjd, vilket är därför research-agenter älskar den. Ett fält. Alltid där. Ser ut som en feature. Det är en marknadsföringsstatistik som råkar ligga i market-data-protobufen.
Torsdag: veckan i en tabell
Fem sessioner, samma clip, samma 20×-regel, samma fill-modell i backtesten. Paper-fill-kvoten är fylld notional över avsedd notional för ordrarna vi faktiskt skickade den sessionen. Måndagens paper är tomt för vi var fortfarande i backtesten.
| Session | Börstape | Orderboksflyttande | Wash-liknande | Likv. prints | Filtret sa kör | Paper-fill |
|---|---|---|---|---|---|---|
| Mån | $38.4m | $22.6m | $13.5m | $2.3m | 41 / 48 signaler | n/a |
| Tis | $41.1m | $24.2m | $15.2m | $1.7m | 36 / 40 | 0.61 |
| Ons | $29.6m | $20.1m | $8.1m | $1.4m | 22 / 31 | 0.77 |
| Tor | $44.8m | $25.6m | $17.4m | $1.8m | 39 / 44 | 0.54 |
| Fre | $33.2m | $22.3m | $9.4m | $1.5m | 28 / 35 | 0.71 |
Wash-liknande prints var 34% av veckans tape. De var inte jämnt fördelade. Torsdagen, sessionen originalfiltret gillade mest, var den smutsigaste. Det är felsättet jag bryr mig om. Grinden överskattar inte bara likviditeten i genomsnitt. Den öppnar sig vidare de dagar wash-bottarna jobbar, för det är då råsiffran ser som friskast ut.
Vi körde om backtesten med enbart orderboksflyttande volym, samma 20×-multipel. Signalerna sjönk från 198 under veckan till 121. Många av de bortkastade låg i de där torsdagsaktiga timmarna där tapen var högljudd och toppen av orderboken var 1,100 USDT. Original-Sharpe använde 198 fulla fills. Jag tänker inte citera den nya som om den vore ett fynd om strategin. Det är ett fynd om fill-modellen: när du slutar bevilja 25,000 USDT till ett pris orderboken inte hade är en bit av "edgen" bara kompletta ordrar som skulle ha varit rester.
Fredag: vad vi faktiskt släpper, och vad jag skulle hoppa över
Grinden vi behöll är tråkig. Rullande orderboksflyttande notional, räknad bara från prints som tog storlek av en nivå, måste klara 20× clippet, och vi mäter den på staplarna före beslutsstapeln så att den aktuella minutens wash inte kan rösta. Likvidationsprints får ett separat tak: om mer än en fjärdedel av den senaste orderboksflyttande volymen är likvidationer står strategin över. Tvingat flöde är riktig storlek som tävlar med dig.
Impact fick samma diet. Den gamla modellen härledde en Kyle-lambda från börsvolym och vårt clip. Mata den med wash och lambda går ner, för marknaden ser djup ut. Mata den med orderboksflyttande volym och samma clip är en mycket större andel av det som faktiskt ändrade orderboken. Paper-slippage på de nästa sessionerna låg närmare den fulare siffran. Närmare, inte identiskt. Vi ser fortfarande inte kön, och ett 100ms-foto missar fortfarande en del genuin storlek.
Det jag skulle hoppa över nästa gång är hela den första måndagen. Börja inte från tickern, börja inte från 24h-volym, låt inte agenten lägga rå dollarvolym i feature store och i grinden som om det vore två idéer. Det är en smutsig serie, använd två gånger. Bygg den orderbokskonsistenta tapen först, även om det betyder att du researchar i två dagar på en enda mid-cap innan du har ett universum. Ett universum filtrerat på wash är en lista över mynt som är duktiga på att se upptagna ut.
Det andra att hoppa över: varje fill-modell som behandlar en passerad volymkontroll som en fill. Tisdagens rest var strategin. Filtret kan bara svara "har någon tradat." Det kan inte svara "kommer dina 25,000 att ligga kvar eller försvinna." Den andra frågan behöver orderboken, en rest och en time-in-force, vilket är en annan dagbok, och den vi borde ha skrivit före den här.
← Alla inlägg


