31 sierpnia 2026 · rynki predykcyjne

Co zawodzi podczas backtestów rynków predykcyjnych: dziennik z ośmiu dni

Co zawodzi podczas backtestów rynków predykcyjnych: dziennik z ośmiu dni

Rynki predykcyjne wyglądają na najłatwiejszą rzecz na świecie do backtestowania. Cena mieści się w przedziale [0, 1]. Wypłata to dolar albo nic. Bez dźwigni, finansowania, bazy ani dziwactw kontraktów perpetual o 00:00 UTC. Mieliśmy już backtester obsługujący kontrakty perpetual na kryptowaluty, z opłatami, finansowaniem i wpływem na cenę. Plan zakładał, że poświęcimy dwa dni na jego dostosowanie, a potem zaczniemy generować strategie.

Zajęło nam to osiem dni. Oto dziennik, mniej więcej chronologicznie — łącznie z dniem, w którym krzywa kapitału wyglądała niesamowicie i rzeczywiście taka była.

Dzień 1: adapter, który miał być banalny

Początkowe odwzorowanie było jeden do jednego i wydawało się proste. Rynek to instrument. Cena YES to cena. Kupno YES oznacza pozycję długą, kupno NO — krótką. Rozliczenie to wymuszone zamknięcie po 1.00 albo 0.00. Wystarczy podać godzinowy szereg cen do tej samej pętli zdarzeń i gotowe.

To odwzorowanie wytrzymało kontakt z prawdziwymi danymi przez jakieś dziewięćdziesiąt minut. Pierwszy problem dotyczył szeregu stóp zwrotu. Cała nasza warstwa ryzyka — dobór wielkości pozycji, targetowanie zmienności, raportowanie Sharpe'a — zakładała logarytmiczne stopy zwrotu z instrumentu, który istnieje bez końca. Rynek, którego cena spada z 0.04 do 0.00, ma niezdefiniowaną logarytmiczną stopę zwrotu i określoną całkowitą stratę. A rynek wyceniony na 0.04 na trzy dni przed rozliczeniem to zupełnie inny obiekt niż rynek wyceniony na 0.04 na cztery minuty przed nim, choć w obu wierszach widnieje 0.04.

Przebudowaliśmy więc cały szereg, używając czasu do rozliczenia zamiast czasu zegarowego, i zaczęliśmy traktować PnL jako wartość końcową, a nie wycenianą na bieżąco. To była słuszna decyzja, która unieważniła każdy zależny od niej fragment kodu raportującego.

Dzień 2: wzór opłaty jest strategią

Na Kalshi opłata transakcyjna nie jest potrąceniem wyrażonym w punktach bazowych. Zależy kwadratowo od ceny: w przybliżeniu 0.07 × contracts × P × (1−P), przy czym na poziomie zlecenia jest zaokrąglana w górę do centa. Oznacza to, że opłata jest najwyższa dokładnie tam, gdzie rynek przypominający rzut monetą jest najciekawszy, a przy skrajnych cenach niemal zerowa.

CenaOpłata za kontraktWymagana przewaga (pkt proc. prawdopodobieństwa)Opłata jako % stawki
5¢0.33¢0.336.7%
10¢0.63¢0.636.3%
25¢1.31¢1.315.3%
50¢1.75¢1.753.5%
75¢1.31¢1.311.8%
90¢0.63¢0.630.7%
95¢0.33¢0.330.35%

Trzecią kolumnę potraktuj jako najważniejszą: aby wyjść na zero przy kupnie po 50¢ i utrzymaniu pozycji do rozliczenia, twoja ocena prawdopodobieństwa musi przewyższać rynkową o 1.75 punktu. Nie o 1.75 procenta w ujęciu względnym, lecz bezwzględnie. Jeśli zamkniesz pozycję przed rozliczeniem, zamiast trzymać ją do końca, zapłacisz tę opłatę dwukrotnie, a do tego spread.

3.5%opłata w jedną stronę przy cenie 50¢, jako część stawki
1.75ppprzewaga w ocenie prawdopodobieństwa potrzebna, by wyjść na zero
1rozliczenie na instrument w całej jego historii

