Look-Ahead Bias: бир бардын катасы таза үндөн 15 Sharpe кантип жасайт
"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 чындыгында эмне

Look-ahead bias — бул сиздин pipeline'ыңыздагы чечим же өлчөө колдонулган учурда реалдуу убакытта жеткиликтүү болбогон маалыматты колдонгон ар кандай чекит. Окуу китептериндеги мисалдар одоно — январда акциянын толук жылдык кирешесин колдонуу, же дагы эле жарыяланбаган кайра эсептөө. Аларды байкоо оңой. Код текшерүүсүнөн аман калгандары назик жана үч жерде жашырынат:
- Аткаруу — сиз
iбарында чечим кабыл аласыз жанаiбарында аткарасыз (же сигналды жараткан ошол эле барда стоп үчүнiбарынын жогорку/төмөнкү маанисин колдоносуз). Сизди козгогон нерсеге корреляцияланган баада бүтүм түзөсүз. - Нормалдаштыруу — сиз бүткүл сериянын боюнча, келечекти кошо эсептелген статистиканы колдонуп, өзгөчөлүктү z-score, min-max же башка жол менен масштабтайсыз. Scaler тест топтомун "билет".
- Индикаторлор / өзгөчөлүктөр — сиз борборлоштурулган (же башка жол менен алдыга караган) терезе менен тегиздейсиз же чыпкалайсыз, ошондуктан
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 менен симулятор

Шишикти өлчөө үчүн чындыкты билүү керек. Чыныгы маалыматтар эч качан чындыкты айтпайт — алар бир гана ишке ашууну беришет, оракул жок. Ошондуктан биз edge'ди өзүбүз белгилеген синтетикалык рынок түзөбүз.
Маалымат жаратуу процесси катуу түрдө себеп-натыйжалуу (causal) жана жарылбоочу:
Бул жерде — экзогендик туруктуу жашыруун дрейф (φ = 0.95 менен AR(1)), ал эми бар кирешеси бир бар мурун белгилүү болгон кичине дрейфине ээ. мурунку кирешелерге көз каранды болбогондуктан, кайтарым байланыш жок жана эч нерсе жарылбайт. параметри канча чыныгы edge бар экенин жөнгө салуучу тумблер:
- — null: такыр эч кандай edge жок. Каалаган оң бэктест Sharpe'и 100% жасалма.
- — чыныгы, соода кылууга боло турган edge: адилет momentum эрежеси чын эле акча табат.
Стратегия атайылап жөнөкөй кылып жасалган — momentum белги эрежеси. Өзгөчөлүк — trailing- кирешелердин суммасы ( бар), позиция болсо анын белгиси:
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]-ны өз бүтүмүңүз катары катасаңыз, сиз жарым-жартылай сиздин өз сигналыңыздын ичинде мурунтан эле бар чоңдукка тигип жатасыз. Бул — так формадагы агып кетүү.
Орнотуу: (бар башына 1% волатилдик), 0.00045 бир багыттагы комиссия (round-trip 0.09%, биздин кыймылдаткычка дал келет), Sharpe аркылуу жылдык эсептелет (сааттык бар), ар бири 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'ден болгону бир сап алыс. Бүт маселе ушунда: булар экзотикалык каталар эмес, алар текшерүүдөн өтүп кете турган нерселер.
Натыйжалар: ар бир агып кетүүнүн чоңдугу

4000 seed боюнча иштетилген, бул жерде ар бир pipeline билдирген жылдык Sharpe, null (edge жок) учурунда жана чыныгы edge (, адилет 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 билдирет. Бул назик четтөө эмес; бул жасалма. Механизм так биз курган нерсе: 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 отчетто бирдей көрүнөт. Сиз капитал салгандан кийин гана кайсынысы болгонун билесиз.
Агып кетүү — градиент, тумблер эмес

Табигый каршылык: "бүткүл сигнал барын катоо — экстремалдуу, реалдуу эмес ката." Ошондуктан биз дозаны сыдырдык — агып кетүү кармаган сигнал барынын бөлүгү, 0дон (адилет) 1ге (толук same-bar) чейин:
| Кармоо бөлүгү | 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'и (кымбат түрү)

Белги: аткаруу баасы сигнал менен корреляцияланган, себеби экөө тең бир бардан келет. Чоңдук: зор (толук доза учурунда үндөн +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 — бардык чек аралардын эң негизгиси — убакыттагы чек ара — жана кокустан бузууга эң арзаны.
Негизги жыйынтыктар

- Look-ahead bias сандык жактан зор жана сапаттык жактан көрүнбөйт. Жалгыз бир-бар аткаруу катасы −0.74 Sharpe'ди (таза үн, туура чыгым тарткан) +14.79га айландырды. Ката бир сап; натыйжасы жасалма track record.
- Бул градиент. Сигнал барынын болгону 25%ин кармоо да эч нерседен +3.90 берет. Сизге ачык-айкын bug керек эмес — аткарууларыңыздагы бир аз ашыкча оптимизм жетиштүү.
- Өлчөнгөн сан чеберчиликти агып кетүүдөн айырмалай албайт. Чыныгы edge болгондо, агып кетүүлөр отчетту соода кылууга боло турган чындыктан алда канча алыска шиширет. Жалгыз коргоо — процесс, метрика эмес.
- Бир-бар жылдыруу сыноосу — эң тез диагностикаңыз. Ар бир аткарууну бир барга кийинчерээк жылдырыңыз. Эгер өндүрүмдүүлүк кулап түшсө, сиз өткөндө соода кылып жаттыңыз.
- Leakage чоңдугу каналга көз каранды. Аткаруу жана индикатор алдын ала карашы кыйратуучу; белги эрежесинин whole-series нормалдаштыруусу дээрлик акысыз. Агып кетүүнү ал чын эле кире турган канал аркылуу өлчөңүз — болжолдобоңуз.
Толук көзөмөлдөнгөн изилдөө — үч агып кетүүнүн баары, доза сыдыруусу, жалган жайылтуу анализи, формалдуу методдор жана бир детерминисттик скрипттен кайра түзүлө турган ар бир сан — коштоочу макалада lookahead.marketmaker.cc дарегинде, код жана маалыматтар github.com/suenot/lookahead-inflation дарегинде.
Биздин null экспериментибиздеги стратегияда такыр эч кандай edge болгон эмес. Ал баары бир 15 Sharpe көрсөттү. Эгер бэктестиңиз өтө эле жакшы көрүнсө, шектенүүчү биринчи нерсе — сиздин генийлигиңиз эмес, ал — сиздин саатыңыз.
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.