← Maqolalarga qaytish
July 2, 2026
5 daqiqa o'qish

Freymvork solig'i: qachonki backtest kutubxonangiz oddiy pandas siklidan sekinroq bo'ladi

Freymvork solig'i: qachonki backtest kutubxonangiz oddiy pandas siklidan sekinroq bo'ladi
#algotrading
#backtest
#unumdorlik
#parametr qidiruvi
#vektorlashtirish
#benchmark
Part 2 of 10 · Collection
High-Performance Backtest Engines

"Illyuziyasiz backtestlar" turkumining bir qismi.

Ko'pchilik algo-trading loyihalarining tubida qulay bir taxmin yotadi: yetuk, ko'p yulduzli backtesting kutubxonasi tez bo'ladi. Uning yillar davomida to'plangan hissalari, haqiqiy hodisalar sikli, broker modeli, komissiya sxemasi bor. Albatta, u siz o'zingiz yozgan bo'lardingiz degan qo'pol pandas siklidan yaxshiroq. Shunday qilib, siz uni tanlaysiz, strategiyangizni ulaysiz va parametr sweepni ishga tushirasiz — bir necha ming konfiguratsiya, tunlik ish. Ertalab qaytasiz, u hali ham ishlab turibdi.

Biz sakkizta backtest dvigatelini bitta bir xil parametr sweepida solishtirdik va qidiruv uchun asbob tanlash tarzingizni o'zgartirishi kerak bo'lgan narsani topdik. Eng mashhur ikkita ochiq kodli hodisaga asoslangan freymvork — backtrader va bt — sweepni bir martalik chiqindi bazasi sifatida yozgan oddiy pandas siklidan sekinroq bajardi. Ozgina emas. backtrader pandas bazasidan taxminan 2.5× ko'proq vaqt oldi; bt esa taxminan 4.7×. Shu bilan birga, xuddi shu ishda vektorlashtirilgan/kompilyatsiya qilingan dvigatel bt dan taxminan 13,000× tezroq ishladi.

Bu freymvork solig'i. Mashhur backtesterlar bitta halol ishga mo'ljallangan — bitta strategiya, bitta ma'lumotlar to'plami, ehtiyotkor to'ldirishlar, brokerdek ish tutadigan broker. Bu esa aynan yakuniy validatsiya yoki jonli-paritet tekshiruvi uchun kerakli narsa. Bu algo tadqiqoti aslida vaqtining ko'p qismini sarflaydigan narsa uchun aynan noto'g'ri asbob: xuddi shu strategiyani biroz boshqacha sozlamalar bilan o'n ming marta ishga tushirish. Ushbu maqola solig'ni o'lchaydi, mexanizmni tushuntiradi va "haqiqiy" backtesting freymvork qachon noto'g'ri tanlov ekanligi haqida qaror qoidasini beradi.

Bu yerdagi har bir raqam bitta takrorlanadigan tekshiruv jihozidan (benchmarks/bench_oss_engines.py, kommit 250dbb5) bir xil, paritetga qulflangan yuklamada olingan. Biz dvigatelni o'zimiz ishga tushirmagan joyda buni aytamiz va raqam o'ylab topish o'rniga uni alohida halollik bo'limiga qo'yamiz.

Bitta ishga tushirish qarshi o'n ming

Bir xil strategiya hisobi uchta ajralib ketuvchi yo'l bo'ylab pastga oqmoqda: qizil-to'q sariq rangdagi hodisaga asoslangan yo'lak har bir bar-bekatda to'xtashga majbur, sarg'ish algo tugunlaridan iborat og'irliklar/qayta balanslash daraxti, va butun qatorni birdaniga hal qiladigan yagona vektorlashtirilgan zumrad-moviy nur — sweep tezligi uchun paradigma taqdirdir

Parametr qidiruvining belgilovchi fakti shundaki, dvigatel minglab marta ishga tushadi, ammo tahlil bir marta sodir bo'ladi. Backtestni sozlash uchun to'lagan har qanday qat'iy narx — hodisalar siklini qurish, brokerni yaratish, har bir bar uchun ob'ekt ajratish — siz uni har bir kombinatsiyada to'laysiz. Bitta ishga tushirishda ko'rinmaydigan narx ("6 soniya kimga qiziq?") butun sweep bo'ylab butun hisobga aylanadi ("6 soniya × 10,000 = 16.6 soat").

