Мультитаймфреймдік бэктестерде келешекке қарамауды дәлелдеу: болашақты бұзып, өткеннің оны көре алмайтынын дәлелдеу
"Иллюзиясыз бэктестер" сериясының бір бөлігі.
Алдыңғы мақала диагностикамен аяқталды: бір-барлық ығысу сынағы. Әрбір орындалуды бір барға кейінге жылжытыңыз; егер нәтиже құласа, сіз өткенде сауда жасап отырғансыз. Бұл сынақ бір таймфреймдік стратегия үшін жеткілікті, онда келешекке қарау орындауда жасырынады — сіз шешімді i барында қабылдап, i барында орындадыңыз.
Мультитаймфреймдік стратегиялардың ағып кетуге арналған екінші, тыныш орны бар, әрі ығысу сынағы оған жетпейді. 1 минуттық бардағы шешім 1 сағаттық трендке жүгінген кезде, ағу енді орындауда емес — ол индикаторда, яғни әлі қалыптасуы аяқталмаған жоғары таймфреймдік бардан есептелген индикаторда. Бұл мақала осы ағу туралы, әрі сіздің қозғалтқышыңызда оның жоқтығын — тек кодқа қарап отырып емес, механикалық түрде — қалай дәлелдеу керектігі туралы.
Соңында біз жасайтын мәлімдеме күшті: біздің мульти-TF қозғалтқышымыз нақты ETHUSDT 1 минуттық деректерінің 86 400 барында 25 паритет пен ағу тексерулерінің 25-ін өтті, оның ішінде болашақтағы әрбір барды бұзатын және өткендегі бір де бір шешімнің қозғалмайтынын растайтын ығыстырылған-болашақ сынағы да бар. Әрі қозғалтқыш тірі боттың канондық өзегімен биттік сәйкес болғандықтан, дәлел тек бэктестің емес, тірі жүйенің қасиеті болып табылады.
Мультитаймфреймдік минералар алаңы

Мультитаймфреймдік (мульти-TF) стратегия баяу сағаттарға жүгіне отырып, жылдам сағат бойынша шешім қабылдайды. Біздің қозғалтқышымыз нақты мысал болып табылады: жоғары таймфрейм (HTF) мен орта таймфрейм (MTF) трендтері кірулерді шектейтін, ал төменгі таймфрейм (LTF) қиылысуы оларды іске қосатын үштік-TF импульс ережесі. 1 минуттық негізгі сағат бойынша кіру тек 1 минуттық HMA/HMA3 қиылысуы 1 сағаттық тренд пен 15 минуттық трендтің бағытымен сәйкес келгенде ғана іске қосылады; шығу жоғары таймфреймдік тренд позицияға қарсы бұрылғанда немесе LTF кері қиылысқанда іске қосылады.
Қауіп құрылымдық сипатта. Осы жоғары таймфреймдік мәндердің әрқайсысына әрбір 1 минуттық барда — сағатына 60 рет — жауап беру керек, әрі әрбір жауап тек тірі бот сол сәтте білетінді ғана пайдалануы тиіс. Осы бар-сайынғы шамамен 180 оқудың (үш таймфрейм, кіру мен шығу трендтері, ажырату шектеулері) бір ғанасы әлі басылмаған барға тиіп кетсе, сізде келешекке қарау бар болғаны. Off-by-one қатесінің таралу аймағы орасан зор, әрі орындау ағуынан айырмашылығы, ол орындалуды ығыстыру арқылы өзін білдірмейді.
Қалыптасып жатқан бардың соңғы жабылу бағасы әлі жоқ
Міне дәл тұзақ. 10:37-де сіз жаңа ғана жабылған 1 минуттық бар бойынша шешім қабылдап отырсыз делік. Сіздің ережеңізге 1 сағаттық тренд керек. 10:00–11:00 аралығын қамтитын 1 сағаттық шам әлі қалыптасып жатыр — оның соңғы жабылу бағасы тек 10:59:59-да белгілі болады. 10:37-де сіз шын мәнінде не білесіз? Тек сол шамның қазіргі уақытқа дейінгі ағымдағы жабылу бағасын, яғни 10:37 барының жабылу бағасын. Шамның соңғы жабылу бағасы 23 минуттан кейінгі болашақта.
Аңғал мульти-TF бэктест мүлдем зиянсыз көрінетін нәрсе жасайды: ол бүкіл 1 минуттық серияны бір рет, алдын ала, 1 сағатқа қайта дискреттейді, содан кейін әрбір 1 минуттық бар үшін "1 сағаттық жабылу бағасын" оқиды. Бірақ ол 10:00 мен 11:00 арасындағы әрбір 1 минуттық бар үшін оқитын мән — нақты уақытта сағат аяқталғанша жоқ болатын 10:00–11:00 аралығының соңғы жабылу бағасы. Сағат ішіндегі әрбір шешім үнсіз түрде 59 минут болашаққа беріліп жатыр. Әрі бұл шамалы ағу емес — жоғары таймфреймдік жабылу бағасы сіз сауда жасамақ болып отырған жақын болашақтағы 1 минуттық кірістердің мүмкін болатын ең күшті болжаушысы, сондықтан оны сыздыру жауап кілтін оқуға жақын. Бұл таксономиядағы индикатор-ағу арнасы, тек күшейтілген түрде: бұл бір бардың қарауы емес, толық HTF кезеңіне дейінгі қарау.
Алдыңғы мақаладағы бір-барлық ығысу сынағы мұны ұстамайды. Сіз орындауды бір барға кейінге жылжыта аласыз, бірақ қайта дискретеленген 1 сағаттық серия әлі де ластанған күйінде қалады — ағу мәміле жасалған уақытта емес, индикатордың қалай құрылғанында жасырынады.
Тірі боттың ережесі, дәл қайталанған: жабық-бар семантикасы

