2026 m. rugsėjo 11 d. · atkuriamumas

Tas pats kodas, tie patys duomenys, du skirtingi Sharpe rodikliai: nedeterminizmo auditas, kurio reikia jūsų atgaliniam testui

Tas pats kodas, tie patys duomenys, du skirtingi Sharpe rodikliai: nedeterminizmo auditas, kurio reikia jūsų atgaliniam testui

Tas pats commit, tie patys parquet failai, tas pats kompiuteris, du paleidimai su valandos pertrauka. Sharpe 1.34 ir Sharpe 1.19. Bendra grąža 41.2% ir 37.8%. Sandorių skaičius 1,418 ir 1,421. O dvi nuosavybės kreivės sutapo iki paskutinio rodomo skaitmens 11,205 barų iš eilės, kol išsiskyrė.

0.15Sharpe skirtumas, tie patys įvesties duomenys
3 / 1,418skirtingi sandoriai
11,205barų sutapo iki išsiskyrimo

Pirmieji trys skaičiai erzina. Paskutinis įdomus, nes rodo, kad problema nėra per visą paleidimą pasklidusi slankiojo kablelio paklaida. Kažkas diskretaus įvyko viename konkrečiame bare, o visa kita buvo sudėtinis poveikis. Šiame įraše pasakojame, kaip radome tą barą ir ką šis 0.15 skirtumas reiškia kiekvienai parametrų paieškai, kurią kada nors vykdėte.

Strategija: skerspjūvio momentumas tarp 30 didžiausios apyvartos USDⓈ-M neterminuotųjų kontraktų, balansavimas kas 4 valandas, ilgoji pozicija penkiuose daugiausia pakilusiuose pagal 12 valandų grąžą, trumpoji – penkiuose labiausiai kritusiuose, 18 mėnesių istorija, komisiniai ir finansavimo mokėjimai skaičiuojami kiekvienai pozicijos kojai.

Baras, kuriame paleidimų rezultatai išsiskyrė

Jei kiekvieno baro nuosavybę registruojate visu tikslumu, tai užtrunka apie keturias minutes. Išrašykite abu paleidimus į (bar_index, equity, open_positions_hash) CSV failą, įkelkite juos abu ir raskite pirmą indeksą, kuriame jie nesutampa. Tą scenarijų jau buvome parašę kitai klaidai aptikti; tik dėl to nepraleidau viso ryto jo kurdamas.

Baras 11,206, 2025-03-14T08:00 UTC. Ankstesniame bare nuosavybė sutapo iki 13 reikšminių skaitmenų. Bare 11,206 pozicijų maišos skyrėsi: A paleidime buvome long SOL, B paleidime – long AVAX. Ta pati kryptis, ta pati nominali vertė, skirtingas simbolis. Visa, kas vyko vėliau, buvo šio skirtumo pasekmė.

Todėl abiejuose paleidimuose išvedžiau to baro reitingo įvesties duomenis. Jie sutapo. Baitas į baitą, tie patys 30 simbolių, tie patys 30 balų. Du balai buvo 0.0. Tiksliai lygūs nuliui, nes abiejų instrumentų 4 valandų barai per retrospektyvos langą rodė nulį sandorių, todėl uždarymo kainų santykis su ankstesnio baro uždarymo kaina buvo vienetas, o logaritmas – nulis. Neapvalinta iki nulio. Nulis.

Du simboliai pasidalijo penktą vietą. Atranka ėmė penkis geriausius. Kuris iš dviejų pateko į penketuką, priklausė nuo jų eiliškumo po rūšiavimo, o rūšiavimas elgėsi ne taip, kaip maniau.

Lygybė, nestabilus rūšiavimas ir tai, ką dvejus metus ignoravau

Reitingas buvo skaičiuojamas grupuojant, o jam perduodamas kadrų duomenų rinkinys sudarytas žodyno generatoriumi, iteruojančiu per simbolių aibę, kuri kiekviename bare buvo atnaujinama asinchroninio duomenų gavimo metu. Aibės iteravimo tvarka keičiasi pagal maišos sėklą, o Python kiekvienam procesui atsitiktinai parenka eilučių maišos sėklą, nebent nustatote PYTHONHASHSEED. Taigi prieš rūšiavimą eilučių tvarka abiejuose paleidimuose skyrėsi, o rūšiuojant vienodą raktą nestabiliu rūšiavimu lygybė buvo išspręsta skirtingai.