Backtest dvigatellari uchta paradigmaga bo'linadi va paradigma sweep unumdorligi uchun taqdirdir:

  1. Hodisaga asoslangan — dvigatel bar-ma-bar yuradi, hodisalar chiqaradi, sizning next()/onBars() callbackingizni chaqiradi, buyurtmalarni broker ob'ekti orqali yo'naltiradi. Bu backtrader, backtesting.py, PyAlgoTrade, zipline va nautilus_trader arxitekturasi. Bu jonli savdo aslida qanday ishlashini aks ettiradi, aynan shu sababli u realistiklik uchun ishoniladi — va aynan shu sababli u sekin: har bir bar uchun Python yuklamasi har bir kombinatsiyada 150,000 marta to'lanadi.
  2. Og'irliklar/qayta balanslashbt shu yerda joylashgan. Siz unga maqsadli-og'irlik matritsasini berasiz va u siz belgilagan sanalarda qayta balanslaydi. Har bir bar uchun callback yo'q, ammo hali ham Python-da baholanadigan har bir hodisa uchun ob'ekt grafi (algolar daraxti, tranzaksiyalar daftarchasi) mavjud.
  3. Vektorlashtirilgan / kompilyatsiya qilingan — butun strategiya massiv operatsiyalari (vectorbt), JIT-kompilyatsiya qilingan kernel (numba) yoki mahalliy kod (Rust, MLX GPU kerneli) sifatida ifodalanadi. Umuman har bir bar uchun Python yo'q. Sikl, agar u bo'lsa, mashina tezligida ishlaydi.

Ushbu maqolaning qolgan qismi shu taksonomiyaning empirik oqibatidir. Biz bitta yuklama qurdik, har bir dvigatelni isbotlangan tarzda bir xil ishni bajarishga majbur qildik va uni vaqt bilan o'lchadik.

Yuklama: bitta strategiya, sakson sozlama, hamma uchun bir xil

Benchmark faqat har bir dvigatel bir xil ishni bajarganda halol bo'ladi. Bizniki ataylab oddiy — dvigatellar o'rtasida yagona farq qiladigan narsa dvigatelning o'zi bo'lgan yuklama.

  • Ma'lumotlar. Bitta sintetik geometrik-Braun-harakat yopilish qatori: 150,000 bar, seed=42, har bir bar uchun o'zgaruvchanlik sigma=0.0008, x0=30000. Determinlashtirilgan, shuning uchun har kim uni bit-ma-bit takrorlashi mumkin. Konstruksiya bo'yicha faqat yopilish — OHLC har bir oyoqda yopilishga o'rnatiladi, chunki strategiya yopilish-krossidir.
  • Strategiya. Hull Moving Average krossi: uzunligi L bo'lgan HMA ga qarshi tezroq HMA-of-a-third varianti (HMA vs HMA3). Har doim bozorda, har bir krossda long/short ga aylantiradi. Bu haqiqiy, ahamiyatli indikator — ikkita ichma-ich joylashgan og'irlikli harakatlanuvchi o'rtachalar va kvadrat-ildiz-oyna silliqlagichi — o'yinchoq SMA emas, shuning uchun har bir bar uchun ish vakillikka egadir.
  • Sweep. 6..200 oralig'ini qamrab oluvchi 80 ta HMA uzunligi. Bu to'g'ridan-to'g'ri o'lchash uchun yetarlicha kichik qilingan "o'n ming ishga tushirish": 80 ta mustaqil kombinatsiya, har biri 150k bar bo'ylab to'liq backtest.
  • Xarajatlar. 0.09% aylanma haqi, yon komissiyalarni modellashtiradigan dvigatellar uchun har bir tomon bo'yicha bo'linadi. Bar i dagi signal o'sha barning yopilishida bajariladi — close[i] da bir xil bar to'ldirishi, bizning ishlab chiqarish dvigatelimiz ishlatadigan konvensiya.

