A múlt hónapban egy generált stratégia olyan tőke görbét produkált, amelyben 63%-os visszaesés volt. Mély, csúnya esés, majd tiszta kilábalás a következő hat hétben — az a fajta alakzat, amelyre egy kutató hunyorogva azt mondja, hogy kisebb pozíciómérettel még túlélhető. Újrafuttattam egy olyan marginkezelő motoron, amely ismeri a fenntartási margin szintjeit. A számlát a 41. napon, az esés kellős közepén likvidálták, és a 41. nap utáni teljes szakasz fikció volt.
Ez a legdrágább backteszt-hibatípus, amellyel találkoztam, mert nem néhány bázisponttal torzítja a hozamot. Kitöröl egy elnyelő állapotot a szimulációból. Az a stratégia, amelyik nullára futhat, és az, amelyik nem, két különböző stratégia; egy backteszt pedig, amely sosem ellenőrzi a margint, nem tudja megmondani, melyik van neked.
Három hibás megoldást látok újra és újra.
Első hibás megoldás: a tőkeáttétel egy szám, amellyel megszorzod a hozamot
Ez a leggyakoribb megközelítés. Kiszámítasz egy hozamsort a jelzéseidből, úgy döntesz, hogy 10x tőkeáttétellel kereskedsz, aztán megszorzod vele. Néha valamivel kifinomultabb a megoldás — a pozícióméret equity * leverage / price —, de a számla állapota továbbra is csak egy skalár, amely fel-le mozog. Nincs egyenleg a marginról, nincs névértékkorlát, nincs bukási feltétel.
A következmények alattomosak, ezért élik túl a felülvizsgálatot. A Sharpe-mutató skálafüggetlen, így a fő mutatód nem változik, ha a tőkeáttételt 3x-ről 30x-re emeled. A kutató pedig arra jut, hogy a tőkeáttétel ingyen tekerő, amellyel a volatilitást hozamra lehet váltani. A maximális visszaesés lineárisan skálázódik, és véletlenül 100% alatt marad, mert a megszorzott hozamok sorozata számtani okból aszimptotikusan tart a nullához, de sosem lépi át. Ha egy -9%-os napot megszorzol 12-vel, a tisztességes változatban -108%-ot kapsz; a naiv változatban pedig „-108%-ot, de a tőke görbéje még mindig pozitív”, attól függően, hogy kamatosan vagy összeadással számoltál. Mindkettőt láttam már.
Az hiányzik, hogy a tőkeáttételt nem a hozamodra alkalmazod. A fedezetedre alkalmazod, a fedezet pedig véges mennyiség, amelyet a tőzsde minden másodpercben figyel. Amint a fenntartási követelmény alá csökken, a pozíció többé nem a tiéd.
Árulkodó jel: ha a szimulációd bármilyen tőkeáttétel mellett képtelen teljes veszteséget produkálni, akkor nem modellezi a tőkeáttételt.
Második hibás megoldás: a likvidálási ár kiszámítása pusztán a tőkeáttételből
A kifinomultság következő szintjén már likvidálási ellenőrzést is hozzáadnak, általában valahogy így: 20x tőkeáttételnél egy 5%-os kedvezőtlen elmozdulás lenullázza a margint, tehát long esetén a belépési ár × 0.95-nél likvidálunk. Egyszerű, intuitív, és négy különböző szempontból is hibás.
A perp tőzsdék nem a tőkeáttételi beállításodból döntik el, mikor fogyott el a mozgástér. Hanem egy fenntartási marginkulcsot használnak, amely a pozíció névértékével lépcsőzetesen emelkedik egy szinttáblázat szerint. A BTCUSDT USDⓈ-M hozzávetőleges táblázata, amely a tőzsdék módosításai nyomán változik:
| Pozíció névértéke (USDT) | Fenntartási marginkulcs | Max. tőkeáttétel |
|---|---|---|
| 0 – 50,000 | 0.40% | 125x |
| 50,000 – 600,000 | 0.50% | 100x |
| 600,000 – 3,000,000 | 1.00% | 50x |
| 3,000,000 – 12,000,000 | 2.50% | 20x |
| 12,000,000 – 70,000,000 | 5.00% | 10x |
Vagyis egy izolált longnál a nagyjából elviselhető kedvezőtlen elmozdulás 1/L − MMR, nem pedig 1/L. A második szint 20x tőkeáttételénél ez 5% − 0.5% = 4.5%. A fél százalék kerekítési hibának tűnhet. 84,000-es BTC-árnál ez 420 dollárnyi ármozgás, egy heves órában pedig 420 dollár dönti el, hogy egy kanóc kivesz-e a pozíciódból. Minden kanóc pénzfeldobás, te pedig mindegyik esélyeit magadnak kedvező irányba torzítottad.
Aztán ott vannak a díjak. A belépési taker díj azonnal levonódik a marginodból, amint teljesül az ügylet: 500,000 névértéknél a 0.045% 225 USDT-t jelent egy 25,000-es margin-egyenleg terhére. Ettől a likvidálási ár már azelőtt elmozdul, hogy a pozíció bármit csinált volna. A funding ugyanezt teszi, folyamatosan; tőkeáttételes névértéken pedig sokkal nagyobb a hatása, mint azt a kutatók várják:
Egy olyan pozíció, amely harminc napig nem csinál semmit — nincs kedvezőtlen elmozdulás, nincsenek ügyletek —, a fedezetének közel ötödét feléli, és érezhetően közelebb hozza a likvidálási árat. A hibás megoldás harmadik és negyedik oka: a szint változik, ahogy növeled a pozíciót, így ha a pozíció a 0.5%-os szinten indul, majd az átlagár növelésével átkerül az 1.0%-os szintre, a likvidálási ára kedvezőtlenebb lesz annál, mint amit belépéskor számoltál; a cross margin pedig több pozíció között osztja meg a fedezetet, így a BTC-longod túlélése attól is függ, mit csinál az ETH-shortod. Ha a cross margint egymástól független, izolált pozíciók halmazaként szimulálod, akkor a saját számlád korrelációs szerkezetét is fordítva látod.
Harmadik hibás megoldás: a likvidálás elszámolása rossz áron, rossz időpontban, rossz teljesülési áron
Tegyük fel, hogy helyesen találtad el a kiváltó szintet. De melyik ár lépi át, mikor ellenőrzöd, és milyen áron teljesül az ügylet?
A likvidálást a mark price váltja ki: ez több azonnali piaci tőzsde indexe, simított bázisösszetevővel, amelyet szándékosan úgy alakítottak ki, hogy ellenálljon az egyetlen tőzsdén megjelenő kanócoknak. A stop-lossod — a beállításaidtól függően — valószínűleg az utolsó kötési árra aktiválódik. Ez a két érték pontosan akkor tér el egymástól, amikor a legnagyobb szükség van az egyezésükre. Egy likvidálási hullám alatt a perp utolsó ára több tíz másodpercig 1–2%-kal a mark price alá csúszhat. Ha a backteszted ugyanazon OHLCV-mélypontról ellenőrzi a stopot és a likvidálást is, akkor olyan tőzsdét modellez, amely nem létezik.
Itt mindkét hiba jelen van, és nem oltják ki egymást. Utolsó ár alapján olyan kanócok miatt likvidálsz, amelyeket a tőzsde figyelmen kívül hagyott. Mark price alapján pedig elszalasztod azt az esetet, amikor maga a mark price mozdult el — egy azonnali piaci tőzsdén kialakuló indexeltérés valóban likvidáláshoz vezethet olyan áron, amely a perp piacon, ahol kereskedtél, sosem jelent meg.
Aztán ott van a teljesülés. A naiv motorok a likvidálási áron zárják a pozíciót, és úgy könyvelik el a veszteséget, mintha stop lett volna. Valójában a likvidálási motor átveszi a pozíciót a csődár szintjén — ahol a marginod pontosan nullára csökken, ami kedvezőtlenebb a kiváltó szintnél —, majd ezen felül felszámításra kerül egy likvidálási díj is, amely szinttől függ, és az alacsonyabb szinteken nagyjából a névérték 1%-a. 20x tőkeáttételnél a névérték 1%-a a megmaradt margined 20%-a. Ha a motor a csődárnál rosszabb áron teljesít, a biztosítási alap fedezi a különbséget; egyes tőzsdéken pedig, ha az alap kimerül, a közösségi veszteségmegosztás a könyv nyereséges oldalát is eléri. A realizált veszteséged nem a likvidálási árig tartó visszaesés. Annál nagyobb, és a többlet éppen azokon a napokon a legnagyobb, amikor a könyv annyira vékony volt, hogy a helyzet a legrosszabbra forduljon.
Az intrabáros működésből ismert időzítési kérdés itt a szokásosnál is élesebben merül fel. Ha egy 1-minute gyertya egyszerre tartalmazza a take-profit- és a likvidálási szintedet, akkor egy olyan backteszt, amely előbb ellenőrzi a kilépéseket, mint a margint, gond nélkül elkönyveli a nyereséget. A tőzsde minden mark price-frissítéskor ellenőrzi a margint — nagyjából másodpercenként —, még minden más előtt, amit szerettél volna, hogy történjen.
Mit kell követnie a motornak helyette
Ehhez semmi különleges nem kell. Állapotkövetésre van szükség. A számla egy egyenleggel rendelkező objektum, nem hozamsor, és minden gyertyánál a tőzsde frissítési sorrendjében kell módosítani az állapotát:
- A tárcaegyenleget és a nem realizált PnL-t külön kell kezelni. A marginarány a fenntartási margin és a margin-egyenleg hányadosa, a margin-egyenleg pedig tartalmazza a nem realizált PnL-t. Ha összemosod ezeket, egy veszteséges pozíció fedezettebbnek látszik a valóságnál.
- Minden szimbólum szinttáblázata, dátum szerint verziózva. A szinteket időnként felülvizsgálják. Egy 2023-as backtesztet 2026-os szintekkel futtatni alattomos look-ahead, általában a stratégiának kedvező, hiszen a tőzsdék idővel többnyire enyhítették a főbb eszközök követelményeit.
- Mark price-idősor, nem csupán kline-adatok. Ha nem tudsz mark price-előzményeket beszerezni, ezt írd bele az eredményekbe, és használj konzervatív helyettesítő értéket. Soha ne helyettesítsd észrevétlenül az utolsó árral.
- A gyertya eseménysorrendjében először a margint ellenőrizd, a stopok, célárak, jelzések vagy újrasúlyozás előtt.
- Csődáron történő teljesülés és a felszámolási díj, a díjkulcsot ugyanabból a szintsorból olvasva ki, mint az MMR-t.
- Elnyelő végállapot. Amikor a saját tőke nullára csökken, a futás véget ér. Nincs újrabázisolás, nincs „tegyük fel, hogy a kereskedő újabb pénzt tesz be”, és nincs a sorozat folytatása friss névértékkel.
Ez utóbbi váltja ki a legtöbb vitát. Valaki mindig megjegyzi, hogy egy valódi kereskedőasztal további fedezetet tenne be, tehát a szimuláció lezárása irreálisan szigorú. Lehet. De azt az állítást, hogy „ez a stratégia működik, ha a bukás után folyamatosan pénzt öntesz bele”, pontosan ezekkel a szavakkal kell megfogalmazni és célzottan tesztelni, a tőkeinjekciókat kifejezett bemenetként megadva, nem pedig alapértelmezésként becsempészve. Amint őszintén leírják, a legtöbben rájönnek, hogy nem is ezt akarták mondani.
Mindez a gyakorlatban így térül meg: amikor ugyanazt a stratégiát papíron lefuttatod az éles tőzsdével párhuzamosan, a tőzsde által jelentett marginarány és a szimulátor által számított értéknek egész nap legfeljebb egy-két bázisponttal szabad eltérnie. Ez az egyezés minden percben, minden nyitott pozíción ellenőrizhető, ráadásul ingyen. Ez a legolcsóbb paritásteszt az egész rendszerben, és szinte senki sem futtatja — pedig ha a két érték eltér, a tőzsdének van igaza, te pedig találtál egy hibát, amelyet érdemes még azelőtt megtalálni, hogy a visszaesés tegye meg helyetted.
← Összes bejegyzés