Tokios lygybės nėra retenybė. Jos kyla iš pačios sandaros. Kai požymio reikšmės pasiekia ribą arba yra apkerpamos, sukuriamos tikslios lygybės: nulio apimties barai duoda tiksliai nulines grąžas, apkirptas z balas sustoja ties ±3.0, reitingavimo transformacija su nedaug skirtingų reikšmių sukuria dešimtis lygiųjų, o loginis filtras viskam, kas jį atitinka, priskiria 1.0 balą. Per 18 mėnesių, skaičiuojant 4 valandų barais, šiame paleidime buvo 47 barai, kuriuose ties atrankos riba susidarė lygybė. Trimis atvejais dėl to pasikeitė atrinktas instrumentų rinkinys. Kitais atvejais lygiąsias pasidalijo du instrumentai, kurie abu jau buvo atrinkti arba abu liko už rinkinio ribų.

Maždaug parą buvau įsitikinęs, kad nedeterminuotai veikia duomenų įkėliklis, nes tai skamba kaip įdomiausias paaiškinimas. Klydau. Taip niekada nebūna. Čia kalta aibė, lygybė ir prielaida apie rūšiavimo stabilumą, kurios niekas neužfiksavo.

Kodėl 3 sandoriai verti 0.15 Sharpe

Šioje vietoje žmonės paprastai paprieštarauja. Atsakymas toks: atgalinis testas, kuriame pozicijos dydis nustatomas kaip nuosavybės dalis, priklauso nuo kelio. Kai kiekvienos kojos dydis sudaro 8% dabartinės nuosavybės, nuosavybės skirtumas bare n reiškia skirtumą kiekvienoje nominalioje pozicijos vertėje nuo baro n ir vėliau.

Pirmasis išsiskyrimas pats savaime kainavo nedaug. B paleidimo AVAX pozicija per devynias valandas prarado 2.1%; A paleidimo SOL pozicija uždirbo 0.4%. Po šio sandorio nuosavybės skirtumas siekė 0.21%. Menkniekis. Tačiau nuo tada abu paleidimai jau vykdė nebe tą pačią strategiją. Pozicijų dydžiai šiek tiek skyrėsi, todėl skyrėsi ir sukaupti finansavimo mokėjimai; vėliau dar du lygiųjų atvejai buvo išspręsti skirtingai, nes juos lemiančius balus jau veikė nežymiai pasikeitusios turimos pozicijos. Vienas iš tų atvejų pasitaikė 2025-03-27 – dieną prieš šešių dienų tendenciją, atnešusią maždaug trečdalį viso paleidimo PnL. A paleidimas išlaikė poziciją per visą judėjimą, o B įėjo vienu balansavimo laikotarpiu vėliau.

Grąžos skirtumas: 3.4 procentinio punkto. Sharpe skirtumas didesnis, nei leidžia manyti grąžų skirtumas, nes B paleidimo persirikiavę sandoriai sutapo su didesnio kintamumo laikotarpiu: vardiklis padidėjo, o skaitiklis sumažėjo. Maža priežastis, du stiprintuvai.

Jei jūsų pozicijų nominali vertė fiksuota, o įėjimai nepriklauso nuo dabartinių pozicijų, poveikis jums gerokai mažesnis. Dauguma įdomių strategijų nėra nei viena, nei kita.

Penki šaltiniai, dėl kurių tai nutinka

