Kaydedilmiş bir backtest’i yeniden çalıştırdık ve farklı bir özsermaye eğrisi elde ettik. Strateji kodu aynıydı, tarih aralığı aynıydı, sembol aynıydı. Bitiş bakiyesi %1.8 farklıydı ve 3 işlem bir bar kaymıştı.
Bu kadarı bile bir araştırma sonucuna güvenmeyi zorlaştırır. Bir ekip arkadaşınız, gelecekteki kendiniz ya da kâğıt üzerinde işlem yapan bir hizmet çalıştırmayı yeniden üretemiyorsa, yapılan değişikliğin stratejiyi mi iyileştirdiğini yoksa yalnızca deneyi mi değiştirdiğini anlayamazsınız. Sapmanın kaynağını bulmak için izlediğimiz adımlar şöyleydi.
1. gün: “Aynı çalıştırma” ile neyi kastettiğimizi yazdık
İlk hatamız, strateji dosyasını deneyin kendisi sanmaktı. Oysa öyle değildi. Çalıştırma; girdi verilerine, motor sürümüne, takvime, enstrüman metaverilerine ve yürütme ayarlarına da bağlıydı. Kod, hesabın yalnızca bir bölümünü tarif ediyordu.
Herhangi bir şeyi değiştirmeden önce bir çalıştırma manifesti hazırladık. Buraya stratejinin commit’ini, veri anlık görüntülerinin tanımlayıcılarını, tarih aralığını, işlem platformunu, ücret tarifesini, fonlama kaynağını, gerçekleşme modelini ve yazılım sürümlerini kaydettik. Ayrıca oluşan emirleri ve gerçekleşmeleri de sakladık; çünkü tek başına özsermaye eğrisi, iki çalıştırmanın ilk nerede ayrıştığını gösteremez.
| Kayıt | Kaydedilecekler | Neden önemli |
|---|---|---|
| Piyasa verisi | Anlık görüntü kimliği, şema sürümü, düzeltmeler | Veri sağlayıcıları geçmiş kayıtları düzeltir ve şirket işlemlerini revize eder |
| Yürütme | Ücret kademesi, fonlama serisi, gerçekleşme ve etki ayarları | Varsayılanlar ve hesap varsayımları sonuçları değiştirir |
| Çalışma ortamı | Kod commit’i, motor ve bağımlılık sürümleri | Kütüphaneler sıralamayı, yuvarlamayı veya göstergeleri değiştirebilir |
| Çıktı | Emirler, gerçekleşmeler, pozisyonlar ve metrikler | Çalıştırmaların nerede ayrışmaya başladığını gösterir |
2. gün: Sharpe’a değil, işlemlere baktık
Özet metrikler dikkatimizi dağıttı. İki çalıştırmanın Sharpe değeri neredeyse aynıydı; ancak gerçekleşme kayıtları ilk uyuşmazlığın bir fonlama mutabakatında ortaya çıktığını gösterdi. Bir çalıştırma, fonlama oranını mutabakat zaman damgasında açık olan pozisyona uygularken diğeri o zaman damgasındaki yeniden dengelemeden sonraki pozisyonu kullanıyordu.
Strateji kodu değişmemişti. Motorun olay sıralaması değişmişti. Küçük bir sürüm güncellemesi, iki olayın tesadüfen nasıl sıralandığına bağlı olan sırayı açıkça tanımlamıştı.
Çalıştırma sözleşmesini sıralamayı belirtecek şekilde düzelttik: önce fonlama, mutabakata taşınan pozisyona uygulanacak, ardından o zaman damgasındaki strateji kararları işlenecek. Kesin kural işlem platformuna ve motora göre değişebilir. Kuralın örtük kalması hatadır.
3. gün: “Aynı” veri dosyasının farklı olduğunu fark ettik
Olay sıralamasını sabitledikten sonra kalan uyuşmazlıklar birkaç hisse senedi işleminde yoğunlaştı. Veri sağlayıcısı geçmişteki bir bölünme düzeltmesini güncellemişti. Dosyamızın adı ve satır sayısı eskisiyle aynıydı; bu yüzden değişmediğini sanmıştık.
Artık her değişmez veri anlık görüntüsünün parmak izini çıkarıyor ve düzeltme politikasını yanında saklıyoruz. Bir özet değeri baytların değişip değişmediğini söyler; neden değiştiğini açıklamaz. Bu yüzden manifestte kaynak, verinin alınma zamanı ve dönüşüm sürümü de yer alıyor. Revize edilen verilerde bu ayrıntılar da sonucun bir parçasıdır.
Yeniden üretilebilir bir backtest, “Geçmişin hangi sürümünü gördü?” sorusuna yanıt verebilmelidir.
4. gün: Gözden kaçan bir varsayılan ayarı bulduk
Son fark, strateji yapılandırmasında alan belirtilmediği için 0 olarak ayarlanmış bir maker ücretinden kaynaklanıyordu. Daha yeni bir motor, hesabın varsayılan ücretini uygulamıştı. Bu tek varsayılan ayar, sınırdaki işlemleri değiştirerek bitiş bakiyesi farkının büyük bölümünü açıklıyordu.
Ekonomik açıdan anlamlı ayarları açıkça belirttik ve motora, çözümlenmiş yapılandırmayı çalıştırma kaydına yazdırmasını söyledik. Keşif aşamasında varsayılanlar kullanışlıdır. Sonuçları zaman içinde karşılaştırırken sağlam kanıt oluşturmazlar.
Bir dahaki sefere atlayacaklarımız
İlk farklı gerçekleşmeye bakmadan önce toplu metrikleri karşılaştırarak yarım gün harcadık. Oradan başlamayın. Her iki olay kaydını zaman damgasına göre sıralayıp ilk ayrışmayı karşılaştırın; sonraki farklar çoğu zaman aynı nedenden kaynaklanır.
Bir kapsayıcı imajının tek başına çalıştırmayı yeniden üretilebilir kıldığı fikrini de bir kenara bırakırdık. Yazılım ortamının büyük bölümünü sabitler; ancak harici bir veri dosyasını, çalışma anında alınan bir ücret tarifesini veya veri sağlayıcısının revize ettiği geçmişi sabitlemez.
Bir backtest değiştiğinde her iki çalıştırmanın manifestlerini ve kayıtlarını saklayın, ardından her seferinde tek bir sapma kaynağını düzeltin. İşe yarar sonuç, yalnızca yeniden çalıştırabileceğiniz bir eğri değildir. Onu hangi veri ve varsayımların ürettiğini, bir sonraki çalıştırmanın neden farklı olabileceğini açıklayan bir kayıttır.
← Tüm yazılar


