Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor · · Updated 2026-08-01

लुक-अहेड बायस: बॅकटेस्टचा धोका

बॅकटेस्टमध्ये भविष्यातील माहिती वापरल्याने लुक-अहेड बायस येतो. समान बार निर्णय, टिकून राहणे आणि सुधारित आकडेवारी निकालांना कशी फुगवते आणि त्याची चाचणी कशी करावी हे जाणून घ्या.

लुक-अहेड बायस (Look-ahead bias) म्हणजे बॅकटेस्टमध्ये (backtest) अशा माहितीचा वापर करणे जी सिम्युलेटेड ट्रेड (simulated trade) ठेवण्याच्या वेळी उपलब्ध नव्हती. इक्विटी कर्व (equity curve) वाढतो, आकडेवारी उत्कृष्ट दिसते, परंतु प्रत्यक्ष ऑर्डर (live order) देताना यापैकी काहीही टिकत नाही. हे पान बायसची व्याख्या करते, ते निर्माण करणाऱ्या तीन यंत्रणांचे वर्णन करते आणि वास्तविक मार्केट डेटामध्ये (market data) प्रत्येकाचे मोजमाप करते.

लुक-अहेड बायस म्हणजे काय

बॅकटेस्ट (backtest) म्हणजे निर्णयाबद्दलचा दावा: या टाइमस्टॅम्पवर (timestamp), या माहितीसह, नियमाने हे केले असते. हा दावा तेव्हाच खरा ठरतो जेव्हा नियमाने वाचलेले प्रत्येक इनपुट (input) त्या टाइमस्टॅम्पपूर्वी अंतिम स्वरूपात अस्तित्वात होते. लुक-अहेड बायस (Look-ahead bias) म्हणजे त्या स्थितीचे कोणतेही उल्लंघन, आणि ते शांतपणे होते. स्प्रेडशीट (spreadsheet) किंवा स्क्रिप्टमध्ये (script) काहीही तक्रार करत नाही जेव्हा एखादी रो (row) ती ज्या निर्णयाला फीड करते त्यापेक्षा नंतरची व्हॅल्यू (value) परत करते.

तीन उल्लंघने व्यवहारात येणाऱ्या बहुतेक गोष्टींना व्यापतात. एक निर्णय जो एकाच बारवर (bar) आधारित असतो ज्यावर तो ट्रेड (trade) देखील करतो. आज सूचीबद्ध असलेल्या नावांवरून तयार केलेले युनिव्हर्स (universe). तारखेच्या नंतर सुधारित केलेले डेटा फील्ड (data field).

यंत्रणा एक: ज्या बारवर तुम्ही ट्रेड करता त्यावर निर्णय घेणे

एका निरुपद्रवी वाटणाऱ्या नियमाने सुरुवात करा. ताकदीवर खरेदी करा, म्हणजे ज्या सत्रांमध्ये फंडाचा (fund) शेवट त्याच्या सुरुवातीपेक्षा वर होतो. निष्काळजीपणे कोडिंग (coding) केल्यास, चाचणी त्या सत्राच्या ओपनिंगला (opening) प्रवेश करते आणि क्लोजिंगला (closing) बाहेर पडते, तर ज्यावर ती स्क्रीन (screen) करते ती अट त्याच बारची क्लोजिंग प्राइस (closing price) आहे. ओपनिंग बेलला (opening bell) कोणालाही क्लोजिंग प्राइस माहित नसते.

खालील पॅनेल (panel) SPY, S&P 500 ट्रॅकरवर (tracker) दहा कॅलेंडर वर्षांमध्ये (calendar years) दोन्ही आवृत्त्या चालवते. पहिला कॉलम अशक्य आहे. दुसरा समान अट एका सत्राने मागे ठेवतो, जी निधी असलेल्या खात्यासाठी ती कृतीत आणण्याची सर्वात लवकरची वेळ आहे.

