Kalendářní rok 1minutových svíček by měl mít 525,600 řádků. Naše data perpetual futures BTCUSDT za rok 2025 jich měla 525,557 — chybělo 43 minut, úplnost tedy činila 99.992%. Perpetual futures altcoinu se střední kapitalizací na téže burze, stažené stejným způsobem a stejným kódem, měly o 1,247 řádků méně: úplnost 99.76%. A minutová řada amerických akcií za stejný rok měla zhruba o 427,000 řádků méně než ta krypto, což není žádná mezera, jen trh, který zavírá.
Tři z těch čísel nestojí za řeč. To čtvrté vydá za tisíc slov: 43.
Čtyři různé věci, které ve vašem dataframe vypadají jako díra
Než se dostaneme k číslu 43, pojďme si ujasnit kategorie, protože většina kódu pro práci s mezerami selhává už na této úrovni. Když ve vašem lokálním parquetu chybí řádek, nevíte, která z těchto příčin za tím je, a správná reakce se v každém případě liší.
| Typ | Co se skutečně stalo | Jak se to projeví | Správná reakce |
|---|---|---|---|
| Žádné obchody | Trh byl otevřený, ale v dané minutě nikdo nepřekročil spread | Svíčka s nulovým objemem (OHLC stejné, trades=0) na některých endpointech, jinde chybějící řádek | Ponechte ji. Je to skutečná informace: nikdo nechtěl obchodovat. |
| Výpadek burzy | Párovací engine byl mimo provoz, plánovaně či neplánovaně | Chybějící řádek, někdy celá série řádků | Označte data jako zastaralá. Přes výpadek neobchodujte. |
| Pozastavení obchodování instrumentu | Překročení pásma LULD, čekání na zprávy, oznámení o vyřazení z obchodování | Chybějící řádek a poté záznam z aukce při obnovení obchodování | Označte data jako zastaralá a obnovení obchodování považujte za diskontinuitu. |
| Vaše chyba | Omezení počtu požadavků při stránkování, opakovaný pokus, který přeskočil stránku, chyba v cyklu na hranici časových pásem | Chybějící řádek, který nelze od výše uvedených příčin rozeznat | Odhalte chybu a stáhněte data znovu. Tohle můžete opravit. |
Burzy se rozcházejí hned u prvního řádku té tabulky, a právě to je zrádné. Endpoint Coinbase pro svíčky úplně vynechává prázdné intervaly, takže historie málo likvidního páru je plná skutečných děr. Binance u klines obvykle vrátí syntetickou svíčku s objemem 0 a hodnotami open=high=low=close nastavenými na cenu předchozího obchodu. Stejná skutečnost, dvě různé podoby. Načítací kód, který přeuspořádá data na úplnou minutovou mřížku, jednu podobu změní na druhou, aniž by vás upozornil. Než napíšete kód na doplňování mezer, ověřte si, jak se chová vaše burza.
Téměř všech 1,247 chybějících minut u altcoinu spadalo do první kategorie: řídká kniha objednávek v neděli ve 04:00 UTC, nikdo neobchodoval. Otravné, snadno pochopitelné a z velké části neškodné, protože strategie by v tu dobu stejně neobchodovala. Právě proto jsem tomu přestal věnovat pozornost a vrátil se k číslu 43.
Těch 43 minut nebylo roztroušených
Kdyby chybějící data měla rovnoměrné rozložení, 43 minut za rok by se projevilo jako 43 osamocených výpadků, jeden zhruba každých osm a půl dne, pokaždé jen drobná odchylka. Tak to ale nedopadlo. Minuty se objevily v 6 souvislých úsecích: jeden trval 19 minut, další 11, dva po 4 minutách a dva po 2 minutách. Šest událostí, ne 43 náhodných výpadků.
A tyto události souvisejí s tím, na čem vám záleží. Burzy vypadávají, když jsou přetížené, a přetížené jsou, když se hýbe cena. Rozdělil jsem všechny hodiny roku podle realizované volatility a zjišťoval, kde se chybějící minuty nacházely: 61% z nich spadalo do nejvyššího decilu. Nepodmíněná pravděpodobnost, že bude chybět libovolná minuta, je 0.008%. Pokud se minuta nachází v hodině z nejvyššího decilu volatility, je to zhruba 0.05% — šestkrát víc, navíc v souvislých shlucích.
Metrika úplnosti na vašem dashboardu kvality dat tedy měří nesprávnou věc. 99.992% působí jako dataset, na který už nemusíte myslet. Ve skutečnosti popisuje časovou řadu, která je úplná v hodinách, kdy vaše strategie nic nedělá, a děravá v těch, kdy dělá všechno. Momentum systém, který spouští rozšíření volatility, má podstatně větší šanci narazit na mezeru, než naznačuje souhrnné číslo — a narazí na ni uprostřed obchodu.
Co dopředné doplnění udělá o 3 řádky dál
Tahle chyba mě přiměla článek napsat. Vezměte si 19minutový výpadek. Běžný postup: přeuspořádat data na úplnou minutovou mřížku, doplnit OHLC poslední známou zavírací cenou a nastavit objem na nulu. Časová řada je teď souvislá a indikátory běží bez jediné hodnoty NaN.
Těchto 19 svíček má high == low == close. True range je u každé z nich nulový. ATR(14) vypočítané v tomto okně po předvýpadkovém údaji přibližně 240 USDT klesne do návratu burzy zhruba na 34 — celý průměr ovlivňuje jen 5 skutečných svíček, které v okně zůstaly. Pak tuto hodnotu použijte ve výpočtu velikosti pozice podle volatility, běžného size = risk_budget / ATR typu. Velikost pozice se zvýší sedminásobně.
Další skutečná svíčka je záznam z obnovení obchodování a rozhodně není klidná. V našem případě otevřela o 1.8% jinde než poslední zavírací cena před výpadkem. Backtest bez mrknutí otevřel pozici 7x větší před mezerou 1.8%, na plnění, které nemohlo nastat, za cenu, kterou nikdo nenabízel. Tento jediný syntetický obchod měl v křivce hodnoty účtu větší dopad než měsíc legitimního P&L, a to nesprávným směrem — vznikl výhradně kvůli řádku na čištění dat, jehož účelem bylo dataframe uklidit.
Řešením není ani řádky místo doplnění zahodit; je to stejná chyba v jiném kabátě. Když je zahodíte, lookbacky indexované celými čísly začnou lhát: „20svíčková EMA“ teď pokrývá 39 minut reálného času přes výpadek, výnos mezi sousedními svíčkami přes hranici výpadku započítá celý skok 1.8% jako pohyb za jednu minutu a jakýkoli odhad volatility na svíčku ho vyhodnotí jako událost o 60 sigma. Nic vás nevaruje. Index je pořád monotónní.
Při převzorkování problém zmizí z očí
Většina výzkumu neběží na 1minutových svíčkách, ale na agregovaných datech, a agregace problém zamaskuje. Při převzorkování na 5 minut se 19minutová mezera změní na 4 svíčky, z nichž první a poslední jsou neúplné. Pandas vypočítá z pouhých 2 dochovaných minut OHLC, které vypadá naprosto rozumně, a označí je stejně jako svíčku sestavenou z 5 minut. Ve výsledku nic neukazuje, která z nich je která.
Nejjednodušší oprava, kterou znám: ponechte sloupec bars_in_window při každém převzorkování a nikdy ho nezahazujte. Jeden celočíselný údaj na řádek stačí, aby se dalo zodpovědět každé další otázce, zda je svíčka důvěryhodná. Přenášíme také seconds_since_last_real_print, tedy stejnou informaci ve formě, se kterou může pracovat exekuční vrstva.
Naše pravidla, jaká jsou
Co naši agenti nyní dělají, v tomto pořadí:
- Nikdy nepřeuspořádávejte data potichu. Načítací kód vytvoří manifest mezer — začátek, konec, délku a odhad, do které ze 4 kategorií spadají. Pokud chybí méně než 3 svíčky a objem okolních svíček je nízký, jde o minutu bez obchodů. Cokoli delšího v době aktivního obchodování považujeme za výpadek, dokud se neprokáže opak.
- Než začnete data vykládat, stáhněte je znovu. Polovina našich prvních mezer vznikla chybami při stránkování. Druhé stažení z jiného endpointu nebo od jiného poskytovatele odhalí chyby čtvrté kategorie a zmenší problém ještě předtím, než je třeba cokoli posuzovat.
- Použijte kontrolu zastaralosti, ne doplňování mezer. Strategie dostává vstup
data_agea jasné pravidlo: žádné nové vstupy, pokud je poslední skutečný záznam starší než N svíček; otevřené pozice se při obnovení obchodování uzavírají pouze tržním příkazem, jehož cena zohledňuje riziko mezery pomocí výslovné srážky. Plnění, která nemohla nastat, jsou horší než obchody, které se neuskutečnily. - Indikátory mají vidět NaN, ne smyšlená data. Dopředu doplněné ceny se nikdy nedostanou do vrstvy příznaků. Pokud nelze vypočítat ATR, zůstává nedefinované a to znamená žádnou pozici. Hlasité selhání je lepší než nenápadné 7x.
- Vykazujte výkonnost s ohledem na mezery. Každý backtest, který zveřejníme, ukazuje P&L včetně hlavního výsledku i výsledek bez obchodů uskutečněných v blízkosti výpadků. Pokud právě tyto obchody nesou celý výsledek, jde o artefakt dat.
Rychlý audit, který můžete provést ještě dnes: seskupte chybějící minuty do souvislých úseků a pak zjistěte, jaký podíl obchodů v backtestu se otevřel nebo zavřel do 30 minut od začátku či konce některého úseku. Pokud je to méně než 1%, mezery nejspíš nic neovlivňují. Pokud 5% nebo více, křivka hodnoty účtu zčásti vypráví příběh o výpadcích burzy.
Nejvíc důvěřuji tvaru rozložení chybějících dat, ne jejich množství. Dataset s tisíci roztroušených mezer v neaktivních hodinách je obvykle v pořádku. Dataset s několika těsně seskupenými výpadky vám říká, že se něco porouchá při vysokém zatížení — a právě tam, kde vaše strategie působí, se něco porouchává při vysokém zatížení.
← Všechny články

