← Мақалаларға оралу
June 27, 2026
5 мин оқу

Look-Ahead Bias: бір бардың қатесі таза шудан қалай 15 Sharpe жасап шығарады

Look-Ahead Bias: бір бардың қатесі таза шудан қалай 15 Sharpe жасап шығарады
#algotrading
#backtest
#look-ahead bias
#data leakage
#overfitting
#validation

"Backtests Without Illusions" сериясының бөлігі.

📄 Бұл мақала зерттеу мақаласына айналды. Үш нәзік look-ahead ағып кетуі белгілі ground truth-қа қарсы бақыланатын тестке салынды (4000 симуляцияланған тарих). Мақаланы онлайн оқыңыз (интерактивті нұсқа + PDF) lookahead.marketmaker.cc сайтында, код пен деректер github.com/suenot/lookahead-inflation мекенжайында.

Бірнеше апта бұрын біздің параметрлерді іздеу benchmark-ымыз бізді алдап жатты, біз мұны байқамай қалатын едік.

Қозғалтқыш таза көрінді. Жабық бар логикасы, адал rolling walk-forward бөлінуі, параметрлер кеңістігі бойынша Sobol/QMC іздеуі, бөлек ұсталған тест терезесі. Іздеу in-sample жақсы көрінетін конфигурацияларды тапты. Жалғыз мәселе: out-of-sample нәтижелердің барлығы дерлік теріс болды. Біз стратегия жай ғана әлсіз деп ойладық.

Содан кейін біз бір жолды таптық. Сигнал i барының жабылуында шешілетін, бірақ орындалу сол бір i барында тіркелетін, келесі бардың ашылуында емес. Орындау индексіндегі off-by-one қатесі. Біз орындалуды open[i+1]-ге ауыстырдық — бар i жабылуын көргеннен кейін нақты мәміле жасауға болатын жалғыз баға — және out-of-sample нәтижесі таңбасын өзгертті. Sobol іздеуі шығыннан пайдаға көшті. Стратегияда еш нәрсе өзгерген жоқ. Біз жай ғана өткенде сауда жасауды тоқтаттық.

Бұл look-ahead bias, әрі алаңдатарлығы — қате қаншалықты кішкентай болғаны және салдары қаншалықты үлкен болғаны. Бұл мақала — бақыланатын өзін-өзі аудиттеу: біз ground truth құрылымы бойынша белгілі симулятор құрамыз, нәзік ағып кетулерді бір-бірден енгіземіз және әрқайсысы бэктестті нақты қаншалықты ісіндіретінін өлшейміз. Басты нәтиже: ешбір нақты edge болмаса да, бір бардағы орындалу таза шудан +14.8 жылдық Sharpe жасап шығарады.

Look-ahead bias шын мәнінде не?

The three places look-ahead hides — execution, normalization, and indicators — as channels of unequal danger feeding one trading decision

Look-ahead bias — бұл сіздің pipeline-ыңыздағы шешім немесе өлшем нақты уақытта, қолданылған сәтте қолжетімді болмайтын ақпаратты пайдаланатын кез келген нүкте. Оқулық мысалдары дөрекі — қаңтарда акцияның толық жылдық пайдасын пайдалану немесе әлі жарияланбаған қайта есептеу. Оларды байқау оңай. Код шолуынан аман қалатындары нәзік және үш жерде жасырылады:

  1. Орындалу — сіз i барында шешім қабылдайсыз және i барында орындайсыз (немесе сигналды тудырған сол барда стоп үшін i барының жоғарғы/төменгі мәнін пайдаланасыз). Сізді іске қосқан нәрсемен корреляцияланған бағамен мәміле жасайсыз.
  2. Нормализация — сіз бүкіл серия бойынша, соның ішінде болашақты қоса есептелген статистиканы пайдаланып, ерекшелікті z-score, min-max немесе басқаша масштабтайсыз. Scaler тест жиынтығын "біледі".
  3. Индикаторлар / ерекшеліктер — сіз орталықтандырылған (немесе басқаша алдын ала қарайтын) тереземен тегістейсіз немесе сүзесіз, сондықтан i барындағы мән қазірдің өзінде i+1 барының бір бөлігін қамтиды.

