2026. augusztus 27. · adatmérnökség

A szimbólum-univerzumod időgép: túlélési torzítás a kriptós örökös futures backtestekben

A szimbólum-univerzumod időgép: túlélési torzítás a kriptós örökös futures backtestekben

Vasárnap este küldted át a notebookot, és azóta is nyitva van a második monitoromon. Keresztmetszeti momentum, a Binance USDⓈ-M perpjei közül a 30 napos dollárforgalom szerinti első 150, heti újrasúlyozás, a felső decilis long, az alsó short, 2021-01-től 2026-06-ig. Sharpe 2.31, maximális visszaesés 14.2%, a költségmodell pedig szerintem tisztességesnek tűnt: taker belépés, taker kilépés, időszakonként elszámolt funding, valamint egy csúszási tag, amely a könyvhöz viszonyított méreteddel skálázódik. A nehéz részeket jól csináltad. Aztán megkérdezted, miért lett stagnáló az eredmény hat hét papírkereskedés után, és hogy elhalványult-e az előny.

Nem halványult el. Benne sem volt a backtestben. Nézd meg a 4. cellát:

info = requests.get(BASE + "/fapi/v1/exchangeInfo").json()
symbols = [s["symbol"] for s in info["symbols"]
           if s["status"] == "TRADING" and s["quoteAsset"] == "USDT"]

Ezt a végpontot 2026 júniusában hívtad meg, és a választ használtad arra, hogy meghatározd, mi volt kereskedhető 2021 márciusában. A lista minden szimbóluma túlélte 2026 júniusát – ebből adódóan. Ez az egész hiba, és többet számít, mint a költségmodelled többi része együttvéve.

2.31 → 0.74Sharpe, túlélőkből álló lista és időponthű adatok összevetése
~1 az 5-bőla 2021-es univerzumodból már nem létezik
380 KBegy napi exchangeInfo-pillanatkép tömörítve

Amit a végpont nem árul el

Az exchangeInfo nem tartalmaz előzményeket. Nincs asOf paraméter, archívum vagy változásnapló. Ez a jelen pillanat fényképe, és a Binance soha nem ígért ennél többet. Amikor kivezetnek egy kontraktust, törlik a bejegyzését a válaszból, és az API szemszögéből a ticker megszűnik létezni. A Binance 2019 óta több mint 600 USDⓈ-M perpetualt listázott, és jóval több mint százat kivezetett. BTS, COCOS, TOMO, RAY, FTT, SC, valamint a 2021-es alt-szezon kontraktusainak hosszú sora, amelyeknek volt egy dicsőséges negyedévük, aztán elapadt irántuk az érdeklődés, míg a platform le nem szedte őket.

Gondold végig, mely neveket kedveli egy 30 napos momentum-szűrő. Nem a BTC-t. Azt szereti, ami épp megháromszorozódott egy listázási felhajtás és egy Twitter-ciklus hatására. Az ilyen eszközök köre erősen átfed a később kivezetettekével, az univerzumod szűrője pedig épp ezt az átfedést távolította el.

Újrafuttattam a stratégiádat az archív pillanatképeinkkel, időponthű univerzummal, ugyanazzal a jelzéssel és költségekkel, és a Sharpe 0.74 lett, 31%-os visszaesés mellett. A különbség nagyjából kétötödét azok a kivezetett eszközök adják, amelyeket soha nem tarthattál volna. További negyedét a tükörképprobléma okozza, ami kevésbé nyilvánvaló – és gyanítom, még kevésbé fog tetszeni.

Az időgép másik vége: a még nem létező szimbólumok

A jellemződ a 90 napos hozam. A gördülő ablakodban min_periods=20 van, mert egyszer beállítottad, hogy a bemelegítési szakasz ne nullázza le a minta első negyedévét, aztán nem nyúltál hozzá. Így egy 21 napja listázott kontraktus a listázás utáni három hét ármozgásából kap momentum-pontszámot, nagyjából mindig a felső decilisbe kerül, ha jól sikerült a listázása, és bekerül a portfóliódba.

