Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

look ahead bias backtest hatası nedir nasıl önlenir

Look-ahead bias, geriye dönük testte gelecekteki verilerin sızmasıdır. Aynı bar kararları, hayatta kalma yanlılığı ve revize edilmiş rakamlar sonuçları şişirir; test yöntemleri

Look-ahead bias, bir geriye dönük testte, simüle edilen işlemin yapıldığı anda hiç kimsenin sahip olamayacağı bilgilerin kullanılmasıdır. Öz sermaye eğrisi yükselir, istatistikler mükemmel görünür ve bunların hiçbiri canlı bir emirle karşılaştığında geçerliliğini korumaz. Bu sayfa, bu yanlılığı tanımlar, onu üreten üç mekanizmayı açıklar ve her birini gerçek piyasa verileri üzerinde ölçer.

Look-ahead bias nedir

Geriye dönük bir test, bir karar hakkında bir iddiadır: bu zaman damgasında, bu bilgiyle, kural bunu yapardı. İddia, yalnızca kuralın okuduğu her girdi, o zaman damgasından önce, nihai haliyle zaten mevcutsa geçerlidir. Look-ahead bias, bu koşulun herhangi bir ihlalidir ve sessizdir. Bir satır, beslendiği karardan daha sonra damgalanmış bir değer geri verdiğinde, bir e-tabloda veya bir betikte hiçbir şey şikayet etmez.

Üç ihlal, pratikte karşılaşılanların çoğunu kapsar. İçinde işlem yaptığı bir fiyat çubuğunu da okuyan bir karar. Bugün hala işlem gören isimlerden oluşturulmuş bir evren. Taşıdığı tarihten sonra revize edilmiş bir veri alanı.

Mekanizma bir: işlem yaptığınız bir çubuk üzerinde karar vermek

Zararsız görünen bir kuralla başlayın. Güçlü olanı satın alın, yani fonun açılışının üzerinde kapandığı seanslar. Dikkatsizce kodlanırsa, test o seansın açılışında girer ve o seansın kapanışında çıkar, oysa taradığı koşul aynı çubuğun kapanış fiyatıdır. Açılış zilinde kimse bir kapanış fiyatı bilmez.

Aşağıdaki panel, her iki versiyonu da SPY (S&P 500 takipçisi) üzerinde on takvim yılı boyunca çalıştırır. İlk sütun imkansız olandır. İkincisi, aynı koşulu tek bir seans geciktirir; bu, finanse edilmiş bir hesabın buna göre hareket edebileceği en erken zamandır.

SorgulaAynı bar kararı ile bir seans gecikmeli karar: SPY, ortalama seans kazancı, 2016-2025
Her verinin arkasındaki tam 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

Ayrım ince değildir. 2016'de, aynı çubuk versiyonu, kalifiye seans başına ortalama 0.447% getiri sağlarken, gecikmeli versiyon -0.008% getiri sağladı; bu, günde 0.455 puanlık bir farktır. 2025'de ikisi 0.636% ve -0.03% olarak okunur. Bir yılda kabaca 140 kalifiye seans varken, seans başına yarım puanlık bir fark, hiçbir canlı hesabın basmadığı bir öz sermaye eğrisine dönüşür.

Tüm avantaj tanımsaldır. Açılışının üzerinde kapanan seansları seçmek ve ardından aynı seanslarda açılıştan kapanışa getiriyi ölçmek, pozitif olması garanti edilen bir miktarı ölçer. Kural kendi filtresini keşfetti.

Bunun varyantları günlük verilerde her zaman gizlidir: bugünün kapanışını içeren ve bugün işlem yapmak için kullanılan hareketli bir ortalama, henüz gerçekleşmemiş bir bölünme için zaten ayarlanmış fiyatlar üzerinden hesaplanan bir sinyal, henüz oluşmamış bir seans yüksekliğine yerleştirilmiş bir gün içi stop. Ortak şekil, kendi girdilerinden birinden daha erken olan bir karar zaman damgasıdır.

Mekanizma iki: bugünün hayatta kalanlarından oluşturulmuş bir evren

İkinci mekanizma asla kurala dokunmaz. Kuralın görmesine izin verilen isimler listesinde yer alır.

Mevcut bir veri sağlayıcısından bir hisse senedi listesi çekin, on yıl geriye çalıştırın ve örneklem, yol boyunca iflas eden, satın alınan veya borsadan çıkarılan her şirketi sessizce hariç tutar. Kurala hiçbir zaman kaybedenler sunulmadı. Panel, bu ihmalin boyutunu ölçer: belirli bir takvim yılında 1 doların üzerinde en az 200 seans işlem gören borsada işlem gören her ABD ismi, bu kohortun Temmuz 2026'da hala fiyat basan payı ve tüm kohortun medyan takvim yılı getirisi, yalnızca hayatta kalanların medyanının yanında.