क्वेरीSame-bar decision vs a one-session lag: SPY, average session gain, 2016-2025
प्रत्येक आकड्यामागील अचूक SQL
WITH bars AS (
    SELECT date,
           toFloat64(open) AS o,
           toFloat64(close) AS c,
           toFloat64(close) > toFloat64(open) AS up_day
    FROM global_markets.stocks_daily_aggs
    WHERE ticker = 'SPY'
      AND date >= toDate('2015-12-01')
      AND date <= toDate('2025-12-31')
),
lagged AS (
    SELECT date, o, c, up_day,
           any(up_day) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prior_up
    FROM bars
)
SELECT toYear(date) AS year,
       countIf(up_day) AS signal_days,
       round(100 * avgIf(c / o - 1, up_day), 3) AS same_bar_avg_pct,
       round(100 * avgIf(c / o - 1, prior_up), 3) AS lagged_avg_pct,
       round(100 * (avgIf(c / o - 1, up_day) - avgIf(c / o - 1, prior_up)), 3) AS gap_pp
FROM lagged
WHERE date >= toDate('2016-01-01')
GROUP BY year
ORDER BY year
Run this yourself

फरक सूक्ष्म नाही. 2016 मध्ये, समान-बार आवृत्तीने पात्र सत्रामागे सरासरी 0.447% मिळवले, तर लॅग्ड (lagged) आवृत्तीने सरासरी -0.008% मिळवले, जो दिवसाला 0.455 टक्के पॉइंट्सचा फरक आहे. 2025 मध्ये, दोघांनी 0.636% आणि -0.03% वाचले. वर्षाला अंदाजे 140 पात्र सत्रे विचारात घेतल्यास, सत्राला अर्धा टक्के पॉइंटचा फरक इक्विटी कर्वमध्ये (equity curve) रूपांतरित होतो जो कोणत्याही प्रत्यक्ष खात्याने कधीही छापलेला नाही.

संपूर्ण एज (edge) व्याख्येवर आधारित आहे. त्यांच्या ओपनिंगपेक्षा वर बंद झालेल्या सत्रांची निवड करणे, आणि नंतर त्याच सत्रांवर ओपन-टू-क्लोज (open-to-close) मोजणे, सकारात्मकतेची हमी देणाऱ्या प्रमाणाचे मोजमाप करते. नियमाने स्वतःचा फिल्टर शोधला.

याचे प्रकार दररोज डेटामध्ये (data) लपलेले असतात: आजच्या क्लोजिंगचा समावेश करणारा आणि आज ट्रेड करण्यासाठी वापरला जाणारा मूव्हिंग ॲव्हरेज (moving average), अजून न झालेल्या स्प्लिटसाठी (split) समायोजित केलेल्या किमतींवर (prices) मोजलेले सिग्नल (signal), अजून प्रिंट न झालेल्या सत्राच्या उच्चांकावर (session high) ठेवलेला इंट्राडे स्टॉप (intraday stop). सामान्य स्वरूप म्हणजे निर्णयाचा टाइमस्टॅम्प (timestamp) त्याच्या स्वतःच्या इनपुटपैकी एकापेक्षा आधीचा असतो.

यंत्रणा दोन: आजच्या वाचलेल्यांमधून काढलेले युनिव्हर्स

दुसरी यंत्रणा नियमाला कधीही स्पर्श करत नाही. ती नावांच्या यादीत बसते ज्यांना नियम पाहण्याची परवानगी आहे.

सध्याच्या डेटा प्रोव्हायडरकडून (data provider) एक टिकर लिस्ट (ticker list) घ्या, ती दहा वर्षे मागे चालवा, आणि नमुना शांतपणे दिवाळखोर झालेल्या, अधिग्रहित झालेल्या किंवा मार्गातील डिलिस्टेड (delisted) झालेल्या प्रत्येक कंपनीला वगळतो. नियमाला कधीही हरणारे दिले गेले नाहीत. पॅनेल त्या वगळण्याच्या आकाराचे मोजमाप करते: दिलेल्या कॅलेंडर वर्षात $1 पेक्षा जास्त 200 सत्रे ट्रेड केलेल्या प्रत्येक यूएस-लिस्टेड (US-listed) नावाचे, जुलै 2026 मध्ये अजूनही किमती प्रिंट करणाऱ्या त्या गटाचा हिस्सा, आणि संपूर्ण गटाचा मध्यक कॅलेंडर-वर्ष परतावा (median calendar-year return) वाचलेल्यांच्या मध्यकासोबत.