Ez a része vitathatóan elfogadható. A következő már nem az: a szolgáltatód egyes szimbólumoknál visszamenőleg spot- vagy indexadatokkal töltötte fel az adatokat a perp létrejötte előtti időszakra, így néhány kontraktus gyertyatörténete megelőzi a saját onboardDate dátumát. Körülbelül egy perc alatt ellenőrizheted. Kapcsold össze az árfolyamtábládat a listázási dátumokkal, és számold meg a listázás előtti sorokat. Az adataidban 41 szimbólumnak vannak listázás előtti gyertyái, és ezek egyike 2023 nyarán 6%-os egyhetes nyereséget ad a tőkeérték-görbéhez egy olyan kontraktusban felvett pozícióból, amely még kilenc napig nem is létezett.

A ticker szövege nem azonosító. Csupán egy címke, amelyet a tőzsde kölcsönad, néha kétszer is.

Ez elvezet az átnevezésekhez. A MATICUSDT-ből POLUSDT lett. Az FTMUSDT-ből SUSDT egy 1:1 arányú átváltással. A 2022 májusi LUNA-helyzetből lett egy LUNCUSDT, majd később egy teljesen új LUNAUSDT, amelynek a tickerje azonos gyökérből ered valamivel, ami szinte mindenét elveszítette. Ha az adatbetöltőd a szimbólum szövegét használja kulcsként, és összefűzi az összes megtalált fájlt, akkor legalább egy olyan idősorod biztosan van, amelyben az ármozgástól független törés található, a momentum-jellemződ pedig ezt a törést a keresztmetszet legerősebb jelzéseként fogja értelmezni.

Minden más, ami közben elmozdul alólad

Ha elfogadod, hogy a szimbólumlista időben változik, ugyanez az érvelés a válasz minden más mezőjére is érvényes. Te pedig mindegyikhez a mai értéket használod.

MezőHogyan változikMi romlik el
statusTRADING → SETTLING → eltűnikTúlélési torzítás; nem valós záróáron végrehajtott, képzeletbeli kilépések
onboardDateHetente új listázások; a megszűnt szimbólumoknál nincs adatKereskedés olyan kontraktusokkal, amelyek még nem léteztek
tickSize / stepSizeAz árszintek változásával újrakalibráljákKerekítés a megbízásoknál, illetve olyan limitárak, amelyeket elutasítottak volna
minNotionalIdővel megemelik a vékony könyveknélKis pozíciórészek, amelyeket az éles útválasztód visszautasítana
fundingIntervalHoursÉvekig 8h, majd sok szimbólumnál 4h vagy 1h2–3×-os eltérés a finanszírozási költségben, épp azoknál az altoknál, amelyeket a szűrőd tart
tőkeáttételi sávokMódosított szintek és fenntartási marginLikvidálás modellezése és a rendelkezésre álló margin

Nálad a funding változása fáj a legjobban. Az elszámoló ciklusod a teljes előzményre napi három kifizetést feltételez. Az altportfólió jelentős része átállt a négyórás fundingra, a magas fundingú eszközökön felvett short pozíciókból pedig sok szimulált PnL-ed származik. Itt nem kerekítési hiba van. Hanem többszörös eltérés.

Maga a kivezetés is esemény, te pedig nem modellezed

Az időponthű újrafuttatásban nagyvonalú kilépési feltételeket adtam a stratégiának. A valódi kivezetések forgatókönyv szerint zajlanak: bejelentés, rendszerint hét-tizennégy nappal korábban, aztán csak pozíciócsökkentést engedő időszak, végül kényszerű elszámolás mark áron. A bejelentés nyilvános információ, amelyre reagálhatsz, ezért a korrekt szimuláció a bejelentés napjának záróárán lép ki. Csakhogy ez a záróár egy átlagos altkivezetésnél már 10-20%-kal alacsonyabb az előző heti szintnél, a könyv vékony, és a csúszási modellnek tudnia kell, hogy más piaci környezetben működik. Ha a végrehajtó motorod piaci hatás nélkül a kényszerelszámolási árat adja, akkor észrevétlenül valós értéken kereskedhetővé tettél haldokló eszközöket.

