Multi-Timeframe Backtest'терде Look-Ahead Жоктугун Далилдөө: Келечекти Бузуп, Өткөндүн Аны Көрө Албастыгын Далилде
"Илюзиясыз Backtest'тер" сериясынын бир бөлүгү.
Мурунку макала бир диагностикалык тест менен аяктаган эле: one-bar shift test. Ар бир fill'ди бир bar кийинчерээк жылдырыңыз; эгер performance кыйрап кетсе, демек сиз өткөндө соода жасап жаткансыз. Бул тест single-timeframe стратегия үчүн жетиштүү, анда look-ahead execution'до жашынат — сиз bar iде чечим кабыл алгансыз жана bar iде эле fill болгонсуз.
Multi-timeframe стратегияларда агып кетүүнүн экинчи, бир аз тынч жери бар, жана shift test ага жетпейт. Качан 1 мүнөттүк bar'дагы чечим 1 сааттык trend'ге кайрылса, агуу эми fill'де эмес — ал indicator'до жашынат, б.а. али толук калыптана элек жогорку timeframe bar'ынан эсептелген indicator'до. Бул макала так ошол агуу жөнүндө, жана коддон карап отуруп эмес, механикалык түрдө сиздин engine'иңизде андай агуу жоктугун кантип далилдөө керектиги жөнүндө.
Multi-timeframe мина талаасы

Multi-timeframe (multi-TF) стратегия тез сааттын негизинде чечим кабыл алат, ал эми жай сааттарга кайрылып турат. Биздин engine — нускалуу мисал: triple-TF momentum эрежеси, анда жогорку timeframe (HTF) trend'и менен орто timeframe (MTF) trend'и кирүүлөрдү (entry) gate кылат (чектейт), ал эми төмөнкү timeframe (LTF) cross'у аларды trigger кылат (иштетет). 1m негизги саат боюнча, кирүү (entry) 1m HMA/HMA3 cross'у 1h trend'дин багыты жана 15m trend'дин багыты менен дал келгенде гана иштейт; чыгуу (exit) жогорку timeframe trend'и позицияга каршы бурулуп кеткенде же LTF кайра cross жасаганда иштейт.
Коркунуч структуралык мүнөздө. Ошол жогорку timeframe маанилеринин ар бири ар бир 1m bar'да жооп берилиши керек — саатына 60 жолу — жана ар бир жооп live бот ошол учурда билген нерсени гана колдонушу керек. Ошол bar-башына окулган 180дей маанинин (үч timeframe, кирүү жана чыгуу trend'дери, separation gate'дер) ичинен бирөө гана али басылып чыга элек bar'га тийсе, сизде look-ahead бар дегенди билдирет. Off-by-one катасы үчүн мейкиндик өтө чоң, жана execution агуусунан айырмаланып, бул өзүн fill'дин жылышы менен билдирбейт.
Калыптанып жаткан bar'дын акыркы close'у али жок
Мына так тузак. Айталы, саат 10:37, жана сиз жаңы эле жабылган 1m bar боюнча чечим кабыл алып жатасыз. Сиздин эрежеңиз 1h trend'ди талап кылат. 10:00–11:00ду камтыган 1h шам али калыптанууда — анын акыркы close'у 10:59:59го чейин белгисиз болот. 10:37де сиз чындыгында эмнени билесиз? Ошол шамдын учурдагы (running) close'ун гана, б.а. 10:37 bar'ынын close'ун. Шамдын акыркы close'у 23 мүнөт кийин, келечекте.
Наивдуу multi-TF backtest толугу менен зыянсыз көрүнгөн бир нерсе жасайт: ал бүт 1m катарды 1h'ге бир жолу, алдын ала resample кылат, андан кийин ар бир 1m bar үчүн "1h close'ун" окуйт. Бирок ал ар бир 10:00 менен 11:00 ортосундагы 1m bar үчүн окуган маани — бул акыркы 10:00–11:00 close'у, б.а. чыныгы убакытта саат бүткөнгө чейин жок болгон сан. Сааттын ичиндеги ар бир чечим унчукпай туруп 59 мүнөт келечекке узатылат. Жана бул кичине агуу эмес: жогорку timeframe'дин close'у сиз соода кылганы жаткан жакынкы келечектеги 1m кирешелердин (return) эң күчтүү мүмкүн болгон божомолчусу, ошондуктан аны агызуу жооп баракчасын окуп алуу менен барабар. Бул taxonomy'дегi indicator-leakage каналы, бирок күчөтүлгөн түрдө: карап алуу бир bar эмес, бүтүндөй HTF мезгилине чейин жетет.
Мурунку макаладагы one-bar shift test муну кармабайт. Сиз fill'ди бир bar кийинчерээк жылдыра аласыз, бирок resample кылынган 1h катар дагы деле булганган бойдон калат — агуу сиз качан trade жасаганыңызда эмес, indicator кандай курулганында жашынган.
Live боттун эрежеси, так кайра жаратылды: closed-bar семантикасы

