KenKem Journal

Apa yang Harus Dilakukan Ketika Backtest Engine Anda Sendiri Salah?

· #research-method #backtesting #reproducibility #validation #systematic-trading

Anda berhenti menjadikannya wasit, dan Anda mengatakannya terang-terangan. Ketika engine riset saya dan MetaTrader 5 berbeda pendapat tentang strategi yang sama pada periode yang sama, saya memutuskan hanya aliran fill milik broker yang boleh dihitung sebagai hasil, menjalankan ulang seluruh pekerjaan di bawah standar itu, dan mencatat apa saja yang pernah diklaim oleh angka-angka lama.

Sebagai quant otodidak, saya sempat lama tidak memposting, dan itu bukan karena kehabisan bahan. Itu adalah waktu saya memeriksa ulang pekerjaan saya sendiri. Berikut yang saya temukan, termasuk bagian yang merugikan saya.

Skema yang membandingkan dua catatan untuk trade yang sama, satu dihasilkan oleh engine riset dan satu dihasilkan oleh aliran fill broker, dengan aliran broker ditandai sebagai wasit
Catatan mana yang berhak memutuskan ketika keduanya berbeda. Ilustrasi skematis, bukan data terukur.

Bagaimana saya tahu engine saya sendiri salah?

Strategi yang sama, periode yang sama, tetapi hasilnya berlawanan tanda di dua tempat.

Hal itu muncul tiga kali secara terpisah sebelum saya berani menyebutnya pola, bukan kebetulan. Sebuah konfigurasi trailing stop untung sekitar 24 persen di engine dan rugi sekitar 24 persen di MetaTrader 5. Sebuah filter penolak entry berbasis penyerapan pada node volume terlihat datar di engine, lalu menjadi bencana di MetaTrader 5, sekitar minus 95 persen net. Sebuah konfigurasi Bitcoin melaporkan profit factor sekitar 1,29 di engine melawan sekitar 1,06 di MetaTrader 5, yaitu selisih antara edge kecil dan tidak ada edge sama sekali. Angka-angka itu berasal dari catatan robustness saya sendiri di repo riset DQuants, bertanggal 2026-06, dan semuanya hasil backtest serta run konfirmasi, bukan hasil live.

Dua dari tiga kasus itu adalah kabar buruk yang hampir saya percayai. Itu bukan catatan kaki. Kalau alat ukurnya salah, setiap angka yang pernah diukur dengannya menjadi meragukan, termasuk angka yang saya sukai.

Apa persisnya yang salah pada engine saya?

Bagian exit, dan salahnya hanya ke satu arah.

Engine riset hanyalah model pasar, dan sebuah model boleh salah. Model saya salah dengan cara yang sangat spesifik dan bisa dipelajari. Ia menyelesaikan exit di dalam bar melalui jalur tick yang diskrit dan tidak bisa tahu ke mana harga bergerak di dalam satu tick, sehingga ketika sebuah trade mungkin saja terkena stop atau ter-trail di tengah pergerakan, engine cenderung memilih pembacaan yang lebih menguntungkan dari dua kemungkinan. Geometri feed memperburuk itu. Pada data saya, tingkat kelanjutan setelah breakout berada di sekitar 45 persen, sementara pengukuran yang sama pada feed vendor lain keluar di sekitar 94 persen, jadi bentuk pergerakan bolak-baliknya pun tidak sama.

Kesimpulan yang saya tulis sengaja dibuat sempit: angka sisi entry dari engine layak dipercaya, sedangkan angka sisi exit secara sistematis terlalu murah hati pada trade yang berjalan panjang. Pembukuan exit yang longgar mengubah sistem biasa-biasa saja menjadi kurva yang indah di layar. Lalu broker sungguhan mengisi order di harga sungguhan, dan keindahan itu menguap.

Aturan apa yang saya pakai sebagai gantinya?

Satu wasit saja, dan wasit itu bukan kode saya.

Sekarang hanya aliran deal milik broker pada tick nyata yang dihitung sebagai hasil. Engine mengusulkan, engine tidak memutuskan. Dalam praktiknya, ide di sisi entry masih boleh disapu di engine, tempat ia cepat dan jujur, sedangkan setiap ide di sisi exit langsung masuk ke uji A dan B di MetaTrader 5 sebelum boleh mengubah apa pun. Cara ini lebih lambat, dan hanya versi inilah yang bisa saya pertahankan di kemudian hari.

Di bawah aturan itu ada satu gerbang yang saya rekomendasikan untuk setiap engineer yang trading dengan kodenya sendiri. Sebelum sebuah build boleh dideploy, output per trade-nya harus identik byte demi byte dengan run referensi, checksum dan semuanya. Gerbang itu pernah menangkap regresi yang membuat hasil yang dilaporkan menjadi lebih baik, bukan lebih buruk. Memandangi kurva laba rugi akan meloloskan cacat semacam itu dengan senang hati. Checksum tidak. Sebuah tinjauan eksternal bernada bermusuhan yang saya minta pada Agustus 2026 menilai urutan otoritas ini sudah benar, dalam rumusan peninjau tersebut: platform yang tidak saya kendalikan berhak membatalkan engine yang saya tulis sendiri.

