W zeszłym miesiącu ze strategii wygenerowanej przez model wyszła krzywa kapitału z obsunięciem 63%. Głębokim, paskudnym, a potem z czystym odbiciem w ciągu kolejnych 6 tygodni — takim kształtem, na który badacz mruży oczy i uznaje, że da się go przetrwać, jeśli zmniejszy wielkość pozycji. Przepuściłem tę strategię ponownie przez silnik margin, który uwzględnia poziomy wymaganego depozytu zabezpieczającego. Konto zostało zlikwidowane 41. dnia, w samym środku obsunięcia, a wszystko po 41. dniu było fikcją.
To najkosztowniejsza klasa błędów w backtestach, jaką znam, bo nie zniekształca wyników o kilka punktów bazowych. Usuwa z symulacji stan, z którego nie ma powrotu. Strategia, która może wyzerować konto, i strategia, która nie może, to dwie różne strategie, a backtest, który nie sprawdza margin, nie powie ci, którą z nich masz.
Widzę wciąż 3 błędne podejścia.
Błędne podejście 1: dźwignia jako liczba, przez którą mnożysz stopy zwrotu
Najczęstszy wariant. Obliczasz serię stóp zwrotu na podstawie sygnałów, decydujesz, że zastosujesz dźwignię 10x, i mnożysz. Czasem ktoś robi to nieco sprytniej — wielkość pozycji wynosi equity * leverage / price — ale stan konta nadal jest tylko liczbą, która rośnie i maleje. Brak salda margin, limitu nominału i warunku utraty środków.
Szkody są subtelne, dlatego ten błąd przechodzi przez review. Sharpe nie zależy od skali, więc główna liczba się nie zmienia, gdy przestawiasz dźwignię z 3x na 30x, a badacz dochodzi do wniosku, że dźwignia to darmowe pokrętło, które zamienia zmienność na zysk. Maksymalne obsunięcie rośnie liniowo i przypadkiem pozostaje poniżej 100%, bo szereg pomnożonych stóp zwrotu zbliża się asymptotycznie do zera i nigdy go nie przekracza. Pomnóż dzienny wynik -9% przez 12, a w uczciwej wersji dostaniesz -108%, zaś w naiwnej „-108%, ale krzywa kapitału nadal jest dodatnia” — zależnie od tego, czy kapitalizowałeś wyniki, czy je sumowałeś. Widziałem oba warianty.
Brakuje tu tego, że dźwigni nie stosuje się do stóp zwrotu. Stosuje się ją do twojego zabezpieczenia, a zabezpieczenie jest ograniczoną kwotą, którą giełda monitoruje co sekundę. Gdy spadnie poniżej wymaganego poziomu, pozycja przestaje należeć do ciebie.
Wskazówka: jeśli symulacja nie może wykazać całkowitej straty przy żadnej dźwigni, nie modeluje dźwigni.
Błędne podejście 2: cena likwidacji wyliczona wyłącznie na podstawie dźwigni
Kolejny poziom zaawansowania to dodanie kontroli likwidacji, zwykle w takiej postaci: przy 20x niekorzystny ruch o 5% wyczerpuje margin, więc likwidujemy pozycję długą przy cenie wejścia × 0.95. Prosto, intuicyjnie i błędnie pod 4 względami naraz.
Platformy perpetual nie używają ustawionej przez ciebie dźwigni, by określić, kiedy twoja gra się kończy. Korzystają z tabeli progów, w której stawka maintenance margin rośnie wraz z nominałem pozycji. Przybliżony układ dla BTCUSDT USDⓈ-M, zmieniający się, gdy giełdy aktualizują parametry:
| Nominał pozycji (USDT) | Stawka maintenance margin | Maksymalna dźwignia |
|---|---|---|
| 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 |
A więc niekorzystny ruch, jaki możesz wytrzymać przy pozycji długiej z isolated margin, wynosi w przybliżeniu 1/L − MMR, a nie 1/L. Przy 20x w drugim progu to 5% − 0.5% = 4.5%. Pół procenta wydaje się zaokrągleniem. Przy BTC po 84,000 to 420 dolarów różnicy w cenie, a podczas gwałtownej godziny 420 dolarów przesądza, czy wyrzuci cię knot, czy nie. Każdy knot staje się rzutem monetą, a ty ustawiasz wszystkie te rzuty na swoją korzyść.
Do tego dochodzą opłaty. Opłata taker za wejście jest potrącana z margin natychmiast po realizacji: 0.045% od nominału 500,000 to 225 USDT przy saldzie margin 25,000. Cena likwidacji przesuwa się więc, zanim pozycja zdąży cokolwiek zrobić. Funding działa tak samo, nieustannie, a przy lewarowanym nominale jest znacznie wyższy, niż badacze się spodziewają:
Pozycja, która przez 30 dni stoi w miejscu — bez niekorzystnych ruchów i transakcji — zużywa prawie 1/5 zabezpieczenia i wyraźnie przybliża cenę likwidacji. Trzeci i czwarty problem: progi zmieniają się, gdy zwiększasz pozycję, więc pozycja, która zaczyna w progu 0.5%, a po uśrednianiu trafia do progu 1.0%, ma gorszą cenę likwidacji niż ta wyliczona na wejściu; a cross margin łączy zabezpieczenia między pozycjami, więc przetrwanie twojej długiej pozycji BTC zależy od tego, co dzieje się z krótką pozycją ETH. Jeśli symulujesz cross margin jako zestaw niezależnych pozycji z isolated margin, źle odtwarzasz strukturę korelacji na własnym koncie.
Błędne podejście 3: rozliczenie likwidacji po niewłaściwej cenie, w niewłaściwym momencie i po niewłaściwej cenie wykonania
Załóżmy, że prawidłowo wyznaczyłeś poziom uruchomienia likwidacji. Teraz pytanie: która cena go przekracza, kiedy to sprawdzasz i po jakiej cenie realizujesz zlecenie?
Likwidację uruchamia cena mark, wyliczana na podstawie indeksu kilku platform spot z wygładzonym komponentem basis, celowo zaprojektowanego tak, by nie reagował na knot z pojedynczej giełdy. Twój stop loss, zależnie od konfiguracji, prawdopodobnie uruchamia się na podstawie ostatniej ceny transakcyjnej. Te 2 wartości rozchodzą się dokładnie wtedy, gdy ma to największe znaczenie. Podczas kaskady ostatnia cena kontraktu perpetual może przez kilkadziesiąt sekund być o 1–2% niższa od ceny mark. Backtest, który sprawdza zarówno stop, jak i likwidację na podstawie tego samego minimum OHLCV, modeluje giełdę, która nie istnieje.
Oba błędy są tu obecne i nie znoszą się nawzajem. Jeśli używasz ostatniej ceny, likwidujesz na knotach, które giełda zignorowała. Jeśli używasz ceny mark, nie uwzględniasz sytuacji, w której sama cena mark się przesunęła — rozjazd indeksu na platformie spot to rzeczywisty sposób na likwidację po cenie, która nigdy nie pojawiła się na kontrakcie perpetual, którym handlowałeś.
Pozostaje cena realizacji. Naiwne silniki zamykają pozycję po cenie likwidacji i księgują stratę tak, jakby zadziałał stop. W rzeczywistości pozycję przejmuje silnik likwidacyjny po cenie upadłości — poziomie, na którym margin wynosi dokładnie zero, gorszym od poziomu uruchomienia likwidacji — a do tego pobierana jest opłata likwidacyjna, zależna od progu i wynosząca w przybliżeniu 1% nominału w niższych progach. Przy 20x 1% nominału to 20% pozostałego margin. Jeśli silnik realizuje zlecenie poniżej ceny upadłości, różnicę pokrywa fundusz ubezpieczeniowy; na niektórych giełdach, gdy fundusz się wyczerpie, strata społeczna obejmuje także zyskowną stronę arkusza zleceń. Zrealizowana strata nie jest równa obsunięciu do ceny likwidacji. Jest większa, a nadwyżka jest największa właśnie w te dni, gdy arkusz był na tyle płytki, by pogorszyć sytuację.
Pytanie o moment zdarzeń wewnątrz świecy ma tu jeszcze poważniejsze konsekwencje niż zwykle. Jeśli świeca 1-minutowa obejmuje zarówno poziom realizacji take profit, jak i poziom likwidacji, backtest, który sprawdza wyjścia przed margin, bez problemu zaksięguje zysk. Giełda sprawdza margin przy każdej aktualizacji ceny mark, mniej więcej raz na sekundę, przed wszystkim innym, co mogłoby się wydarzyć.
Co silnik musi śledzić zamiast tego
Nic z tego nie wymaga wymyślnych rozwiązań. Wymaga przechowywania stanu. Konto to obiekt z saldem, a nie szereg stóp zwrotu. Przy każdej świecy jego stan aktualizuje się w kolejności stosowanej przez giełdę:
- Saldo portfela i niezrealizowane PnL, osobno. Wskaźnik margin to maintenance margin podzielony przez saldo margin, które uwzględnia niezrealizowane PnL. Pomieszanie tych wartości sprawia, że tracąca pozycja wygląda na lepiej zabezpieczoną, niż jest w rzeczywistości.
- Tabela progów dla każdego symbolu, z wersją przypisaną do daty. Progi są aktualizowane. Backtest z 2023 uruchomiony z progami z 2026 to subtelny look-ahead — zwykle korzystny, bo z czasem giełdy na ogół łagodziły wymagania dla głównych aktywów.
- Szereg cen mark, nie tylko kline. Jeśli nie możesz zdobyć historycznych cen mark, napisz o tym w wynikach i użyj konserwatywnego przybliżenia. Nigdy po cichu nie podstawiaj ostatniej ceny.
- Kontrolę margin jako pierwsze zdarzenie w kolejności zdarzeń świecy, przed stopami, targetami, sygnałami czy rebalansowaniem.
- Realizację po cenie upadłości i opłatę likwidacyjną, przy czym stawka opłaty pochodzi z tego samego wiersza tabeli progów co MMR.
- Pochłaniający stan końcowy. Gdy kapitał spada do zera, symulacja się kończy. Bez przeliczania salda od nowa, bez „załóżmy, że trader dopłaca”, bez kontynuowania szeregu od nowego nominału.
Ten ostatni punkt budzi najwięcej sporów. Ktoś zawsze zauważa, że prawdziwy desk dopłaciłby zabezpieczenie, więc kończenie symulacji jest nierealistycznie surowe. Może. Ale „ta strategia działa, jeśli po jej wyzerowaniu wciąż będziesz ją zasilać pieniędzmi” to twierdzenie, które należy wyrazić właśnie tymi słowami i celowo przetestować, podając dopłaty jako jawne dane wejściowe, zamiast przemycać je jako ustawienie domyślne. Gdy zapiszesz to uczciwie, większość ludzi odkrywa, że wcale tego nie miała na myśli.
Praktyczna korzyść jest taka: gdy uruchamiasz tę samą strategię na papierze wobec działającej giełdy, wskaźnik margin raportowany przez giełdę i ten obliczany przez symulator powinny przez cały dzień pokrywać się z dokładnością do 1 lub 2 punktów bazowych. Zgodność można bezpłatnie sprawdzać co minutę dla każdej otwartej pozycji. To najtańszy test zgodności w całym stosie i prawie nikt go nie uruchamia — a gdy te 2 wartości się rozchodzą, rację ma giełda i masz błąd, który warto znaleźć, zanim zrobi to za ciebie obsunięcie.
← Wszystkie wpisy