Үшеуі де машиналық оқыту әдебиеті leakage деп атайтын нәрсенің түрлері: мақсаттың болашағынан алынған ақпаратпен оқыту/бағалаудың ластануы (Kaufman et al., 2012; Kapoor & Narayanan, 2023). Қаржыда канондық еңбек — López de Prado-ның Advances in Financial Machine Learning (2018) кітабы — purged cross-validation, embargoing, бэктестингтің қауіптері. Point-in-time тәртібі кем дегенде Fama & French (1992) еңбегіне дейін барады, олар бухгалтерлік деректерді әдейі алты айға кешіктіреді, сол арқылы айнымалы ол түсіндіретін кірістен бұрын белгілі болады.

Бұл мақала жауап беретін сұрақ сандық сипатта: "leakage жаман ба" емес (бәрі келіседі), керісінше "әр форма қанша Sharpe ұпайын сатып алады, әрі қайсылары қауіпті?" Санынсыз бұл туралы ойлана алмайсыз. +0.3 ісінудің шу екенін немесе +14 ісінудің дәлел екенін ажырата алмайсыз.

Белгілі ground truth-і бар симулятор

A controlled synthetic market with a known edge dial: a null world with no real edge beside an edge world whose equity genuinely rises

Ісінуді өлшеу үшін ақиқатты білу керек. Нақты деректер ешқашан ақиқатты айтпайды — олар бір ғана жүзеге асуды береді, оракул жоқ. Сондықтан біз edge-ті өзіміз белгілейтін синтетикалық нарық құрамыз.

Деректер генерациялау процесі қатаң түрде себеп-салдарлық (causal) және жарылмайтын:

gt=ϕgt1+1ϕ2  ut,utN(0,1)g_t = \phi\, g_{t-1} + \sqrt{1-\phi^2}\; u_t, \qquad u_t \sim \mathcal{N}(0,1)

rt=agt1+σεt,εtN(0,1)r_t = a\, g_{t-1} + \sigma\, \varepsilon_t, \qquad \varepsilon_t \sim \mathcal{N}(0,1)

Мұнда gtg_tэкзогенді тұрақты жасырын дрейф (φ = 0.95 бар AR(1)), ал бар кірісі rtr_t бір бар бұрын белгілі болатын кішкентай agt1a\,g_{t-1} дрейфіне ие. gg өткен кірістерге тәуелді болмағандықтан, кері байланыс жоқ және ештеңе жарылмайды. aa параметрі қанша нақты edge бар екенін реттейтін тұтқа:

  • a=0a = 0null: мүлдем edge жоқ. Кез келген оң бэктест Sharpe-і 100% жасанды.
  • a>0a > 0нақты, сауда жасауға болатын edge: адал momentum ережесі шынымен ақша табады.

Стратегия әдейі қарапайым — momentum таңба ережесі. Ерекшелік — trailing-LL кірістер сомасы (L=24L = 24 бар), ал позиция — оның таңбасы:

csum = np.concatenate(([0.0], np.cumsum(r)))      # csum[k] = sum r[0..k-1]
mom = np.full(n, np.nan)
tt = np.arange(L - 1, n)
mom[tt] = csum[tt + 1] - csum[tt - L + 1]

signal = np.sign(mom)                              # position for the next bar

Бұл momentum ерекшелігі бір-бар ағып кетуін зерттеу үшін тамаша құрал, өйткені онда нақты индикаторлар бөлісетін қасиет бар: ол ағымдағы барды механикалық түрде қамтиды. mom[t] құрамында r[t] бар. Сондықтан r[t]-ны мәміле ретінде тіркесеңіз, сіз өзіңіздің сигналыңыздың ішінде қазірдің өзінде бар шамаға жартылай тігесіз. Бұл — нақтыланған ағып кету.

Баптау: σ=0.01\sigma = 0.01 (бар сайын 1% волатильділік), 0.00045 бір бағыттағы комиссия (round-trip 0.09%, біздің қозғалтқышымызға сәйкес), Sharpe 8760\sqrt{8760} арқылы жылдық есептеледі (сағаттық бар), әрқайсысы 4000 бардан тұратын 4000 тәуелсіз тарих. Барлығы seeded және детерминистік.