Туура эреже — бул live бот мурунтан эле аткарып жаткан эреже. Биздин codebase'де бул кичинекей класс, RunningCandleBuffer, ал live tick симуляторунан сөзмө-сөз (verbatim) көчүрүлүп алынган. Ал base bar'ларды туруктуу мезгилдеги шамдарга агым түрүндө өткөрөт жана ар бир base bar'да HTF indicator'ун так белгилүү бир массивден эсептейт:
all_closes = np.array(self.closes + [self.current_close], dtype=np.float64)
Муну сөзмө-сөз окуңуз. self.closes — бул мурунтан эле жабылган шамдардын акыркы close'дору — шам жаңы период чек арасы кесилгенде гана кошулат, жана анын сакталган мааниси период ичиндеги акыркы base bar'дын close'у болуп саналат (candle_buffer.py:39–44). Калыптанып жаткан шам так бир сан менен катышат, self.current_close, бул — учурдагы (running) close, б.а. эң акыркы base bar'дын close'у, base_close[i]. Бул bar iде аныктама боюнча белгилүү болгон чоңдук. Калыптанып жаткан шамдын акыркы close'у эч качан колдонулбайт, себеби ал али жок.
Демек, 10:37дегi HTF indicator'у [..., close(9:00 candle), close(10:37 so far)] дегенди көрөт. 10:38 басылып чыкканда, акыркы уяча close(10:38)ге жаңыртылат. 11:00 кесилгенде, close(10:59) жаңыдан жабылган шамдын акыркы мааниси болуп калат жана жаңы калыптануучу уяча ачылат. Сааттын ичиндеги эч бир чечим акыркы 10:00–11:00 close'уна эч качан тийбейт. Дал ушул closed-bar семантикасы: жабылган шамдар бүткөн close'дорду беришет, ал эми калыптанып жаткан шам болсо өзүнүн учурдагы close'ун гана берет.
Биздин тез engine (engine_multitf.py) — мунун vectorized, numba менен compile кылынган кайра ишке ашырылышы. Өсүп жаткан тизме менен Python цикли ордуна, ал ар бир base bar i үчүн канча шам толук жабылганын (n_closed[i]) алдын ала эсептейт жана HMA/HMA3 терезесин [closed candle closes…, base_close[i]] түрүндө жайгаштырат — учурдагы close акыркы уячага бекитилген (engine_multitf.py:168–169). Бул так ошол эле математика, ылдамдык үчүн үч timeframe боюнча directional separation gate'дер менен жайылтылган. Келишим ачык айтылган: bar iдеги маани base_close[0..i]дан гана көз каранды.
Бул — биздин талап (claim). Макаланын калган бөлүгү аны кантип далилдегенибиз жөнүндө, себеби docstring'деги дооматтын эч кандай баасы жок.
Parity керек, бирок жетишсиз
Streaming класты ачык-айкын циклдерге жайган vectorized numba engine — дал off-by-one каталар көбөйгөн жер. Ошондуктан биринчи gate — канондук эталонго карата чыныгы кесиндиде bit-for-bit parity тести, ETHUSDT 1m, 2024-жылдын январь–февралы, 86,400 bar.
Биз эки көз каранды эмес эталонго карата эки көз каранды эмес нерсени текшеребиз:
- Indicator'лор жана cross'тор — bar-by-bar иштетилген
RunningCandleBufferга карата. Ар бир timeframe үчүн биз live класты бардык 86,400 bar'дын үстүнөн кайра ойнотобуз жана cross окуяларын — bar'ды, багытты, separation'ду — так дал келүүгө салыштырабыз, ошондой эле HMA/HMA3 маанилерин floating-point толеранттуулугуна чейин (эталонnp.dotколдонот, engine болсо ачык-айкын циклдерди, ошондуктан суммалоо тартиби ~1e-15де айырмаланат). Cross'тор так дал келет: HTF'де (1h, HMA узундугу 21) 408 cross, MTF'де (15m/14) 2,792, LTF'де (1m/50) 3,691. Бир да cross окуясы bar же багыт боюнча айырмаланбайт. - Trade'дер — эталондун өз cross'тору менен иштетилген көз каранды эмес таза Python симуляциясына карата. Бул live backtest'тин циклин кайра түзөт — кирүү trend'дери кирүүлөрдү gate кылат, чыгуу trend'инин бурулушу же карама-каршы LTF cross жабат, fill
open[i+1]де болот, round-trip fee 0.09%, акыркы bar'да force-close — жана муну engine'дин numba механизминин эч бир бөлүгүсүз жасайт. Андан кийин биз trade-by-trade салыштырабыз: кирүү/чыгуу bar'лары, тараптар, кирүү/чыгуу баалары, PnL, чыгуу себептери, жана позициядагы жалпы active-time.
Тесттеги separation threshold'дору зыянсыз демейки маанилер эмес. Алар атайын ыңгайсыз бир бурчту — дал келген entry threshold'дан жогору коюлган MTF exit threshold'ун — кагылыштыруу үчүн тандалган, бул эталон реверсия катары карай турган "позиция ачык турганда exit trend'и биринчи жолу аныкталышы" бутагын мажбурлайт. Parity жеңил жол боюнча гана эмес, дал ушул бурчтук учурларда да сакталышы керек.
Field-by-field, trade'дер бирдей: dual конфигурация үчүн 466 trade, triple үчүн 211 trade, жалпы PnL 1e-12ге чейин дал келет жана ар бир trade'дин талаалары толеранттуулукка чейин барабар. Эч кандай код бөлүшпөгөн эки ишке ашыруу — compile кылынган vectorized engine жана үчүнчү ишке ашыруунун cross'торунда иштеген наивдуу Python цикли — акыркы ондук санга чейин бирдей trade'дерди берет.
Бул күчтүү жыйынтык, бирок бул look-ahead жоктугунун далили эмес. Parity тез engine эталонду ишенимдүү түрдө кайра жаратат дегенди гана айтат. Эгер эталондун өзү агып жаткан болсо — эгер RunningCandleBuffer алдын ала карап алса — parity ошол агууну ишенимдүү түрдө кайра жаратып, өтүп кетмек. Ишке ашыруулардын ортосундагы дал келүү алар бирдей экенин билдирет, алар каузалдуу (causal) экенин эмес. Каузалдуулук үчүн башка түрдөгү тест керек — engine'ден түз эле өткөн келечекти көрө алабы деп сурай турган тест.
Shifted-future probe: чыныгы далил