क्वेरीSurvivorship in the universe: names trading each year, share still listed in July 2026, and median return
प्रत्येक आकड्यामागील अचूक SQL
WITH recent AS (
    SELECT DISTINCT ticker
    FROM global_markets.stocks_daily_aggs
    WHERE date >= toDate('2026-06-15')
      AND date <= toDate('2026-07-28')
),
per_name AS (
    SELECT toYear(date) AS year,
           ticker,
           argMin(toFloat64(close), date) AS first_close,
           argMax(toFloat64(close), date) AS last_close,
           count() AS sessions
    FROM global_markets.stocks_daily_aggs
    WHERE date >= toDate('2015-01-01')
      AND date <= toDate('2024-12-31')
      AND close > 1
    GROUP BY year, ticker
    HAVING sessions >= 200
)
SELECT year,
       uniqExact(ticker) AS names_trading,
       round(100 * uniqExactIf(ticker, ticker IN (SELECT ticker FROM recent)) / uniqExact(ticker), 1) AS still_listed_pct,
       round(100 * quantileDeterministic(0.5)(last_close / first_close - 1, cityHash64(ticker)), 2) AS median_return_all_pct,
       round(100 * quantileDeterministicIf(0.5)(last_close / first_close - 1, cityHash64(ticker), ticker IN (SELECT ticker FROM recent)), 2) AS median_return_survivors_pct,
       round(100 * (quantileDeterministicIf(0.5)(last_close / first_close - 1, cityHash64(ticker), ticker IN (SELECT ticker FROM recent))
                    - quantileDeterministic(0.5)(last_close / first_close - 1, cityHash64(ticker))), 2) AS survivor_gap_pp
FROM per_name
GROUP BY year
ORDER BY year
Run this yourself

2015 मध्ये बार क्लिअर (clear) केलेल्या 7063 नावांपैकी, 52.5% जुलै 2026 मध्ये अजूनही ट्रेड करत होते. 2024 गटासाठी हा आकडा 87.5% आहे, जो प्रामुख्याने कालावधीचा (elapsed time) विषय आहे: 2024 च्या नावाकडे गायब होण्यासाठी दोन वर्षे आहेत आणि 2015 च्या नावाकडे अकरा वर्षे आहेत.

परतावा कॉलम (return columns) बायस स्वतःच वाहून नेतात. 2017 मध्ये, मध्यक नावाने 7.51% परतावा दिला, तर मध्यक वाचलेल्याने 11.32% परतावा दिला, जो 3.81 टक्के पॉइंट्सचा मोफत मिळालेला फरक आहे. चार्ट केलेल्या 10 वर्षांपैकी प्रत्येक वर्षात हा फरक सकारात्मक आहे. वाचलेल्यांवर (survivors) टेस्ट (test) केलेली स्ट्रॅटेजी (strategy) एकही निर्णय घेण्यापूर्वीच तो वारसा मिळवते, आणि कमकुवतपणासाठी स्क्रीन (screen) करणारे नियम अधिक वारसा मिळवतात, कारण गायब झालेली नावे या गटात जास्त प्रमाणात असतात.

सुधारणा म्हणजे पॉइंट-इन-टाइम युनिव्हर्स (point-in-time universe): प्रत्येक रीबॅलन्स तारखेला (rebalance date) असलेल्या नावांची यादी, डिलिस्टिंगसह (delistings), डिलिस्टेड पोझिशन (delisted position) अंतिम प्रिंटवर बंद केली जाते, रेकॉर्डमधून वगळण्याऐवजी.

यंत्रणा तीन: तारखेच्या स्टॅम्पनंतर सुधारित केलेला डेटा