Адал pipeline (жалғыз сауда жасауға болатын)

t барының жабылуында шешім қабылдау, келесі бардың кірісін табу, позиция өзгерген кезде комиссия төлеу:

def sharpe(sig, ret_booked):
    dpos = np.abs(np.diff(np.concatenate(([0.0], sig))))
    pnl  = sig * ret_booked - FEE_ONEWAY * dpos
    return pnl.mean() / pnl.std() * np.sqrt(8760)

honest = sharpe(signal[idx], r[idx + 1])           # earn r[t+1]: tradable

Үш ағып кету, әрқайсысы жалғыз хирургиялық өзгеріс

same_bar  = sharpe(signal[idx], r[idx])

z_full    = (mom - mom[valid].mean()) / mom[valid].std()
norm_full = sharpe(np.sign(z_full[idx]), r[idx + 1])

z_sm      = (mom[:-2] + mom[1:-1] + mom[2:]) / 3.0   # uses t-1, t, t+1
indicator = sharpe(np.sign(z_sm[idx]), r[idx + 1])

Әр ағып кету адал pipeline-нен бар-жоғы бір жол қашықтықта. Бүкіл мәселе осында: бұлар экзотикалық қателер емес, олар шолудан өтетін нәрселер.

Нәтижелер: әр ағып кетудің шамасы

Pure market noise funneled through a same-bar leak into a soaring, fake equity curve and a performance gauge pinned near its maximum

4000 seed бойынша жүргізілген, мұнда әр pipeline хабарлайтын жылдық Sharpe, null (edge жоқ) кезінде және нақты edge (a=0.0011a = 0.0011, адал Sharpe сенімді +1.57 болатындай реттелген) кезінде:

Pipeline Null (edge жоқ) Нақты edge
Адал (ақиқат) −0.74 +1.57
Same-bar орындалу +14.79 +15.85
Индикатор алдын ала қарауы (1 бар) +4.76 +6.62
Whole-series нормализация −0.84 +1.46

Seed-тер бойынша 95% сенімділік интервалдары әр ұяшықта ±0.05 немесе одан тар; әсер нақты жерде ісінуге жасалған paired t-тестілер астрономиялық түрде маңызды (t > 400, p ≈ 0).

Алдымен null бағанын оқыңыз, өйткені бұл ең таза мүмкін эксперимент: edge жоқ, сондықтан адал pipeline дұрыс түрде ақша жоғалтады (−0.74, шуды сауда жасау үшін комиссия төлеудің кедергісі). Енді ағып кетулер сол ешнәрсеге не істейтінін көріңіз:

  • Same-bar орындалу: −0.74 → +14.79. Ешбір болжамдық қуаты жоқ, кездейсоқ шуды сауда жасайтын стратегия шамамен 15 жылдық Sharpe хабарлайды. Бұл нәзік bias емес; бұл жасандылық. Механизм дәл біз құрастырған нәрсе: momentum ерекшелігінде r[t] бар, сондықтан r[t]-ны тіркеу — өз сигналыңызға тігу деген сөз.
  • Индикатор алдын ала қарауы: −0.74 → +4.76. Тегістеушіге болашаққа бір бар қарауға рұқсат беру шудан 5-ке жақын Sharpe жасайды, өйткені t барындағы тегістелген мән енді сіз таба жатырған r[t+1]-мен корреляцияланады.
  • Whole-series нормализация: −0.74 → −0.84. Іс жүзінде ешбір ісіну жоқ. Бұл адал, айқын емес нәтиже (төменде толығырақ).

Edge бағаны одан да қатерлі хабарды береді. Нақты edge бар болғанда (адал +1.57), ағып кетулер тек тұрақтыны қоспайды — олар өлшенген Sharpe-ті сіз шынымен сауда жасай алатын +1.57-ден әлдеқайда жоғары, +15.85 және +6.62-ге дейін итереді. Сондықтан өлшенген сан шеберлікті ағып кетуден ажырата алмайды. Ағып кеткен +6 мен адал +6 есепте бірдей көрінеді. Сіз капитал салғаннан кейін ғана қайсысы болғанын білесіз.