Look-ahead'дин аныктамасы операциялык мүнөздө, ошондуктан аны операциялык түрдө текшер. Look-ahead дегени — өткөндөгү чечим келечектеги маалыматтан көз каранды болот. Мунун контрапозициясы — сиз иштете турган тест: эгер сиз келечекти өзгөртсөңүз, жана кайсы бир өткөн чечим жылса, демек өткөн келечекти окуп жаткан. Ошондуктан келечекти — катаал түрдө — өзгөрт жана өткөндү байкап тур.
Катардын 60 пайызында кесүү чекитин j тандаңыз (86,400дүн 51,840-bar'ы). jден баштап ар бир bar'ды бузуңуз: бардык келечектеги close жана open'дорду 1.05ке көбөйтүңүз. Бузулган маалымат боюнча үч timeframe'дин баары үчүн бүткүл сигнал стегин кайра эсептеңиз. Андан кийин jден так мурункунун баары бузулбаган иштетүүгө bitwise бирдей экенин ырастаңыз:
j = int(n * 0.6) # bar 51,840
cl2 = cl.copy(); cl2[j:] *= 1.05 # shove the future up 5%
op2 = op.copy(); op2[j:] *= 1.05
base = [precompute_tf_signals(cl, ts, p, L) for (p, L) in tf_params]
pert = [precompute_tf_signals(cl2, ts, p, L) for (p, L) in tf_params]
for s0, s1 in zip(base, pert):
assert eq_nan(s0.hma[:j], s1.hma[:j]) # HMA identical, NaNs included
assert eq_nan(s0.hma3[:j], s1.hma3[:j])
assert np.array_equal(s0.cross[:j], s1.cross[:j]) # every cross event
assert np.array_equal(s0.sep[:j], s1.sep[:j]) # every separation
"Жакын" эмес. "Толеранттуулук ичинде" эмес. np.array_equal, мында NaN'дар NaN'дарга дал келиши талап кылынат — 51,840 өткөн bar'дын ар бир HMA мааниси, ар бир HMA3 мааниси, ар бир cross флагы, жана ар бир separation так ошол эле float болушу керек. Андан кийин trade'дер боюнча да ошол эле ырастоо: чыгуусу jден мурун болгон ар бир trade field-for-field өзгөрбөшү керек. Эгер келечекке 5% түртүү өткөндөгү бирдиктүү HMAны он экинчи ондук орунда жылдырса, демек өткөн чечим келечекке кайрылган, жана probe өтпөй калат.
Жеңилe албай турган тест эч нерсени далилдебейт
Жогорудагы probe'дон эч нерсе далилдебей туруп өтүүнүн бир жолу бар: эгер бузуу эч нерсеге таасир этпесе — эгер келечекти 1.05ке көбөйтүү эч жерде эч нерсени өзгөртпөсө — анда "өткөн өзгөргөн жок" дегени тривиалдуу түрдө туура, бирок такыр эч кандай маалымат бербейт. Жеңиле албай турган тесттеги жашыл белги тесттин жоктугунан да жаман, себеби ал жалган ишенимди жаратат. Ошондуктан probe'до ага тиш бере турган дагы эки ырастоо бар.
Келечек чын эле өзгөрүшү керек. Биз бузуунун [j, n) аралыгындагы бир жерде cross'торду чын эле өзгөрткөнүн ырастайбыз:
assert not np.array_equal(s0.cross[j:], s1.cross[j:]) # probe has teeth
Эми жыйынтык мааниге ээ: келечекти кайра жазган ошол эле 5% түртүү өткөндү bit-for-bit бирдей калтырды. Бузуу чыныгы, ал алдыга карай таралат, жана кесимде такыр токтойт. Бир тараптуу агуу — өткөн келечекти окуса — j аркылуу артка карай агып кетмек; бирок бул болбойт.
Чек ара так учурдагы bar'да — бир мурда эмес, бир кийин да эмес. Андан да нептик каталык — бул каузалдуу, бирок эскирген (stale) engine: ал учурдагы bar'дын running close'ун этибарга албай, бир bar кийин реакция кылат (агуу жок, бирок live соода болбой турган лаг бар), же болбосо бир bar мурда реакция кылат (бир bar'дык агуу). Ошондуктан биз бир гана j bar'ын бузабыз (1.02ге көбөйтүп) жана эки нерсени бир учурда ырастайбыз: [0, j) өткөнү тийбей калды, жана hma[j] дароо реакция кылат.
cl3 = cl.copy(); cl3[j] *= 1.02 # nudge exactly one bar
s3 = precompute_tf_signals(cl3, ts, p_ltf, L_ltf)
assert eq_nan(s0.hma[:j], s3.hma[:j]) # nothing before j moves
assert s0.hma[j] != s3.hma[j] # bar j reacts on the same bar
Бул чек араны так белгилейт. Калыптанып жаткан шамдын running close'у indicator'го bar jде нөл кечиктирүү жана нөл алдын ала көрүү менен кирет: bar j өзүнүн close'ун дароо көрөт, ал эми андан мурунку эч бир bar аны такыр көрбөйт. Дал ушул — closed-bar семантикасы турушу керек болгон бычак кыры, жана тест engine дал ошол кырда тургандыгын ырастайт.
Мына толук gate — бул engine менен жасалма backtest'тин ортосунда турган бардык 25 текшерүү:
| Топ | Ар бир текшерүү эмнени ырастайт | Саны |
|---|---|---|
| Indicator'лор жана cross'тор (×3 timeframe) | RunningCandleBufferга карата так cross окуялары; cross'тордогу separation; HMA/HMA3 маанилери (rtol 1e-9) |
9 |
| Trade'дер (dual + triple) | trade саны; field-by-field бирдей; жалпы PnL 1e-12ге чейин; позициядагы active-time | 8 |
| Shifted-future probe (dual + triple) | өткөн сигналдар bitwise өзгөрбөйт; probe тиштүү (келечек чын эле өзгөрдү); jден мурунку trade'дер өзгөрбөйт; бир bar'дык бузуу локалдаштырылган |
8 |
| Жыйынтык | 25 |
Биринчи эки топ тез engine live эталон экенин тастыктайт. Үчүнчүсү эталон каузалдуу экенин тастыктайт. Сизге үчөө тең керек: агып жаткан тез engine, каузалдуу бирок агып жаткан engine, жана лагы бар каузалдуу engine — булар үч башка-башка каталык, жана gate ар бирин четке кагат.
Эмне үчүн probe timeframe'ге көз каранды эмес
Shifted-future probe'дун жарашыктуулугу — ал агуу кайда жашай турганын билбейт жана этибарга да албайт. Ал timeframe'дерди, resample'ди же шам чек араларын эч качан эске албайт. Ал бир гана суроо берет: келечекти бузуу өткөндү жылдырабы? Дал ушул аны multi-TF агуусу үчүн так туура курал кылат, ал эми shift-the-fill тести муну байкабай калат.
Наивдуу resample-the-whole-series катасын түз карап көрөлү. Эгер 1h агымы толук катарды алдын ала resample кылуу менен курулган болсо, bar j-1000де (jден кийин жабылган сааттын ичинде терең жайгашкан) окулган "1h close" — акыркы close'у j жана андан аркы bar'ларга көз каранды болгон шамдын акыркы close'у болмок. Келечекти 1.05ке көбөйтсөңүз, ошол акыркы close өзгөрөт — демек bar j-1000дегi HTF indicator'у өзгөрөт, bar j-1000дегi gate өзгөрөт, жана өткөн чечим жылат. Probe HTF агымында дароо, кесимден миң кадам мурдараак турган bar'да жанмак.
Биздин engine'дин HTF агымы жылбайт, себеби bar j-1000де калыптанып жаткан шам base_close[j-1000]ди гана берет — өткөн close — жана шамдын акыркы close'у чек ара өткөнгө чейин эч качан колдонулбайт. Probe механизмге сокур, бирок ошого карабай катаны кармайт — далилден так ушул күтүлөт: ал implementation'ду аудит кылуунун ордуна (resample'ди туура индекстедикпи?) жүрүм-турумду чектейт (эч бир өткөн чечим келечектеги маалыматтан көз каранды эмес). Соода жасаган нерсе — жүрүм-турум; сиз ага дал келет деп үмүттөнгөн нерсе — implementation.
Backtest жана live бир эле чындыкты бөлүшөт