Har bir kombinatsiya taymeri aniq ikki narsani o'raydi: numpy HMA oldindan hisoblanishi va dvigatel ishlashi. Haqiqatan bir martalik bo'lgan sozlash (ma'lumotlarni yuklash, bar ob'ektlarini qurish) taymerdan tashqarida joylashgan. Bitta isitish ishga tushishi, so'ngra N martadan eng yaxshisi takrorlanadi va — hodisaga asoslangan dvigatellar 80 ta to'liq kombinatsiya bir necha daqiqadan bir soatdan ko'proq vaqtni oladigan darajada sekin bo'lgani uchun — biz to'rning bir xil namunasini vaqt bilan o'lchaymiz va chiziqli tarzda ekstrapolyatsiya qilamiz. Kombinatsiyalar mustaqil, shuning uchun chiziqli ekstrapolyatsiya kutish bo'yicha aniq; xuddi shu konvensiya pandas bazasiga qo'llaniladi, shuning uchun hech bir dvigatel undan afzallik olmaydi.

Paritet: har kim bir xil ishni bajarayotganini isbotlash

Bu yerda oddiy dvigatellarni solishtirish tushib qoladigan tuzoq bor: "tez" dvigatel shunchaki kamroq ish bajarayotgan bo'lishi mumkin. Agar backtrader 2,700 ta savdo qaydga olsa va sizning vektorlashtirilgan dvigatelingiz 40 tasini qaydga olsa, vektorlashtirilgan dvigatel tezroq emas — u noto'g'ri va solishtirish ma'nosizdir.

Shuning uchun biz solishtirishni savdolar sonining paritet tekshiruvi bilan qulflaymiz. L=104 da numpy etaloni aniq 2,707 ta yopilgan savdo hosil qiladi. Har bir dvigatel buni ±1 tolerantlik doirasida takrorlashi kerak, aks holda ishga tushirish work-parity FAILED tasdig'i bilan bekor qilinadi. Tolerantlik faqat dvigatellar hisob-kitob konvensiyalari bo'yicha kelishmaganligi sababli mavjud — yakuniy ochiq pozitsiya majburan yopiladi va hisoblanadimi, boshlang'ich kirish "savdo" mi — savdolarning o'zi bo'yicha emas:

Dvigatel Qaydga olingan savdolar @ L=104 Konvensiya
numpy etaloni 2707 yopilgan aylanma savdolar
backtesting.py 2708 +1: yakuniy pozitsiya oxirida majburan yopilgan
backtrader 2707 yakuniy ochiq pozitsiya hisoblanmagan
bt 2708 +1: boshlang'ich kirish tranzaksiya sifatida hisoblangan
PyAlgoTrade 2708 +1: boshlang'ich kirish to'ldirish sifatida hisoblangan

Har bir dvigatel 2707 ± 1 ga tushadi. Tezlik farqlari qanday bo'lib chiqmasin, ular bitta dvigatelning jimgina ishni o'tkazib yuborishi natijasi emas. Bu bizga hodisaga asoslangan freymvork va GPU kernelini bir xil jadvalga qo'yish va uni jiddiy qabul qilish imkonini beradigan intizomdir.

Natijalar

Mana butun jadval, eng tezdan eng sekingacha saralangan. combos/s — bu o'tkazuvchanlik; oxirgi ustun — to'liq 80-kombinatsiyali sweep qancha vaqt olishi. Baza qatori — bu M0 — oddiy pandas dvigateli, skalar hisob-kitob bilan barlar bo'ylab for sikli, siz bir kunda yozadigan va tashlab yuboradigan narsa. Undan sekinroq bo'lgan hamma narsa qalin shriftda.

Dvigatel combos/s Paradigma To'liq 80-kombinatsiyali sweep
MLX GPU kernel 779 vektorlashtirilgan (Apple GPU) 0.10 s
mahalliy Rust ~350 kompilyatsiya qilingan 0.23 s
mp + numba 246 kompilyatsiya qilingan JIT + multiprocess 0.33 s
vectorbt 56.9 vektorlashtirilgan (numpy/numba) 1.4 s
numba (bitta yadro) 39.7 kompilyatsiya qilingan JIT 2.0 s
backtesting.py 1.42 hodisaga asoslangan 56 s
PyAlgoTrade 0.51 hodisaga asoslangan 2.6 daqiqa
M0 — oddiy pandas + sikl 0.28 skalar baza 4.8 daqiqa
backtrader 0.11 hodisaga asoslangan 12.7 daqiqa
bt 0.06 og'irliklar / qayta balanslash 22.5 daqiqa