SorgulaEvrende hayatta kalma: her yıl işlem gören isimler, Temmuz 2026'da hâlâ listelenen pay ve medyan getiri
Her verinin arkasındaki tam 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'da çıtayı geçen 7063 isimden 52.5%'u Temmuz 2026'da hala işlem görüyordu. 2024 kohortu için bu rakam 87.5%'dir; bu çoğunlukla geçen zaman meselesidir: 2024'teki bir ismin kaybolması için iki yılı, 2015'teki bir ismin ise on bir yılı olmuştur.

Getiri sütunları yanlılığın kendisini taşır. 2017'de medyan isim 7.51% getiri sağlarken, medyan hayatta kalan 11.32% getiri sağladı; bu, bedavaya verilen 3.81 puanlık bir farktır. Fark, grafiği çizilen 10 yılın her birinde pozitiftir. Hayatta kalanlar üzerinde test edilen bir strateji, tek bir karar vermeden önce bunu miras alır ve zayıflık için tarama yapan kurallar, ortalamadan daha fazlasını miras alır, çünkü ortadan kaybolan isimler orantısız bir şekilde bu kovada yer alır.

Düzeltme, anlık bir evrendir: her yeniden dengeleme tarihinde olduğu gibi isimlerin listesi, borsadan çıkarılanlar dahil, borsadan çıkarılan bir pozisyonun kayıttan düşürülmek yerine son fiyatından kapatıldığı bir liste.

Mekanizma üç: tarih damgasından sonra revize edilen veri

Fiyatlar bir kez damgalanır. Temel veriler öyle değildir. Üç aylık bir rakam, çeyreğin bitiş tarihini taşır, daha sonraki bir dosyayla değiştirilir ve yalnızca mevcut sürümü depolayan bir veritabanı, değiştirilmiş sayıyı orijinal tarihe karşı memnuniyetle sunar. Bu sayıyı tarayan bir kural, gelmesi aylar süren bir düzeltmeyi okuyordur.

Aynı model, mevcut bileşenlere yeniden oluşturulmuş endeks üyelik listeleri, nihai konsensüs ile üzerine yazılmış analist tahmin geçmişleri ve tüm bir fiyat serisi boyunca geriye doğru uygulanan kurumsal eylem ayarlamaları boyunca uzanır. Her durumda, depolanan kayıt, geçmiş zamanlı bir tarih giyen şimdiki zamanlı bir anlık görüntüdür.

İki uygulama bunu içerir. Her tarihte şimdi bilinen değer yerine o tarihte bilinen değer anlamına gelen, yılları (vintage) tutan bir kaynak kullanın. Yılların mevcut olmadığı durumlarda, gerçek olanı kapsayacak kadar cömert bir raporlama gecikmesi uygulayın ve bu gecikmenin uzunluğunu tahmin etmeye değer bir ayrıntıdan ziyade test etmeye değer bir parametre olarak ele alın.

Gelecek sızdığında eğri neye benzer

Look-ahead bias'ın bir imzası vardır: altta yatan piyasanın sunduğunun çok üzerinde performans. Yararlı bir referans noktası, geriye dönük bakış tavanıdır (hindsight ceiling), yani mükemmel bir günlük tahminin tek bir enstrümanda üreteceği büyüme.

SorgulaGeriye dönük tavan: SPY al ve tut, en büyük yükseliş günleri olmayan aynı yıl ve mükemmel bir günlük öngörü
Her verinin arkasındaki tam 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

Tavan çok büyüktür. 2020'de, SPY üzerinde mükemmel bir günlük öngörü, sermayeyi 253 seansta 27.7 katına çıkarırken, fonu basitçe tutmak 16.2% kat getirdi. On yılın en sakin yılı olan 2017'de, aynı mükemmel tahmin 2.2 kat sermaye getirdi.

Orta sütun, bu tavanın ne kadar yoğun olduğunu gösterir. %2'den fazla kazanan seansları çıkarın ve 2020, 16.2%'ten -44.9%'ya dönüşür. Yılda bu seanslardan yalnızca bir avuç kadarına denk gelen bir sızıntı, bir geriye dönük testi çok uzun bir yol kat ettirir. Sığ düşüşleri, yüksek isabet oranı ve en iyi günleri piyasanın en şiddetli seanslarında kümelenmiş bir eğri, bir denetimi hak etmiştir.

Kalibrasyon, herhangi bir eşikten daha önemlidir. On yıl boyunca yılda %40 gibi düzgün bir getiri iddia eden bir kural, geriye dönük bakış tavanının büyük bir kısmını talep ediyordur ve dürüst soru, hangi girdinin ona ne olacağını söylediğidir.