ŠaltinisPožymisPataisymas
Nenustatyta PYTHONHASHSEED reikšmė; aibės ar žodyno iteravimo tvarka perduodama rūšiavimuiLygiųjų tvarka tarp paleidimų apsiverčia; pirmas išsiskyrimas įvyksta konkrečiame bareNustatykite sėklą; lygiųjų atveju rūšiuokite pagal aiškų antrinį raktą (simbolį), kad rezultatai būtų deterministiniai
Nestabilus rūšiavimas pagal vienodą raktą (quicksort NumPy/pandas numatytoji parinktis)Tas pats kaip pirmiau, išlieka net nustačius sėkląkind="stable" arba sukurkite raktą, kuris visada duoda vienareikšmę tvarką
RNG be nustatytos sėklos naudojimas bootstrap, mokymo ir testavimo duomenų maišymo ar sintetinio sandorių vykdymo atsitiktinio svyravimo metuNukrypsta visas paleidimas, nėra aiškaus išsiskyrimo taškoKiekvienam komponentui nurodykite atskirą sėklą ir užregistruokite ją paleidimo manifeste
Lygiagretus slankiojo kablelio redukavimas (sumavimo tvarka priklauso nuo gijų skaičiaus)Skiriasi keli paskutiniai bitai; paprastai tai nepavojinga, kol skirtumas neperžengia slenkstinės sąlygosTyrimų paleidimuose nustatykite gijų skaičių; sprendimo ribose niekada nelyginkite slankiojo kablelio skaičių su ==
Nenustatytos bibliotekų versijosŠiandien atkartojama, bet lapkritį – jau neĮtraukite lockfile maišą į manifestą kartu su duomenų momentinės kopijos maiša

Ketvirtoji eilutė ne tokia dažnai svarbi, kaip žmonės baiminasi, o pirmoji nuolat pakiša koją.

Atkuriamumas iki bito yra įrankis, o ne dorybė

Determinizmas reikalingas tam, kad pakeitus vieną eilutę nuosavybės kreivės skirtumą būtų galima priskirti būtent tam pakeitimui. Tuo viskas ir pasakyta. Dabar kiekvieno Stratmill agento paleidimo manifeste įrašoma duomenų momentinės kopijos maiša, lockfile maiša ir visos sėklos, o paleidimas iš naujo, neatkuriantis ankstesnės kreivės bitas į bitą, laikomas nesėkmingu surinkimu, o ne įdomybe.

Tačiau kai jau galite atkurti rezultatą, sąmoningai panaikinkite determinizmą. Paleiskite tą patį 64 kartus su 64 sėklomis ir pažiūrėkite į rezultatų sklaidą:

Svyravimo juosta. Ta pati strategija, tie patys duomenys, 64 lygiųjų sprendimo ir sandorių vykdymo tvarkos permutacijos su nustatytomis sėklomis. Sharpe p5 1.12, mediana 1.27, p95 1.41. Juostos plotis 0.29.

Dabar grįžkite prie parametrų paieškos. Geriausia konfigūracija surinko 1.46. Konfigūracija, užėmusi 40 vietą iš 96, surinko 1.31. Skirtumas tarp jų – 0.15, pusė juostos pločio. Paieška šių dviejų konfigūracijų nesurikiavo. Ji paėmė po vieną reikšmę iš kiekvienos jų pasiskirstymo ir surikiavo tas reikšmes.

Toks požiūris pakeitė mūsų atrankos būdą. Paieškos rezultatas rodo tikrą reitingą tik tada, kai konfigūracijų skirtumai viršija vienos konfigūracijos svyravimus; o strategijoje, kurios rezultatas priklauso nuo kelio ir kurioje yra 1,400 sandorių, svyravimai paprastai tokie dideli, kad viršutinis trečdalis lyderių lentelėje tampa lygus. Tada rinkitės pagal tai, ko juosta negali paslėpti: mažesnę apyvartą, mažiau parametrų, sąnaudų prielaidą, kurią apgintumėte skeptikui, geresnį elgesį jums mažiausiai patinkančioje walk-forward dalyje. Tai tikri lygiųjų sprendimo kriterijai. 0.15 Sharpe persvara tokia nėra.

Dar vieną dalyką verta padaryti prieš pasitikint bet kuriuo iš šių rezultatų. Paleiskite atgalinį testą du kartus jau dabar, palyginkite kiekvieno baro nuosavybę ir išsiaiškinkite, ar jūsų atvejis priklauso visiško sutapimo grupei, ar 0.15 grupei. Tai 15 minučių eksperimentas, kuris parodys, kiek jūsų tyrimų istorijos matavo strategiją, o kiek – maišos sėklą.

determinizmasatgalinis testavimasduomenų inžinerijapersimokymaspython
← Visi įrašai