Veriden Rapora Eksiksiz Bir Araştırma Not Defteri Projesi ve İleriye Bakma Yanlılığına ve Aşırı Uyuma Karşı Bir Kod İnceleme Kontrol Listesi
Eksiksiz bir strateji çalışmasını yeniden üretilebilir bir proje olarak düzenleyin, ham veriden yazılı bir sonuca kadar çalıştırın ve kodu, geriye dönük testleri olduğundan iyi gösteren hataları yakalayan bir kontrol listesiyle gözden geçirin.
Neler öğreneceksiniz
- Bir çalışmayı altı ay sonra sizin veya başka birinin yeniden üretebilmesini sağlayan bir klasör ve not defteri düzeni.
- Çalışma sırası: veri, temizleme, öznitelikler, sinyaller, geriye dönük test, metrikler, örneklem dışı kontrol, rapor.
- İleriye bakma yanlılığı, hayatta kalma yanlılığı (survivorship bias) ve aşırı uyum için satır satır bir kod inceleme kontrol listesi.
- Denenen ve işe yaramayan şeyler dahil, bir sonucun dürüstçe nasıl yazılacağı.
Açıklama
Örneklem dışı test, parametre platoları ve çok sayıda denemenin bedeli "Sistematik Trading" kursunda (6. ve 7. dersler) ele alınmıştı. Bu ders, bu fikirlerin geçerliliğini koruyan mühendislik ile ilgilidir: bir proje yapısı, sabit bir iş akışı ve başka birinin tekrarlayabileceği bir inceleme.
Proje düzeni
project/data/raw/ # indirmeler, asla elle düzenlenmezdata/clean/ # 01_data.ipynb tarafından üretilen parquet dosyalarınotebooks/ # 01_data, 02_features, 03_backtest, 04_reportsrc/ # indicators.py, engine.py, metrics.py (6., 8., 9. dersler)tests/ # test_metrics.py, test_engine.pyconfig.yaml # semboller, tarihler, parametreler, maliyet varsayımlarırequirements.txt # sabitlenmiş sürümler: pandas==2.x, numpy==…
Yeniden kullanılan kod src/ içinde yaşar; not defterleri yalnızca fonksiyonları çağırır ve sonuçları gösterir. Paket sürümlerini sabitleyin, çünkü bir pandas güncellemesi bir varsayılanı (frekans dizeleri, yeniden örnekleme etiketleri) değiştirip sayılarınızı oynatabilir. Rastgelelik içeren her şey için tohum değeri (seed) belirleyin ve verinin indirilme tarihini rapora kaydedin.
Sırasıyla iş akışı
- Önce hipotez. Veriye dokunmadan önce tek cümlelik bir ekonomik gerekçe ve kesin kurallar ("Sistematik Trading", 2. ders). Örneklem içi / örneklem dışı ayrımını şimdi sabitleyin ve örneklem dışı dosyayı 7. adıma kadar açmayın.
- Veri. İndirin, ham olarak saklayın, kaynağı ve düzeltme yöntemini belgeleyin (4. ders). On yıl geriye doğru test edilen bir "bugünkü endeks üyeleri" listesi hayatta kalma yanlılığıdır.
- Temizleme ve doğrulama. Boşluklar, tekrarlar, sıfır fiyatlar, saat dilimleri;
data/clean/klasörüne kaydedin. - Öznitelikler ve sinyaller:
src/içindeki test edilmiş fonksiyonlarla oluşturulur; t çubuğundaki her öznitelik yalnızca t'ye kadarki veriyi kullanır. - Maliyet modeli dahil 8. dersin motoruyla geriye dönük test ("Sistematik Trading", 8. ders).
- Metrikler ve grafikler (9. ve 10. dersler); örneklem içi dönemde, en iyi hücreyi aramak yerine küçük bir parametre ızgarasıyla.
- Parametreler dondurulmuş hâlde örneklem dışı çalıştırma bir kez. Sonuç ne olursa olsun kaydedin.
- Rapor: hipotez, veri, kurallar, maliyetler, her iki sonuç tablosu, grafikler, denenen varyant sayısı, karar.
Kod inceleme kontrol listesi
Not defterinizi başkasınınmış gibi gözden geçirin; her satır evet-hayır şeklinde yanıtlanacak bir sorudur.
| Alan | Kontrol | Tipik düzeltme |
|---|---|---|
| Zamanlama | Her sinyal, bir pozisyon belirlemeden önce bir çubuk kaydırılıyor mu? | pos = signal.shift(1) |
| Zamanlama | Kayan pencereler center=False (varsayılan) kullanıyor ve bfill() kullanmıyor mu? |
Merkezlemeyi ve geriye doğru doldurmaları kaldırın |
| Zamanlama | Normalleştirmeler (z-skorları, sıralamalar, ölçekleyiciler) yalnızca geçmiş veriye göre mi uyarlanıyor? | Genişleyen veya kayan pencereyle uyarlama |
| Veri | Hisse evreni her tarihte bilindiği şekliyle mi tanımlanmış? | Zamana göre (point-in-time) bileşen listeleri veya dürüst bir çekince |
| Veri | Getiriler için düzeltilmiş, gerektiğinde stop mesafeleri için düzeltilmemiş fiyatlar kullanılıyor mu? | Her iki sütunu da tutun |
| Gerçekleşmeler | Fiyat boşlukları stop veya sinyal fiyatından değil, açılıştan mı gerçekleştiriliyor? | min(open, stop) |
| Maliyetler | Komisyonlar, spread ve kayma işlem başına ve her yön için uygulanıyor mu? | Yapılandırmada maliyet modeli |
| Aşırı uyum | Kaç parametre seti, kural ve hisse evreni denendi? Bu sayı raporda var mı? | Her çalıştırmayı kaydedin |
| Aşırı uyum | Komşu parametreler benzer sonuçlar (bir plato) veriyor mu? | Izgaranın ısı haritası |
| Aşırı uyum | Örneklem dışı veriye birden fazla kez dokunuldu mu? | Evetse artık örneklem içidir; yeni veri bulun |
| Yeniden üretilebilirlik | "Restart kernel and run all" (çekirdeği yeniden başlat ve tümünü çalıştır) rapordaki sayıları yeniden üretiyor mu? | Gizli durumu ve hücre sırasını düzeltin |
Anlamlılık için pratik kural: yıllıklandırılmış bir Sharpe oranının t-istatistiği kabaca Sharpe × √yıl'dır. Dört yıl boyunca 0.8'lik bir Sharpe 1.6 verir; bu, yaklaşık 2 olan olağan eşiğin altındadır ve bu hesap denenen varyant sayısı henüz hesaba katılmadan yapılmıştır; yirmi deneme arasında en iyisinin tesadüfen iyi görünmesi beklenir.
Çözümlü örnek
Varsayımsal örnek, tüm sayılar uydurmadır. Bir trader, "100 günlük bir kırılımda al, 3 × ATR iz süren stopla çık" kuralını 30 büyük ölçekli hisse üzerinde, 2014–2025 döneminde, yön başına 0.1 % maliyetle test ediyor.
- Ayrım. Örneklem içi 2014–2021 (8 yıl), örneklem dışı 2022–2025 (4 yıl); ilk çalıştırmadan önce karar verilmiştir.
- Izgara. Kırılım uzunlukları 50, 100, 150 × ATR katları 2, 3, 4 = 9 varyant, kayıt altına alınmış. Örneklem içi Sharpe 0.6 ile 1.1 arasında değişiyor ve en iyi hücre (100, 3) = 1.1; komşuları 0.9 ve 1.0, yani bir plato; dolayısıyla seçim korunuyor.
- İnceleme. Kontrol listesi, ATR sütununun
rolling(14).mean()ifadesini bugünkü stop için bugünün gerçek aralığına uyguladığını ortaya çıkarıyor. Motor, önceki çubuğun ATR'sini kullanacak şekilde değiştiriliyor (8. ders). Örneklem içi Sharpe 1.1'den 1.0'a düşüyor; maksimum düşüş −22 %'de değişmeden kalıyor. - Örneklem dışı. Bir kez çalıştırılıyor: Sharpe 0.6, CAGR 7.2 %, maksimum düşüş −19 %, 118 işlem. Anlamlılık: 0.6 × √4 = 1.2; örneklem içi rakam 1.0 × √8 = 2.8 vermişti. Örneklem dışı sonuç pozitif, ancak tek başına istatistiksel olarak zayıf.
- Rapordaki karar. "Kural, örneklem içi Sharpe'ının yaklaşık 60 %'ını örneklem dışında korudu (0.6 / 1.0); bir plato üzerinde, 9 varyant denendi, ileriye bakmaya yol açan bir hata düzeltildi. Kanıt sınırlıdır; bir sonraki adım gerçek sermaye değil, 12. dersteki betikle altı aylık kâğıt üzerinde işlem (paper trading) yapmaktır." Ücretler modellenmiştir; vergiler ve finansman hariçtir.
Sık yapılan hata
Uygulama etkinliği
Kâğıt üzerinde: bu not defteri parçasını ve ardından gelen sonucu gözden geçirin.
df['z'] = (df.close - df.close.mean()) / df.close.std()df['signal'] = df.z < -1.5df['pos'] = df.signal.astype(int)df['ret'] = df.close.pct_change() * df.pos
6 yıl boyunca örneklem içi Sharpe 2.4; 2 yıl boyunca örneklem dışı Sharpe −0.3. (a) Koddaki iki ileriye bakma sorununu belirleyin. (b) Örneklem içi ve örneklem dışı Sharpe oranları için yaklaşık t-istatistiklerini hesaplayın. (c) Dört satırı ileriye bakmadan arınmış olacak şekilde yeniden yazın (isterseniz değişiklikleri düz yazıyla anlatın).
Çözümü göster
(a) Birincisi, df.close.mean() ve df.close.std() gelecekteki fiyatlar dahil tüm örneklemi kullanır; dolayısıyla herhangi bir tarihteki z-skoru gelecekteki ortalamayı "bilir". İkincisi, pos kaydırılmamıştır: bugünün getirisi, bugünün kapanışından hesaplanan bir sinyalle kazanılır.
(b) Örneklem içi: 2.4 × √6 = 5.9; örneklem dışı: −0.3 × √2 = −0.4. Büyük örneklem içi değeri hatalar üretmişti; çökmesinin nedeni budur.
(c) Kayan veya genişleyen bir pencere ve bir kaydırma kullanın:
m = df.close.rolling(250).mean(); s = df.close.rolling(250).std()df['z'] = (df.close - m) / sdf['signal'] = df.z < -1.5df['pos'] = df.signal.shift(1).fillna(False).astype(int)df['ret'] = df.close.pct_change() * df.pos
Sınırlamalar: ileriye bakmayı ortadan kaldırmak testi kârlı değil, dürüst yapar; düzeltilmiş kural hâlâ maliyetlere, stoplu bir motora ve yeni bir örneklem dışı döneme ihtiyaç duyar.
Önemli çıkarımlar
- Yeniden kullanılabilir kodu testleriyle birlikte
src/içinde tutun, sürümleri sabitleyin ve "tümünü çalıştır" komutunun raporu yeniden üretmesini sağlayın. - İlk geriye dönük testten önce hipotezi, kuralları ve örneklem içi / örneklem dışı ayrımını sabitleyin; örneklem dışı testi bir kez çalıştırın.
- Zamanlamayı, veriyi, gerçekleşmeleri, maliyetleri ve deneme sayılarını bir kontrol listesiyle gözden geçirin; denediğiniz her varyantı kaydedin.
- Anlamlılığı kabaca Sharpe × √yıl olarak, varyant sayısını ve kararı ("yeterli kanıt yok" dahil) raporlayın.
Sonraki adım
Böylece "Yatırımcılar ve Trader'lar için Python: Fiyat Verisinden Geriye Dönük Teste" kursu tamamlanıyor; bir sonraki kurs olan "Prop Firmalar, Fonlanmış Hesaplar ve Bir İş Olarak Trading", değerlendirme kurallarını, düşüş türlerini ve bir iş olarak trading'in pratik yönünü ve Alman vergi boyutunu ele alıyor; burada oluşturduğunuz gibi test edilmiş, betiğe dökülmüş bir süreç bunun başlangıç noktasıdır.
Öz değerlendirme
Soruları yanıtlayın, ardından yanıtlarınızı kontrol edin. İstediğiniz kadar tekrar deneyebilirsiniz.
Kendi tekrarınız için otomatik öz değerlendirme. Cevaplarınız tarayıcınızda kontrol edilir; bunları görmez ve değerlendirmeyiz. Bu bir sınav veya yeterlilik değildir.
İlerlemeniz
“Tamamlandı” yalnızca dersi bitirdiğinizi işaretlediğiniz anlamına gelir. Anlayışınızın bir sınavı değildir. İlerleme ve notlar yalnızca bu cihazdaki bu tarayıcıda saklanır — bir hesapta değil.