Мунун адаттагы backtest аудитинен да маанилүү болушунун дагы бир себеби бар. Engine карата далилденген эталон — RunningCandleBuffer — backtest'ти жакшы көрсөтүү үчүн жазылган тест fixture эмес. Бул production'до иштеген tick симуляторунан сөзмө-сөз алынган, live боттун өзүнүн шам логикасы. Probe текшерген closed-bar эрежеси — бул live бот bar сайын аткарган эреже.
Ошондуктан parity gate эки милдетти аткарат. Ал тез engine эталонго дал келерин далилдейт, жана эталон live өзөк болгондуктан, ал тез engine live менен дал келерин да далилдейт. Мурунку макала агуу backtest-live parity ажырымынын эң таза түшүндүрмөсү экенин эскерткен — live бот сиз механикалык түрдө карап алалбай турган жалгыз жер, ошондуктан карап алган backtest live'ге чыккан замат ажырап кетет. Бул жерде ошол ажырым курулуш боюнча эле жабылат: backtest жана бот бир эле шам буферин, бир эле cross эрежесин, "bar iде белгилүү" деген бир эле аныктаманы бөлүшөт. Search оптимизациялаган сан — бот чын эле соода кыла ала турган сан.
Look-ahead жоктугун болжолдоонун ордуна далилдөөнүн бүт максаты дал ушул. Multi-TF search миңдеген конфигурацияны иштетет; эгер engine агып жатса, search агууну эң агрессивдүү пайдаланган конфигурацияны табат жана сизге жасалма жеңүүчүнү берет — taxonomy таза шумдан Sharpe 15ти өлчөгөн ошол каталык режими. Probe — капиталга туташтыруудан мурун жеңүүчүнүн чыныгы экенине ишенүүгө мүмкүндүк берген нерсе.
Probe эмнени далилдейт жана эмнени далилдебейт
Тест жөнүндөгү катуулук эки жакка тең иштейт, ошондуктан анын чегин так белгилөө керек. Shifted-future probe бир гана так касиетти далилдейт: бул маалыматта, bar jде же андан мурда эч бир сигнал же trade чечими jден кийинки эч бир bar'дан көз каранды эмес — убакыттагы маалымат чек арасы indicator, cross жана trade жолу боюнча сакталат. Бул — биз жок кылганы турган дал ошол multi-TF агуусу, жана бул код-ревью тарабынан аныкталбай турган касиет.
Ал стратегиянын edge'и (артыкчылыгы) бар экенин далилдебейт. Толук каузалдуу engine адилеттик менен акча жоготушу мүмкүн, жана probe бул жөнүндө унчукпайт — так ушундай болушу керек да; агуу жоктугун далилдөө жана чыныгы edge табуу — эки башка-башка иш, жана аларды аралаштыруу агып жаткан backtest'тердин production'го чыгарылышынын жолу. Ал убактылуу эмес biases'терди камтыбайт: инструменттеги survivorship, probe'ду engine жакшы көрүнгөндөн кийин гана иштетүүдөн келип чыккан selection bias, же өтө жумшак fee модели. Жана бул өзү менен эле live fill'дер backtest fill'дерине дал келерин далилдебейт — slippage жана latency probe көрө албай турган чыныгы ажырымдар, себеби ал execution venue'до эмес, чечим кабыл алуу жолунда иштейт. Ошол ажырымды жабуучу нерсе — engine'дин шам өзөгүнүн live боттукуна bit-identical болгону деген өзүнчө факт.
Probe'дун өзүнүн дизайны жөнүндө бир так эскертүү: ал бир гана jде (катардын 60%инде) кесет. Ал текшерген касиет j боюнча бирдей — bar 51,840до өзгөчө эч нерсе жок — ошондуктан бир кесим структуралык касиеттин адилеттүү тести, бирок паранойялуу версия jди катар боюнча жылдырып чыгар эле. Биз бир жакшы тандалган кесим менен бир bar'дык локализация текшерүүсүн жетиштүү деп эсептейбиз, себеби 34,560 bar'дык келечек бузуудан жашырынып, башка бир кесимде пайда болгон агуу өтө сейрек кездешкен ката болмок. Максат — далилиңиздин чектерин билүү, бир тесттин универсалдуу квантор экенине жасалма ишенүү эмес.
Негизги жыйынтыктар
- Multi-timeframe стратегиялар fill'ден эмес, калыптанып жаткан bar аркылуу агат. Бүтпөгөн HTF мезгилинин ичиндеги чечим ошол шамдын учурдагы close'ун гана (эң акыркы base close) колдонушу керек, анын акыркы close'ун эч качан эмес. Resample-the-whole-series backtest'тер мезгил ичиндеги ар бир чечимди бүтүндөй HTF мезгилинин келечегине узатып беришет.
- One-bar shift test бул агууга жетпейт. Ал execution look-ahead'ин кармайт; multi-TF агуусу indicator кандай курулганында жашайт. Сизге башка probe керек.
- Live эрежени так кайра жаратып, андан кийин далилде. Биз боттун
RunningCandleBufferclosed-bar семантикасын vectorized engine катары кайра курдук жана аны 25 текшерүүнүн артына gate кылдык: эталонго карата так cross'тор (408 / 2,792 / 3,691), field-by-field бирдей trade'дер (466 dual, 211 triple), PnL 1e-12ге чейин. - Parity керек, бирок жетишсиз. Эталонго дал келүү сиз бирдей экениңизди далилдейт, каузалдуу экениңизди эмес. Ишенимдүү түрдө кайра жаратылган агып жаткан эталон дагы деле агат.
- Shifted-future probe — чыныгы далил. Bar
jде же андан кийин турган ар бир bar'ды бузуңуз;jден мурунку ар бир сигнал жана trade bitwise өзгөрбөгөнүн ырастаңыз. Эгер келечек өткөндү жылдыра алса, сизде look-ahead бар. - Probe'го тиш бериңиз. Келечектин чын эле өзгөргөнүн (бузуу no-op эмес экенин) жана бир bar'дык түртүү так ошол эле bar'да реакция кыларын (агуу жок, лаг жок) ырастаңыз. Жеңилe албай турган тест эч нерсени далилдебейт.
- Backtest жана live бир эле өзөктү бөлүшкөндө, далил өтөт. Engine live боттун шам логикасына bit-identical болгондуктан, look-ahead жоктугу live системанын да касиети болуп саналат — жана backtest-live parity ажырымы курулуш боюнча жабылат.
Мурунку макала бир сап код агуусу Sharpe 15ти кантип жасалмалай турганын көрсөткөн. Бул макала карама-каршы дисциплинаны көрсөтөт: "агуулар сени кантип алдайт" эмес, кандайча белгилүү бир engine агып жатпаганын, механикалык түрдө жана чыныгы маалыматта, далилдөө керектигин. Келечекти бузуңуз. Эгер өткөн селт этпесе, сиз учурда соода кылып жатасыз.
Authors
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.