Ағып кету — градиент, ауыстырғыш емес

The same-bar leak as a smooth dose-response: capturing a larger fraction of the signal bar lifts the equity curve monotonically across the deployable threshold

Табиғи қарсылық: "бүкіл сигнал барын тіркеу — экстремалды, шынайы емес қате." Сондықтан біз дозаны сынадық — ағып кету ұстап алатын сигнал барының ff бөлігі, 0-ден (адал) 1-ге (толық same-bar) дейін:

Ұстап алу бөлігі ff Null Sharpe Edge Sharpe
0.00 (адал) −0.74 +1.57
0.25 +3.90 +6.41
0.50 +9.86 +12.20
1.00 (толық ағып кету) +14.79 +15.85

Сигнал барының тек төрттен бірін ұстап алу edge-і жоқ стратегияны −0.74-тен +3.90-ге дейін жеткізеді. Алдануыңыз үшін толық off-by-one қажет емес; сәл ыңғайлырақ орындалу — сигнал барындағы оптимистік slippage тиюі, оны тудырған сол барға қарсы тексерілген intrabar стоп — көптеген "орналастыруға болатын" шектерден өту үшін жеткілікті. Ісіну сіз қазіргі уақыттың қанша бөлігін сауда жасауға өзіңізге рұқсат беретініңізге қарай тегіс және монотонды.

Бұл шығынды стратегияны қаншалықты жиі өндіріске жібереді?

Практикті алаңдату керек сан — жалған орналастыру жылдамдығы: ағып кету шынымен ақша жоғалтатын конфигурацияны сіз оны жасыл жарыққа шығару үшін қолданатын шектен қаншалықты жиі өткізеді. "Жылдық Sharpe ≥ 1.0" орналастыру критерийі ретінде пайдаланып, null кезінде:

  • Same-bar орындалу: edge-і жоқ стратегиялардың 68%-ы орналастыруға болатындай көрінеді және шынымен ақша жоғалтады. Таза шудың үш конфигурациясының екеуі Sharpe-≥-1 қақпасынан өтіп, тірі жүйеде ақша жоғалтатын еді. (Бұл жылдамдық мұнда таза анықталған, өйткені ағып кету таза орындалуда; адал баламасы — адал орындалуы бар сол сигнал.)
  • Индикатор алдын ала қарауы: ол іс жүзінде edge-і жоқ әрбір конфигурацияны да орналастыру шегінен өткізеді (99.9% Sharpe ≥ 1-ден өтеді) — ол шуды тікелей өндіріске сілтейтін еді.
  • Whole-series нормализация: 12% шектен өтеді — бұл негізінен шудың базалық жылдамдығы, ешбір leakage сыйақысы жоқ.

Таксономия, әрі әрқайсысын қалай анықтау керек

Үш ағып кету бірдей қауіпті емес, әрі айырмашылықтар пайдалы сабақ береді.

1. Орындалу leakage-і (қымбат түрі)

The same-bar fill off-by-one: an execution arrow curling back into the bar that generated the signal, versus the honest fill on the next bar's open

Симптом: орындалу бағасы сигналмен корреляцияланған, өйткені олар бір бардан келеді. Шамасы: орасан зор (толық доза кезінде шудан +15, ширек доза кезінде +3.9). Неге ол ең жаманы: сіздің сигналыңыз, дерлік анықтамасы бойынша, соңғы баға қозғалысынан құрылады, сондықтан сигнал барының кірісі — сіздің ерекшелігіңіз ең көп корреляцияланатын дәл сол нәрсе. Оны тіркеу жауапты іздеп табуға жақын.

Анықтау — бір-бар ауыстыру тесті. Бұл осы мақаладағы ең құнды диагностика. Бэктестіңізді алып, әр орындалуды бір барға кейінірек ауыстырыңыз (i-де шешім қабылдау, open[i+1]-де орындау). Егер нәтиже әрең қозғалса, орындалуыңыз адал болды. Егер нәтиже құлдырап кетсе немесе таңбасын өзгертсе, сіз өткенде сауда жасап жаттыңыз. Дәл осы біздің Sobol іздеуімен болды: орындалуларды ауыстырыңыз, "пайдалы" OOS шығын болып шықты — дұрысырағы, ағып кету жойылғаннан кейін нақты байланыс беткейге шықты.

