← Макалаларга кайтуу
July 2, 2026
5 мүн окуу

Фреймворк салыгы: качан сиздин backtest китепканаңыз жөнөкөй pandas циклинен жайыраак болот

Фреймворк салыгы: качан сиздин backtest китепканаңыз жөнөкөй pandas циклинен жайыраак болот
#algotrading
#backtest
#аткаруучулук
#параметр издөө
#векторлоштуруу
#benchmark
Part 2 of 10 · Collection
High-Performance Backtest Engines

"Иллюзиясыз backtestтер" сериясынын бир бөлүгү.

Көпчүлүк алго-трейдинг долбоорлорунун түбүндө ыңгайлуу божомол жатат: жетилген, көп жылдыздуу backtesting китепканасы тез. Анын жылдар бою чогулган салымдары, чыныгы окуялар цикли, брокер модели, комиссия схемасы бар. Албетте, ал сиз өзүңүз жазмак болгон одоно pandas циклин жеңет. Ошентип, сиз аны тандап, стратегияңызды туташтырып, параметр свипин баштайсыз — бир нече миң конфигурация, түнкү иш. Эртең менен кайтасыз, ал дагы эле иштеп жатат.

Биз сегиз backtest кыймылдаткычын бирдей параметр свипинде салыштырдык жана издөө үчүн курал тандоо ыкмаңызды өзгөртүшү керек болгон нерсени таптык. Эң популярдуу эки ачык кодду окуяга негизделген фреймворк — backtrader жана bt — свипти бир жолку таштанды базасы катары жазган жөнөкөй pandas циклинен жайыраак аткарды. Бир аз эмес. backtrader pandas базасынан болжол менен 2.5× көп убакыт алды; bt болсо болжол менен 4.7×. Ошол эле учурда, ошол эле иште векторлоштурулган/компиляцияланган кыймылдаткыч bt дан болжол менен 13,000× тезирээк иштеди.

Бул фреймворк салыгы. Популярдуу backtesterлер бир адал ишке арналган — бир стратегия, бир маалымат топтому, кылдат толтуруулар, брокердей иштеген брокер. Бул дал акыркы валидация же тирүү-паритет текшерүү үчүн керектүү нерсе. Бул алго изилдөө чындыгында убактысынын көбүн сарптаган нерсе үчүн дал туура эмес курал: ошол эле стратегияны бир аз башкача жөндөөлөр менен он миң жолу иштетүү. Бул макала салыкты өлчөйт, механизмди түшүндүрөт жана "чыныгы" backtesting фреймворк качан туура эмес тандоо экендиги жөнүндө чечим эрежесин берет.

Бул жердеги ар бир сан бир кайталанма текшерүү шайманынан (benchmarks/bench_oss_engines.py, коммит 250dbb5) бирдей, паритетке кулпуланган жүктөмдө алынган. Биз кыймылдаткычты өзүбүз иштетпеген жерде муну айтабыз жана сан ойлоп табуунун ордуна аны өзүнчө адалдык бөлүмүнө коебуз.

Бир иштетүү он миңге каршы

Бирдей стратегия эсеби үч ажырап турган жол боюнча төмөн агып жатат: кызыл-кызгылт сары түстөгү окуяга негизделген жол ар бир бар-станцияда токтоого мажбур, саргыч алго түйүндөрүнөн турган салмактар/кайра тең салмактоо дарагы, жана бүт катарды бир заматта чечкен жалгыз векторлоштурулган зумурут-көгүш нур — свип ылдамдыгы үчүн парадигма тагдыр

Параметр издөөнүн аныктоочу фактысы — кыймылдаткыч миңдеген жолу иштейт, бирок талдоо бир жолу болот. Backtestти орнотуу үчүн төлөгөн ар кандай туруктуу баа — окуялар циклин куруу, брокерди түзүү, ар бир бар үчүн объект бөлүү — сиз аны ар бир комбинацияда төлөйсүз. Бир иштетүүдө көрүнбөгөн баа ("6 секунд кимге кызык?") бүт свип боюнча бүт эсепке айланат ("6 секунд × 10,000 = 16.6 саат").