Jadvalni yuqoridan pastga o'qing va paradigma o'zini saralaydi: yuqoridagi beshtasi vektorlashtirilgan yoki kompilyatsiya qilingan, pastdagi beshtasi hodisaga asoslangan yoki ob'ekt-grafiga asoslangan — oddiy pandas sikli ikkita yetuk, mashhur freymvorkdan yuqorida o'tirgan holda. Yuqoridan pastgacha tarqalish to'rt tartib kattaligini tashkil qiladi. Aynan bir xil 2,707-savdo yuklamada MLX kerneli sweepni soniyaning o'ndan bir qismida tugatadi; bt esa yigirma ikki yarim daqiqaga muhtoj. Bu taxminan 13,000× koeffitsientdir.

Jadvalning o'rtasidagi mojaro

Jadval o'rtasidagi paradoks: oddiy kulrang-moviy oddiy for-sikl yuguruvchisi finish chizig'idan ikkita bezakli, funksiyaga boy hodisaga asoslangan freymvork mashinasidan oldin o'tmoqda, ular qizil-to'q sariq rangda porlab hali ham orqada mehnat qilmoqda, broker modellari va analizator steklari bilan og'irlashgan — kamtar baza yetuk freymvorklarni bir xil 2,707-savdo yuklamada mag'lub etmoqda

E'tiborni tortadigan raqamlar chetlarda, ammo o'rgatuvchi natija o'rtada: backtrader (0.11 combos/s) va bt (0.06 combos/s) ikkalasi ham oddiy pandas bazasidan (0.28 combos/s) sekinroq.

Bunga singib ketishga arziydi. M0 aqlli dvigatel emas. Bu DataFramega indekslaydigan, pozitsiya va pulni oddiy skalarlarda kuzatib boradigan va savdolarni ro'yxatga qo'shadigan Python for sikli — bizga urib tushirish uchun aniq yomon narsa bo'lishi uchun kiritilgan ataylab optimizatsiya qilinmagan "nazorat". pandas ning har bir qator uchun kirishi juda sekinligi bilan mashhur va biz bunga tayanchdik. Va shunga qaramay, ekotizimda eng ko'p tavsiya etilgan ikkita backtesting kutubxonasi unga yutqazadi: backtrader 2.5× ga, bt 4.7× ga.

Buni halol saqlaydigan nuancy: har bir hodisaga asoslangan dvigatel pandas dan sekinroq emas. backtesting.py (1.42 combos/s) bazani 5× ga ortda qoldiradi, chunki u har bir bar uchun ob'ekt yaratishni minimal darajada saqlaydigan lakon, numpy-ga asoslangan hodisalar siklidir. PyAlgoTrade (0.51) ham bazadan oldinga o'tadi. Shunday qilib "hodisaga asoslangan" avtomatik ravishda o'lim hukmi emas — ammo har bir bar uchun mexanizm qanchalik og'ir bo'lsa, u shunchalik yomonroq bo'ladi va backtrader va bt bu yerda eng og'ir mexanizmni ko'tarib yuradi. Paradigma tomni o'rnatadi; amalga oshirilishi o'sha tom ostida qayerga tushishingizni hal qiladi.

Gap bu kutubxonalar yomon degani emas. backtrader ning broker modeli va bt ning algolar-daraxti dizayni sizga to'g'rilik va ifodaviylik olib berish uchun mavjud — realistik buyurtma bilan ishlash, portfelni qayta balanslash, analizatorlar. Bu funksiyalar ish vaqti xarajatiga ega va bu xarajat siz bir marta ishga tushirganda ko'rinmaydi. Sweep bo'ylab esa u butun hikoyadir.

Nima uchun hodisaga asoslangan dvigatellar soliq to'laydi

Freymvork solig'i qayerda undirilishi, har bir bar bo'yicha: bitta bar-iteratsiya uning qimmat komponentlariga portlatilgan — moddiylashtirilgan bar ob'ekti, callback freymi, buyurtmani yo'naltirayotgan broker, qo'shilayotgan daftarcha — har biri qizil-to'q sariq rangdagi porlab turgan bojxona shoxobchasi tanga oladi, o'n ikki million bir xil bar-iteratsiyaning ulkan uzoqlashayotgan yo'lagi bo'ylab takrorlanadi