किमती एकदाच स्टॅम्प केल्या जातात. फंडामेंटल्स (fundamentals) नाही. तिमाही आकृती (quarterly figure) तिमाहीच्या शेवटची तारीख घेऊन येते, नंतरच्या फाइलिंगद्वारे (filing) सुधारित केली जाते, आणि फक्त वर्तमान आवृत्ती संग्रहित करणारा डेटाबेस मूळ तारखेच्या विरोधात सुधारित क्रमांक आनंदाने देतो. त्या क्रमांकावर स्क्रीन करणारा नियम महिनोन्महिने येणाऱ्या सुधारणेला वाचत आहे.

हाच पॅटर्न (pattern) इंडेक्स सदस्यत्व याद्यांमध्ये (index membership lists) दिसतो, ज्या वर्तमान घटकांवर (constituents) पुनर्बांधल्या जातात, विश्लेषक अंदाजांच्या (analyst estimate) इतिहासांवर अंतिम सहमतीने ओव्हरराइट (overwrite) केले जाते, आणि कॉर्पोरेट कृती समायोजन (corporate action adjustments) संपूर्ण किंमत मालिकेत (price series) मागे लागू केले जातात. प्रत्येक बाबतीत संग्रहित रेकॉर्ड (stored record) भूतकाळातील तारखेला घातलेला वर्तमान-काळ स्नॅपशॉट (snapshot) आहे.

दोन पद्धतींमध्ये हे समाविष्ट आहे. व्हिंटेज (vintages) जतन करणारा स्रोत वापरा, म्हणजे प्रत्येक तारखेला ज्ञात असलेले मूल्य, आता ज्ञात असलेल्या मूल्याऐवजी. जिथे व्हिंटेज उपलब्ध नाहीत, तिथे वास्तविक कालावधी कव्हर करण्यासाठी पुरेसा रिपोर्टिंग लॅग (reporting lag) लागू करा, आणि त्या लॅगची लांबी अंदाज लावण्यासारखे तपशील म्हणून नव्हे तर चाचणी करण्यासारखे पॅरामीटर (parameter) म्हणून वापरा.

जेव्हा भविष्य लीक होते तेव्हा कर्व कसा दिसतो

लुक-अहेड बायसचे एक वैशिष्ट्य आहे: अंतर्निहित मार्केटने (underlying market) ऑफर केलेल्यापेक्षा खूप जास्त कामगिरी. एक उपयुक्त संदर्भ बिंदू म्हणजे हिंटसाइड सीलिंग (hindsight ceiling), एकाच इन्स्ट्रुमेंटवर (instrument) एक दिवसाच्या पुढे परिपूर्ण अंदाजाद्वारे (perfect one-day-ahead forecast) तयार झालेली वाढ.

क्वेरीThe hindsight ceiling: SPY buy and hold, the same year without its biggest up days, and perfect one-day foresight
प्रत्येक आकड्यामागील अचूक SQL
WITH bars AS (
    SELECT date,
           toFloat64(close) AS c,
           any(toFloat64(close)) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_c
    FROM global_markets.stocks_daily_aggs
    WHERE ticker = 'SPY'
      AND date >= toDate('2015-12-01')
      AND date <= toDate('2025-12-31')
),
rets AS (
    SELECT toYear(date) AS year,
           c / prev_c - 1 AS r
    FROM bars
    WHERE date >= toDate('2016-01-01')
      AND prev_c > 0
)
SELECT year,
       count() AS sessions,
       round(100 * (exp(sum(log(1 + r))) - 1), 1) AS buy_and_hold_pct,
       round(100 * (exp(sumIf(log(1 + r), r < 0.02)) - 1), 1) AS without_big_up_days_pct,
       round(exp(sum(log(1 + abs(r)))), 1) AS hindsight_ceiling_multiple
FROM rets
GROUP BY year
ORDER BY year
Run this yourself

सीलिंग प्रचंड आहे. 2020 मध्ये, SPY वर परिपूर्ण एक-दिवसाच्या दूरदृष्टीने 253 सत्रांमध्ये 27.7 पट भांडवल वाढवले, तर फक्त फंड होल्डिंगसाठी 16.2%. दहा वर्षांतील सर्वात शांत वर्षात, 2017, त्याच परिपूर्ण अंदाजाने 2.2 पट भांडवल परत केले.

