2026 m. rugsėjo 3 d. · duomenų inžinerija

Neegzistuojančios minutės: spragos, sustabdymai ir nulinės apimties OHLCV istorijos žvakės

Neegzistuojančios minutės: spragos, sustabdymai ir nulinės apimties OHLCV istorijos žvakės

Kalendorinių metų 1 minutės žvakių sekoje turėtų būti 525,600 eilučių. Mūsų 2025 m. BTCUSDT neterminuotų ateities sandorių duomenų išraše buvo 525,557 – trūko 43 minučių, o aprėptis siekė 99.992%. Toje pačioje biržoje, tuo pačiu būdu ir tuo pačiu kodu atsisiųstame vidutinės kapitalizacijos altkoino neterminuotų ateities sandorių duomenų išraše trūko 1,247 minučių: aprėptis siekė 99.76%. O tų pačių metų JAV akcijų minučių sekoje buvo maždaug 427,000 eilučių mažiau nei kriptovaliutų duomenyse. Tai visai ne spraga – tiesiog rinka, kuri užsidaro.

Trys iš šių skaičių nieko ypatingo nepasako. Tas, kuris vertas tūkstančio žodžių, yra 43.

525,6001 minutės žvakių nekeliamaisiais metais
0.008%BTCUSDT duomenyse trūko 2025 m.
61%šių minučių teko didžiausio kintamumo valandoms (aukščiausias decilis)

Keturi skirtingi atvejai, kurie jūsų duomenų lentelėje atrodo kaip spraga

Prieš aptardami tas 43 minutes, susitarkime dėl kategorijų, nes dauguma spragų tvarkymo kodų jau šiame etape veikia neteisingai. Kai vietiniame Parquet faile nėra eilutės, nežinote, kuris iš šių atvejų ją sukėlė, o tinkamas sprendimas kiekvienu atveju skiriasi.

AtvejisKas iš tikrųjų įvykoKaip tai atrodo duomenyseTinkamas sprendimas
Sandorių nebuvoRinka veikė, tačiau tą minutę niekas neperžengė spredoKai kurios sąsajos pateikia nulinės apimties žvakę (visos OHLC reikšmės vienodos, sandorių skaičius = 0), kitos eilutę praleidžiaPalikite. Tai tikra informacija: niekas nenorėjo prekiauti.
Birža neveikėSandorių sudarymo sistema neveikė – planuotai arba neNėra eilutės, kartais jų trūksta daug iš eilėsPažymėkite kaip pasenusius duomenis. Tuo metu neprekiaukite.
Prekyba instrumentu sustabdytaPažeista LULD riba, laukiama naujienų arba pranešta apie išbraukimą iš prekybos sąrašoNėra eilutės, o vėliau pateikiamas aukciono atidarymo sandorisPažymėkite duomenis kaip pasenusius, o prekybos atnaujinimą laikykite rinkos lūžiu.
Jūsų kaltėUžklausų ribojama puslapių navigacija, bandant dar kartą praleistas puslapis arba laiko juostos ribos klaida cikleEilutės nėra; iš pirmo žvilgsnio nesiskiria nuo ankstesnių atvejųAptikite ir atsisiųskite iš naujo. Šią problemą galite išspręsti.

Biržos nesutaria, kaip pateikti pirmąjį lentelės atvejį, ir čia slypi pavojus. Coinbase žvakių sąsaja visai praleidžia tuščius intervalus, todėl nelikvidžios poros istorijoje pilna tikrų spragų. Binance klines paprastai pateikia sintetinę žvakę: apimtis 0, o atidarymo, aukščiausia, žemiausia ir uždarymo kainos sutampa su ankstesnio sandorio kaina. Tas pats faktas, bet du skirtingi pavidalai. Įkėlimo kodas, kuris perkuria indeksą pagal visų minučių tinklelį, vieną pavidalą paverčia kitu jums apie tai nepranešęs. Prieš rašydami spragų užpildymo kodą, patikrinkite, ką daro jūsų birža, o ne po to.

Beveik visos tos 1,247 trūkstamos altkoino minutės priklausė pirmajai kategorijai: sekmadienį 04:00 UTC pavedimų knyga buvo plona, niekas neprekiavo. Nemalonu, bet lengva suprasti ir iš esmės nepavojinga, nes strategija tuo metu vis tiek nebūtų prekiavusi. Būtent todėl nustojau į tai gilintis ir grįžau prie tų 43 minučių.