Ha sosem archiváltad az exchangeInfo adatait, még nincs minden veszve. A nyilvános adatletöltés a data.binance.vision/data/futures/um/monthly/klines/ helyen még jóval azután is megőrzi a kivezetett szimbólumok könyvtárait, hogy az API már elfelejtette őket. Listázd ki a könyvtárakat; szimbólumonként az első és az utolsó havi fájlból nagyjából meghatározható a listázás és a kivezetés időszaka, külső adatszolgáltató nélkül is. Ez rekonstrukció, nem hiteles nyilvántartás, és a tickméreteket vagy a funding időközeit nem állítja helyre. De megmutatja, mi mikor létezett, ami hétfőre szükséges tudásod 80%-át jelenti.

Mit építenék meg, mielőtt újra hozzányúlsz a jelzéshez

  1. Egy cron-feladatot, amely naponta lekéri az exchangeInfo adatait minden általad kutatott platformról, és dátum szerint kulcsolt objektumtárolóba írja. Tömörítve fél megabájtnál is kisebb. Tíz évnyi adat költsége kerekítési hiba az S3-ban, cserébe olyan kutatási képességet kapsz, amelyet később már nem tudsz megvásárolni.
  2. Az ezekből a pillanatképekből származtatott eszköznyilvántartást: minden (platform, szimbólum, valid_from, valid_to) kombinációhoz egy sort a mezők teljes készletével. Hasonlítsd össze az egymást követő pillanatképeket az előállításához, és minden mezőváltozást kezelj új sorként.
  3. Univerzumfüggvényt kötelező időbélyeg-paraméterrel. universe(ts), soha ne universe(). Tedd lehetetlenné az alapértelmezett használatot, hogy senki, még te magad se tudj hajnali 1-kor véletlenül a túlélőkből álló listához nyúlni.
  4. Listázás előtti ellenőrzést az adatbetöltőbe: egyetlen gyertya sem lehet korábbi, mint onboard_ts mínusz egy nap. A futás álljon le; ne csak figyelmeztessen.
  5. Stabil belső instrumentumazonosítót, amely az átnevezések után is megmarad, a tickert pedig kezeld attribútumként. Rendeld a POL-t és a MATIC-ot ugyanahhoz az azonosítóhoz, a címletváltásokat pedig jelöld meg, hogy az idősor-összefűzési logika megtagadhassa az összekapcsolásukat.

Csináld meg ezeket, aztán futtasd újra. Szerintem a 0.74 környékére jutsz, és az lesz az érdekes kérdés, hogy van-e bármi értelme papíron kereskedni egy olyan 0.74-es eredménynek, amely a halott eszközöket is tartalmazza. Lehet, hogy igen. A perpetualök keresztmetszeti momentuma nem légből kapott, és abból, ami az univerzum javítása után megmarad, egy rész valódi carry a short oldalról. Azt is látni fogod, hogy a papírkereskedés eredményei és a backtested végre egybevágnak, hiszen a papírkereskedés mindig időponthű univerzumon futott. Nem is használhatott mást.

Ui. Ez nem kriptós sajátosság, itt csak feltűnőbb. A részvénypiaci kutatók a CRSP adatszolgáltatásának kezdete óta küzdenek a kivezetések hozamával és az újrahasznosított tickerekkel, a predikciós piacokon pedig ez a végletekig fokozódik: minden kontraktus szükségszerűen lejár, vagyis az univerzum nem áll másból, csak listázásokból és megszűnésekből. Ha valaha átviszed ezt a szűrőt a Kalshira, előbb építsd meg az eszköznyilvántartást. Ott nincs másfajta múlt.

túlélési torzításidőponthű adatokkriptós futuresbacktestingadatmérnökség
← Összes bejegyzés