Bir geriye dönük testte look-ahead bias nasıl test edilir

  • Her şeyi bir çubuk geciktirin. Her sinyali bir tam dönem sonraya kaydırın ve yeniden çalıştırın. Gerçek avantajlar biraz azalır. Sızıntılar çöker, genellikle sıfıra iner.
  • Geleceği bozun. Her karar zaman damgasından sonraki verileri alın, gürültü veya yeniden karıştırma ile değiştirin ve karar mantığını yeniden çalıştırın. Her karar aynı çıkmalıdır. Hareket eden herhangi bir karar, bilemeyeceği bir şey okumuştur.
  • Zaman damgalarını veri olarak ele alın. Her girdi için, bir değerin kullanılabilir hale geldiği anı, tanımladığı anın yanında saklayın. Bu iki sütunu asla karşılaştırmayan bir birleştirme, kuralı uygulayamaz.
  • Evreni tarih itibarıyla yeniden oluşturun. Borsadan çıkarılan ve satın alınan isimleri dahil edin, onları son fiyatlarından kapatın ve hayatta kalma katkısını boyutlandırmak için aynı kuralı her iki evrende de çalıştırın.
  • Tavana karşı ölçün. Stratejinin getirisini, aynı pencere için bir al ve tut rakamının ve mükemmel öngörü rakamının yanına koyun. Tavandan uzaklık, tek başına bir Sharpe oranının vermediği bir bağlamdır.

Pozisyon boyutlandırması tüm bunların akış aşağısındadır. Şişirilmiş bir kazanma oranı, şişirilmiş bir bahis boyutunu besler; bu da Kelly kriteri pozisyon boyutlandırmasının bir muhasebe hatasını bir düşüşe dönüştürdüğü yerdir. Gerçek sermaye hareket etmeden önce aynı disiplin geçerlidir: gerçek para öncesi kağıt üzerinde işlem yapmak emir mekaniklerini test eder ve otomatik yığınlar, çok ajanlı AI ticaret sistemlerinde ele alınan, makine hızında aynı tehlikeyi taşır. Dikkatli anlık testlerden sağ çıkan etkiler, örneğin düşük volatilite anomalisi, tam da bu nedenle ilginçtir.

SSS

Geriye dönük testte look-ahead bias nedir?

Simüle edilmiş bir işlemde, işlemin yapılacağı sırada mevcut olmayan verilerin kullanılmasıdır. Yaygın biçimler, işlemin aynı zamanda içinde yürüttüğü bir fiyat çubuğu üzerinde karar vermek, bugün hala işlem gören şirketlerden oluşan bir evreni taramak ve kendisine eklenen tarihten sonra revize edilmiş bir finansal rakamı okumaktır.

Look-ahead bias nasıl tespit edilir?

Her sinyali bir tam dönem geciktirin ve yeniden çalıştırın: bir sızıntı genellikle çökerken, gerçek bir avantaj hafifçe azalır. Daha güçlü bir test, her karar zaman damgasından sonraki tüm verileri gürültüyle değiştirir ve her kararın değişmeden çıktığını onaylar.

Hayatta kalma yanlılığı (survivorship bias) look-ahead bias ile aynı mıdır?

Farklıdırlar ancak birlikte seyahat ederler. Hayatta kalma yanlılığı, dayanan isimlerden oluşturulmuş bir örneklemdir ve hangi isimlerin dayandığını bilmek, gelecekten gelen bilginin ta kendisidir; bu nedenle, yalnızca hayatta kalanlardan oluşan bir evren, kuralda değil, veride bulunan bir look-ahead sızıntısıdır.

Look-ahead bias içeren geriye dönük testler neden bu kadar iyi görünür?

Sızıntı, sonuçları tahmin etmek yerine seçer. Yukarıdaki panelde, seansları kendi kapanış fiyatlarına göre taramak, 2016'de gecikmeli versiyona göre seans başına ortalama yaklaşık 0.455 puanlık bir getiri avantajı üretti; bu, kazanılmış olmaktan ziyade tanımsal bir avantajdır.

Anlık (point-in-time) veri nedir?

Anlık veri, her bir değeri, orijinal rakam ve sonraki her revizyon dahil olmak üzere, her tarihsel tarihte bilindiği şekliyle ve o gün var olan menkul kıymetler evreniyle birlikte saklar. Bir geriye dönük testin, girdilerinin kararlarından önce var olduğunu göstermek için ihtiyaç duyduğu referanstır.


Yukarıdaki her rakam, gerçek günlük çubuklar üzerinde depolanmış, sürümlenmiş bir sorgudur. Herhangi bir panelin SQL'ini genişletin veya Strasmore terminalinde kendi kuralınız üzerinde gecikme testini çalıştırın.

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