CLOB Polymarket historycznie miał zupełnie inną strukturę opłat: sama transakcja kosztowała niewiele, a większość kosztu wynikała ze spreadu i głębokości rynku. Ta sama logika strategii ma więc zupełnie inną ekonomikę zależnie od platformy, a każde porównanie między platformami oparte na jednym modelu opłat jest fikcją. Teraz używamy funkcji opłat przypisanej do każdej platformy, a nie pojedynczej wartości.

Jeśli czytasz tylko jeden wiersz raportu z backtestu rynku predykcyjnego, niech będzie to wiersz z opłatą wyrażoną w punktach prawdopodobieństwa. Strategia z deklarowaną przewagą prognostyczną 1.2 punktu na rynkach wycenionych na 50¢ przynosi straty na Kalshi, zanim uwzględni się choćby jeden inny koszt. Ta informacja powinna być widoczna na pierwszej stronie, a nie wymagać samodzielnego wyliczenia przez czytelnika.

Dzień 3: księga zleceń jest schodkowa i płytka

Nasz model wpływu na cenę był funkcją pierwiastkową skalibrowaną na księgach zleceń kontraktów perpetual na BTC. Tu ma zły kształt. Przy kroku ceny 1¢ dla instrumentu o wartości $1 w całej księdze jest tylko 99 możliwych poziomów cen, a na rynku o średniej płynności na najlepszym poziomie może czekać kilkaset kontraktów, po czym pojawia się luka.

Oto migawka z rynku danych ekonomicznych, który próbkowaliśmy — strona YES, około 30 godzin przed rozliczeniem:

PoziomWolumen (kontrakty)Skumulowany koszt zakupu
42¢310310 @ śr. 42.0¢
43¢85395 @ śr. 42.2¢
45¢140535 @ śr. 42.9¢
49¢6001,135 @ śr. 46.1¢

Zlecenie na 1,000 kontraktów — ryzyko o wartości pięciuset dolarów, drobiazg na rynku kryptowalut — przesuwa efektywną cenę o cztery centy. To ponad dwa razy więcej niż opłata. Nie da się tu dopasować gładkiej funkcji; trzeba przechodzić przez kolejne poziomy księgi albo zmyślać. Usunęliśmy model sqrt dla tej klasy aktywów i napisaliśmy dosłowny algorytm przechodzący po księdze. Jest wolniejszy, ale poprawny.

W pewnym momencie przyłapałem się na irytacji, że te rynki są „zbyt małe, by miało to znaczenie”. Są małe, bo wyceniają pojedyncze pytanie o rzeczywisty świat z określonym terminem, a liczba osób mających opinię o początkowych wnioskach o zasiłek dla bezrobotnych w USA w środę jest ograniczona. Ta wielkość jest rynkiem. Narzekanie na nią przypomina narzekanie, że przy stole pokerowym mieszczą się tylko dziewięć osób.

Dzień 4: dzień, w którym krzywa kapitału była piękna

Sharpe 4.1 na 1,400 rynkach. Gładka krzywa. Każdy badacz powinien poczuć ścisk w żołądku na ten widok — ja poczułem go w końcu, jakieś czterdzieści minut po tym, jak zrobiłem zrzut ekranu.

Błąd tkwił w resamplerze. Historia cen na niepłynnych rynkach ma nieregularne znaczniki czasu, więc przekształciliśmy ją do równomiernej siatki godzinowej. Ostatni punkt każdej zarchiwizowanej serii to wartość rozliczenia: 1.00 albo 0.00. Przy ponownym próbkowaniu użyliśmy interpolacji najbliższego sąsiada bez ograniczenia kierunku, więc na każdym rynku, na którym ostatnia transakcja odbyła się kilka godzin przed rozliczeniem, wartość rozliczenia rozprzestrzeniała się wstecz przez całą lukę. Model odczytywał jutrzejszą odpowiedź w dzisiejszym wierszu — dokładnie na tych niepłynnych rynkach, na których mógł zwiększać pozycję bez napotykania limitów głębokości.