43 minutės nebuvo išsibarsčiusios

Jei trūkstamos minutės pasiskirstytų tolygiai, 43 minutės per metus būtų 43 pavieniai atvejai – maždaug po vieną kas aštuonias su puse dienos, kiekvienas tesudarantis apvalinimo paklaidą. Taip nebuvo. Jos pasitaikė šešiais intervalais: vienas truko 19 minučių iš eilės, kitas – 11, du – po 4, o dar keli buvo dviejų minučių. Šeši įvykiai, ne 43 atsitiktinumai.

Be to, šie įvykiai susiję su tuo, kas jums rūpi. Biržos sutrinka, kai yra apkrautos, o apkrova didelė, kai kinta kaina. Suskirsčiau kiekvieną metų valandą pagal realizuotą kintamumą ir patikrinau, kuriose iš jų trūko minučių: 61% teko didžiausio kintamumo deciliui. Besąlyginė tikimybė, kad trūks bet kurios minutės, yra 0.008%. Jei valanda patenka į didžiausio kintamumo decilį, tikimybė išauga iki maždaug 0.05% – šešis kartus, be to, trūkstamos minutės telkiasi į grupes.

Vadinasi, duomenų kokybės skydelyje rodoma aprėptis matuoja ne tai, ko reikia. 99.992% atrodo kaip rodiklis, dėl kurio duomenimis nebereikia rūpintis. Iš tikrųjų jis apibūdina seką, kuri pilna tomis valandomis, kai jūsų strategija nieko nedaro, ir su spragomis tomis, kai ji veikia visu pajėgumu. Momentum strategijai, kuri įsijungia išaugus kintamumui, tikimybė pataikyti į spragą yra gerokai didesnė, nei leidžia manyti pagrindinis rodiklis, o spraga pasitaiko sandorio metu.

Ką paskutinės reikšmės perkėlimas padaro vos po 3 eilučių

Štai klaida, paskatinusi mane apie tai parašyti. Paimkime 19 minučių intervalą. Įprastas duomenų sutvarkymas: perkurti indeksą pagal visų minučių tinklelį, OHLC reikšmėms perkelti paskutinę uždarymo kainą ir apimtį nustatyti į nulį. Seka dabar vientisa, o indikatoriai veikia be nė vieno NaN.

Visų tų 19 žvakių high == low == close. Kiekvienos jų tikrasis kainos intervalas yra nulis. Šiame intervale apskaičiuotas ATR(14), kurio reikšmė prieš sutrikimą buvo apie 240 USDT, iki biržos veiklos atkūrimo sumažėja maždaug iki 34 – visą vidurkį sudaro 5 išlikusios tikros žvakės. Tada šį rodiklį perduodame kintamumu pagrįstam pozicijos dydžio skaičiuokliui, įprastam size = risk_budget / ATR tipo įrankiui. Pozicijos dydis padidėja 7 kartus.

Kita tikra žvakė yra pirmasis sandoris atnaujinus prekybą, ir jos intervalas nėra ramus. Mūsų atveju atidarymo kaina nuo paskutinės kainos prieš sutrikimą skyrėsi 1.8%. Atgalinis testas be dvejonių atidarė 7 kartus didesnę poziciją esant 1.8% kainos šuoliui – sandoris įvyko už kainą, kurios pasiekti nebuvo įmanoma ir kurios niekas nesiūlė. Šis vienas sintetinis sandoris nuosavo kapitalo kreivėje kainavo daugiau nei mėnesio teisėtas P&L, tik į blogąją pusę. Jį sukūrė viena duomenų valymo eilutė, skirta tvarkingai duomenų lentelei gauti.

Eilučių šalinimas vietoj užpildymo irgi neišsprendžia problemos – tai ta pati klaida su kita kauke. Pašalinus eilutes, jūsų sveikaisiais skaičiais indeksuojami slenkamieji langai klaidina: „20 žvakių EMA“ per sutrikimą apima 39 minučių laikotarpį, grąža tarp žvakių prieš ir po ribos yra visas 1.8% šuolis, palaikytas vienos minutės pokyčiu, o kiekvienos žvakės kintamumo įvertis jį laiko 60 sigma įvykiu. Nieko neįspėja. Indeksas vis dar monotoniškas.

Agreguojant problema tampa nematoma

