Tady máme jednu svíčku. Perpetuální kontrakt Binance USDⓈ-M, BTCUSDT, minuta začínající v 13:46:00 UTC. Z endpointu klines přišla jako prosté pole dvanácti hodnot a jde o zdaleka nejběžnější vstupní jednotku v retailovém a přidruženém kvantitativním výzkumu. Téměř každá strategie, kterou generujeme, pracuje s něčím, co vypadá právě takto.
Pojďme ji tedy rozebrat index po indexu a podívat se, kolik z ní backtest interpretuje špatně.
| Index | Hodnota | Název |
|---|---|---|
| 0 | 1773495960000 | čas otevření (ms) |
| 1 | "84120.50" | open |
| 2 | "84177.90" | high |
| 3 | "84098.10" | low |
| 4 | "84163.40" | close |
| 5 | "38.417" | objem base (BTC) |
| 6 | 1773496019999 | čas uzavření (ms) |
| 7 | "3232108.94" | objem quote (USDT) |
| 8 | 1204 | počet obchodů |
| 9 | "21.883" | base objem nákupů takerů |
| 10 | "1841203.55" | quote objem nákupů takerů |
| 11 | "0" | ignorovat |
[0] a [6]: která minuta to je a čí hodiny to určují
Čas otevření 1773495960000, čas uzavření 1773496019999. Všimněte si druhého čísla: končí na 19999, tedy jednu milisekundu před otevřením další svíčky. Okno je zleva uzavřené a zprava otevřené a burza vám to říká zcela jasně. Polovina datových chyb, které jsem řešil, začala tím, že někdo považoval oba konce za zahrnuté a započítal obchod na hranici dvakrát, nebo zarovnal resampling tak, že každá 5minutová svíčka si od sousední vypůjčila jednu milisekundu.
Časová razítka pocházejí z matching enginu burzy. Ne z vašich hodin, ne z hodin, kdy data přijal váš vendor, a ne ze stejných hodin, které používá snapshot funding rate. Když spojíte řadu kline s řadou funding rate nebo open interest staženou z jiného endpointu, propojujete zdroje, které se většinou shodují s přesností přibližně jedné sekundy. U 1minutové strategie je to na každém spojeném řádku chyba načasování 1,7 %. U čehokoli kratšího než minuta je fatální.
A tato svíčka je označena svým open. Informace v ní obsažené nejsou známy dříve než ve 13:46:59.999. Každá otázka kolem konvence indexování — mám posunout o jednu, použít jako čas události timestamp close nebo open svíčky — je ve skutečnosti tatáž otázka lookaheadu v převleku.
[1] "84120.50": open, za který nemůžete obchodovat
Open je cena prvního obchodu, který proběhl uvnitř okna. Je to dokončená transakce mezi dvěma jinými lidmi. Než se svíčka objeví jako řádek ve vašem dataframe, je tato cena šedesát sekund stará.
Předchozí svíčka uzavřela na 84109.80, takže mezi dvěma sousedními 1minutovými svíčkami leží cenový pohyb $10.70. To je 1,3 bazického bodu, na grafu neviditelného a přibližně čtvrtina poplatku taker. Dobře. Podívejte se ale na stejnou řadu u altcoinového perpu během zveřejnění amerického CPI a tyto mezisvíčkové mezery dosahují 15 až 40 bps. Backtest, který generuje signál při close svíčky a plní ho na open další svíčky, potichu předpokládá nulovou mezeru — a ta je nulová přesně ve chvíli, kdy na ní záleží.
[2] a [3]: high "84177.90", low "84098.10"
Právě tady většina fill enginů umírá, takže tato část bude dlouhá.
High a low jsou extrémní dotčené ceny. Nenese se k nim žádný objem ani doba trvání. Z raw trade tapu pro tutéž minutu vyplývá, že vše na 84100.00 nebo níže představovalo 0.62 BTC v devíti obchodech během 1,4 sekundy. Backtest tedy na stopu 84100 „provede“ fill — a pokud je vaše pozice 3 BTC, cestou dolů jste snědli celou viditelnou knihu a zbytek objemu se zobchodoval někde při návratu přes 84105–84130. Svíčka říká, že low bylo 84098.10. Neříká ale, že se tam zobchodoval notional pouze $52,000.
Opačný směr je horší, protože vám lichotí. Představte si, že máte čekající limitní prodej na 84175. High svíčky je 84177.90, takže naivní engine vás vyplní na 84175 a zaúčtuje maker rebate místo nákladu taker. Zda k fillu skutečně došlo, závisí na pozici ve frontě na dané cenové úrovni, kterou svíčka nemůže znát a kterou jste pravděpodobně nikdy nezaznamenali. Dotknout se úrovně neznamená vyplnit objednávku.
Pravidlo, na kterém jsme se ve fill enginu shodli: čekající limitní příkaz se vyplní jen tehdy, když svíčka úrovní projde, nikoli když se jí pouze dotkne. Fills přesně na extrémním ticku vyžadují důkaz objemu na ceně z trade tapu; jinak je zamítáme. Z typického mean-reversion portfolia to odstranilo přibližně 6 % obchodů a snížilo backtestovaný Sharpe jednoho kandidáta z 1.9 na 1.1. Tento kandidát nikdy nebyl skutečný; pravidlo fillů bylo jen první věcí, která měla dost odvahy to říct.
Související past: intrabarová trajektorie. Pokud rozpětí svíčky zahrnuje váš stop i take-profit, OHLCV vám neřekne, co nastalo dříve. Každý engine si musí zvolit konvenci. My vždy předpokládáme nejprve stop, což je pesimistické, občas nesprávné a nikdy to negeneruje falešnou výhru. Pokud váš engine předpokládá nejprve take-profit, svíčky s velkým rozpětím budou vyrábět z nejednoznačnosti zisk — a právě tyto svíčky dominují rozložení vašeho PnL.
[4] "84163.40": nejméně robustní číslo ve svíčce
Close je poslední obchod v okně. To je vše. Může jít o lichý lot 0.002 BTC od bota, který si ve 13:46:59.8 dorovnával pozici. Tento jediný, strukturálně arbitrární tick používá většina výzkumných pipeline k výpočtu každého signálu, ocenění každé pozice a vyhodnocení každého výstupu.
U BTC perpů na tom sotva záleží; u nelikvidního altcoinového perpu ve 04:00 UTC na tom záleží enormně a rozdíl mezi close dvou burz pro tutéž minutu může překonat celou vaši výhodu na obchod. Když PnL strategie závisí konkrétně na close, spouštíme ji znovu s oceněním za mark price burzy, která vychází z indexu a manipuluje se s ní podstatně hůře. Pokud se výsledky rozcházejí, strategie obchodovala artefakt.
[5] a [7]: "38.417" a "3232108.94", objem v jakých jednotkách
Base volume je BTC; quote volume je USDT. Zde obojí, což je úslužnost, kterou neposkytují všechny venue. Důvod, proč na tom záleží, je agregace napříč venue. Coin-margined kontrakty se kotují v kontraktech s notionalem $100. Některé akciové feedy uvádějí round lots. Venue predikčních trhů uvádějí počty podílů, kde jeden podíl představuje binární nárok denominovaný v dolarech. Sčítání „objemu“ napříč smíšeným univerzem bez normalizace na jedinou jednotku notionalu vytvoří žebříček likvidity, který je naprostý nesmysl — a bude to nesmysl stabilního vzhledu, jenž projde kontrolou.
Při ingestu vše normalizujte na quote notional. Raw pole si také ukládejte, ale nikdy ho nenechte spatřit strategii.
[8] 1204: pole, které by mělo nastavit váš model market impactu
Objem base dělený počtem obchodů dává průměrný obchod 0.032 BTC, tedy přibližně $2,700. Pokud chce vaše kandidátní strategie najednou vstoupit za $250,000, žádá si být zhruba 92krát větší než typická transakce v dané minutě. Právě toto číslo, nikoli nějaká obecná konstanta skluzu 5 bps, by mělo určovat váš člen impactu s odmocninou. Participaci počítáme pro každou svíčku jako plnohodnotný sloupec a strategie, jejichž medián vstupu překračuje několik procent notionalu svíčky, zamítáme, protože vše, co následuje, je fikce.
Počet obchodů také levně odhalí podivné minuty. Objem normální, počet obchodů se propadl na 11? Někdo provedl block trade. Objem normální, počet obchodů 9,000? To je likvidační kaskáda rozkousaná na drobné části.
[9] a [10]: "21.883", pole, které všichni zahazují
Base volume nákupů takerů. Z 38.417 BTC v této svíčce iniciovali nákupci 21.883, takže signed volume delta je +5.349 BTC a rozdělení agresorů je 57/43 ve prospěch kupujících. Burza vám zdarma předává nerovnováhu order flow v poli, které většina lidí nikdy nečte, protože pandas za ně sloupec nepojmenoval.
Netvrdím, že samo o sobě předpovídá výnosy; naivní delta strategie patří mezi spolehlivější způsoby, jak přispívat do účetní knihy poplatků. Jde ale o skutečně jiné měření než cena, je dostupné ve stejném requestu, který už stejně posíláte, a umožňuje odlišit růst nakoupený od růstu, k němuž došlo proto, že prodejci ustoupili. V OHLC vypadají tyto dvě situace stejně, ale za deset minut se chovají jinak. Náš výzkumný agent považuje hypotézu, která ignoruje rozdělení takerů na venue, jež ho zveřejňuje, za hypotézu, která nechává důkazy ležet na stole.
[11] "0": ignorovat — a všechno ostatní, co tu není
Index 11 je zastaralé pole, trvale rovné nule. Zajímavější je seznam věcí, které tato svíčka neobsahuje: žádný bid, ask, spread, hloubku knihy, funding rate, open interest, likvidace, mark price ani index price. A především žádný způsob, jak zjistit, zda by vaše objednávka byla maker nebo taker, což je na této venue rozdíl mezi zaplacením 0.045 % a vyděláním 0.01 %.
Každý fee model postavený pouze na klines je tedy předpoklad převlečený za číslo. Řešíme to tak, že každou strategii nutíme předem deklarovat styl exekuce a poté účtujeme taker u všeho, co nedokáže prokázat opak.
Svíčka, která se nikdy neobjevila
Poslední část — a ta mimo hlavní trhy kouše nejvíc. Minuta s nulovým počtem obchodů nevytvoří žádnou kline. Vendeři a knihovny ji běžně doplní metodou forward-fill: open = high = low = close = předchozí close, volume 0. Váš indikátor spokojeně počítá. Strategie vidí platný řádek a může vygenerovat signál v minutě, během níž s daným instrumentem nikdo na světě neobchodoval.
U jednoho perp trhu se střední kapitalizací, který jsme ingestovali, mělo v dvanáctiměsíčním okně 4,1 % 1minutových svíček nulový počet obchodů. Kandidátní mean-reversion strategie na tomto symbolu zadávala 38 % vstupů na syntetických svíčkách, protože ploché syntetické ceny jsou magnetem pro vše, co měří odchylku od klouzavého průměru. V backtestu vypadala skvěle. Obchodovala mezery v datech.
Proto ingestovací vrstva nyní nese pro každou svíčku boolean synthetic, který se propaguje každým resamplingem, a ověřovací síto selže u každé strategie, jejíž obchody se na něm shlukují. Levný sloupec. Zabil více kandidátů než jakýkoli indikátor, který jsme kdy napsali.
Dvanáct hodnot. Čtyři z nich se běžně čtou špatně, dvě se běžně zahazují a celá jedna kategorie v řádku chybí, přesto ji engine považuje za přítomnou. Před příštím backtestem si ze svého úložiště vytáhněte jednu raw svíčku a přečtěte nahlas každé pole v porovnání s tím, co o něm předpokládá vaše fill logika. Je to dvacet minut práce a ještě jsem neviděl nikoho, kdo by ji udělal a nic neodhalil.
← Všechny články