Her backtest'in kaçındığı bir soru vardır: aynı kod, aynı piyasayı canlı olarak besleseydi, aynı şeyi yapar mıydı? Bunu daha fazla backtest yaparak yanıtlayamazsınız. Yanıtın tek yolu, stratejiyi gerçek emir gerçekleşme semantiğiyle canlı veriye karşı çalıştırmak ve ardından — işlem işlem — iki dünyanın uyuştuğunu doğrulamaktır. Biz bu kontrolü her gün, otomatik olarak yapıyoruz ve platformdaki en verimli hata avcısı bu oldu.
Birinci gün: aynayı kurun
Terfi eden her strateji, gerçek borsa akışlarını tüketen kendi izole canlı düğümünde çalışır: gerçekleşmeler için canlı kotasyonlar, gerçek spread'ler, gerçek seans saatleri. Stratejiler arasında paylaşılan durum yok (bunu zor yoldan öğrendik — paylaşılan bir düğüm, bir stratejinin pozisyon sorgularının bir başkasına sızmasına izin veriyordu). Her gerçekleşme, onu üreten sinyal değeriyle birlikte kaydedilir.
Her sabah: replay ve karşılaştırma
Günlük bir iş, her stratejinin kâğıt penceresini alır, aynı kodu aynı dönem boyunca katalog verisi üzerinde backtest motorundan geçirir ve gerçekleşmeleri bire bir eşleştirir: aynı yön, aynı zaman damgası toleransı, aynı büyüklük. Çıktı bir korelasyon ya da "his" değildir. Bir tablodur: eşleşen, yalnızca kâğıtta, yalnızca replay'de. Sağlıklı bir strateji 55'te 54 eşleşme gösterir. Sağlıksız olanı ise hangi işlemin, ne zaman ayrıştığını tam olarak söyler.
Neler bozuldu, bozulma sırasıyla
- Isınma gerçekleşmeleri. Canlı düğüm, göstergeleri ısıtmak için geçmiş veriyi besliyordu — ve özel bar işleyicileri olan stratejiler bu veri üzerinde keyifle işlem açıyordu. Backtest'ler bu hayalet girişleri hiç görmedi. Çözüm bir strateji düzeltmesi değil, gönderim katmanında bir koruma oldu; çünkü aksi hâlde her strateji bu hatayı miras alıyor.
- Sıralı çok bacaklı ısınma. Kesitsel bir strateji enstrümanları teker teker ısıtıyordu; her bacak kardeşlerini boş görüyor ve çapa hiç başlatılmıyordu. Canlıda hiç işlem yapmadı; replay'de gayet iyi işlem yaptı. Sıfır eşleşen işlem — ama bunu yüksek sesle söyleyen tek şey karşılaştırmaydı.
- Tick hassasiyeti çökme döngüleri. Canlı aggTrade tick'leri, sandbox enstrümanının beklediğinden farklı bir hassasiyetle geliyor. Düğüm, backtest'in asla tetikleyemeyeceği bir assertion üzerinde çökme döngüsüne giriyordu; çünkü katalog barları zaten normalize edilmiş durumda.
- Yeniden başlatma amnezisi. Süreç yeniden başlatmaları, hâlihazırda var olan pozisyonlar üzerinde giriş mantığını yeniden tetikliyordu — yeniden dengeleyen bir strateji için bir yeniden başlatma sessizce bir yeniden dengelemeye dönüşüyordu. Canlı işlemde bu bir paralellik dipnotu değildir; parayla ilişkili bir kırmızı bayraktır.
Örüntüye dikkat edin: bunların hiçbiri bir sinyal hatası değil. Hepsi emir gerçekleşme sınırındaki hatalar — ısınma, durum, hassasiyet, yeniden başlatmalar. Bu tam da backtest'lerin yapısal olarak göremediği hata sınıfı; çünkü bir backtest'te emir gerçekleşme sınırı zaten backtest motorunun kendisidir.
Bilerek koruduğumuz asimetriler
İki dünya kasıtlı olarak birebir aynı değil. Backtest, PnL içinde modellenmiş bir yarım spread artı karekök etkisi tahsil eder; kâğıt ise gerçekleşme fiyatında gerçek spread'i öder ve hiçbir etki modeli uygulanmaz. Modellenmiş spread'i kâğıda (ya da gerçek olanı backtest'e) eklemek çift sayım olurdu. Paralellik demek aynı kararlar, tolerans içinde aynı gerçekleşmeler demektir — bit düzeyinde aynı PnL değil. Hangi farkların ilkesel, hangilerinin hata olduğunu bilmek bu disiplinin büyük kısmıdır.
Backtest bir hipotezdir. Kâğıt üzerinde işlem deneydir. Replay paralelliği ise kendinizi kandırdığınız anı yakalayan laboratuvar defteridir.
Strateji çalıştırıyor ve canlı davranışı replay edilmiş davranışla düzenli olarak karşılaştırmıyorsanız, hiç görmediğiniz bir hata sınıfına sahipsiniz demektir. Biz kabaca iki haftada bir tanesini buluyoruz ve her biri backtest'in içinden bakıldığında görünmezdi.
← Tüm yazılar