Asumsi nyaman apa yang masih ada di model biaya saya?

Ada tiga, dan saya lebih suka Anda mendengarnya dari saya.

Tick engine saya saat ini memodelkan spread dan komisi opsional, sementara slippage, latency, dan swap masih nol. Di atas itu, feed emas yang saya pakai untuk riset punya spread sekitar sepuluh kali lebih rapat dibanding yang benar-benar saya lihat di akun live, kira-kira 19 poin melawan 189 poin. Catatan saya sendiri menempatkan ini sebagai celah dengan nilai kebenaran tertinggi di seluruh stack sekaligus yang paling murah untuk ditutup, dan itu kalimat yang tidak nyaman untuk sudah ditulis tetapi belum dituntaskan.

Asumsi yang nyaman itu seperti pinjaman. Pasar akan menagihnya, biasanya dengan biaya tambahan. Mengumumkan sisa tagihan itu bukan kerendahan hati, itu sekadar versi yang akurat.

Kenapa tidak menampilkan saja jendela data yang terlihat bagus?

Karena hampir semua hal punya jendela yang menang, kalau Anda mau mencarinya.

Saya punya contoh konkret di berkas saya sendiri. Satu konfigurasi Bitcoin negatif secara net pada seluruh jendela uji dan positif secara net pada potongan yang lebih baru. Kedua pernyataan itu benar. Melaporkan hanya yang kedua adalah marketing dengan spreadsheet, dan itu kebohongan paling mudah di bidang ini karena penulisnya tidak perlu menulis satu kalimat salah pun. Hal serupa berlaku untuk konfigurasi emas saya yang lebih tipis, di mana profit factor utama sekitar 1,43 hampir seluruhnya ditopang oleh satu kuartal yang sangat menguntungkan, sedangkan pada jendela pelatihannya sendiri angka itu lebih dekat ke 1,15.

Jadi periode out-of-sample terbaru yang belum tersentuh adalah satu-satunya uji adil yang saya izinkan untuk saya laporkan, dan saya melaporkannya baik ketika ia menyanjung saya maupun tidak. Kejujuran dalam backtesting ternyata sebagian besar soal angka mana yang Anda tolak untuk dipakai.

Angka mana yang paling menyakitkan untuk dibaca?

Ada dua, dan yang kedua lebih berat.

Yang pertama datang dari akun live. Satu-satunya uang sungguhan yang pernah dijalankan oleh logika utama saya adalah aliran kecil di akun prop, 62 trade dengan profit factor 0,68, yaitu di bawah titik impas dan sekaligus tidak signifikan secara statistik pada ukuran sampel itu. Rumusan jujurnya bukan sebuah persentase. Rumusan jujurnya adalah belum ada bukti live sama sekali, ke arah mana pun.

Yang kedua datang dari audit eksternal tadi. Angka robustness yang paling sering saya kutip, deflated Sharpe ratio 1,000, ternyata bersandar pada gerbang yang, pada dispersi trial yang saya catat sendiri, butuh sekitar sepuluh pangkat empat belas konfigurasi kandidat sebelum ia bisa gagal. Kalimat auditornya lebih tajam dari apa pun yang akan saya tulis sendiri: vonis itu bukan bukti, itu aritmetika. Lebih buruk lagi, uji yang benar-benar membedakan, yaitu probabilitas overfitting backtest, keluar di atas 0,5 pada delapan dari sembilan sel, dan saya membiarkan sebuah narasi menimpanya.

Tidak satu pun dari itu membuktikan edge-nya palsu. Yang terbukti adalah bukti yang saya tampilkan paling depan tidak mampu memberi tahu saya seandainya edge itu palsu.

Kenapa mempublikasikan semua ini?

Karena tidak berbohong pada diri sendiri tidak bisa dipisahkan dari tidak berbohong pada pembaca.

Merek yang hanya memposting kemenangan hanyalah mesin judi berlogo. Catatan riset di balik artikel-artikel ini saat ini berisi 137 eksperimen, 45 di antaranya ditolak langsung dan 72 berhenti sebagai riset saja, melawan 11 yang sampai ke konfigurasi terkunci. Itu kira-kira satu dari dua belas, dengan setiap kegagalan tetap tersimpan dan bisa ditelusuri, dan angka itu menggambarkan pekerjaan ini jauh lebih baik daripada kurva mana pun. Di dalamnya bahkan ada prediksi saya sendiri yang meleset dan dicatat sebagai meleset: saya menduga kurang dari 25 dari sekitar 180 parameter yang terekspos benar-benar mengubah trade mana yang terjadi, dan hasil pengukurannya adalah 49.