Mexanizm sirli emas. Hodisaga asoslangan backtest har bir bar uchun shunga o'xshash narsani qiladi:

  1. Soatni oldinga suradi, ma'lumotlar oqimidan keyingi barni ajratadi va uni ob'ekt sifatida moddiylashtiradi (Bar, Line, dict).
  2. Foydalanuvchi kodiga callbackni chaqiradi (next(), onBars()), bu o'z freymiga ega bo'lgan Python funksiyasini chaqirishdir.
  3. Callback ichida broker/pozitsiya holatini so'raydi, yana metod chaqiruvlari va atribut qidiruvlari orqali.
  4. Agar buyurtma yaratilsa, uni broker orqali yo'naltiradi: uni tasdiqlaydi, marja/pulni tekshiradi, to'ldirishni rejalashtiradi, portfel ob'ektini o'zgartiradi, tranzaksiya daftarchasiga qo'shadi.
  5. Analizatorlarni, kuzatuvchilarni va freymvork saqlaydigan har qanday hisob-kitobni yangilaydi.

Endi 150,000 barga, so'ngra 80 kombinatsiyaga ko'paytiring: har bir sweep uchun o'n ikki million bar-iteratsiya, har biri Python darajasidagi ob'ekt ajratishlar va dinamik yuborishlar to'plami. Python ning har bir operatsiya uchun yuklamasi — atribut qidiruvi yoki kichik ajratish uchun o'nlab dan yuzlab nanosekundgacha — bir marta ahamiyatsiz va o'n ikki million marta halokatli. bt holati bir xil kasallikning bir varianti: u har bir bar emas, balki savdo sanalaridagina qayta balanslasa ham, har bir qayta balanslash algo ob'ektlari daraxtini baholaydi va pandas-ga asoslangan portfel daftarchasiga tegadi va har bir kombinatsiyada ularning 2,707 tasi, 80 martaga ko'paytiriladi.

Oddiy pandas sikli backtrader va bt ni ochiq sabab bilan mag'lub etadi: u har bir bar uchun kamroq ish qiladi. U brokerni, hodisa ob'ektlarini, analizator stekini, buyurtmani yo'naltirish holat mashinasini o'tkazib yuboradi. U pandas ning xunuk har bir qator uchun solig'ini to'laydi, ammo o'sha yagona xunuk soliq hali ham freymvorkning ozoda, funksiyaga to'liq, har bir hodisa uchun ob'ekt solig'idan arzonroqdir. Backtestni "pozitsiya × keyingi-daromad − haqlar" ga tushirganingizda, freymvork har bir bar uchun qiladigan narsalarning aksariyati siz qidiruv paytida ishlatmayotgan yuklamadir.

Va bu tuzoq: yuklama sizning freymvorkni tanlash sababingizdir. Siz realistik brokerni xohladingiz. Siz analizatorlarni xohladingiz. Yakuniy validatsiya paytida siz bularning barchasini xohlaysiz. Boshqa tomondan faqat bitta skalar maqsadni o'qiydigan 10,000-kombinatsiyali qidiruv paytida siz doiralar bo'ylab yugurish uchun limuzin uchun to'layapsiz.

Jadvalning boshqa uchi: vektorlashtirilgan va kompilyatsiya qilingan

Jadvalning yuqori qismi har bir bar uchun Pythonni butunlay o'chirganingizda nima bo'lishidir.

  • vectorbt (56.9 combos/s) butun strategiyani numpy/numba massiv operatsiyalari sifatida ifodalaydi. Pythonda bar sikli yo'q — signal, pozitsiya, PnL barchasi massiv darajasidir. U sweepni bt ning 22.5 daqiqasiga qarshi 1.4 soniyada ishga tushiradi: bir xil ishda taxminan 950× tezroq. (Biz vectorbt dizaynini vectorbt sharhida va kengroq pandas-vs-polars taqqoslashida chuqurroq yoritamiz.)
  • numba (39.7) — bu pandas sikli, shakli o'zgarmagan, mahalliy kodga JIT-kompilyatsiya qilingan. M0 bilan bir xil algoritm, ammo @njit 0.28 combos/s ni 39.7 ga aylantiradi — dekoratordan ~140× tezlashuv, chunki skalar siklda hukmronlik qilgan interpretator yuklamasi shunchaki bug'lanib ketadi.
  • mp + numba (246) kompilyatsiya qilingan kernelni CPU yadrolari bo'ylab ishga tushiradi. Kombinatsiyalar uyatli darajada parallel — har biri mustaqil — shuning uchun multiprocessing JIT ustidan deyarli chiziqli tarzda masshtablanadi.
  • mahalliy Rust (~350) Python yelimining oxirgisini olib tashlaydi: butun sweep mahalliy.
  • MLX GPU (779) sweepni Apple-silicon GPU kerneliga xaritalaydi. 80 kombinatsiya 80 ta parallel arifmetika yo'lagiga aylanadi; sweep siz enter tugmasini qo'yib yubormasdan oldin tugaydi.