Дұрыс ереже — тірі боттың қазірдің өзінде қолданатын ережесі. Біздің кодтық базамызда бұл RunningCandleBuffer деп аталатын кішкентай класс, тірі тик симуляторынан сөзбе-сөз көшірілген. Ол негізгі барларды тұрақты периодты шамдарға ағынмен береді және әрбір негізгі барда HTF индикаторын нақты бір массивтен есептейді:
all_closes = np.array(self.closes + [self.current_close], dtype=np.float64)
Мұны сөзбе-сөз оқыңыз. self.closes — бұл қазірдің өзінде жабылған шамдардың соңғы жабылу бағалары — шам тек жаңа период шекарасы кесіп өткенде ғана қосылады, ал оның сақталған мәні период ішіндегі соңғы негізгі бардың жабылу бағасы (candle_buffer.py:39–44). Қалыптасып жатқан шам дәл бір сан қосады, self.current_close — бұл ағымдағы жабылу бағасы, яғни ең соңғы негізгі бардың жабылу бағасы, base_close[i]. Бұл i барында анықтамасы бойынша белгілі шама. Қалыптасып жатқан шамның соңғы жабылу бағасы ешқашан пайдаланылмайды, себебі ол әлі жоқ.
Сонымен, 10:37-де HTF индикаторы [..., close(9:00 шамы), close(10:37 қазіргі)] көреді. 10:38 басылғанда, соңғы ұяшық close(10:38)-ге жаңарады. 11:00 кескенде, close(10:59) жаңа жабылған шамның соңғы мәні болады да, жаңа қалыптасу ұяшығы ашылады. Сағат ішіндегі шешім ешбір сәтте 10:00–11:00 аралығының соңғы жабылу бағасына тимейді. Дәл осы — жабық-бар семантикасы: жабық шамдар аяқталған жабылу бағаларын береді, ал қалыптасып жатқан шам тек өзінің ағымдағы жабылу бағасын береді.
Біздің жылдам қозғалтқышымыз (engine_multitf.py) осының векторланған, numba-компиляцияланған қайта жүзеге асырылуы. Өсіп келе жатқан тізіммен Python циклы орнына, ол әрбір негізгі бар i үшін қанша шам толықтай жабылғанын (n_closed[i]) алдын ала есептейді және HMA/HMA3 терезесін [жабық шам жабылу бағалары…, base_close[i]] түрінде жайғастырады — ағымдағы жабылу бағасы соңғы ұяшыққа бекітілген (engine_multitf.py:168–169). Бұл дәл сол математика, жылдамдық үшін үш таймфреймде бағыттық ажырату шектеулерімен ашылған. Келісім анық: i барындағы мән тек base_close[0..i]-ге тәуелді.
Бұл — мәлімдеме. Мақаланың қалған бөлігі — оны қалай дәлелдейтінімізге арналған, себебі докстрингтегі мәлімдеменің ешқандай құны жоқ.
Паритет қажет, бірақ жеткіліксіз
Ағынды класты нақты циклдарға ашатын векторланған numba қозғалтқышы дәл off-by-one қателерінің өсетін жері. Сондықтан бірінші шлюз — нақты кесіндіде, ETHUSDT 1 минуттық, 2024 жылдың қаңтар–ақпаны, 86 400 бар, канондық анықтамаға қарсы бит-бітпен паритет сынағы.
Біз екі тәуелсіз анықтамаға қарсы екі тәуелсіз нәрсені тексереміз:
- Индикаторлар мен қиылысулар бар-бармен жүргізілген
RunningCandleBuffer-ге қарсы. Әрбір таймфрейм үшін біз тірі кластың барлық 86 400 барын қайта ойнатамыз және қиылысу оқиғаларын — барды, бағытты, ажыратуды — дәл сәйкестікке салыстырамыз, сонымен қатар HMA/HMA3 мәндерін өзгермелі нүктелік дәлдікке дейін салыстырамыз (анықтамаnp.dotпайдаланады, қозғалтқыш нақты циклдарды, сондықтан қосу реті ~1e-15 деңгейінде ерекшеленеді). Қиылысулар дәл сәйкес келеді: HTF-те (1 сағат, HMA ұзындығы 21) 408 қиылысу, MTF-те (15 минут/14) 2 792, LTF-те (1 минут/50) 3 691. Бірде-бір қиылысу оқиғасы барда немесе бағытта ерекшеленбейді. - Мәмілелер анықтаманың өз қиылысуларымен жүргізілетін сауда ережелерінің тәуелсіз таза Python симуляциясына қарсы. Бұл тірі бэктест циклын қайталайды — кіру трендтері кірулерді шектейді, шығу-тренд бұрылуы немесе қарсы LTF қиылысуы жабады, орындау
open[i+1]-де, 0.09% екі жақты комиссия, соңғы барда мәжбүрлі жабу — қозғалтқыштың numba механизмінсіз. Содан кейін біз мәміле-мәмілемен салыстырамыз: кіру/шығу барлары, жақтар, кіру/шығу бағалары, PnL, шығу себептері және позициядағы жалпы белсенді уақыт.
Сынақтағы ажырату шектері зиянсыз әдепкі мәндер емес. Олар қиын бұрышқа тиетіндей таңдалған — MTF шығу шегі сәйкес кіру шегінен жоғары орнатылған — бұл анықтама бұрылу деп қарастыратын "позиция ашық кезінде шығу трендінің алғашқы анықтамасы" тармағын мәжбүрлейді. Паритет тек оңай жолда емес, бұрыштық жағдайларда да сақталуы керек.
Өріс бойынша, мәмілелер бірдей: қосарланған конфигурация үшін 466 мәміле, үштік үшін 211 мәміле, жалпы PnL 1e-12 дейін сәйкес келеді, әрі әрбір мәміленің өрісі дәлдікке дейін тең. Ортақ код бөліспейтін екі жүзеге асыру — компиляцияланған векторланған қозғалтқыш пен үшінші жүзеге асырудың қиылысуларына арналған аңғал Python циклы — соңғы ондыққа дейін бірдей мәмілелер шығарады.
Бұл күшті нәтиже, бірақ ол келешекке қарамаудың дәлелі емес. Паритет жылдам қозғалтқыштың анықтаманы адалдықпен қайталайтынын айтады. Егер анықтаманың өзі ағып кетсе — егер RunningCandleBuffer алдын ала қараса — паритет ағуды адалдықпен қайталар еді және өтер еді. Жүзеге асырулар арасындағы сәйкестік олардың бірдей екенін айтады, себепті екенін емес. Себептілік үшін басқа түрдегі сынақ керек, ол қозғалтқыштан өткен болашақты көре алатынын тікелей сұрайды.
Ығыстырылған-болашақ сынағы: нағыз дәлел

