3. november 2026 · eksekvering

Vi paper-handlet en basis-handel. Ett bein ble fylt.

Vi paper-handlet en basis-handel. Ett bein ble fylt.

Funksjonen het enter_pack. Det burde ha vært advarselen. En research-agent hadde skrevet en BTC cash-and-carry: når perpetualen handlet mer enn åtte basispunkter over spot, kjøp spot, short perpen, sitt stille. Funding og basis skulle gjøre resten. Backtesten fylte begge bein i samme millisekund, på mid, pluss et tick av høflighet. Egenkapitalkurven var en trapp. Ingen ville kalle den spennende. Det var salgsargumentet.

Vi flyttet den til paper en mandag.

Mandag: pakken som alltid ble fylt

Det første signalet landet kl. 11:17 UTC. Basis på skjermen var 9.4 bps, perp dyr. I backtesten returnerte enter_pack to fills og en residual på null. I paper returnerte den en spot-fill på 0.40 BTC på ask, og en hvilende short på perpen som ikke ble handlet.

Spot hadde betalt et 4 bp taker-gebyr og omtrent 1 bp spread. Perp-prisen vi ville ha, lå fortsatt i boken, så var den det ikke. Tjue sekunder senere var den noterte basisen 5 bps, fordi vi nettopp hadde løftet spot. Førti sekunder senere fylte perpen, etter bevegelsen. Vi var pakket. Vi var pakket til en basis som ikke lenger dekket å komme inn og ut.

Backtesten ville ha bokført "+9.4 bps carry, residual 0." Blotteren hadde 4 bps i spot taker-kostnad, en 40-sekunders usikret long, og et inngangsgap på omtrent 5. Jeg hadde et utvalg på én og likevel for mye tillit til trappen.

Tirsdag: vi åpnet funksjonen

enter_pack tok en liste med bein og en target mid. Den itererte, fylte hvert bein på mid * (1 ± slip), og skrev én porteføljerad. Det fantes ingen andre tidsstempel. Det fantes ingen gren der bein to ikke eksisterte. Enhetstesten assertet residual == 0.

Det er en test som får deg til å føle deg som en voksen. Den vil aldri feile.

Vi brøt pakken opp i to ordre med hver sin tilstand: submitted, partial, filled, canceled. Incomplete ble et førsteklasses objekt. Den historiske replayen hadde fortsatt ingen ekte bok, så vi jukset. Forsink den andre fillen med et trekk fra mandagens ventetid (gjennomsnitt 26 sekunder, en hale jeg ikke likte), og driv prisen med det spot gjorde i det vinduet. Grovt, men trappen fikk hakk før lunsj: pakker som gikk inn på 3 bps, pakker som aldri ble pakker.

Onsdag: tre sekunder, så dump den

Hvis det andre beinet ikke er på innen tre sekunder, flat ut det første. Vi burde ha startet der. Det høres konservativt ut til du priser aborten. Å flate ut betyr at du krysset spot for å komme inn og krysser den for å komme ut. To taker-gebyrer, to spread, ingen carry, ingen funding. I den omskrevne replayen var de abortene ikke sjeldne. De klumpet seg på barene der basisen så mest "ekte" ut, som vanligvis er barene der noe allerede flyter gjennom spot.

Onsdag kveld hadde vi sytten paper-signaler å krangle med.

17paper-signaler på fire dager
7pakker med begge bein fylt
18 bpssenere bevegelse mot en gjenværende long
Backtest, mandag morgenPaper, per onsdag
InngangBegge bein på mid, ett tidsstempelSpot på ask; perp 5–40s senere, eller aldri
ResidualAlltid 0Usikret på 10 av 17 signaler
Gebyrer på en handel som gårTo takereTo takere, eller fire hvis vi aborterer
PnL-driverBasis + fundingDet spot gjorde mens vi ventet
En pakke er komplett når begge ordrene er fylt, ellers er den en retningsposisjon du ikke har dimensjonert for. Marker residualen mot den live boken hele tiden den eksisterer. Hvis du ikke kan markere den, kan du ikke kjøre strategien.

En kollega har fortsatt en notebook som behandler pakken som et notert produkt, BTC_CARRY, med en flat 2 bp "eksekveringsskatt". Jeg likte den notebooken. Den produserte den samme trappen som agenten. En skatt er et gjennomsnitt. Foreldreløse er en fordeling. Gjennomsnitt blir ikke overkjørt i en tynn time; 0.40 BTC i gjenværende spot kan.

Torsdag: gjenværende, så kaffe

Tre sekunder aborterte nesten alt da vi også ventet i en kø. Vi løsnet paper til femten. Kl. 02:11 UTC torsdag fylte spot, og perpen gjorde det ikke. Jeg var fortsatt i "den vil hvile, den vil løfte"-fasen av sorgen da jeg gikk for å lage kaffe.

02:11:08 filled BTCUSDT 0.40 kjøp
02:11:08 submitted BTCUSDT-PERP 0.40 salg, post-only
02:11:41 fortsatt i arbeid
02:26:00 residual-mark −18.1 bps

BTC falt 18 bps i et stille vindu. Residualen var hele handelen. Funding, da den printet, krediterte en perp vi ikke hadde. Spot bare satt der og var long. Den opprinnelige backtestens forløp over natten inneholdt aldri en enbeinet posisjon, så den hadde aldri stilt spørsmålet vi stiller til alle andre bøker: hva er den verste baren denne gjenværende kan printe, og hvor er stoppen for en posisjon vi ikke mente å holde?

De sju fulle pakkene var heller ikke helter. Da det andre beinet printet, hadde vårt eget spot-løft allerede lent seg mot indeksen, og inngangsbasisen var 3–5 bps dårligere enn snapshotet som hadde utløst signalet. Åtte-bps-terskelen var et tall om en skjerm.

Det vi ville hoppe over neste gang

Vi ville ikke shippe en multi-leg som én fill-funksjon. Samme regel for en perp-spot-carry, en calendar, eller call-verticalen en agent sender inn som to limiter og så feirer når begge "fyller" på mid.

  1. Ordretilstand per bein, inkludert partials. Behandle pakken som parent for to tickets.
  2. En max-orphan-timer som faktisk fyrer, og en flatten-sti som betaler to spread på vei ut.
  3. Mark-to-book på residualen, med en stop dimensjonert for den gjenværende. Den pakkede nettoen er feil notional.
  4. Ingen carry kreditert, ingen funding påløpt, før begge bein er på. Incomplete er incomplete.
  5. Avvis mid-på-mid som standard for alt som har to tickets. Hvis du må gjette, gjett verre på det tynne beinet og senere på den andre fillen.

Og vi ville ikke slippe test_pack_is_atomic inn i repoet. Atomic er en egenskap ved en matching engine, ikke en hjelpefunksjon. BTC spot og BTC perpetual er to bøker som noen ganger rimer. Paper er der de slutter å rime, som er den eneste grunnen til at trappen noensinne var interessant.

backtestingcash-and-carryeksekveringpapirhandelkrypto-futures
← Alle innlegg