Backtest кыймылдаткычтары үч парадигмага бөлүнөт жана парадигма свип аткаруучулугу үчүн тагдыр:

  1. Окуяга негизделген — кыймылдаткыч бар-барга басат, окуяларды чыгарат, сиздин next()/onBars() callbackиңизди чакырат, буйрутмаларды брокер объекти аркылуу багыттайт. Бул backtrader, backtesting.py, PyAlgoTrade, zipline жана nautilus_trader архитектурасы. Бул тирүү соода чындыгында кантип иштээрин чагылдырат, дал ошондуктан ага реалдуулук үчүн ишенишет — жана дал ошондуктан ал жай: ар бир бар үчүн Python жүктөмү ар бир комбинацияда 150,000 жолу төлөнөт.
  2. Салмактар/кайра тең салмактооbt ушул жерде жайгашкан. Сиз ага максаттуу-салмак матрицасын бересиз жана ал сиз белгилеген даталарда кайра тең салмактайт. Ар бир бар үчүн callback жок, бирок дагы эле Python-до бааланган ар бир окуя үчүн объект графы (алголордун дарагы, транзакция дептери) бар.
  3. Векторлоштурулган / компиляцияланган — бүт стратегия массив операциялары (vectorbt), JIT-компиляцияланган ядро (numba) же жергиликтүү код (Rust, MLX GPU ядросу) катары туюнтулат. Такыр ар бир бар үчүн Python жок. Цикл, эгер ал бар болсо, машина ылдамдыгында иштейт.

Бул макаланын калган бөлүгү ошол таксономиянын эмпирикалык натыйжасы. Биз бир жүктөм курдук, ар бир кыймылдаткычты далилденген түрдө бирдей ишти аткарууга мажбур кылдык жана аны убакыт менен өлчөдүк.

Жүктөм: бир стратегия, сексен жөндөө, баары үчүн бирдей

Benchmark ар бир кыймылдаткыч бирдей ишти аткарганда гана адал. Бизники атайын жөнөкөй — кыймылдаткычтардын ортосунда жалгыз айырма кыймылдаткычтын өзү болгон жүктөм.

  • Маалымат. Бир синтетикалык геометриялык-Браун-кыймыл жабылуу катары: 150,000 бар, seed=42, ар бир бар үчүн өзгөрмөлүүлүк sigma=0.0008, x0=30000. Детерминирленген, ошондуктан ар ким аны бит-битке кайталай алат. Конструкция боюнча жабылуу гана — OHLC ар бир бутта жабылууга орнотулат, анткени стратегия жабылуу-кроссу.
  • Стратегия. Hull Moving Average кроссу: узундугу L болгон HMA каршы тезирээк HMA-of-a-third варианты (HMA vs HMA3). Ар дайым базарда, ар бир кроссто long/short ко бурулат. Бул чыныгы, олуттуу индикатор — эки ичине жайгашкан салмактуу жылма орточолор жана квадрат-тамыр-терезе тегиздегич — оюнчук SMA эмес, ошондуктан ар бир бар үчүн иш өкүлчүлүктүү.
  • Свип. 6..200 аралыгын камтыган 80 HMA узундугу. Бул түздөн-түз өлчөө үчүн жетишерлик кичине кылынган "он миң иштетүү": 80 көз карандысыз комбинация, ар бири 150k бар боюнча толук backtest.
  • Чыгымдар. 0.09% айланма акысы, бүйрлүк комиссияларды моделдеген кыймылдаткычтар үчүн ар бир тарап боюнча бөлүнөт. Бар i дагы сигнал ошол бардын жабылуусунда аткарылат — close[i] да бирдей бар толтуруусу, биздин өндүрүш кыймылдаткычы колдонгон конвенция.

Ар бир комбинация таймери так эки нерсени ороп турат: numpy HMA алдын ала эсептөө жана кыймылдаткычтын иштөөсү. Чындыгында бир жолку болгон орнотуу (маалыматты жүктөө, бар объекттерин куруу) таймерден сыртта жайгашкан. Бир жылытуу иштетүүсү, андан кийин N дан эң жакшысы кайталанат жана — окуяга негизделген кыймылдаткычтар 80 толук комбинация бир нече мүнөттөн бир сааттан ашык убакытты алаарлык жай болгондуктан — биз тордун бирдей үлгүсүн убакыт менен өлчөйбүз жана сызыктуу түрдө экстраполяциялайбыз. Комбинациялар көз карандысыз, ошондуктан сызыктуу экстраполяция күтүү боюнча так; ошол эле конвенция pandas базасына колдонулат, ошондуктан эч бир кыймылдаткыч андан артыкчылык албайт.

