Proyek akhir: strategi yang bisa diperiksa
Menyusun strategi yang dapat diatur dan menelusuri sinyal, transaksi, serta hasilnya.
Proyek akhir menyatukan materi buku dalam satu file: moving average, input, kondisi, fungsi sendiri, order, dan tampilan. Tujuannya adalah program yang setiap keputusannya bisa ditelusuri kembali ke data dan aturan tertulis.
Mendeskripsikan program tanpa kode
Strategi memantau persilangan dua EMA. SMA ketiga yang lebih panjang memeriksa apakah harga penutupan berada di atas rata-rata.
Entry long memerlukan EMA cepat melintas dari bawah ke atas EMA lambat dan harga penutupan berada di atas SMA penyaring tren. Urutan tiga panjang harus cepat < lambat < tren. Jika panjang yang diberikan tidak memenuhi urutan ini, program tidak mengirim order masuk.
Posisi long menerima order penutupan pasar saat persilangan EMA ke bawah. Entry juga memiliki stop dan target dalam tick. Simulasi menggunakan jumlah tetap satu unit, komisi 0,1 persen, dan slippage dua tick.
Inilah aturan tugasnya. Kita tidak menyimpulkan bahwa program akan menguntungkan pada suatu pasar. Pemeriksaan menggunakan data demo tetap dari buku.
Program lengkap
Buat file final_strategy.py:
"""
@pyne edge
"""
from pynecore.lib import close, color, input, location, plot, plotshape, script, shape, strategy, ta
def lengths_are_ordered(fast: int, slow: int, trend: int) -> bool:
return fast < slow and slow < trend
@script.strategy(
"Filtered Crossing Strategy",
overlay=True,
initial_capital=10000,
default_qty_type=strategy.fixed,
default_qty_value=1,
pyramiding=1,
commission_type=strategy.commission.percent,
commission_value=0.1,
slippage=2,
)
def main(
fast_length: int = input.int(9, title="Fast EMA length", minval=1, maxval=200),
slow_length: int = input.int(21, title="Slow EMA length", minval=1, maxval=200),
trend_length: int = input.int(50, title="Trend SMA length", minval=1, maxval=200),
use_trend_filter: bool = input.bool(True, title="Use trend filter"),
stop_ticks: int = input.int(100, title="Stop distance (ticks)", minval=1),
target_ticks: int = input.int(200, title="Target distance (ticks)", minval=1),
):
fast_average = ta.ema(close, fast_length)
slow_average = ta.ema(close, slow_length)
trend_average = ta.sma(close, trend_length)
crosses_up = ta.crossover(fast_average, slow_average)
crosses_down = ta.crossunder(fast_average, slow_average)
valid_lengths = lengths_are_ordered(fast_length, slow_length, trend_length)
trend_passes = not use_trend_filter or close > trend_average
entry_signal = valid_lengths and crosses_up and trend_passes
if entry_signal:
strategy.entry("Long", strategy.long)
if crosses_down:
strategy.close("Long")
strategy.exit("Bracket", "Long", loss=stop_ticks, profit=target_ticks)
plot(fast_average, "Fast EMA", color=color.blue, linewidth=2)
plot(slow_average, "Slow EMA", color=color.orange, linewidth=2)
plot(trend_average, "Trend SMA", color=color.gray, linewidth=2)
plotshape(entry_signal, "Entry signal", style=shape.triangleup,
location=location.belowbar, color=color.green)Simpan dan jalankan pada data demo. Grafik menampilkan tiga rata-rata dan segitiga hijau yang menandai kondisi entry. Penanda transaksi strategi menunjukkan entry dan exit yang benar-benar dieksekusi.