Interpolacja najbliższego sąsiada sprawdza się w przypadku instrumentu ciągłego. Gdy ostatnia obserwacja instrumentu jest prawdą, działa jak maszyna do lookahead bias. Teraz wymuszamy, by każda imputacja przebiegała wyłącznie naprzód, a wiersz rozliczenia był oznaczony i wykluczony z obliczania cech. Ten warunek ma dziewięć wierszy i jest najcenniejszym kodem, jaki napisaliśmy przez cały tydzień.

Dni 5–6: 1,412 rynków, mniej więcej 180 zakładów

Wielkość próby na rynkach predykcyjnych to pułapka o przyjaznym obliczu. Rozliczasz 1,412 rynków, wydaje ci się, że masz 1,412 obserwacji, i odpowiednio obliczasz statystykę t. Ale czternaście meczów NFL w tę samą niedzielę zależy od tego samego układu pogodowego, publikacji raportów o kontuzjach i wspólnego przepływu zleceń graczy. Pięćdziesiąt jeden rynków wyborczych na poziomie stanów zależy od jednego ogólnokrajowego przesunięcia poparcia. „Czy X wydarzy się do 31 marca” i „czy X wydarzy się do 30 czerwca” to ten sam zakład z różnymi terminami wygaśnięcia; rozstrzygają się jednocześnie.

Pogrupowaliśmy rynki według źródła zdarzenia i daty rozstrzygnięcia. Otrzymaliśmy efektywną liczbę niezależnych obserwacji bliską 180. To za mało, by przy analizowanych przez nas wielkościach efektu odróżnić rzeczywistą przewagę od szumu. Nie naprawi tego bootstrap dla każdego rynku z osobna, bo bootstrap musi losować klastry, a nie wiersze. Błędne podejście po cichu zawyża istotność dwu- lub trzykrotnie.

Dzień 7: rozliczenie również ma rozkład prawdopodobieństwa

Oto rzeczy, których w ogóle nie uwzględniliśmy w modelu, a o których przekonaliśmy się na własnej skórze:

Dodaliśmy do symulatora koszt utrzymania pozycji i losowe przesunięcie daty rozliczenia. Żadne z tych rozwiązań nie jest precyzyjne. Oba są lepsze od niejawnego założenia, że rozliczenie nastąpi dokładnie w podanym dniu i z całkowitą pewnością.

Dzień 8: co byśmy pominęli, a od czego zaczęli

  1. Całkowicie pomińmy szkielet oparty na stopach zwrotu. Nie dostosowuj warstwy ryzyka targetującej zmienność do instrumentu z końcową wypłatą. Napisz warstwę doboru wielkości zakładu, operującą prawdopodobieństwem i stawką. Straciliśmy dwa dni, próbując dopasować starą warstwę.
  2. Zbudujmy funkcję opłat przed strategią. Dla każdej platformy, na której planujesz handlować, wydrukuj krzywą przewagi potrzebnej do wyjścia na zero i powieś ją nad biurkiem. Odrzuci mniej więcej połowę pomysłów, zanim zdążą kosztować cię jedno uruchomienie backtestu.
  3. Od pierwszego dnia przechodźmy po księdze zleceń. Każdy parametryczny model wpływu na cenę przeniesiony z rynku ciągłego będzie błędny w sposób korzystny dla ciebie.
  4. Najpierw grupujmy, potem liczmy. Ustal klucz grupowania dla efektywnej wielkości próby w tym samym czasie, w którym ustalasz uniwersum, a nie dopiero wtedy, gdy masz już Sharpe'a, który ci się podoba.
  5. Wymuś właściwy kierunek imputacji. Jeden warunek przy każdym łączeniu. Jeśli seria kończy się wartością stanowiącą prawdę, z definicji traktuj imputację wstecz jako błąd, zamiast liczyć na to, że ktoś zauważy go podczas przeglądu kodu.

Te osiem dni było tego warte, głównie dlatego, że rynki predykcyjne usuwają niejednoznaczności, przez które tak łatwo oszukać samego siebie w backtestach kryptowalut. Nie ma stopy finansowania, którą można zbyć machnięciem ręki, ani konwencji ceny mark, o którą można się spierać. Jest tylko pytanie, termin i odpowiedź. Gdy backtest na tych rynkach jest błędny, można wskazać konkretny powód.

rynki predykcyjnebacktestingopłatymikrostruktura rynkuinżynieria danych
← Wszystkie wpisy