Паритет: ар ким бирдей ишти аткарып жатканын далилдөө

Бул жерде жөнөкөй кыймылдаткычтарды салыштыруу түшүп кала турган тузак бар: "тез" кыймылдаткыч жөн гана азыраак иш аткарып жаткан болушу мүмкүн. Эгер backtrader 2,700 сооданы каттаса жана сиздин векторлоштурулган кыймылдаткычыңыз 40ты каттаса, векторлоштурулган кыймылдаткыч тезирээк эмес — ал туура эмес жана салыштыруу маанисиз.

Ошондуктан биз салыштырууну сооданын санынын паритет текшерүүсү менен кулпулайбыз. L=104 дагы numpy эталону так 2,707 жабылган соода чыгарат. Ар бир кыймылдаткыч муну ±1 толеранттуулук чегинде кайталашы керек, антпесе иштетүү work-parity FAILED бекитүүсү менен жокко чыгарылат. Толеранттуулук кыймылдаткычтар эсеп-кысап конвенциялары боюнча макул болбогону үчүн гана бар — акыркы ачык позиция мажбурлап жабылып, эсептелетпи, баштапкы кирүү "соода"бы — соодалардын өзү боюнча эмес:

Кыймылдаткыч Катталган соодалар @ L=104 Конвенция
numpy эталону 2707 жабылган айланма соодалар
backtesting.py 2708 +1: акыркы позиция аягында мажбурлап жабылган
backtrader 2707 акыркы ачык позиция эсептелбеген
bt 2708 +1: баштапкы кирүү транзакция катары эсептелген
PyAlgoTrade 2708 +1: баштапкы кирүү толтуруу катары эсептелген

Ар бир кыймылдаткыч 2707 ± 1 ге түшөт. Ылдамдык айырмалары кандай болуп чыкса да, алар бир кыймылдаткычтын жымжырт ишти өткөрүп жибергенинин натыйжасы эмес. Бул бизге окуяга негизделген фреймворк менен GPU ядросун бир таблицага коюуга жана аны олуттуу кабыл алууга мүмкүндүк берген тартип.

Натыйжалар

Мына бүт таблица, эң тезинен эң жайыраагына чейин иреттелген. combos/s — бул өткөрүмдүүлүк; акыркы тилке — толук 80-комбинациялуу свип канча убакыт алаары. База сабы — бул M0 — жөнөкөй pandas кыймылдаткычы, скаляр эсеп-кысап менен барлар боюнча for цикл, сиз бир күндө жазып, ыргытып жиберчү нерсе. Андан жайыраак болгон баары калың арип менен.

Кыймылдаткыч combos/s Парадигма Толук 80-комбинациялуу свип
MLX GPU ядросу 779 векторлоштурулган (Apple GPU) 0.10 s
жергиликтүү Rust ~350 компиляцияланган 0.23 s
mp + numba 246 компиляцияланган JIT + multiprocess 0.33 s
vectorbt 56.9 векторлоштурулган (numpy/numba) 1.4 s
numba (бир ядро) 39.7 компиляцияланган JIT 2.0 s
backtesting.py 1.42 окуяга негизделген 56 s
PyAlgoTrade 0.51 окуяга негизделген 2.6 мүнөт
M0 — жөнөкөй pandas + цикл 0.28 скаляр база 4.8 мүнөт
backtrader 0.11 окуяга негизделген 12.7 мүнөт
bt 0.06 салмактар / кайра тең салмактоо 22.5 мүнөт

Таблицаны жогорудан төмөн окусаңыз парадигма өзүн иреттейт: жогорку бешөө баары векторлоштурулган же компиляцияланган, төмөнкү бешөө баары окуяга негизделген же объект-графга негизделген — жөнөкөй pandas цикли эки жетилген, популярдуу фреймворктон жогору отурган абалда. Жогорудан төмөнгө чейинки жайылуу төрт даражалуу чоңдукту түзөт. Дал ошол эле 2,707-соода жүктөмүндө MLX ядросу свипти секунданын ондон бир бөлүгүндө бүтүрөт; bt болсо жыйырма эки жарым мүнөткө муктаж. Бул болжол менен 13,000× коэффициент.