मध्यभागी असलेला कॉलम दाखवतो की ती सीलिंग किती केंद्रित आहे. 2% पेक्षा जास्त वाढलेल्या सत्रांना वगळल्यास, 2020 16.2% वरून -44.9% पर्यंत बदलते. वर्षाला फक्त काही सत्रांइतकाच लीक (leak) बॅकटेस्टला (backtest) खूप पुढे नेतो. कमी ड्रॉडाउन (drawdowns), उच्च हिट रेट (hit rate) आणि मार्केटच्या सर्वात हिंसक सत्रांवर केंद्रित असलेले सर्वोत्तम दिवस असलेला कर्व ऑडिटसाठी (audit) पात्र आहे.

कॅलिब्रेशन (Calibration) कोणत्याही एका थ्रेशोल्डपेक्षा (threshold) अधिक महत्त्वाचे आहे. एका दशकात 40% चा स्मूथ (smooth) परतावा देणारा नियम हिंटसाइड सीलिंगचा (hindsight ceiling) मोठा भाग असल्याचा दावा करतो, आणि प्रामाणिक प्रश्न हा आहे की कोणत्या इनपुटने त्याला काय होणार आहे हे सांगितले.

बॅकटेस्टसाठी लुक-अहेड बायस कसा तपासावा

  • प्रत्येक गोष्ट एका बारने लॅग करा. प्रत्येक सिग्नल (signal) एक पूर्ण कालावधीने पुढे ढकला आणि पुन्हा चालवा. खरी एज (edge) थोडी कमी होते. लीक (leaks) कोसळतात, अनेकदा शून्यावर.
  • भविष्याला अस्थिर करा. प्रत्येक निर्णय टाइमस्टॅम्पनंतरचा डेटा घ्या, त्याला नॉईजने (noise) किंवा शफलने (reshuffle) बदला आणि निर्णय लॉजिक (decision logic) पुन्हा चालवा. प्रत्येक निर्णय समान आला पाहिजे. जो निर्णय बदलतो त्याने काहीतरी वाचले आहे जे त्याला माहित असू शकत नव्हते.
  • टाइमस्टॅम्पला डेटा म्हणून वागवा. प्रत्येक इनपुटसाठी, मूल्य उपलब्ध होण्याची वेळ आणि ते वर्णन करत असलेल्या वेळेसोबत संग्रहित करा. त्या दोन कॉलमची तुलना न करणारा जॉईन (join) नियम लागू करू शकत नाही.
  • युनिव्हर्सला तारखेनुसार पुनर्बांधा. डिलिस्टेड (delisted) आणि अधिग्रहित (acquired) नावे समाविष्ट करा, त्यांना त्यांच्या अंतिम प्रिंटवर बंद करा, आणि वाचलेल्यांच्या योगदानाचे मोजमाप करण्यासाठी दोन्ही युनिव्हर्सवर समान नियम चालवा.
  • सीलिंगच्या विरोधात मोजमाप करा. स्ट्रॅटेजीचा परतावा त्याच विंडोसाठी (window) बाय अँड होल्ड (buy and hold) आकृती आणि परिपूर्ण- foresight आकृतीसोबत ठेवा. सीलिंगपासूनचे अंतर हे शार्प रेशो (Sharpe ratio) एकटे देत नाही.

पोझिशन सायझिंग (Position sizing) या सर्वांच्या खाली येते. वाढलेला विन रेट (win rate) वाढलेल्या बेट साइजला (bet size) फीड करतो, जिथे Kelly criterion position sizing अकाउंटिंग त्रुटीला (accounting error) ड्रॉडाउनमध्ये (drawdown) रूपांतरित करते. प्रत्यक्ष भांडवल हलवण्यापूर्वी तीच शिस्त लागू होते: paper trading before real money ऑर्डर मेकॅनिक्सची (order mechanics) चाचणी करते, आणि ऑटोमेटेड स्टॅक्स (automated stacks) मशीन स्पीडवर (machine speed) समान धोका वाहतात, जे multi agent AI trading systems मध्ये समाविष्ट आहे. पॉइंट-इन-टाइम चाचणीतून वाचलेले प्रभाव, जसे की low volatility anomaly, त्याच कारणासाठी मनोरंजक आहेत.