Dauguma tyrimų atliekama ne su 1 minutės žvakėmis, o su agreguotais duomenimis, ir agregavimas problemą užmaskuoja. Agregavus iki 5 minučių, 19 minučių spraga virsta 4 žvakėmis, iš kurių pirmoji ir paskutinė apima tik dalį intervalo. Pandas iš 2 išlikusių minučių apskaičiuos visai įtikinamai atrodančias OHLC reikšmes ir priskirs jas taip pat, kaip žvakei iš 5 minučių duomenų. Iš rezultato neįmanoma atskirti, kuri yra kuri.

Pigiausias mano žinomas sprendimas: per kiekvieną agregavimą išsaugoti bars_in_window stulpelį ir niekada jo neišmesti. Po vieną sveikąjį skaičių kiekvienai eilutei – ir į visus vėlesnius klausimus, ar žvake galima pasitikėti, jau galima atsakyti. Taip pat išsaugome seconds_since_last_real_print, kuriame ta pati informacija pateikiama vykdymo sluoksniui tinkamu formatu.

Mūsų taikoma tvarka

Mūsų agentai dabar veikia taip:

  1. Niekada neatkurkite indekso tyliai. Įkėlimo kodas pateikia spragų aprašą: pradžią, pabaigą, trukmę ir tikėtiną kategoriją iš 4 galimų. Jei trūkstamų minučių intervalas trumpesnis nei 3 žvakės, o aplinkinių žvakių apimtis maža, tai minutės, kai nebuvo sandorių. Ilgesnį intervalą aktyviomis prekybos valandomis laikome sutrikimu, kol հակrodymas neįrodож.
  2. Prieš darydami išvadas, parsisiųskite duomenis iš naujo. Pusę ankstyvųjų spragų sukėlė puslapių navigacijos klaidos. Pakartotinai atsisiuntus duomenis iš kitos sąsajos ar tiekėjo, galima nustatyti ketvirtąją kategoriją ir sumažinti problemą, kol dar nereikia imtis kitų veiksmų.
  3. Taikykite duomenų senumo ribą, o ne užpildykite spragas. Strategijai pateikiama data_age įvestis ir griežta taisyklė: neatidaryti naujų pozicijų, kai paskutinis tikras sandoris senesnis nei N žvakių, o atviras pozicijas prekybai atsinaujinus uždaryti tik rinkos pavedimu, kainai taikant aiškiai nurodytą apsaugą nuo kainos šuolio rizikos. Neįvykdomi sandoriai blogiau už neįvykusius sandorius.
  4. Indikatoriams pateikite NaN, ne išgalvotas reikšmes. Paskutinės reikšmės perkeltos kainos neturi pasiekti požymių skaičiavimo sluoksnio. Jei ATR apskaičiuoti neįmanoma, jo reikšmė neapibrėžta, vadinasi, pozicija turi būti lygi nuliui. Aiški klaida geriau už tylų 7 kartus padidintą dydį.
  5. Skelbkite rezultatus, atsižvelgdami į spragas. Kiekviename mūsų paskelbtame atgaliniame teste pateikiamas P&L kartu su pagrindiniu rezultatu, neįtraukiant sandorių prie pat prekybos sutrikimų. Jei būtent tokie sandoriai lemia rezultatą, tai duomenų artefaktas.

Greitas patikrinimas, kurį galite atlikti šiandien: suskirstykite trūkstamas minutes į gretimus intervalus, tada patikrinkite, kokia atgalinio testo sandorių dalis buvo atidaryta arba uždaryta per 30 minučių nuo intervalo ribos. Jei mažiau nei 1%, spragos greičiausiai nieko nelemia. Jei 5% ar daugiau, jūsų nuosavo kapitalo kreivė iš dalies pasakoja apie biržos prastovas.

Patikimiausias ženklas, kurį išmokau atpažinti, yra trūkstamų duomenų pasiskirstymo forma, o ne jų kiekis. Duomenų rinkinys su tūkstančiais pavienių spragų tyliomis valandomis paprastai nekelia problemų. Duomenų rinkinys su keliomis glaudžiomis spragų grupėmis rodo, kad kažkas lūžta esant apkrovai. O tai, kas lūžta esant apkrovai, yra kaip tik ta vieta, kur veikia jūsų strategija.

OHLCV spragosduomenų inžinerijaatgalinis testavimasagregavimaskriptovaliutų ateities sandoriai
← Visi įrašai