Таблицанын ортосундагы жаңжал

Таблицанын ортосундагы парадокс: жөнөкөй боз-көгүш жөнөкөй for-цикл жүгүрүүчүсү финиш сызыгынан эки кооздолгон, функцияга бай окуяга негизделген фреймворк машинасынан мурда өтүп жатат, алар кызыл-кызгылт сары түстө жаркырап дагы эле артта эмгектенип жатышат, брокер моделдери жана анализатор стектери менен оордолгон — момун база жетилген фреймворкторду бирдей 2,707-соода жүктөмүндө жеңип жатат

Көзгө урунган сандар четтерде, бирок үйрөтүүчү натыйжа ортосунда: backtrader (0.11 combos/s) жана bt (0.06 combos/s) экөө тең жөнөкөй pandas базасынан (0.28 combos/s) жайыраак.

Буга сиңип кетүүгө арзыйт. M0 акылдуу кыймылдаткыч эмес. Бул DataFrameге индекстеген, позицияны жана акчаны жөнөкөй скалярларда байкаган жана соодаларды тизмеге кошкон Python for цикли — бизге уруп түшүрүү үчүн даана жаман нерсе болушу үчүн киргизилген атайын оптималдаштырылбаган "көзөмөл". pandas тин ар бир сап үчүн кирүүсү абдан жай экени менен белгилүү жана биз буга таяндык. Ошого карабастан, экосистемада эң көп сунушталган эки backtesting китепканасы ага утулат: backtrader 2.5× ке, bt 4.7× ке.

Муну адал сактаган нюанс: ар бир окуяга негизделген кыймылдаткыч pandas тан жайыраак эмес. backtesting.py (1.42 combos/s) базаны 5× ке артта калтырат, анткени ал ар бир бар үчүн объект түзүүнү минималдуу деңгээлде сактаган лаконикалуу, numpy-ге негизделген окуялар цикли. PyAlgoTrade (0.51) да базадан алдыга өтөт. Ошентип "окуяга негизделген" автоматтык түрдө өлүм өкүмү эмес — бирок ар бир бар үчүн механизм канчалык оор болсо, ал ошончолук начарлайт жана backtrader менен bt бул жерде эң оор механизмди көтөрүп жүрөт. Парадигма шыпты орнотот; ишке ашыруу ошол шыптын алдында кайда түшөрүңдү чечет.

Кеп бул китепканалар жаман деген эмес. backtrader дин брокер модели жана bt тин алголор-дарагы дизайны сизге тууралыкты жана туюнтуучулукту алып берүү үчүн бар — реалдуу буйрутма менен иштөө, портфелди кайра тең салмактоо, анализаторлор. Бул функциялар иштөө убактысынын чыгымына ээ жана бул чыгым сиз бир жолу иштеткенде көрүнбөйт. Свип боюнча болсо ал бүт окуя.

Эмне үчүн окуяга негизделген кыймылдаткычтар салык төлөйт

Фреймворк салыгы кайда алынат, ар бир бар боюнча: бир бар-итерация анын кымбат компоненттерине жарылган — материалдашкан бар объекти, callback фрейми, буйрутманы багыттаган брокер, кошулуп жаткан дептер — ар бири кызыл-кызгылт сары түстөгү жаркыраган бажы бекети тыйын алат, он эки миллион бирдей бар-итерациянын зор алыстап бараткан жолу боюнча кайталанат

Механизм сырдуу эмес. Окуяга негизделген backtest ар бир бар үчүн ушуга окшош нерсени кылат:

  1. Саатты алдыга сүрөт, маалымат агымынан кийинки барды бөлүп алат жана аны объект катары материалдаштырат (Bar, Line, dict).
  2. Колдонуучу кодуна callbackти чакырат (next(), onBars()), бул өз фреймине ээ болгон Python функциясын чакыруу.
  3. Callback ичинде брокер/позиция абалын сурайт, кайра метод чакырууларынын жана атрибут издөөлөрдүн аркылуу.
  4. Эгер буйрутма түзүлсө, аны брокер аркылуу багыттайт: аны бекитет, маржаны/акчаны текшерет, толтурууну пландаштырат, портфель объектин өзгөртөт, транзакция дептерине кошот.
  5. Анализаторлорду, байкоочуларды жана фреймворк сактаган ар кандай эсеп-кысапты жаңылайт.