Apa yang dihitung pada setiap candle?
Tiga rata-rata dan dua persilangan dihitung sebelum kondisi. Kita tetap menghitungnya meskipun penyaring akhirnya mencegah entry. Dengan begitu, status perhitungannya mengikuti seluruh rangkaian candle.
Fungsi buatan lengths_are_ordered memeriksa tiga angka dan mengembalikan nilai logika. Fungsi ini tidak memiliki status candle sendiri. valid_lengths menyimpan hasil pemeriksaan saat ini untuk ekspresi selanjutnya.
trend_passes benar jika penyaring tidak aktif atau harga penutupan berada di atas SMA. input.bool menyediakan input logika yang bisa diaktifkan dan dinonaktifkan. not use_trend_filter benar saat penyaring tidak aktif, sehingga kondisi kedua tidak diperlukan.
Saat penyaring dinonaktifkan, rata-rata tetap dihitung dan digambar. Sakelar mengubah pemeriksaan entry, bukan tampilan garis.
Hubungan panjang yang tidak valid
Batas input masing-masing hanya menentukan setiap panjang harus antara 1 dan 200. Kamu masih bisa memberikan panjang cepat 30 dan lambat 10. Ini melanggar urutan yang disyaratkan tugas.
Karena itu, fungsi pemeriksa menguji hubungan tersebut secara terpisah. Dengan urutan yang salah, garis tetap digambar tetapi entry_signal tidak bisa benar. Program tidak mulai mengirim entry dengan hubungan panjang yang bertentangan dengan tugas.
Kamu bisa memeriksanya langsung melalui variabel valid_lengths dalam debugger. Kondisi tetap salah sepanjang eksekusi jika input tersimpan tidak sesuai.
Sinyal belum tentu menghasilkan transaksi baru
Segitiga hijau menandai kondisi entry. Strategi mengirim order kepada simulator. Eksekusinya mungkin memerlukan syarat tambahan: misalnya candle berikutnya tersedia, modal cukup, dan jumlah diizinkan.
Dengan pyramiding=1, simulator belum tentu mengizinkan entry long tambahan ketika posisi long sudah terbuka. Karena itu, jangan menganggap jumlah sinyal otomatis sama dengan jumlah transaksi.
Pada awal rangkaian data, SMA lima puluh penyaring tren belum tersedia. Jika penyaring aktif, kondisi harga di atasnya belum bisa dianggap benar, sehingga entry tidak memenuhi syarat tersebut.
Memeriksa perilaku program
Mulai dengan nilai bawaan dan periksa jumlah, biaya, serta mode eksekusi pada Properties. Penggantian yang pernah disimpan bisa mengubah pengaturan dalam kode sumber.
Cari satu sinyal hijau. Gunakan debugger atau nilai pada grafik untuk memeriksa kedua EMA pada candle tersebut dan sebelumnya. Periksa persilangan rata-rata cepat dan lambat, penyaring SMA, serta hubungan panjang. Ketiganya harus benar.
Kemudian cari entry terkait dalam tabel Trades. Lihat candle dan harga eksekusinya. Untuk exit, periksa apakah persilangan, stop, atau target menjelaskan penutupan.
Mencoba kasus dengan hasil yang bisa diperkirakan
Untuk memeriksa perilaku, pilih perubahan yang hasilnya dapat diperkirakan terlebih dahulu:
| Perubahan | Yang perlu diperiksa |
|---|---|
| Panjang cepat dan lambat sama | Tidak ada sinyal entry baru karena pemeriksaan panjang |
| Penyaring tren tidak aktif | Persilangan EMA tidak memerlukan harga di atas SMA |
| Jarak stop dan target bertambah | Perubahan jarak tingkat bisa menghasilkan candle exit lain |
| Jumlah berubah | Sinyal harga tetap sama, besaran moneter transaksi bisa berbeda |
Lakukan hanya satu perubahan tersebut dalam satu pengujian. Sebelum mencoba, tuliskan perkiraanmu, lalu catat hasil sebenarnya. Jika berbeda, gunakan debugger untuk menemukan keputusan pertama yang menyimpang.
Membandingkan hasil
Saat membandingkan penyaring aktif dan tidak aktif, pertahankan data, jumlah, biaya, dan panjang yang sama. Lihat kurva ekuitas Performance bersama tabel Trades. Jumlah transaksi yang sedikit atau posisi terakhir yang masih terbuka juga memengaruhi ringkasan.
Jika menguji dengan data historis nyata, tetapkan periode pengaturan dan periode pemeriksaan terpisah sebelum melihat hasil. Jika parameter diubah setelah melihat periode pemeriksaan, periode itu juga menjadi bagian dari proses pengaturan.
Awal data input harus mencakup cukup candle pemanasan. Jika potongan periode dijalankan tersendiri, moving average dan status posisi dibangun ulang. Akibatnya, bagian awal pengujian terpisah bisa berbeda dari hasil periode yang sama di tengah rangkaian data yang lebih panjang.
Coba sendiri
Tambahkan sakelar Use crossings exit. Jika aktif, pertahankan penutupan saat persilangan turun; jika tidak aktif, hanya stop dan target yang menutup posisi. Persilangan turun tetap harus dihitung pada kedua keadaan.
Solusi latihan
Dalam daftar parameter main():
use_crossing_exit: bool = input.bool(True, title="Use crossings exit"),Cabang penutupan:
if use_crossing_exit and crosses_down:
strategy.close("Long")Pertahankan baris crosses_down = ta.crossunder(...) sebelum kondisi. Pemanggilan strategy.exit tetap ada pada kedua keadaan sakelar.
Jika penutupan persilangan dinonaktifkan, posisi bisa tetap terbuka setelah persilangan EMA turun. Sinyal entry berikutnya masih bisa muncul, sementara posisi yang sudah ada mencegah transaksi baru.
Membuat versi sendiri
Salin program dengan nama baru dan tulis satu aturan baru yang ingin ditambahkan. Jelaskan data apa dan candle mana yang digunakan untuk membuat keputusan, cara memeriksanya secara manual, dan input yang mengubahnya.
Hitung aturan baru sebagai variabel tersendiri terlebih dahulu. Gambar atau pantau dalam debugger sebelum menjadikannya kondisi masuk atau keluar. Dengan begitu, kamu bisa mencari kesalahan pada perhitungan sebelum mencoba menjelaskan hasil seluruh strategi.
Sumber kode, pengaturan tersimpan, dan data yang digunakan bersama-sama mendeskripsikan percobaanmu. Jika semuanya disimpan, pengujian dapat dibuat ulang dan diperiksa.