वारंवार विचारले जाणारे प्रश्न

बॅकटेस्टिंगमध्ये लुक-अहेड बायस म्हणजे काय?

हा सिम्युलेटेड ट्रेडमध्ये (simulated trade) अशा डेटाचा वापर आहे जो ट्रेड ठेवला गेला असता तेव्हा उपलब्ध नव्हता. सामान्य प्रकार म्हणजे ज्या प्राइस बारवर (price bar) ट्रेड कार्यान्वित होतो त्यावर निर्णय घेणे, आज सूचीबद्ध असलेल्या कंपन्यांच्या युनिव्हर्सवर (universe) स्क्रीन करणे आणि त्याला जोडलेल्या तारखेनंतर सुधारित केलेल्या आर्थिक आकृतीला वाचणे.

लुक-अहेड बायस कसा शोधता येतो?

प्रत्येक सिग्नलला (signal) एका पूर्ण कालावधीने लॅग करा आणि पुन्हा चालवा: एक लीक (leak) सहसा कोसळते तर खरी एज (edge) हळू हळू कमी होते. एक मजबूत चाचणी प्रत्येक निर्णय टाइमस्टॅम्पनंतरचा सर्व डेटा नॉईजने (noise) बदलून टाकते आणि प्रत्येक निर्णय अपरिवर्तित राहतो याची पुष्टी करते.

सर्व्हायव्हरशिप बायस (Survivorship bias) लुक-अहेड बायससारखाच आहे का?

ते वेगळे आहेत पण एकत्र प्रवास करतात. सर्व्हायव्हरशिप बायस (Survivorship bias) म्हणजे टिकलेल्या नावांवरून तयार केलेला नमुना, आणि कोणती नावे टिकली हे जाणून घेणे हे स्वतःच भविष्यातील माहिती आहे, त्यामुळे फक्त वाचलेल्यांचे युनिव्हर्स (universe) हे नियमात नसून डेटामध्ये (data) असलेला लुक-अहेड लीक (look-ahead leak) आहे.

लुक-अहेड बायस असलेले बॅकटेस्ट इतके चांगले का दिसतात?

लीक (leak) अंदाज लावण्याऐवजी परिणाम निवडतो. वरील पॅनेलमध्ये, त्यांच्या स्वतःच्या क्लोजिंग प्राइसवर (closing price) सत्रांना स्क्रीन केल्याने 2016 मध्ये लॅग्ड आवृत्तीपेक्षा 0.455 टक्के पॉइंट्सने जास्त सरासरी सत्र लाभ मिळाला, जो अर्जित करण्याऐवजी व्याख्येवर आधारित फायदा आहे.

पॉइंट-इन-टाइम डेटा (Point-in-time data) म्हणजे काय?

पॉइंट-इन-टाइम डेटा (Point-in-time data) प्रत्येक मूल्याला ते ऐतिहासिक तारखेला जसे ज्ञात होते तसे संग्रहित करते, मूळ आकृती आणि प्रत्येक नंतरच्या सुधारणांसह, त्या दिवसाच्या सिक्युरिटीजच्या (securities) युनिव्हर्ससह. बॅकटेस्टला (backtest) हे दाखवण्यासाठी की त्याचे इनपुट (inputs) त्याच्या निर्णयांपूर्वी अस्तित्वात होते, यासाठी हा संदर्भ आवश्यक आहे.


वरील प्रत्येक आकृती ही वास्तविक दैनिक बारवरील (daily bars) संग्रहित, आवृत्तीकृत क्वेरी (versioned query) आहे. कोणत्याही पॅनेलचे SQL (SQL) विस्तृत करा, किंवा Strasmore टर्मिनलवर (Strasmore terminal) तुमच्या स्वतःच्या नियमावर लॅग चाचणी (lag test) चालवा.

#backtesting#look-ahead bias#survivorship bias#quant#research process