Эми 150,000 барга, андан кийин 80 комбинацияга көбөйтүңүз: ар бир свип үчүн он эки миллион бар-итерация, ар бири Python деңгээлиндеги объект бөлүштүрүүлөрдүн жана динамикалык жөнөтүүлөрдүн тобу. Python дин ар бир операция үчүн жүктөмү — атрибут издөө же кичине бөлүштүрүү үчүн ондон жүздөгөн наносекундга чейин — бир жолу маанисиз жана он эки миллион жолу кыйратуучу. bt учуру ошол эле оорунун бир варианты: ал ар бир бар эмес, соода даталарында гана кайра тең салмактаса да, ар бир кайра тең салмактоо алго объекттеринин дарагын баалайт жана pandas-ге негизделген портфель дептерине тиет жана ар бир комбинацияда алардын 2,707и, 80 жолуга көбөйтүлөт.

Жөнөкөй pandas цикли backtrader жана bt ти ачык себеп менен жеңет: ал ар бир бар үчүн азыраак иш кылат. Ал брокерди, окуя объекттерин, анализатор стегин, буйрутманы багыттоо абал машинасын өткөрүп жиберет. Ал pandas тин ыраатсыз ар бир сап үчүн салыгын төлөйт, бирок ошол жалгыз ыраатсыз салык дагы эле фреймворктун таза, функцияга толук, ар бир окуя үчүн объект салыгынан арзаныраак. Backtestти "позиция × кийинки-киреше − акылар" га түшүргөндө, фреймворк ар бир бар үчүн кылган нерселердин көбү сиз издөө учурунда колдонбогон жүктөм.

Жана бул тузак: жүктөм сиздин фреймворкту тандоо себебиңиз. Сиз реалдуу брокерди кааладыңыз. Сиз анализаторлорду кааладыңыз. Акыркы валидация учурунда сиз булардын баарын каалайсыз. Экинчи жагынан бир гана скаляр максатты окуган 10,000-комбинациялуу издөө учурунда сиз тегерек боюнча жүгүрүү үчүн лимузинге төлөп жатасыз.

Таблицанын экинчи учу: векторлоштурулган жана компиляцияланган

Таблицанын жогорку бөлүгү ар бир бар үчүн Pythonду толугу менен өчүргөнүңүздө эмне болоору.

  • vectorbt (56.9 combos/s) бүт стратегияны numpy/numba массив операциялары катары туюнтат. Pythonдо бар цикли жок — сигнал, позиция, PnL баары массив деңгээлинде. Ал свипти bt тин 22.5 мүнөтүнө каршы 1.4 секундда иштетет: бирдей иште болжол менен 950× тезирээк. (Биз vectorbt дизайнын vectorbt сереби жана кеңири pandas-vs-polars салыштыруусунда тереңирээк чагылдырабыз.)
  • numba (39.7) — бул pandas цикли, формасы өзгөрбөгөн, жергиликтүү кодго JIT-компиляцияланган. M0 менен бирдей алгоритм, бирок @njit 0.28 combos/s ти 39.7 ге айландырат — декоратордон ~140× тездөө, анткени скаляр циклде үстөмдүк кылган интерпретатор жүктөмү жөн гана бууланып кетет.
  • mp + numba (246) компиляцияланган ядрону CPU ядролору боюнча иштетет. Комбинациялар уят деңгээлде параллель — ар бири көз карандысыз — ошондуктан multiprocessing JIT үстүнөн дээрлик сызыктуу түрдө масштабданат.
  • жергиликтүү Rust (~350) Python желиминин акыркысын алып салат: бүт свип жергиликтүү.
  • MLX GPU (779) свипти Apple-silicon GPU ядросуна карталайт. 80 комбинация 80 параллель арифметика жолуна айланат; свип сиз enter баскычын коё бергенге чейин бүтөт.

