Commit sama, fail parquet sama, mesin sama, dua larian dengan jarak sejam. Sharpe 1.34 dan Sharpe 1.19. Pulangan keseluruhan 41.2% dan 37.8%. Bilangan dagangan 1,418 dan 1,421. Dan kedua-dua lengkung ekuiti sepadan hingga setiap perpuluhan yang dipaparkan untuk 11,205 bar berturut-turut sebelum berpecah.
Tiga nombor pertama itu menjengkelkan. Nombor terakhir itulah yang menarik, kerana ia menunjukkan masalahnya bukan ralat titik apung yang cuai dan tersebar sepanjang larian. Sesuatu yang diskret berlaku pada satu bar tertentu, kemudian kesannya berganda. Tulisan ini membincangkan cara mencari bar itu dan kesan nilai 0.15 tersebut terhadap setiap sapuan parameter yang pernah anda jalankan.
Strateginya: momentum keratan rentas pada 30 perps USDⓈ-M dengan volum tertinggi, imbangan semula setiap 4 jam, long lima teratas berdasarkan pulangan 12 jam, short lima terbawah, sejarah 18 bulan, dengan yuran dan funding dikenakan bagi setiap posisi.
Mencari bar tempat kedua-dua larian mula berbeza
Jika anda merekodkan ekuiti setiap bar dengan ketepatan penuh, proses ini mengambil kira-kira empat minit. Eksport kedua-dua larian ke CSV bagi (bar_index, equity, open_positions_hash), muatkan kedua-duanya, kemudian cari indeks pertama yang nilainya berbeza. Kami sudah pun menulis skrip itu untuk pepijat lain; itulah satu-satunya sebab saya tidak menghabiskan sepanjang pagi untuk mencarinya.
Bar 11,206, 2025-03-14T08:00 UTC. Ekuiti pada bar sebelumnya serupa hingga 13 angka bererti. Pada bar 11,206, hash posisi berbeza: larian A long SOL, larian B long AVAX. Arah sama, nilai nosional sama, simbol berbeza. Segala-galanya selepas itu ialah kesan susulannya.
Jadi saya mencetak input pemeringkatan bagi bar itu daripada kedua-dua larian. Semuanya serupa. Sama tepat hingga ke bait, 30 simbol yang sama, 30 skor yang sama. Dua skor bernilai 0.0. Tepat sifar, kedua-duanya, kerana kedua-dua aset mencatat bar 4 jam tanpa dagangan dalam tetingkap tinjauan, maka nisbah penutupan kepada penutupan menjadi satu, dan logaritmanya menjadi sifar. Bukan sifar akibat pembundaran. Memang sifar.
Dua simbol seri pada kedudukan kelima. Pemilihan mengambil lima teratas. Simbol yang terpilih bergantung pada susunan yang ditinggalkan oleh fungsi isihan, dan fungsi itu tidak berkelakuan seperti yang saya sangka.
Seri, isihan tidak stabil, dan perkara yang saya abaikan selama dua tahun
Pemeringkatan dijalankan melalui agregasi berkumpulan, dan bingkai data yang membekalkan input datang daripada kefahaman kamus yang dibina berasaskan set simbol yang dijana semula pada setiap bar melalui pengambilan data async. Susunan lelaran set berubah mengikut benih hash, dan Python mengacak benih hash rentetan bagi setiap proses melainkan anda menetapkan PYTHONHASHSEED. Maka susunan baris sebelum isihan berbeza antara larian, dan dengan isihan tidak stabil pada kunci yang seri, keputusan seri itu berbeza.
Keseri seperti ini bukan kejadian luar biasa. Ia berpunca daripada struktur sistem. Setiap kali ciri mencapai had atau dipotong, anda menghasilkan nilai yang sama tepat: bar tanpa volum memberikan pulangan sifar tepat, skor-z yang dipotong ditetapkan pada ±3.0, transformasi pangkat dengan sedikit nilai berbeza menghasilkan berpuluh-puluh seri, penapis boolean memberikan skor 1.0 kepada semua yang melepasi penapis. Sepanjang 18 bulan dengan bar 4 jam, larian ini mempunyai 47 bar dengan seri pada sempadan pemilihan. Tiga daripadanya mengubah bakul yang dipilih. Selebihnya seri antara dua aset yang kedua-duanya sudah terpilih atau kedua-duanya tidak terpilih.
Selama kira-kira sehari saya yakin pemuat data itu tidak deterministik, kerana itulah jawapan yang paling mengujakan. Bukan begitu. Memang tidak pernah. Puncanya set, seri, dan andaian tentang kestabilan isihan yang tidak pernah dicatat sesiapa.
Mengapa tiga dagangan bernilai 0.15 Sharpe
Inilah bahagian yang sering dipertikaikan orang, dan jawapannya ialah backtest dengan saiz berdasarkan pecahan ekuiti ialah sistem yang bergantung pada laluan. Menetapkan saiz pada 8% daripada ekuiti semasa bagi setiap posisi bermakna perbezaan ekuiti pada bar n ialah perbezaan pada setiap nilai nosional mulai bar n dan seterusnya.
Penyimpangan pertama itu sendiri hampir tidak membawa kerugian. Posisi AVAX larian B rugi 2.1% dalam tempoh sembilan jam; posisi SOL larian A untung 0.4%. Jurang ekuiti selepas dagangan itu: 0.21%. Kecil sahaja. Tetapi selepas itu kedua-dua larian bukan lagi strategi yang sama. Saiz pegangan mereka sedikit berbeza, jadi jumlah funding terakru juga sedikit berbeza, dan dua seri sempadan yang muncul kemudian sekali lagi menghasilkan keputusan berbeza kerana skor yang membekalkan nilainya kini datang daripada posisi pegangan yang sedikit berbeza. Salah satunya berlaku pada 2025-03-27, sehari sebelum trend enam hari yang menyumbang kira-kira satu pertiga daripada keseluruhan PnL larian. Larian A berada dalam pasaran sepanjang pergerakan itu; larian B masuk satu imbangan semula lewat.
Jurang pulangan: 3.4 mata. Jurang Sharpe lebih besar daripada yang ditunjukkan oleh jurang pulangan kerana dagangan larian B yang disusun semula bertindih dengan tempoh yang lebih tidak menentu, lalu penyebut meningkat sementara pengangka menurun. Punca kecil, dua faktor penguat.
Jika saiz posisi anda bernilai nosional tetap dan kemasukan tidak bergantung pada pegangan semasa, anda lebih terlindung. Kebanyakan strategi yang menarik tidak memenuhi kedua-dua syarat itu.
Lima punca yang benar-benar menyebabkannya
| Punca | Gejala | Penyelesaian |
|---|---|---|
PYTHONHASHSEED tidak ditetapkan, susunan lelaran set/dict membekalkan input kepada isihan | Keputusan seri berubah antara larian; penyimpangan pertama berlaku pada bar tertentu | Tetapkan benih; isih berdasarkan kunci kedua yang jelas (simbol) supaya keputusan seri deterministik |
Isihan tidak stabil pada kunci seri (quicksort lalai dalam NumPy/pandas) | Sama seperti di atas, masih berlaku walaupun benih ditetapkan | kind="stable", atau jadikan kunci itu menyeluruh |
| RNG tanpa benih dalam bootstrap, pengocokan latihan/ujian, atau jitter isian sintetik | Perbezaan sepanjang keseluruhan larian, tanpa titik penyimpangan yang jelas | Satu benih jelas bagi setiap komponen, direkodkan dalam manifes larian |
| Pengurangan titik apung selari (susunan penjumlahan bergantung pada bilangan utas) | Perbezaan pada beberapa bit terakhir, biasanya tidak memudaratkan sehingga melepasi ambang perbandingan | Tetapkan bilangan utas untuk larian penyelidikan; jangan sekali-kali membandingkan nilai apung dengan == pada sempadan keputusan |
| Versi pustaka tidak ditetapkan | Boleh dihasilkan semula hari ini, tetapi tidak pada bulan November | Hash fail kunci dalam manifes bersama hash petikan data |
Baris keempat jarang menjadi masalah sebesar yang disangka orang, manakala baris pertama kerap menimbulkan masalah.
Kebolehulangan bit demi bit ialah alat, bukannya nilai murni
Anda mahukan determinisme supaya apabila anda mengubah satu baris, perbezaan pada lengkung ekuiti dapat dikaitkan dengan baris itu. Itulah satu-satunya sebabnya. Kini setiap larian ejen di Stratmill menulis manifes yang mengandungi hash petikan data, hash fail kunci dan setiap benih. Jika larian semula tidak menghasilkan lengkung yang sama tepat bit demi bit, binaan itu dianggap gagal, bukannya sesuatu yang sekadar menarik perhatian.
Tetapi sebaik sahaja anda boleh mengulang hasil, sengaja ganggu proses itu. Jalankan sebanyak 64 kali dengan 64 benih dan perhatikan julat hasilnya:
Julat jitter. Strategi sama, data sama, 64 variasi terikat benih bagi pemecah seri dan susunan isian. Sharpe p5 1.12, median 1.27, p95 1.41. Lebar julat 0.29.
Sekarang kembali kepada sapuan parameter. Konfigurasi terbaik mendapat skor 1.46. Konfigurasi pada kedudukan ke-40 daripada 96 mendapat skor 1.31. Jurang antara kedua-duanya ialah 0.15, separuh daripada julat itu. Sapuan tersebut tidak menentukan kedudukan kedua-dua konfigurasi itu. Ia mengambil satu sampel daripada setiap taburan, kemudian menyusun sampel tersebut.
Cara fikir itu mengubah cara kami memilih. Hasil sapuan hanya boleh dianggap sebagai pemeringkatan jika jurang antara konfigurasi melebihi jitter bagi satu konfigurasi, dan dalam strategi yang bergantung pada laluan dengan 1,400 dagangan, jitter biasanya cukup besar untuk meratakan sepertiga teratas papan kedudukan menjadi seri. Apabila itu berlaku, pilih berdasarkan perkara yang tidak dapat disembunyikan oleh julat itu: kadar pusing ganti lebih rendah, parameter lebih sedikit, andaian kos yang sanggup anda pertahankan kepada pengkritik, atau tingkah laku yang lebih baik dalam lipatan walk-forward yang paling anda ragui. Itulah pemecah seri yang sebenar. Kelebihan Sharpe 0.15 bukan begitu.
Ada satu lagi perkara yang elok dibuat sebelum mempercayai semua ini. Jalankan backtest anda dua kali sekarang, bandingkan ekuiti setiap bar, dan ketahui sama ada anda berada dalam kumpulan yang serupa tepat bit demi bit atau kumpulan 0.15. Eksperimen ini mengambil masa 15 minit dan memberitahu anda sejauh mana sejarah penyelidikan anda mengukur strategi berbanding mengukur benih hash.
← Semua catatan