Aniq nomlashga arziydigan ikki narsa bor. Birinchidan, numba paradigma tildan ko'ra ko'proq muhim ekanligini isbotlaydi. M0 va numba bir xil algoritmni ishga tushiradi — farq faqat shundaki, biri har bir bar uchun interpretatsiya qilingan Python, ikkinchisi esa kompilyatsiya qilingan. Bu nazorat ostidagi A/B da butun freymvork solig'idir: ichki sikldan interpretatorni o'chirish uchun ~140×. Ikkinchidan, numba (39.7) dan mp+numba (246) ga, MLX (779) ga sakrash endi umuman dvigatel haqida emas — bu orkestratsiya va apparat haqida. Har bir bar uchun soliq ketganidan keyin, tezlik siz qancha kombinatsiyani parallel ravishda va qanday kremniyda ishga tushirishingiz masalasiga aylanadi. Biz bu to'liq progressiyani backtest dvigateli tezlik zinapoyasida yuramiz va oxirgi milya nima uchun jarayon/serializatsiya xarajati bilan hukmronlik qilinishini IPC-solig'i maqolasida yoritamiz.

Biz nimani o'lchamaganimiz (va nima uchun sizga aytyapmiz)

Benchmarkning ishonchliligi u nimani soxtalashtirishdan bosh tortishida yashaydi. Biz sakkizta dvigatelni paritet ostida to'liq ishga tushirdik. Bir necha taniqli freymvorklarga biz raqam qo'ymadik va biz o'lchamagan raqamni ekstrapolyatsiya qilishdan ko'ra ularni halolgina sanab o'tishni afzal ko'ramiz:

  • zipline / zipline-reloaded — hodisaga asoslangan, Quantopian nasli. Og'ir sozlash (to'liq savdo taqvimi va ma'lumotlar to'plami), bu har bir kombinatsiya uchun olma-olmaga vaqt o'lchashni murakkablashtiradi. Arxitektura jihatidan u backtrader bilan hodisaga asoslangan lagerda o'tiradi; biz uni jadvalning o'sha uchi yaqinida kutgan bo'lardik, ammo biz buni isbotlamaganmiz.
  • nautilus_trader — Rust/Cython yadrosi bilan hodisaga asoslangan, aniq jonli-paritet uchun mo'ljallangan. Uning yadrosi kompilyatsiya qilingan, shuning uchun u to'liq Python solig'ini to'lamaydigan eng ehtimoliy hodisaga asoslangan dvigatel — biz hali ishga tushirmagan chinakam qiziqarli o'lchov.
  • QuantConnect Lean — C# ga asoslangan, butunlay boshqa ish vaqti; Python jihozida to'g'ridan-to'g'ri taqqoslab bo'lmaydi.
  • Jesse — hodisaga asoslangan, kriptoga yo'naltirilgan; biz uning dizaynini alohida eslatmada ko'rib chiqdik, ammo bu yerda benchmark qilmadik.
  • QSTrader — hodisaga asoslangan, portfelga yo'naltirilgan; bir xil paradigma ogohlantirishlari.
  • fastquant — biz urinib ko'rdik; o'rnatish/API bizning muhitimizda buzilgan edi, shuning uchun raqam yo'q. Biz uni taxmin qilmoqchi emasmiz.

Biz hisobot beradigan raqamlar haqida ikki halol ogohlantirish. vectorbt, numba, mp+numba, mahalliy-Rust va MLX raqamlari to'rtta hodisaga asoslangan qatorni hosil qilgan OSS jihozidan emas, balki bir xil yuklamada bizning o'z dvigatel zinapoyamizdan olingan — ular bir xil yuklama, ammo boshqa o'lchov jihozi va mahalliy-Rust raqami taxminan ~350, aniq o'lchov emas. Va mutlaq combos/s apparatga xosdir; sayohat qiladigan narsa — bu tartib va nisbatlar, ular yetarlicha katta (yuqoridan pastgacha 13,000×, pandas-vs-freymvork inversiyasi uchun 2.5–4.7×), shuning uchun hech qanday oqilona apparat farqi ularni ag'darmaydi.