Келешекке қараудың анықтамасы операциялық, сондықтан оны операциялық түрде тексеріңіз. Келешекке қарау дегеніміз — өткен шешім болашақ деректерге тәуелді. Оның контрапозициясы сіз орындай алатын сынақ: егер сіз болашақты өзгертсеңіз де, кез келген өткен шешім қозғалса, өткен болашақты оқыған болды. Сондықтан болашақты — қатал түрде — өзгертіңіз де, өткенге бақылап отырыңыз.
Серияның 60%-ында кесу нүктесін j таңдаңыз (86 400-ден 51 840-ыншы бар). j-ден бастап әрбір барды бұзыңыз: барлық болашақ жабылу және ашылу бағаларын 1.05-ке көбейтіңіз. Бұзылған деректерде үш таймфреймнің барлығы үшін бүкіл сигнал стегін қайта есептеңіз. Содан кейін j-ден қатаң түрде бұрынғының барлығы бұзылмаған жүгіртумен бит-бітімен бірдей екенін растаңыз:
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 өткен бардың әрбір HMA мәні, әрбір HMA3 мәні, әрбір қиылысу жалауы және әрбір ажырату бірдей флоат болуы керек. Содан кейін мәмілелерге дәл сол мәлімдеме қолданылады: j-ден бұрын шығуы жабылған әрбір мәміле өріс-өрісімен өзгермеген болуы керек. Егер болашаққа 5% итеру бір ғана өткен HMA-ны он екінші ондық таңбада қозғалтса, өткен шешім болашақпен ақылдасқан болды, әрі сынақ сәтсіз аяқталады.
Біздің қозғалтқыш оны өтеді — барлық үш таймфрейм үшін, әрі қосарланған және үштік сауда симуляциялары үшін де. 34 560 болашақ барды бұзу 51 840 өткен барды және солардың арасында жабылған әрбір мәмілені дәл бұрынғыдай қалдырады. Бұл жүзеге асырулар арасындағы сәйкестік емес — бұл уақыттағы ақпараттық шекараның сақталатынын тікелей көрсету.
Сәтсіз бола алмайтын сынақ ешнәрсені дәлелдемейді
Жоғарыдағы сынақтан өту жолы бар, ол ешнәрсені дәлелдемейді: егер бұзылу ешнәрсе жасамайтын әрекет болса — егер болашақты 1.05-ке көбейту еш жерде ешнәрсені өзгертпесе — онда "өткен өзгермеген" деген тривиалды түрде рас болады да, мүлдем ақпаратсыз болады. Сәтсіз бола алмайтын сынақтағы жасыл белгі сынақ жоқтан да жаман, себебі ол жалған сенімділік жасайды. Сондықтан сынақта оған тіс беретін тағы екі мәлімдеме бар.
Болашақ шынымен өзгеруі керек. Біз бұзылудың [j, n) аралығында бір жерде қиылысуларды шынымен өзгерткенін растаймыз:
assert not np.array_equal(s0.cross[j:], s1.cross[j:]) # probe has teeth
Енді нәтиже мағыналы болады: болашақты қайта жазған дәл сол 5% итеру өткенді бит-бітімен өзгеріссіз қалдырды. Бұзылу нақты, ол алға таралады және j-де толығымен тоқтайды. Бір жақты ағу — өткен болашақты оқиды — j арқылы кейін ағар еді; ол ондай емес.
Шекара нақ ағымдағы барда — бір ерте емес, бір кеш емес. Нәзіктеу сәтсіздік — себептік, бірақ ескірген қозғалтқыш болар еді: ол ағымдағы бардың ағымдағы жабылу бағасын елемей, бір бар кеш реакция жасайды (ағу жоқ, бірақ тірі саудада болмайтын кідіріс) немесе бір бар ерте реакция жасайды (бір-барлық ағу). Сондықтан біз жалғыз бар j-ні бұзамыз (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
Бұл шекараны дәл бекітеді. Қалыптасып жатқан шамның ағымдағы жабылу бағасы индикаторға j барында нөлдік кідіріспен және нөлдік болжаумен кіреді: j бары өзінің жабылу бағасын лезде көреді, ал одан ертерек бар оны мүлде көрмейді. Бұл — жабық-бар семантикасы отыруы тиіс дәл сол пышақ жүзі, әрі сынақ қозғалтқыштың сол жерде отырғанын растайды.
Міне толық шлюз — осы қозғалтқыш пен жасанды бэктест арасында тұрған 25 тексерудің барлығы:
| Топ | Әрбір тексеру нені растайды | Саны |
|---|---|---|
| Индикаторлар мен қиылысулар (×3 таймфрейм) | қиылысу оқиғалары RunningCandleBuffer-ге қарсы дәл; қиылысулардағы ажырату; HMA/HMA3 мәндері (rtol 1e-9) |
9 |
| Мәмілелер (қосарланған + үштік) | мәміле саны; өріс-өрісімен бірдей; жалпы PnL 1e-12 дейін; позициядағы белсенді уақыт | 8 |
| Ығыстырылған-болашақ сынағы (қосарланған + үштік) | өткен сигналдар бит-бітімен өзгермеген; сынақтың тісі бар (болашақ шынымен өзгерді); j-ден бұрынғы мәмілелер өзгермеген; бір-барлық бұзылу локальданған |
8 |
| Барлығы | 25 |
Алғашқы екі топ жылдам қозғалтқыштың тірі анықтама екенін белгілейді. Үшіншісі анықтаманың себепті екенін белгілейді. Сізге үшеуі де керек: ағып кететін жылдам қозғалтқыш, себепті болатын ағып кететін қозғалтқыш, әрі кешігетін себепті қозғалтқыш — бұл үш түрлі сәтсіздік, әрі шлюз әрқайсысын жоққа шығарады.
Неге сынақ таймфреймге тәуелсіз
Ығыстырылған-болашақ сынағының сәні — ол ағудың қайда тұратынын білмейді әрі мойындамайды. Ол ешқашан таймфреймдерді, қайта дискреттеуді немесе шам шекараларын атамайды. Ол тек: болашақты бұзу өткенді қозғала ма деп сұрайды. Бұл оны орындауды ығыстыру сынағы жіберіп алатын мульти-TF ағуы үшін дәл дұрыс құрал етеді.
Аңғал бүкіл-серияны-қайта-дискреттеу қатесін тікелей қарастырайық. Егер 1 сағаттық ағын алдын ала бүкіл серияны қайта дискреттеу арқылы құрылса, j-1000 барында (сағат ішінде, j-ден кейін жабылатын) оқылатын "1 сағаттық жабылу бағасы" j-де және одан кейінгі барларға тәуелді соңғы жабылу бағасы болатын шамның соңғы жабылу бағасы болар еді. Болашақты 1.05-ке көбейтіңіз де, сол соңғы жабылу бағасы өзгереді — сонда j-1000-дегі HTF индикаторы өзгереді, j-1000-дегі шектеу өзгереді, әрі өткен шешім қозғалады. Сынақ HTF ағынында бірден, кесуден мың қадам бұрынғы барда жанады.
Біздің қозғалтқыштың HTF ағыны қозғалмайды, себебі j-1000-де қалыптасып жатқан шам тек base_close[j-1000] — өткен жабылу бағасын — береді, ал шамның соңғы жабылу бағасы шекара өткенше мүлде қаралмайды. Сынақ механизмге соқыр, бірақ қатені әлі де ұстайды, бұл нақты дәлелден күтетін нәрсе: ол жүзеге асыруды (қайта дискреттеуді дұрыс индекстедік пе?) тексерудің орнына мінез-құлықты (ешбір өткен шешім болашақ деректерге тәуелді емес) шектейді. Мінез-құлық сауда жасайтын нәрсе; жүзеге асыру сіз оның сәйкес келуін үміт ететін нәрсе.
Бэктест пен тірі бот бір ақиқатты бөліседі

Бұл әдеттегі бэктест аудитінен маңыздырақ болатын тағы бір себеп бар. Қозғалтқыш оған қарсы дәлелденетін анықтама — RunningCandleBuffer — бэктестті жақсы көрсету үшін жазылған сынақ құрылғысы емес. Бұл өндірісте жұмыс істейтін тик симуляторынан сөзбе-сөз алынған тірі боттың өз шам логикасы. Сынақ растайтын жабық-бар ережесі — тірі боттың бар-сайын орындайтын ережесі.
Сондықтан паритет шлюзі екі қызмет атқарады. Ол жылдам қозғалтқыштың анықтамаға сәйкес келетінін дәлелдейді, әрі анықтама тірі өзек болғандықтан, ол жылдам қозғалтқыштың тірі ботқа сәйкес келетінін дәлелдейді. Алдыңғы мақала ағудың бэктест-тірі паритет алшақтығының ең таза түсіндірмесі екенін ескертті — тірі бот сіз механикалық түрде алдын ала қарай алмайтын жалғыз орын, сондықтан алдын ала қарайтын бэктест тірі болған сәтте бөлектенеді. Мұнда бұл алшақтық құрылым бойынша жабылады: бэктест пен бот бір шам буферін, бір қиылысу ережесін, "i барында белгілі" деген бір анықтаманы бөліседі. Іздеу оңтайландыратын сан — бот шынымен сауда жасай алатын сан.
Бұл — келешекке қарамауды болжаудың орнына дәлелдеудің бүкіл мәні. Мульти-TF іздеуі мыңдаған конфигурацияны жүргізеді; егер қозғалтқыш ағып кетсе, іздеу ағуды ең агрессивті пайдаланатын конфигурацияны тауып, сізге жасанды жеңімпаз ұсынар еді — бұл таксономия таза шудан 15 Шарп коэффициентінде өлшеген сәтсіздік режимі. Сынақ капиталға қосылмас бұрын жеңімпаздың нақты екеніне сенуге мүмкіндік беретін нәрсе.
Сынақ нені дәлелдейді және нені дәлелдемейді
Сынақ туралы қаталдық екі жаққа да қолданылады, сондықтан оның ауқымы туралы дәл болыңыз. Ығыстырылған-болашақ сынағы бір, нақты қасиетті дәлелдейді: осы деректерде, j барында немесе одан бұрын ешбір сигнал немесе мәміле шешімі j-ден кейінгі кез келген барға тәуелді емес — уақыттағы ақпараттық шекара индикатор, қиылысу және мәміле жолы арқылы сақталады. Бұл дәл біз жоюға тырысқан мульти-TF ағуы, әрі бұл код тексеруі белгілей алмайтын қасиет.
Ол стратегияның басымдығы бар екенін дәлелдемейді. Толықтай себепті қозғалтқыш адал түрде ақша жоғалта алады, әрі сынақ бұл туралы үнсіз — солай болуы керек те; ағудың жоқтығын дәлелдеу мен нақты басымдықты табу — бөлек жұмыстар, әрі оларды араластыру ағып кеткен бэктестердің қалай орналастырылатынының себебі. Ол уақытқа қатысты емес бейімдерді қамтымайды: құралдағы аман қалу бейімі, қозғалтқыш жақсы көрінгеннен кейін ғана сынақты жүргізуден туындайтын таңдау бейімі, немесе тым жайлы комиссия моделі. Әрі ол өз бетінше тірі орындаулардың бэктест орындауларына сәйкес келетінін дәлелдемейді — сырғанау мен кідіріс сынақ көре алмайтын нақты алшақтықтар, себебі ол орындау алаңында емес, шешім жолында жұмыс істейді. Сол алшақтықты жабатын нәрсе — қозғалтқыштың шам өзегінің тірі боттың өзегімен биттік сәйкес екендігінің бөлек фактісі.
Сынақтың өз құрылымы туралы бір адал ескерту: ол жалғыз j-де кесіледі (серияның 60%-ы). Ол тексеретін қасиет j бойынша біркелкі — 51 840 барда ерекше ештеңе жоқ — сондықтан бір кесу құрылымдық қасиеттің әділ сынағы, бірақ параноидалды нұсқа j-ні бүкіл серия бойынша сипап шығар еді. Біз бір жақсы таңдалған кесу мен бір-барлық локализация тексеруін жеткілікті деп есептейміз, себебі 34 560-барлық болашақ бұзудан жасырынатын, бірақ басқа бір кесуде пайда болатын ағу өте оғаш қате болар еді. Мәселе — дәлелдердің шегін білу, бір сынақты әмбебап квантор ретінде елестету емес.
Негізгі қорытындылар
- Мультитаймфреймдік стратегиялар орындау арқылы емес, қалыптасып жатқан бар арқылы ағады. Аяқталмаған HTF периоды ішіндегі шешім тек сол шамның ағымдағы жабылу бағасын (соңғы негізгі жабылу бағасын) пайдалануы керек, оның соңғы жабылу бағасын емес. Бүкіл-серияны-қайта-дискреттеу бэктестері период ішіндегі әрбір шешімді бүкіл HTF периодына дейінгі болашаққа тапсырады.
- Бір-барлық ығысу сынағы бұл ағуға жетпейді. Ол орындау келешекке қарауын ұстайды; мульти-TF ағуы индикатордың қалай құрылғанында тұрады. Сізге басқа сынақ керек.
- Тірі ережені дәл қайталаңыз, содан кейін оны дәлелдеңіз. Біз боттың
RunningCandleBufferжабық-бар семантикасын векторланған қозғалтқыш ретінде қайта құрдық та, оны 25 тексеруден өткіздік: анықтамаға қарсы дәл қиылысулар (408 / 2 792 / 3 691), мәмілелер өріс-өрісімен бірдей (466 қосарланған, 211 үштік), PnL 1e-12 дейін. - Паритет қажет, бірақ жеткіліксіз. Анықтамаға сәйкестік сіздің бірдей екеніңізді дәлелдейді, себепті екеніңізді емес. Адалдықпен қайталанған ағып кеткен анықтама әлі де ағады.
- Ығыстырылған-болашақ сынағы — нағыз дәлел.
j-де немесе одан кейін әрбір барды бұзыңыз;j-ден бұрынғы әрбір сигнал мен мәміленің бит-бітімен өзгермегенін растаңыз. Егер болашақ өткенді қозғала алса, сізде келешекке қарау бар. - Сынаққа тіс беріңіз. Болашақтың шынымен өзгергенін (бұзылу ешнәрсе жасамайтын әрекет емес) және бір-барлық жанама сол бар өзінде реакция жасайтынын (ағу жоқ, кідіріс жоқ) растаңыз. Сәтсіз бола алмайтын сынақ ешнәрсені дәлелдемейді.
- Бэктест пен тірі бот бір өзекті бөліскенде, дәлел ауысады. Қозғалтқыш тірі боттың шам логикасымен биттік сәйкес болғандықтан, келешекке қарамау тірі жүйенің де қасиеті болып табылады — әрі бэктест-тірі паритет алшақтығы құрылым бойынша жабылады.
Алдыңғы мақала бір жолдық ағудың қалай 15 Шарп коэффициентін жасанды түрде жасайтынын көрсетті. Бұл мақала қарама-қарсы тәртіпті көрсетеді: "ағулар сізді қалай алдайды" емес, ал нақты қозғалтқыштың ағып кетпейтінін нақты деректерде, механикалық түрде қалай дәлелдеу керектігін. Болашақты бұзыңыз. Егер өткен селк етпесе, сіз қазіргі уақытта сауда жасап отырсыз.
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.