entry_price = open_[i + 1]      # NOT close[i], NOT open[i]

2. Индикатор / ерекшелік leakage-і (тыныш түрі)

Симптом: i барындағы индикатор i+1 немесе одан кейінгі деректерге тәуелді — орталықтандырылған жылжымалы орта, себеп-салдарлық кешігуі жоқ сүзгі, растау үшін болашақ барлар қажет ететін шың/аңғар белгісі, болашақ шамдарды қабылдайтын Heikin-Ashi тәрізді түрлендіру. Шамасы: үлкен (шудан +4.8). Неге жасырынады: ағып кету кітапхана шақыруының ішінде көмілген. scipy.signal.filtfilt нөлдік-фазалы — ал нөлдік-фаза себеп-салдарлық емес дегенді білдіреді. "Бұл бар — локалды максимум" ерекшелігі келесі бар шыққанға дейін белгісіз болып қалады.

Анықтау: әр индикатор үшін сұраңыз: ол оқитын ең жоғары индекс қандай? Егер t-дегі мәнді есептеу қашанда t+1-ге тисе, ол себеп-салдарлық емес. Индикаторларды кеңейетін/жылжымалы себеп-салдарлық терезеде есептеп, t-ден кейінгі барлар массивте бар-жоғына қарамастан t барындағы мән бірдей екенін тексеріңіз. (Біздің HMA/ADX іске асыруларымыз бұл тесттен өтеді: t-дегі әр шығыс тек ≤ t кірістерін оқиды.)

3. Нормализация leakage-і (арнаға тәуелді түрі)

Симптом: scaler (StandardScaler, min-max, ғаламдық z-score) тест жиынтығын қоса, бүкіл деректер жиынына бейімделеді. Канондық ML ескертулері бұл туралы нақты айтады — Hastie, Tibshirani & Friedman-ның Elements of Statistical Learning §7.10.2 ("the wrong and right way to do cross-validation") және scikit-learn-нің өзінің жалпы қателер бойынша нұсқаулығы: "the average should be the average of the train subset, not the average of all the data."

Біздің тестегі шамасы:нөл (−0.74 → −0.84). Бұл — таңғаларлық, адал нәтиже, әрі оны жаттап алудың орнына түсіну маңызды.

Ол неге ісінбеді? Себебі біздің стратегия ерекшелікті тек оның таңбасы арқылы пайдаланады (нөлдік шек). Стандартты ауытқу арқылы масштабтау ешқашан таңбаны өзгертпейді, ал ғаламдық-орта-центрлеу нөлдік кесіп өтуді сәл ғана жылжытады. Сондықтан таза таңба ережесінің whole-series стандарттауы дерлік зиянсыз.

Мұны шамадан тыс жалпылап жіберменіз. Нормализация leakage-і арнаға тәуелді. Стратегияңыз ерекшеліктің шамасын пайдаланған сәтте — z-score-ке пропорционал позиция мөлшерлеу, масштабталған үлестірімге қарап таңдалған нөлден ерекшеленетін кіру шегі, стандартталған кірістерді қабылдайтын нейрондық желі — болашақты білетін scaler маңызды бола бастайды, әрі ғаламдық статистика себеп-салдарлықтан неғұрлым көп ерекшеленсе, соғұрлым маңызды бола түседі. Біздің нәтиже "нормализация leakage-і қауіпсіз" дегенді білдірмейді. Ол "leakage шамасы ағып кеткен шама шешімге кіретін арнаға байланысты, әрі оны болжамдаудың орнына өлшеу керек" дегенді білдіреді. Таңба ережесі — бұл нақты ағып кетудің арзан болатын жалғыз жағдайы.

Бұл қайда байланысады