Saya lebih memilih lambat tetapi benar di depan publik daripada cepat tetapi salah dalam diam. Audit yang membuat saya malu hari ini adalah kredibilitas yang boleh saya belanjakan nanti.

Pertanyaan yang sering diajukan

Apa artinya kalau backtest engine dan MetaTrader 5 berbeda hasil? Artinya salah satu memodelkan sesuatu yang tidak dimodelkan yang lain, dan sampai Anda tahu yang mana, tidak ada angka yang bisa dipakai. Dalam kasus saya, perbedaannya terpusat di sisi exit dan punya arah yang jelas, bukan acak, dan itu tanda bias model, bukan noise. Platform di luar kendali saya berhak benar secara default.

Kenapa backtest engine cenderung terlalu murah hati pada exit? Karena sebuah bar atau sebuah tick bukan sebuah jalur. Kalau stop dan target berada di interval yang sama, engine harus menebak urutan sentuhannya, dan tebakan yang nyaman itu menumpuk di setiap trade yang punya bagian berjalan panjang. Keputusan entry tidak punya masalah ini, karena diambil pada harga yang benar-benar dilihat engine.

Bagaimana mencegah bug engine menyanjung hasil Anda? Dengan menjadikan sistem yang tidak Anda kendalikan sebagai wasit, dan dengan mengaitkan izin deploy pada reproduksi yang persis, bukan pada kurva yang tampak mirip. Gerbang deploy saya menuntut output per trade dari build yang dikirim cocok byte demi byte dengan run referensi. Gerbang itu pernah menangkap cacat yang menaikkan laba yang dilaporkan, persis jenis bug yang akan diloloskan oleh tinjauan manusia.

Apakah satu jendela out-of-sample yang rugi berarti strategi harus ditinggalkan? Belum tentu, tetapi itu alasan untuk berhenti mengutip jendela yang bagus. Satu konfigurasi saya negatif secara net pada periode terbaru yang belum tersentuh, sementara jendela yang lebih lama dan lebih ramah tetap ada. Jendela lama itu bertumpang tindih dengan data yang dipakai membangunnya, jadi memakainya adalah seleksi, bukan bukti.

Kenapa cherry-picking pada backtest sulit terdeteksi? Karena ia tidak butuh satu pernyataan salah pun. Setiap angka dalam laporan yang diseleksi bisa benar secara individual sementara laporannya secara keseluruhan menyesatkan, sebab ketidakjujurannya ada pada pemilihan jendela. Pertahanannya adalah menetapkan jendela pelaporan sebelum melihat hasil, bukan sesudahnya.

Bagian mana dari MasterVP yang membaca chart, dan bagian mana yang trading? Kedua bagian itu ada, dan pembagiannya penting. MasterVP Profiler adalah indikatornya, di TradingView dan di MetaTrader 5: ia menunjukkan pembacaannya kepada Anda, di mana volume benar-benar diperdagangkan dan bagaimana struktur chart terbentuk, dan keputusan order tetap ada pada Anda. Ia bukan layanan sinyal. Eksekusi berada di sisi Expert Advisor, dan itu hanya memperdagangkan aturan yang dikonfigurasi sendiri oleh pengguna.

Apakah ada track record live di balik angka-angka ini? Tidak ada, dan saya tidak akan menyiratkan sebaliknya. Setiap angka di atas adalah backtest, run konfirmasi MetaTrader 5 pada tick historis nyata, atau temuan dari audit eksternal terhadap proses saya. Satu-satunya aliran live yang saya punya berisi 62 trade dan di bawah titik impas, terlalu kecil untuk menyimpulkan apa pun. Hasil live sebaiknya diharapkan lebih tipis daripada hasil riset, karena slippage, latency, dan swap belum ada di model biaya saya.

Apa itu parity gate dalam bahasa sederhana? Itu aturan bahwa sebuah perangkat lunak harus mereproduksi run referensi yang sudah diketahui secara persis sebelum boleh mendekati uang sungguhan. Bukan kira-kira, dan bukan hanya pada metrik ringkasan, melainkan trade demi trade. Ini praktik biasa dalam rekayasa perangkat lunak, dan ini satu-satunya kebiasaan dari pekerjaan utama saya yang pindah ke riset trading tanpa perlu diubah sama sekali.


Ditulis oleh KenKem, seorang software engineer dan founder dengan dua puluh tahun pengalaman, yang sedang belajar quantitative trading secara terbuka dan mempublikasikan prosesnya, termasuk penolakan-penolakannya.

Artikel ini disusun dari post 221 sampai 230 dalam seri build-log KenKem. Hanya untuk tujuan edukasi. Bukan nasihat keuangan. Semua angka yang dikutip adalah hasil backtest, run konfirmasi, atau audit, bukan track record live. Kinerja masa lalu tidak menjamin hasil di masa depan.

← All journal articles

Chat