Так атоого арзыган эки нерсе бар. Биринчиден, numba парадигма тилден маанилүүрөөк экенин далилдейт. M0 менен numba бирдей алгоритмди иштетет — айырма жөн гана бири ар бир бар үчүн интерпретацияланган Python, экинчиси болсо компиляцияланган. Бул көзөмөлдөнгөн A/B дагы бүт фреймворк салыгы: ички циклден интерпретаторду өчүрүү үчүн ~140×. Экинчиден, numba (39.7) дан mp+numba (246) га, MLX (779) га секирүү эми такыр кыймылдаткыч жөнүндө эмес — бул оркестрлөө жана аппарат жөнүндө. Ар бир бар үчүн салык кеткенден кийин, ылдамдык сиз канча комбинацияны параллель түрдө жана кайсы кремнийде иштетээриңиз маселесине айланат. Биз бул толук прогрессияны backtest кыймылдаткычынын ылдамдык тепкичинде басып өтөбүз жана акыркы миля эмне үчүн процесс/сериализация чыгымы менен үстөмдүк кылынаарын IPC-салыгы макаласында чагылдырабыз.

Биз эмнени өлчөбөгөнбүз (жана эмне үчүн сизге айтып жатабыз)

Benchmarkтын ишенимдүүлүгү анын эмнени жасалмалоодон баш тартканында жашайт. Биз сегиз кыймылдаткычты паритет алдында толук иштеттик. Бир нече белгилүү фреймворкторго биз сан койбодук жана биз өлчөбөгөн санды экстраполяциялоонун ордуна аларды адал гана санап өтүүнү туура көрөбүз:

  • zipline / zipline-reloaded — окуяга негизделген, Quantopian тукуму. Оор орнотуу (толук соода календары жана маалымат топтому), бул ар бир комбинация үчүн алма-алмага убакыт өлчөөнү татаалдаштырат. Архитектуралык жактан ал backtrader менен окуяга негизделген лагерде отурат; биз аны таблицанын ошол учу жанында күтмөкбүз, бирок биз муну далилдей элекбиз.
  • nautilus_trader — Rust/Cython ядросу менен окуяга негизделген, так тирүү-паритет үчүн иштелип чыккан. Анын ядросу компиляцияланган, ошондуктан ал толук Python салыгын төлөбөгөн эң ыктымал окуяга негизделген кыймылдаткыч — биз дагы иштете элек чын кызыктуу өлчөө.
  • QuantConnect Lean — C# ге негизделген, такыр башка иштөө убактысы; Python шайманында түздөн-түз салыштырууга болбойт.
  • Jesse — окуяга негизделген, криптого багытталган; биз анын дизайнын өзүнчө эскертүүдө карадык, бирок бул жерде benchmark кылган жокпуз.
  • QSTrader — окуяга негизделген, портфелге багытталган; ошол эле парадигма эскертүүлөрү.
  • fastquant — биз аракет кылдык; орнотуу/API биздин чөйрөбүздө бузук эле, ошондуктан сан жок. Биз аны божомолдогубуз келбейт.

Биз отчет берген сандар жөнүндө эки адал эскертүү. vectorbt, numba, mp+numba, жергиликтүү-Rust жана MLX сандары төрт окуяга негизделген сапты чыгарган OSS шайманынан эмес, тескерисинче бирдей жүктөмдө биздин өз кыймылдаткыч тепкичибизден алынган — алар бирдей жүктөм, бирок башка өлчөө шайманы жана жергиликтүү-Rust саны болжол менен ~350, так өлчөө эмес. Жана абсолюттук combos/s аппаратка мүнөздүү; саякаттаган нерсе — бул тартип жана катыштар, алар жетишерлик чоң (жогорудан төмөнгө 13,000×, pandas-vs-фреймворк инверсиясы үчүн 2.5–4.7×), ошондуктан эч кандай акылга сыярлык аппарат айырмасы аларды оодарбайт.

Окуяга негизделген кыймылдаткычтарды коргоодо