Look-ahead bias — осы серия құжаттап келе жатқан тізбектің бірінші буыны:

  • Ол валидацияның кірісін ластайды. Ағып кеткен бэктест walk-forward бөлінуінен кедергісіз өтіп, overfit шыңынан гөрі кең плато сияқты көрінеді — ағып кету қатпарлар (folds) бойынша тұрақты, сондықтан cross-validation оны ұстай алмайды. Leakage — overfitting-тен жоғарыдағы ақаулық режимі, әрі одан кейінгі ешбір адал валидация сізді құтқармайды.
  • Ол параметрлерді іздеумен әрекеттеседі: ағып кеткен деректерде мыңдаған сынақтар бойынша іздеу ағып кетуді ең агрессивті пайдаланатын конфигурацияны табады. "Жеңімпаз" — ең жаман бұзушы.
  • Сол себепті бэктест-тірі жүйе паритеті алшақтайды. Ағып кету — бэктест пен бот арасындағы 30–50% алшақтықтың ең таза түсіндірмесі, өйткені тірі сауда, механикалық түрде, алдын ала қарауға болмайтын жалғыз орын.

Мұның бәрін ұстайтын тәртіп — академиялық әдебиет жылдар бойы талап етіп келе жатқан дәл сол тәртіп: бэктестті қатаң ақпараттық шекарасы бар статистикалық эксперимент ретінде қараңыз. Bailey, Borwein, López de Prado & Zhu overfitting-тің жалған өнімділікті қаншалықты оңай жасап шығаратынын көрсетті (2014); Arnott, Harvey & Markowitz-тың бэктестинг хаттамасы (2019) осы гигиенаны кодификациялайды. Look-ahead bias — барлық шекаралардың ең негізгісі — уақыттағы шекара — және кездейсоқ бұзуға ең арзаны.

Негізгі қорытындылар

The one-bar shift diagnostic: nudging every fill one bar later deflates a fake soaring curve back down to the honest truth

  1. Look-ahead bias сандық тұрғыдан орасан зор әрі сапалық тұрғыдан көрінбейді. Жалғыз бір-бар орындалу қатесі −0.74 Sharpe-ті (таза шу, дұрыс шығынға ұшыраған) +14.79-ға айналдырды. Қате бір жол; салдары — жасанды track record.
  2. Бұл градиент. Сигнал барының тек 25%-ын ұстап алу да ешнәрседен +3.90 береді. Сізге айқын bug қажет емес — орындалуларыңыздағы сәл артық оптимизм жеткілікті.
  3. Өлшенген сан шеберлікті ағып кетуден ажырата алмайды. Нақты edge болғанда, ағып кетулер есепті сауда жасауға болатын ақиқаттан әлдеқайда алысқа ісіндіреді. Жалғыз қорғаныс — процесс, метрика емес.
  4. Бір-бар ауыстыру тесті — ең жылдам диагностикаңыз. Әр орындалуды бір барға кейінірек жылжытыңыз. Егер өнімділік құлдыраса, сіз өткенде сауда жасап жатқансыз.
  5. Leakage шамасы арнаға тәуелді. Орындалу мен индикатор алдын ала қарауы жойқын; таңба ережесінің whole-series нормализациясы дерлік тегін. Ағып кетуді ол шынымен кіретін арна арқылы өлшеңіз — болжамдамаңыз.

Толық бақыланатын зерттеу — үш ағып кетудің барлығы, доза сынағы, жалған орналастыру талдауы, формальды әдістер және бір детерминистік скрипттен қайта жасалатын әрбір сан — серіктес мақалада lookahead.marketmaker.cc сайтында, код пен деректер github.com/suenot/lookahead-inflation мекенжайында.

Біздің null экспериментіміздегі стратегияда мүлдем edge болмады. Ол бәрібір 15 Sharpe көрсетті. Бэктестіңіз тым жақсы көрінсе, күдіктенетін бірінші нәрсе — сіздің данышпандығыңыз емес, ол — сіздің сағатыңыз.

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 сауда талдаулары, нарық аналитикасы және платформа жаңалықтары үшін біздің ақпараттық бюллетеньге жазылыңыз.

Біз сіздің жекелігіңізді құрметтейміз. Кез келген уақытта жазылымнан шығуға болады.