Hodisaga asoslangan dvigatellarni himoya qilishda

Hodisaga asoslangan dvigatel o'zining tegishli rolida: joylashtirishga tayyor bir tirik qolgan strategiyaning yagona puxta yuqori-aniqlikdagi validatsiya ishga tushishi, realistik to'ldirishni modellashtiruvchi, marjani va buyurtma hayot siklini hurmat qiluvchi aniq zumrad-va-moviy asbob sifatida tasvirlangan — qidiruv paytida sof isrofgarchilik bo'lgan har bir bar uchun mexanizm bu yerda joylashtirishdan oldin bitta ehtiyotkor mashq sifatida qimmatli hunarmandchilik sifatida ko'rsatilgan

Buni "hodisaga asoslangan backtesterlar yomon" deb o'qish oson bo'lardi. Bu noto'g'ri dars va adolatsizdir.

Hodisaga asoslangan dvigatellar boshqa ish uchun qurilgan va ular bunda yaxshi. Har bir bar uchun broker, buyurtma hayot sikli, to'ldirish mantig'i, analizatorlar — bu mexanizm backtestni jonli savdoga imkon qadar yaqin qilish uchun mavjud. Maqsadingiz siz joylashtirmoqchi bo'lgan strategiyaning yagona, ishonchli mashqi bo'lganda, siz dvigatelning har bir to'ldirishga terlashini, qisman ijrolarni modellashtirishini, marjani hurmat qilishini va sizni olib bo'lmaydigan narxlarda savdo qilishga ruxsat bermasligini xohlaysiz. Bu aniqlik mahsulotdir. Uning ish vaqti xarajati realistiklik narxidir va bitta ishga tushirish uchun narx ahamiyatsizdir.

Muvaffaqiyatsizlik dvigatelda emas; u uni noto'g'ri bosqich uchun ishlatishdadir. Tadqiqotning qarama-qarshi talablarga ega ikki alohida bosqichi bor:

  • Qidiruv o'tkazuvchanlikni xohlaydi. Siz landshaftni o'rganyapsiz, uning ko'p qismi axlat va siz ikkinchi qarashga arziydigan bir nechtasini topish uchun minglab nuqtalarni baholashingiz kerak. Har bir nuqta uchun aniqlik deyarli muhim emas — siz saralayapsiz, joylashtirmayapsiz. Bu yerda freymvork solig'i sof isrofgarchilikdir.
  • Validatsiya aniqlikni xohlaydi. Sizda bir nechta nomzod bor va siz ular realistik ijro, haqlar, sirg'anish va qog'oz daromadlarini oshiradigan oldindan qarash tuzoqlaridan omon qolishini imkon qadar aniq bilishingiz kerak. Bu yerda hodisaga asoslangan dvigatel o'z xarajatini oqlaydi.

Freymvork solig'i jazolaydigan xato — bu qidiruvingizni validatsiya dvigatelingizda ishga tushirish — 99% ini tashlab yuboradigan landshaftni o'rganish uchun limuzin narxlarini to'lash.

Qaror qoidasi

Amaliy xulosa yagona qarorga siqiladi:

Vektorlashtirilgan/kompilyatsiya qilingan dvigatelda qidiring. Tirik qolganlarni hodisaga asoslangan dvigatelda validatsiya qiling.