Окуяга негизделген кыймылдаткыч өзүнүн туура ролунда: жайгаштырууга даяр бир тирүү калган стратегиянын жалгыз кылдат жогорку-тактыктагы валидация иштетүүсү, реалдуу толтурууну моделдеген, маржаны жана буйрутма жашоо циклин сыйлаган так зумурут-жана-көгүш аспап катары чагылдырылган — издөө учурунда таза ысырапкорчулук болгон ар бир бар үчүн механизм бул жерде жайгаштыруудан мурда бир кылдат машыгуу катары баалуу кол өнөрчүлүк катары көрсөтүлгөн

Муну "окуяга негизделген backtesterлер жаман" деп окуу оңой болмок. Бул туура эмес сабак жана адилетсиз.

Окуяга негизделген кыймылдаткычтар башка иш үчүн курулган жана алар мунда жакшы. Ар бир бар үчүн брокер, буйрутма жашоо цикли, толтуруу логикасы, анализаторлор — бул механизм backtestти тирүү соодага мүмкүн болушунча жакын кылуу үчүн бар. Максатыңыз сиз жайгаштыргыңыз келген стратегиянын жалгыз, ишенимдүү машыгуусу болгондо, сиз кыймылдаткычтын ар бир толтурууга тердээрин, жарым-жартылай аткарууларды моделдээрин, маржаны сыйлаарын жана сизди ала албай турган баада соода кылууга уруксат бербээрин каалайсыз. Бул тактык продукт. Анын иштөө убактысынын чыгымы реалдуулуктун баасы жана бир иштетүү үчүн баа маанисиз.

Ийгиликсиздик кыймылдаткычта эмес; ал аны туура эмес этап үчүн колдонууда. Изилдөөнүн карама-каршы талаптарга ээ эки өзүнчө этабы бар:

  • Издөө өткөрүмдүүлүктү каалайт. Сиз ландшафтты изилдеп жатасыз, анын көбү таштанды жана сиз экинчи көз карашка арзыган бир нечесин табуу үчүн миңдеген чекитти баалашыңыз керек. Ар бир чекит үчүн тактык дээрлик маанилүү эмес — сиз иреттеп жатасыз, жайгаштырган жоксуз. Бул жерде фреймворк салыгы таза ысырапкорчулук.
  • Валидация тактыкты каалайт. Сизде бир нече талапкер бар жана сиз алар реалдуу аткаруу, акылар, тайгаланма жана кагаз кирешелерин ашырган алдын ала кароо тузактарынан аман калаарын мүмкүн болушунча так билишиңиз керек. Бул жерде окуяга негизделген кыймылдаткыч өз чыгымын актайт.

Фреймворк салыгы жазалаган ката — бул издөөңүздү валидация кыймылдаткычыңызда иштетүү — 99% ын ыргытып жиберчү ландшафтты изилдөө үчүн лимузин баасын төлөө.

Чечим эрежеси

Практикалык корутунду жалгыз чечимге кысылат:

Векторлоштурулган/компиляцияланган кыймылдаткычта издеңиз. Аман калгандарды окуяга негизделген кыймылдаткычта валидациялаңыз.

Тагыраак:

  1. Свип үчүн тез ядро куруңуз же алыңыз. Эгер аны текчеден каалсаңыз vectorbt; эгер стратегияңыз таза векторлошпосо numba-компиляцияланган цикл (@njit декоратору жалгыз бул жерде ~140× алып келди). Бүт параметр мейкиндигин анын аркылуу иштетиңиз.
  2. Эч качан чоң свипти backtrader, bt, zipline же ар кандай оор окуяга негизделген фреймворкто иштетпеңиз. Эгер алардын биринин свипи сиздин тоскоолуңуз болсо, оңдоо чоңураак машина эмес — бул туура эмес кыймылдаткыч. Атүгүл жөнөкөй pandas цикли да алардын экөөсүн жеңмек.
  3. Кыска тизмени тактык текшерүү үчүн окуяга негизделген кыймылдаткычка көтөрүңүз. Бир нече аман калгандарды алыңыз жана аларды реалдуу кыймылдаткычта кайра иштетиңиз, ал жерде брокер модели жана толтуруу логикасы тез ядро абстракциялаган көйгөйлөрдү ашкерелей алат.
  4. Экөөнүн ортосунда паритетти камсыз кылыңыз. Тез кыймылдаткыч жана тактык кыймылдаткычы туруктуу конфигурацияда сооданын саны жана PnL боюнча макул болушу керек (биздин L=104 дагы ±1-соода текшерүүбүз), антпесе издөө жана валидация ар кандай стратегияларды өлчөп жатат жана бүт түтүк жалган.

Бул издөө жана валидация карама-каршы чыгым профилдерине ээ болгондо пайда болгон ошол эки ылдамдыктуу архитектура жана ошондуктан биздин өз стегибиз параметр издөө үчүн тез векторлоштурулган/компиляцияланган жолду сактайт жана акыркы максат баалоо жана плато текшерүүлөрү үчүн оор механизмди сактайт.

Корутундулар

  1. Популярдуу ≠ свиптер үчүн тез. Бир бирдей, паритетке кулпуланган жүктөмдө (150k бар, 80 HMA-cross комбинациясы, 2,707 соода) backtrader (0.11 combos/s) жана bt (0.06) экөө тең жөнөкөй pandas циклинен (0.28) жайыраак иштеди. Жетилген, көп жылдыздуу фреймворк автоматтык түрдө тез тандоо эмес.
  2. Фреймворк салыгы ар бир бар үчүн жана свип аны көбөйтөт. Ар бир свип үчүн он эки миллион бар-итерация, ар бири окуя объектин, callbackти жана брокер айланышын көтөрүп жүрөт. Бир иштетүүдө көрүнбөгөн баа он миң боюнча бүт эсеп.
  3. Парадигма шыпты орнотот. Векторлоштурулган/компиляцияланган кыймылдаткычтар (vectorbt 56.9, numba 39.7, mp+numba 246, жергиликтүү Rust ~350, MLX 779) окуяга негизделген кыймылдаткычтарды эки-төрт даражалуу чоңдукка жеңет — жогорудан төмөнгө ~13,000× ке чейин. Жөн гана JIT-компиляцияланган бирдей алгоритм 140× тезирээк кетти.
  4. Бардык окуяга негизделген кыймылдаткычтар тең эмес. backtesting.py (1.42) жана PyAlgoTrade (0.51) дагы эле жөнөкөй базаны жеңет; салык ар бир бар үчүн механизм канчалык оор экени менен масштабданат. Ишке ашыруу шыптын алдында кайда түшөрүңдү чечет.
  5. Эки кыймылдаткыч, эки этап. Векторлоштурулган/компиляцияланган ядрода издеңиз; аман калгандарды реалдуу окуяга негизделген кыймылдаткычта валидациялаңыз. Экөө тең бирдей стратегияны өлчөшү үчүн алардын ортосунда сооданын саны/PnL паритетин камсыз кылыңыз.
  6. Эмнени өлчөгөнүңүз жөнүндө адал болуңуз. Биз сегиз кыймылдаткычты паритет алдында benchmark кылдык жана биз кылбагандарды (zipline, nautilus_trader, Lean, Jesse, QSTrader жана иштебеген fastquant орнотуусу) алар үчүн сан ойлоп табуунун ордуна санап өттүк.

Ыңгайсыз корутунду: эгер параметр свип сиздин тоскоолуңуз болсо, көйгөй кыязы сиздин машинаңыз эмес жана стратегияңыз эмес. Бул сиз издөөнү бир адал иштетүү үчүн курулган кыймылдаткычта иштетип жатканыңыз — жана сиз сактоого уялган pandas цикли менен тезирээк болмоксуз.

Толук шайман, паритет бекитүүлөрү жана ар бир кыймылдаткыч үчүн чийки JSON натыйжалары коммит 250dbb5 дагы benchmarks/bench_oss_engines.py жана benchmarks/results_oss/ да жайгашкан. Тепкичтин компиляцияланган/GPU учу үчүн backtest кыймылдаткычынын ылдамдык тепкичин жана IPC-салыгы талдоосун караңыз.

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

Рынктан бир кадам алдыда болуңуз

AI соода аналитикасы, рынок талдоолору жана платформа жаңылыктары үчүн биздин жаңылыктар бюллетенине жазылыңыз.

Биз сиздин купуялыгыңызды урматтайбыз. Каалаган убакта жазылымдан чыга аласыз.