Aniqrog'i:

  1. Sweep uchun tez kernel quring yoki oling. Agar uni javondan xohlasangiz vectorbt; agar strategiyangiz toza vektorlashtirmasa numba-kompilyatsiya qilingan sikl (@njit dekoratori yolg'iz bu yerda ~140× olib keldi). Butun parametr fazosini u orqali ishga tushiring.
  2. Hech qachon katta sweepni backtrader, bt, zipline yoki har qanday og'ir hodisaga asoslangan freymvorkda ishga tushirmang. Agar ulardan biridagi sweep sizning to'sig'ingiz bo'lsa, tuzatish kattaroq mashina emas — bu noto'g'ri dvigatel. Hatto oddiy pandas sikli ham ulardan ikkitasini mag'lub etardi.
  3. Qisqa ro'yxatni aniqlik tekshiruvi uchun hodisaga asoslangan dvigatelga ko'taring. Bir nechta tirik qolganlarni oling va ularni realistik dvigatelda qayta ishga tushiring, u yerda broker modeli va to'ldirish mantig'i tez kernel abstraktsiya qilgan muammolarni fosh qilishi mumkin.
  4. Ikkalasi o'rtasida paritetni ta'minlang. Tez dvigatel va aniqlik dvigateli qat'iy konfiguratsiyada savdolar soni va PnL bo'yicha kelishishi kerak (bizning L=104 dagi ±1-savdo tekshiruvimiz), aks holda qidiruv va validatsiya turli strategiyalarni o'lchayapti va butun quvur yolg'ondir.

Bu qidiruv va validatsiya qarama-qarshi xarajat profillariga ega bo'lganda paydo bo'ladigan bir xil ikki tezlikli arxitekturadir va shu sababli bizning o'z stekimiz parametr qidiruvi uchun tez vektorlashtirilgan/kompilyatsiya qilingan yo'lni saqlaydi va yakuniy maqsad baholashi va plato tekshiruvlari uchun og'ir mexanizmni ajratadi.

Xulosalar

  1. Mashhur ≠ sweeplar uchun tez. Bitta bir xil, paritetga qulflangan yuklamada (150k bar, 80 ta HMA-cross kombinatsiyasi, 2,707 savdo) backtrader (0.11 combos/s) va bt (0.06) ikkalasi ham oddiy pandas siklidan (0.28) sekinroq ishladi. Yetuk, ko'p yulduzli freymvork avtomatik ravishda tez tanlov emas.
  2. Freymvork solig'i har bir bar uchundir va sweep uni ko'paytiradi. Har bir sweep uchun o'n ikki million bar-iteratsiya, har biri hodisa ob'ekti, callback va broker aylanishini ko'tarib yuradi. Bitta ishga tushirishda ko'rinmaydigan narx o'n ming bo'ylab butun hisobdir.
  3. Paradigma tomni o'rnatadi. Vektorlashtirilgan/kompilyatsiya qilingan dvigatellar (vectorbt 56.9, numba 39.7, mp+numba 246, mahalliy Rust ~350, MLX 779) hodisaga asoslangan dvigatellarni ikki to'rt tartib kattaligiga mag'lub etadi — yuqoridan pastgacha ~13,000× gacha. Faqat JIT-kompilyatsiya qilingan bir xil algoritm 140× tezroq ketdi.
  4. Barcha hodisaga asoslangan dvigatellar teng emas. backtesting.py (1.42) va PyAlgoTrade (0.51) hali oddiy bazani mag'lub etadi; soliq har bir bar uchun mexanizm qanchalik og'ir bo'lishi bilan masshtablanadi. Amalga oshirish tom ostida qayerga tushishingizni hal qiladi.
  5. Ikki dvigatel, ikki bosqich. Vektorlashtirilgan/kompilyatsiya qilingan kernelda qidiring; tirik qolganlarni realistik hodisaga asoslangan dvigatelda validatsiya qiling. Ikkalasi ham bir xil strategiyani o'lchashi uchun ular o'rtasida savdolar soni/PnL paritetini ta'minlang.
  6. Nimani o'lchaganingiz haqida halol bo'ling. Biz sakkizta dvigatelni paritet ostida benchmark qildik va biz qilmaganlarni (zipline, nautilus_trader, Lean, Jesse, QSTrader va ishga tushmagan fastquant o'rnatilishi) ular uchun raqam o'ylab topish o'rniga sanab o'tdik.

Noqulay xulosa: agar parametr sweep sizning to'sig'ingiz bo'lsa, muammo ehtimol sizning mashinangiz emas va strategiyangiz emas. Bu siz qidiruvni bitta halol ishga tushirish uchun qurilgan dvigatelda ishga tushirishingizdir — va siz saqlashga uyalgan pandas sikli bilan tezroq bo'lardingiz.

To'liq jihoz, paritet tasdiqlari va har bir dvigatel uchun xom JSON natijalari kommit 250dbb5 da benchmarks/bench_oss_engines.py va benchmarks/results_oss/ da joylashgan. Zinapoyaning kompilyatsiya qilingan/GPU uchi uchun backtest dvigateli tezlik zinapoyasi va IPC-solig'i tahliliga qarang.

blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Bozordan bir qadam oldinda bo'ling

Sun'iy intellekt savdo tahlillari, bozor tahlili va platforma yangiliklari uchun bizning xabarnomaga obuna bo'ling.

Biz sizning maxfiyligingizni hurmat qilamiz. Istalgan vaqtda obunadan chiqishingiz mumkin.