[TOC]
Tutorial video pendukung:https://www.youtube.com/watch?v=CA3SwJQb_1g
FMZ Quant Trading Platform mendukung penulisan strategi bahasa Pine, backtesting, dan perdagangan langsung strategi bahasa Pine, dan kompatibel dengan versi bahasa Pine yang lebih rendah.Strategy Squaredi Platform Perdagangan Kuantum FMZ (FMZ.COM).
FMZ mendukung tidak hanya bahasa Pine, tetapi juga fungsi gambar yang kuat dari bahasa Pine. Berbagai fungsi, alat yang kaya dan praktis, manajemen yang efisien dan nyaman pada platform FMZ lebih meningkatkan kepraktisan strategi Pine (script). Berdasarkan kompatibilitas dengan bahasa Pine, FMZ juga memperluas, mengoptimalkan dan mengedit bahasa Pine sampai batas tertentu. Sebelum memasuki tutorial secara resmi, mari kita lihat perubahan apa yang telah dilakukan pada bahasa Pine di FMZ dibandingkan dengan versi asli.
Gambaran singkat tentang beberapa perbedaan yang jelas:
//@version
danstrategy
, indicator
pernyataan di awal kode tidak wajib untuk menulis, FMZ tidak mendukungimport
untuk diimporlibrary
fungsi untuk saat ini.Hal ini dapat dilihat bahwa beberapa strategi yang ditulis seperti ini:
//@version=5
indicator("My Script", overlay = true)
src = close
a = ta.sma(src, 5)
b = ta.sma(src, 50)
c = ta.cross(a, b)
plot(a, color = color.blue)
plot(b, color = color.black)
plotshape(c, color = color.red)
Atau tulis seperti ini:
//@version=5
strategy("My Strategy", overlay=true)
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
strategy.entry("My Long Entry Id", strategy.long)
shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
if (shortCondition)
strategy.entry("My Short Entry Id", strategy.short)
Pada FMZ dapat disederhanakan menjadi:
src = close
a = ta.sma(src, 5)
b = ta.sma(src, 50)
c = ta.cross(a, b)
plot(a, color = color.blue, overlay=true)
plot(b, color = color.black, overlay=true)
plotshape(c, color = color.red, overlay=true)
Atau:
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
strategy.entry("My Long Entry Id", strategy.long)
shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
if (shortCondition)
strategy.entry("My Short Entry Id", strategy.short)
Model harga penutupan dan model harga real-time
Pada tampilan perdagangan, kita dapat menggunakancalc_on_every_tick
parameter daristrategy
fungsi untuk mengatur skrip strategi untuk mengeksekusi logika strategi dalam waktu nyata ketika harga berubah setiap kali.calc_on_every_tick
Parameter harus diatur ketrue
.calc_on_every_tick
parameter default adalahfalse
, yaitu, logika strategi dijalankan hanya ketika BAR garis K saat ini dari strategi sepenuhnya selesai.
Di FMZ, itu ditetapkan oleh parameter
Kontrol presisi numerik, seperti harga dan jumlah pesanan ketika strategi dieksekusi perlu ditentukan pada FMZ Pada pandangan perdagangan, tidak ada masalah akurasi saat menempatkan pesanan perdagangan nyata, karena hanya dapat diuji dalam simulasi. Pada FMZ, dimungkinkan untuk menjalankan strategi Pine dalam perdagangan nyata. Kemudian strategi perlu dapat menentukan akurasi harga dan akurasi jumlah pesanan dari varietas perdagangan secara fleksibel. Pengaturan akurasi mengontrol jumlah tempat desimal dalam data yang relevan untuk mencegah data tidak memenuhi persyaratan pesanan bursa dan dengan demikian gagal untuk menempatkan pesanan.
Kode kontrak berjangka
Jika produk perdagangan di FMZ adalah kontrak, ia memiliki dua atribut, yaitu swap
, dan kode kontrak tergantung pada apakah bursa yang beroperasi memiliki kontrak tersebut.quarter
Kode kontrak ini konsisten dengan kode kontrak berjangka yang didefinisikan dalam dokumen API bahasa Javascript/python/c++ FMZ.
Untuk pengaturan lainnya, seperti jumlah pesanan minimum, jumlah pesanan default, dll, silakan lihat pengantar parameter pada
runtime.debug
, runtime.log
, runtime.error
digunakan untuk debugging.3 fungsi telah ditambahkan ke platform FMZ untuk debugging.
runtime.debug
: Mencetak informasi variabel pada konsol, yang umumnya tidak digunakan dengan fungsi ini.
runtime.log
Fungsi khusus bahasa PINE di FMZ.
runtime.log(1, 2, 3, close, high, ...), Multiple parameters can be passed.
runtime.error
: Ini akan menghasilkan kesalahan runtime dengan pesan kesalahan yang ditentukan dalam parameter pesan ketika dipanggil.
runtime.error(message)
overlay
parameter diperpanjang dalam beberapa fungsi gambarDalam bahasa Pine di FMZ, fungsi gambarplot
, plotshape
, plotchar
, dll telah menambahkanoverlay
dukungan parameter, memungkinkan untuk menentukan gambar pada bagan utama atau sub- bagan.overlay
diatur untuktrue
untuk menggambar pada bagan utama, danfalse
diatur untuk menarik pada sub-chart, yang memungkinkan strategi Pine pada FMZ untuk menarik grafik utama dan sub-chart pada saat yang sama.
syminfo.mintick
Variabel bawaanVariabel bawaan darisyminfo.mintick
didefinisikan sebagai nilai tick minimum untuk simbol saat ini. Nilai ini dapat dikontrol oleh presisi mata uang parameter templat harga di syminfo.mintick
adalah 0,01.
Misalnya: harga pesanan adalah 8000, arah penjualan, jumlahnya adalah 1 lot (potongan, lembaran), harga rata-rata setelah transaksi tidak 8000, tetapi lebih rendah dari 8000 (biaya termasuk biaya penanganan).
Ketika mulai mempelajari dasar-dasar bahasa Pine, mungkin ada beberapa contoh instruksi dan tata bahasa kode yang tidak kita kenal. Tidak masalah jika Anda tidak mengerti, kita dapat membiasakan diri dengan konsep terlebih dahulu dan memahami tujuan tes, atau Anda dapat memeriksa dokumentasi bahasa Pine di FMZ untuk petunjuk. Kemudian ikuti tutorial langkah demi langkah untuk membiasakan diri dengan berbagai tata bahasa, instruksi, fungsi, dan variabel bawaan.
Ketika mulai belajar bahasa Pine, sangat penting untuk memahami konsep terkait seperti proses eksekusi program skrip bahasa Pine. Strategi bahasa Pine berjalan berdasarkan grafik. Dapat dipahami bahwa strategi bahasa Pine adalah serangkaian perhitungan dan operasi, yang dijalankan pada grafik dalam urutan deret waktu dari data tertua yang telah dimuat pada grafik. Jumlah data yang awalnya dimuat grafik terbatas. Dalam perdagangan nyata, jumlah maksimum data biasanya ditentukan berdasarkan volume data maksimum yang dikembalikan oleh antarmuka pertukaran, dan jumlah maksimum data selama backtesting ditentukan berdasarkan data yang disediakan oleh sumber data sistem backtesting. Bar K-line paling kiri pada grafik, yaitu set data pertama dari grafik, memiliki nilai indeks 0. Nilai indeks data K-line saat ini dapat dieksekusi ketika skrip Pine dirujuk melalui variabel indeks yang dibangun.bar_index
dalam bahasa Pine.
plot(bar_index, "bar_index")
Peraturanplot
fungsi adalah salah satu fungsi yang akan kita gunakan lebih banyak di masa depan. penggunaan sangat sederhana, adalah untuk menggambar garis pada grafik sesuai dengan parameter input, data input adalahbar_index
, dan garis ini diberi nama sebagaibar_index
Hal ini dapat dilihat bahwa nilai baris bernama bar_index pada Bar pertama adalah 0, dan meningkat dengan 1 ke kanan sebagai Bar meningkat.
Karena pengaturan strategi berbeda, metode pelaksanaan model strategi berbeda, mereka dapat dibagi menjadiclosing price model
danreal-time price model
Kami juga telah secara singkat memperkenalkan konsep mereka sebelumnya.
Model harga penutupan
Pada titik ini, logika strategi Pine dieksekusi sekali, dan sinyal perdagangan yang dipicu akan dieksekusi pada awal K-line Bar berikutnya.
Model harga real-time
Ketika kode strategi dieksekusi, terlepas dari apakah Bar K-line saat ini ditutup atau tidak, logika strategi Pine akan dieksekusi setiap kali pasar berubah, dan sinyal perdagangan yang dipicu akan dieksekusi segera.
Ketika strategi bahasa Pine dijalankan dari kiri ke kanan pada grafik, garis K Bars pada grafik dibagi menjadiHistorical Bars
danReal-time Bars
:
Historical Bar
Ketika strategi diatur ke Historical Bars
. Logika strategi dijalankan hanya sekali pada setiaphistorical bar
Aku tidak tahu.
Ketika strategi diatur ke historical bars
. Logika strategi dijalankan hanya sekali pada setiaphistorical bar
.
Perhitungan berdasarkan Bars historis: Kode strategi dieksekusi sekali dalam keadaan penutupan bilah sejarah, dan kemudian kode strategi terus dieksekusi di bilah sejarah berikutnya sampai semua bilah sejarah dieksekusi sekali.
Bar waktu nyata
Ketika strategi dijalankan ke K-line Bar terakhir di sebelah kanan, Bar adalah Bar real-time. Setelah bar real-time ditutup, bar menjadi bar real-time yang dilewati (menjadi bar historis). Bar real-time baru akan dihasilkan di sebelah kanan grafik.
Ketika strategi ditetapkan pada
Perhitungan berdasarkan waktu nyata Bar:
Jika strategi ditetapkan pada high
, low
, close
Bars bersejarah, dan nilai-nilai ini dapat berubah setiap kali pasar berubah pada Bars real-time. Oleh karena itu, data seperti indikator yang dihitung berdasarkan nilai-nilai ini juga akan berubah secara real-time.close
selalu mewakili harga terbaru saat ini, danhigh
danlow
selalu mewakili titik tertinggi dan titik terendah yang dicapai sejak awal bar real-time saat ini. Variabel bawaan ini mewakili nilai akhir Bar real-time ketika terakhir diperbarui.
Mekanisme rollback saat menjalankan strategi pada Bar real-time (model harga real-time): Selama eksekusi Bar real-time, pengaturan ulang variabel yang didefinisikan pengguna sebelum setiap iterasi baru strategi disebut rollback.
Perhatian:
/*backtest
...
..
.
*/
Isi paket adalah informasi konfigurasi backtest yang disimpan dalam bentuk kode pada platform FMZ.
/*backtest
start: 2022-06-03 09:00:00
end: 2022-06-08 15:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/
var n = 0
if not barstate.ishistory
runtime.log("before n + 1, n:", n, " current bar_index:", bar_index)
n := n + 1
runtime.log("after n + 1, n:", n, " current bar_index:", bar_index)
plot(n, title="n")
Kami hanya memeriksa adegan yang dilaksanakan selama real-time Bars, jadi kami menggunakannot barstate.ishistory
ekspresi untuk membatasi akumulasi variabel n hanya dalam real time Bar, dan menggunakanruntime.log
fungsi untuk output informasi dalam log strategi sebelum dan setelah operasi akumulasi.plot
, dapat dilihat bahwa n selalu 0 ketika strategi berjalan di Bars historis. Ketika real-time Bar dieksekusi, operasi penjumlahan 1 ke n dipicu, dan operasi penjumlahan 1 ke n dieksekusi ketika strategi dieksekusi di setiap putaran real-time Bar. Dari pesan log dapat diamati bahwa n akan disetel kembali ke nilai yang akhirnya dikirimkan oleh strategi eksekusi Bar sebelumnya ketika kode strategi dieksekusi kembali di setiap putaran. Pembaruan nilai n akan dikirimkan ketika kode strategi dieksekusi di real-time Bar untuk terakhir kalinya, sehingga Anda dapat melihat bahwa nilai kurva n meningkat sebesar 1 dengan setiap peningkatan Bar mulai dari real-time Bar pada grafik.
Ringkasan:
Karena data rollback, operasi menggambar, seperti kurva pada grafik juga dapat menyebabkan menggambar ulang.
var n = 0
if not barstate.ishistory
runtime.log("before n + 1, n:", n, " current bar_index:", bar_index)
n := open > close ? n + 1 : n
runtime.log("after n + 1, n:", n, " current bar_index:", bar_index)
plot(n, title="n")
Screenshot dari waktu A
Screenshot dari waktu B
Kami hanya memodifikasi kalimat:n := open > close ? n + 1 : n
, hanya menambahkan 1 ke n ketika Bar real-time saat ini adalah garis negatif (yaitu, harga pembukaan lebih tinggi dari harga penutupan). Dapat dilihat bahwa pada grafik pertama (waktu A), karena harga pembukaan lebih tinggi dari harga penutupan (garis negatif) pada saat itu, n diakumulasi oleh 1, dan nilai n yang ditampilkan pada kurva grafik adalah 5. Kemudian pasar berubah dan harga diperbarui seperti yang ditunjukkan pada grafik kedua (waktu B). Pada saat ini, harga pembukaan lebih rendah dari harga penutupan (garis positif), dan nilai n bergulir kembali tanpa meningkat 1. kurva n dalam grafik juga ditarik ulang segera, dan nilai n pada kurva adalah 4. Oleh karena itu, sinyal, seperti crossup dan crossdown yang ditampilkan pada bar real-time, tidak pasti dan dapat berubah.
Konten variabel dalam fungsi
Mari kita mempelajari variabel dalam fungsi bahasa Pine bersama-sama. Menurut beberapa deskripsi pada tutorial Pine, variabel dalam fungsi memiliki perbedaan berikut dari variabel di luar fungsi:
Sejarah variabel seri yang digunakan dalam fungsi Pine dibuat dengan setiap panggilan berturut-turut ke fungsi. Jika fungsi tidak dipanggil pada setiap bar di mana skrip berjalan, ini akan menghasilkan perbedaan antara nilai historis seri di dalam dan di luar blok lokal fungsi. Oleh karena itu, jika fungsi tidak dipanggil pada setiap bar, seri yang dirujuk di dalam dan di luar fungsi dengan nilai indeks yang sama tidak akan merujuk ke titik historis yang sama.
Tidak masalah, kita akan mencari tahu dengan tes kode yang berjalan di FMZ:
/*backtest
start: 2022-06-03 09:00:00
end: 2022-06-08 15:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
*/
f(a) => a[1]
f2() => close[1]
oneBarInTwo = bar_index % 2 == 0
plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")
plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")
plot(close[2], title = "close[2]", color = color.red, overlay = true)
plot(close[1], title = "close[1]", color = color.green, overlay = true)
Screenshot dari backtest berjalan
Kode pengujian relatif sederhana, terutama untuk memeriksa data yang dirujuk dengan dua metode, yaitu:f(a) => a[1]
danf2() => close[1]
.
f(a) => a[1]
: Menggunakan metode melewati parameter, fungsi kembali kea[1]
finally.
f2() => close[1]
: Gunakan variabel bawaanclose
langsung, dan fungsi kembali keclose[1]
finally.
Peraturan[]
simbol digunakan untuk merujuk pada nilai historis dari variabel seri data, dan close[1] mengacu pada data harga penutupan pada Bar sebelum harga penutupan saat ini.
plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")
Menggambar karakter f(close)
.
plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")
Menggambar karakter f2()
.
plot(close[2], title = "close[2]", color = color.red, overlay = true)
Gambar garis, warnanya merah, dan posisi yang digambar (di sumbu Y) adalah:close[2]
, yang merupakan harga penutupan bar kedua sebelum bar saat ini (menghitung 2 bar ke kiri).
plot(close[1], title = "close[1]", color = color.green, overlay = true)
Gambar garis, warnanya hijau, dan posisi yang digambar (di sumbu Y) adalah:close[1]
, yang merupakan harga penutupan bar pertama sebelum bar saat ini (menghitung 1 bar ke kiri).
Hal ini dapat dilihat dari tangkapan layar dari strategi backtesting bahwa meskipun kedua fungsif(a) => a[1]
digunakan untuk menggambar penanda A dan fungsif2() => close[1]
digunakan untuk menggambar penanda B menggunakan [1] untuk merujuk pada data historis pada seri data, posisi penanda plot(close[2], title = "close[2]", color = color.red, overlay = true)
, data yang digunakan untuk menggambar garis adalahclose[2]
.
Alasannya adalah untuk menghitung apakah untuk menarik penanda bar_index
. Penanda f(a) => a[1]
tidak akan sama dengan nilai yang dirujuk oleh fungsif2() => close[1]
jika fungsi tidak dipanggil pada setiap Bar (bahkan jika keduanya menggunakan indeks yang sama seperti [1]).
Beberapa fungsi built-in perlu dihitung pada setiap Bar untuk menghitung hasilnya dengan benar
Untuk menggambarkan situasi ini dengan contoh sederhana:
res = close > close[1] ? ta.barssince(close < close[1]) : -1
plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)
Kita menulis kode panggilan fungsita.barssince(close < close[1])
dalam operator ternarcondition ? value1 : value2
. Ini menyebabkan fungsi ta.barssince dipanggil hanya ketikaclose > close[1]
Tapi...ta.barssince
fungsi adalah untuk menghitung jumlah K-garis sejak terakhir kaliclose < close[1]
Ketika fungsi ta.barssince dipanggil, itu selalu dekat > dekat[1], yaitu, harga penutupan saat ini lebih besar dari harga penutupan Bar sebelumnya. Ketika fungsi ta.barssince dipanggil, kondisi dekat < dekat [1] tidak ditetapkan, dan tidak ada posisi baru-baru ini di mana ia memegang.
ta.barssince: Ketika dipanggil, fungsi mengembalikan na jika kondisi tidak pernah terpenuhi sebelum K-line saat ini.
Seperti yang ditunjukkan pada grafik:
Jadi ketika grafik digambar, hanya data dengan nilai untuk variabel res (-1) yang digambar.
Untuk menghindari masalah ini, kita hanya mengambilta.barssince(close < close[1])
fungsi panggilan keluar dari operator ternary dan menulisnya di luar setiap cabang bersyarat mungkin, membuatnya melakukan perhitungan pada setiap K-line Bar.
a = ta.barssince(close < close[1])
res = close > close[1] ? a : -1
plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)
Konsep deret waktu sangat penting dalam bahasa Pine, dan ini adalah konsep yang harus kita pahami ketika kita belajar bahasa Pine. deret waktu bukan tipe tetapi struktur dasar untuk menyimpan nilai kontinu variabel dari waktu ke waktu. kita tahu bahwa skrip Pine didasarkan pada grafik, dan konten paling dasar yang ditampilkan dalam grafik adalah grafik K-line. deret waktu di mana setiap nilai dikaitkan dengan timestamp dari K-line Bar.open
adalah variabel built-in (built-in) dari bahasa Pine, dan strukturnya adalah untuk menyimpan deret waktu dari harga pembukaan dari setiap K-line Bar.open
mewakili harga pembukaan dari semua K-line Bars dari Bar pertama di awal grafik K-line saat ini ke Bar di mana skrip saat ini dijalankan. Jika grafik K-line saat ini adalah periode 5 menit, ketika kita mengutip (atau menggunakan)open
dalam kode strategi Pine, itu adalah harga pembukaan K-line Bar ketika kode strategi sedang dijalankan saat ini.[]
Ketika strategi Pine dijalankan pada garis K tertentu Bar, menggunakanopen[1]
untuk merujuk pada harga pembukaan Bar K-line sebelumnya (yaitu, harga pembukaan periode K-line sebelumnya) yang merujuk padaopen
deret waktu di mana ini K-line Bar sedang dijalankan saat ini oleh skrip.
Variabel pada seri waktu sangat nyaman untuk komputasi
Mari kita ambil fungsi built-inta.cum
sebagai contoh:
ta.cum
Cumulative (total) sum of `source`. In other words it's a sum of all elements of `source`.
ta.cum(source) → series float
RETURNS
Total sum series.
ARGUMENTS
source (series int/float)
SEE ALSO
math.sum
Kode pengujian:
v1 = 1
v2 = ta.cum(v1)
plot(v1, title="v1")
plot(v2, title="v2")
plot(bar_index+1, title="bar_index")
Ada banyak fungsi built-in sepertita.cum
yang dapat memproses data pada deret waktu secara langsung.ta.cum
adalah akumulasi nilai yang sesuai dengan variabel yang diteruskan pada setiap garis K Bar, dan selanjutnya kita menggunakan grafik untuk membuatnya lebih mudah dipahami.
Proses Operasi Strategi | Variabel bawaan bar_index | v1 | v2 |
---|---|---|---|
Strategi berjalan pada garis K Bar pertama | 0 | 1 | 1 |
Strategi berjalan pada kedua K-line Bar | 1 | 1 | 2 |
Strategi berjalan pada ketiga K-line Bar | 2 | 1 | 3 |
… | … | … | … |
Strategi berjalan pada N + 1th K-line Bar | N | 1 | N+1 |
Hal ini dapat dilihat bahwa v1, v2 dan bahkan bar_index semua struktur deret waktu, dan ada data yang sesuai pada setiap bar. Apakah kode tes menggunakan
Karena variabel v1 adalah 1 pada setiap Bar, ketikata.cum(v1)
fungsi ini dijalankan pada garis K pertama Bar, hanya ada Bar pertama, sehingga hasil perhitungan adalah 1 dan ditugaskan untuk variabel v2.
Kapan?ta.cum(v1)
adalah dieksekusi pada kedua K-line Bar, sudah ada 2 K-line Bars (bar_index variabel built-in yang sesuai dengan yang pertama adalah 0, dan yang kedua yang sesuai dengan bar_index variabel built-in adalah 1), sehingga hasil perhitungan adalah 2, yang diberikan kepada variabel v2, dan sebagainya.bar_index
meningkat dari 0, makabar_index + 1
Pada grafik, kita juga bisa melihat bahwa garis-garisv2
danbar_index
benar-benar tumpang tindih.
Demikian pula, saya juga dapat menggunakanta.cum
fungsi built-in untuk menghitung jumlah harga penutupan untuk semua Bars pada grafik saat ini. semua yang perlu saya lakukan adalah menulis seperti ini:ta.cum(close)
, Ketika strategi berjalan ke real-time Bar di sebelah kanan, hasil yang dihitung olehta.cum(close)
adalah jumlah harga penutupan dari semua Bar pada grafik (jika tidak berjalan ke kanan, hanya terakumulasi sampai Bar saat ini).
Variabel pada deret waktu juga dapat dihitung menggunakan operator, seperti kode:ta.sma(high - low, 14)
, mengurangi variabel bawaanhigh
(harga tertinggi dari K-line Bar) darilow
(harga terendah dari K-line Bar), dan akhirnya menggunakanta.sma
fungsi untuk menghitung nilai rata-rata.
Hasil panggilan fungsi juga akan meninggalkan jejak nilai dalam deret waktu.
v1 = ta.highest(high, 10)[1]
v2 = ta.highest(high[1], 10)
plot(v1, title="v1", overlay=true)
plot(v2, title="v2", overlay=true)
Kode uji berjalan selama backtesting, dan dapat diamati bahwa nilai dariv1
danv2
Hasil yang dihitung oleh panggilan fungsi akan meninggalkan jejak nilai dalam deret waktu, sepertita.highest(high, 10)
dalam kodeta.highest(high, 10)[1]
. Hasil yang dihitung oleh panggilan fungsi juga dapat menggunakan [1] untuk merujuk nilai historisnya.ta.highest(high, 10)
sesuai dengan bar sebelumnya dari Bar saat ini, hasil perhitungan adalahta.highest(high[1], 10)
Jadi.ta.highest(high[1], 10)
danta.highest(high, 10)[1]
sama persis.
Gunakan fungsi gambar lain untuk output verifikasi informasi:
a = ta.highest(close, 10)[1]
b = ta.highest(close[1], 10)
plotchar(true, title="a", char=str.tostring(a), location=location.abovebar, color=color.red, overlay=true)
plotchar(true, title="b", char=str.tostring(b), location=location.belowbar, color=color.green, overlay=true)
Kita dapat melihat bahwa nilai variabel a dan variabel b dalam deret waktu ditampilkan di atas dan di bawah Bars yang sesuai. Kita dapat menyimpan kode gambar ini selama proses pembelajaran, karena kita seringkali perlu mengeluarkan informasi pada bagan untuk pengamatan selama backtesting dan eksperimen.
Pada bagian awal tutorial, kami telah meringkas beberapa perbedaan dalam menggunakan bahasa Pine pada FMZ dan Trading View.indicator()
, strategy()
, danlibrary()
Tentu saja, untuk kompatibel dengan versi sebelumnya dari skrip Pine, strategi seperti://@version=5
, indicator()
, strategy()
Beberapa pengaturan strategi juga dapat diatur dengan melewati parameter distrategy()
function.
<version>
<declaration_statement>
<code>
Peraturan<version>
informasi kontrol versi dapat dihilangkan.
Bahasa Pine menggunakan//
sebagai simbol komentar satu baris, karena bahasa Pine tidak memiliki simbol komentar multi baris. FMZ memperluas simbol komentar/**/
untuk komentar multi-baris.
Baris dalam skrip yang bukan komentar atau arahan kompilator adalah pernyataan, yang mengimplementasikan algoritma skrip.
if
, for
, while
atauswitch
strukturPernyataan dapat diatur dengan berbagai cara
space
atau ```tab` (kunci tab). karakter pertama mereka juga harus karakter pertama baris. baris yang dimulai di posisi pertama, oleh definisi, menjadi bagian dari ruang lingkup global skrip.local block
. Blok lokal harus ditarik dengan satu tab atau empat spasi (jika tidak, itu akan dianalisis sebagai kode terkonkaden dari baris sebelumnya, yaitu, dinilai sebagai konten berkelanjutan dari baris kode sebelumnya), dan setiap blok lokal mendefinisikan ruang lingkup lokal yang berbeda.Misalnya, termasuk tiga blok lokal, satu di deklarasi fungsi kustom, dan dua di deklarasi variabel menggunakan struktur if, sebagai berikut:
indicator("", "", true) // declaration statement (global scope), can be omitted
barIsUp() => // function declaration (global scope)
close > open // local block (local scope)
plotColor = if barIsUp() // variable declaration (global scope)
color.green // local block (local scope)
else
color.red // local block (local scope)
runtime.log("color", color = plotColor) // Call a built-in function to output the log (global scope)
Garis panjang dapat dibagi menjadi beberapa baris, atau dibalut. Garis yang dibalut harus diindentasi dengan sejumlah ruang, selama tidak kelipatan dari 4 (batas ini digunakan untuk mengindentasi blok lokal).
a = open + high + low + close
Hal ini dapat dibungkus sebagai (perhatikan bahwa jumlah ruang yang terindikasi per baris tidak dapat menjadi kelipatan dari 4):
a = open +
high +
low +
close
Sebuah panggilan plot panjang dapat dibungkus sebagai:
close1 = request.security(syminfo.tickerid, "D", close) // syminfo.tickerid daily level closing price data series for the current trading pair
close2 = request.security(syminfo.tickerid, "240", close) // syminfo.tickerid 240-minute level closing price data series for the current trading pair
plot(ta.correlation(close, open, 100), // line-long plot() calls can be wrapped
color = color.new(color.purple, 40),
style = plot.style_area,
trackprice = true)
Pernyataan dalam deklarasi fungsi yang didefinisikan pengguna juga dapat dibungkus. Namun, karena blok lokal harus dimulai dengan indentasi dalam tata bahasa (4 spasi atau 1 tab), ketika membaginya ke baris berikutnya, kelanjutan pernyataan harus dimulai dengan lebih dari satu indentasi (tidak sama dengan 4 kelipatan ruang).
test(c, o) =>
ret = c > o ?
(c > o+5000 ?
1 :
0):
(c < o-5000 ?
-1 :
0)
a = test(close, open)
plot(a, title="a")
Sebelum mengenali variabel, kita harus memahami konsep
(A-Z)
atau huruf kecil(a-z)
huruf atau tanda bawah(_)
sebagai karakter pertama dari penanda.Seperti penanda nama berikut:
fmzVar
_fmzVar
fmz666Var
funcName
MAX_LEN
max_len
maxLen
3barsDown // Wrong naming! It used a numeric character as the leading character of the marker
Seperti kebanyakan bahasa pemrograman, bahasa Pine juga memiliki saran menulis.
// name variables, constants
GREEN_COLOR = #4CAF50
MAX_LOOKBACK = 100
int fastLength = 7
// name functions
zeroOne(boolValue) => boolValue ? 1 : 0
Operator adalah beberapa simbol operasi yang digunakan dalam bahasa pemrograman untuk membangun ekspresi, dan ekspresi adalah aturan komputasi yang dirancang untuk tujuan komputasi tertentu ketika kita menulis strategi.
Operator penugasan, operator aritmatika, operator perbandingan, operator logis,? :
operator ternary,[]
operator referensi historis.
Mengambil operator aritmatika*
sebagai contoh, berbeda dari masalah tipe yang disebabkan oleh hasil pengembalian operator bahasa Pine di Trading View.
//@version=5
indicator("")
lenInput = input.int(14, "Length")
factor = year > 2020 ? 3 : 1
adjustedLength = lenInput * factor
ma = ta.ema(close, adjustedLength) // Compilation error!
plot(ma)
Ketika menjalankan skrip ini di Trading View, kesalahan kompilasi akan terjadi. alasannya adalah bahwa setelah mengalikanadjustedLength = lenInput * factor
, hasilnya adalahseries int
tipe (serangkaian), tetapi parameter kedua dari fungsita.ema
Tapi tidak ada pembatasan yang ketat pada FMZ, kode di atas dapat berjalan normal.
Mari kita lihat penggunaan berbagai operator bersama-sama.
Ada 2 jenis operator penugasan:=
, :=
, yang telah kita lihat dalam beberapa contoh di bagian awal tutorial.
Peraturan=
Operator digunakan untuk menetapkan nilai pada variabel ketika diinitialisasi atau dinyatakan.=
akan dimulai dengan nilai tersebut pada setiap Bar berikutnya. Ini adalah deklarasi variabel yang valid:
a = close // Use built-in variables to assign values to a
b = 10000 // Use numerical assignment
c = "test" // Use string assignment
d = color.green // Use color value assignment
plot(a, title="a")
plot(b, title="b")
plotchar(true, title="c", char=str.tostring(c), color=d, overlay=true)
Perhatikan bahwa pernyataan penugasana = close
, variabel a pada setiap Bar adalah harga penutupan saat ini (penutupan) dari Bar. Variabel lainnyab
, c
, d
tidak berubah dan dapat diuji dalam sistem backtest di FMZ, dan hasilnya dapat dilihat pada grafik.
:=
digunakan untuk menugaskan kembali nilai untuk variabel yang ada.:=
operator digunakan untuk memodifikasi nilai variabel yang telah dinyatakan dan diinitialisasi.
Jika kita menggunakan:=
operator untuk menugaskan nilai ke variabel yang tidak diinisialisasi atau dinyatakan, itu akan menyebabkan kesalahan, misalnya:
a := 0
Oleh karena itu,:=
operator penugasan umumnya digunakan untuk menetapkan kembali variabel yang ada, misalnya:
a = close > open
b = 0
if a
b := b + 1
plot(b)
Menghakimi jikaclose > open
(yaitu BAR saat ini adalah garis positif), variabel a adalah benar. Kode dalam blok lokal dari pernyataan ifb := b + 1
dilakukan, dan operator penugasan:=
Kemudian kita menggunakan fungsi plot untuk menggambar nilai variabel b pada setiap BAR dari deret waktu pada grafik, dan menghubungkannya menjadi garis.
Apakah kita berpikir bahwa ketika garis positif BAR muncul, b akan terus menumpuk dengan 1? tentu saja tidak, di sini kita menyatakan dan menginisialisasi variabel b sebagai 0 tanpa menggunakan sebutan kata kunci. kalimat inib=0
dieksekusi pada setiap BAR, jadi kita dapat melihat bahwa hasil dari kode ini adalah untuk mengatur ulang variabel b ke 0 setiap kali, jika variabel a benar, yaitu, sesuai denganclose > open
, maka b akan ditingkatkan dengan 1 ketika kode dijalankan dalam putaran ini, dan b adalah 1 ketika fungsi plot menarik, tetapi b ditugaskan kembali ke 0 ketika kode dijalankan dalam putaran berikutnya.
Ketika datang ke operator penugasan, kita harus memperluas pada dua kata kunci:var
, varip
VAR
Bahkan, kita telah melihat dan menggunakan kata kunci ini dalam tutorial sebelumnya, tetapi kita tidak membahas secara rinci pada saat itu. mari kita lihat deskripsi kata kunci ini terlebih dahulu:
var adalah kata kunci yang digunakan untuk mengalokasikan dan satu kali inisialisasi variabel. Secara umum, grammar penugasan variabel yang tidak mengandung kata kunci var menyebabkan nilai variabel akan ditimpa setiap kali data diperbarui. Sebaliknya, ketika variabel ditugaskan dengan menggunakan kata kunci var, mereka dapat
menjaga status meskipun pembaruan data.
Kita masih menggunakan contoh ini, tapi kita menggunakanvar
kata kunci ketika menetapkan nilai untuk b di sini.
a = close > open
var b = 0
if a
b := b + 1
plot(b)
Peraturanvar
kata kunci memungkinkan variabel b untuk melakukan penugasan awal saja, dan kemudian tidak akan mengatur ulang b ke 0 setiap kali logika strategi dijalankan, sehingga dapat diamati dari garis yang ditarik pada saat runtime bahwa b adalah jumlah garis positif BAR yang muncul ketika garis K saat ini BAR backtested.
Variabel yang dinyatakan oleh var dapat ditulis tidak hanya dalam ruang lingkup global, tetapi juga dalam blok kode, seperti contoh ini:
strategy(overlay=true)
var a = close
var b = 0.0
var c = 0.0
var green_bars_count = 0
if close > open
var x = close
b := x
green_bars_count := green_bars_count + 1
if green_bars_count >= 10
var y = close
c := y
plot(a, title = "a")
plot(b, title = "b")
plot(c, title = "c")
Variabel
bermacam-macam
Kita melihat kata kuncivarip
untuk pertama kalinya, kita bisa melihat deskripsi kata kunci ini:
varip (var intrabar persist) adalah kata kunci untuk penugasan dan inisialisasi variabel satu kali.
Apakah sulit dimengerti? Tidak masalah, kami menjelaskan melalui contoh, itu mudah dimengerti.
strategy(overlay=true)
// test var varip
var i = 0
varip ii = 0
// Print the i and ii changed in each round of the strategy logic on the chart
plotchar(true, title="ii", char=str.tostring(ii), location=location.abovebar, color=color.red)
plotchar(true, title="i", char=str.tostring(i), location=location.belowbar, color=color.green)
// Increment i and ii by 1 for each round of logic execution
i := i + 1
ii := ii + 1
Kode uji ini memiliki kinerja yang berbeda pada
Model Bar:
Apakah Anda ingat bahwa pelaksanaan strategi yang kami jelaskan sebelumnya dibagi menjadi tahap BAR historis dan tahap BAR real-time?i
, ii
dinyatakan dalamvar
, varip
melakukan operasi inkremental pada setiap putaran eksekusi kode strategi. Oleh karena itu dapat dilihat bahwa angka yang ditampilkan pada K-line BAR dari hasil backtest ditingkatkan 1 satu per satu. Ketika tahap K-line historis berakhir, tahap K-line real-time dimulai. Variabel yang dinyatakan oleh var dan varip mulai mengalami perubahan yang berbeda. Karena Bar Model, kode strategi akan dieksekusi sekali untuk setiap perubahan harga di K-line BAR,i := i + 1
danii := ii + 1
Perbedaannya adalah bahwa ii dimodifikasi setiap kali. Meskipun i dimodifikasi setiap kali, nilai sebelumnya akan dikembalikan ketika logika strategi dieksekusi pada putaran berikutnya (ingat mekanisme rollback yang kami jelaskan di bab sebelumnya
Tick Model: Karena Tick Model mengeksekusi logika strategi hanya sekali per K-line BAR. Jadi dalam model harga penutupan, variabel yang dinyatakan oleh var dan varip berperilaku persis sama dalam contoh di atas meningkat sebesar 1 untuk setiap K-line BAR selama tahap K-line historis dan tahap K-line real-time.
Operator | Deskripsi |
---|---|
+ | Penambahan |
- | Pengurangan |
* | Perkalian |
/ | Divisi |
% | Modulo |
Peraturan+
dan-
Operator aritmatika lainnya hanya dapat digunakan sebagai operator biner dan akan melaporkan kesalahan jika digunakan sebagai operator unary.
+
, hasil perhitungan adalah string, nilainya akan dikonversi ke bentuk string, dan kemudian string dijahit bersama-sama. Jika operator aritmatika lain, itu akan mencoba untuk mengkonversi string ke nilai dan kemudian melakukan operasi.a = 1 + 1
b = 1 + 1.1
c = 1 + "1.1"
d = "1" + "1.1"
e = 1 + na
runtime.log("a:", a, ", b:", b, ", c:", c, ", d:", d, ", e:", e)
// a: 2 , b: 2.1 , c: 11.1 , d: 11.1 , e: NaN
Bahasa Pine di FMZ sedikit berbeda dari bahasa Pine di Trading View, bahasa Pine di FMZ tidak terlalu ketat tentang jenis variabel.
a = 1 * "1.1"
b = "1" / "1.1"
c = 5 % "A"
plot(a)
plot(b)
plot(c)
Ini bekerja pada FMZ, tetapi melaporkan kesalahan tipe pada Trading View. Jika kedua operand operator aritmatika adalah string, sistem mengkonversi string ke nilai numerik dan kemudian menghitungnya. Jika string non-numerik tidak dapat dihitung, hasil operasi sistem adalah nilai nol
Operator perbandingan adalah semua operator biner.
Operator | Deskripsi |
---|---|
< | < |
> | > |
<= | <= |
>= | >= |
== | == |
!= | != |
Contoh pengujian:
a = 1 > 2
b = 1 < 2
c = "1" <= 2
d = "1" >= 2
e = 1 == 1
f = 2 != 1
g = open > close
h = na > 1
i = 1 > na
runtime.log("a:", a, ", b:", b, ", c:", c, ", d:", d, ", e:", e, ", f:", f, ", g:", g, ", h:", h, ", i:", i)
// a: false , b: true , c: true , d: false , e: true , f: true , g: false , h: false , i: false
Seperti yang bisa kita lihat, operator perbandingan sangat mudah digunakan, tapi ini juga operator yang paling banyak kita gunakan saat menulis strategi. baik nilai numerik dan built-in variabel dapat dibandingkan, seperticlose
, open
, dll.
Seperti halnya operator, ada perbedaan tentang bahasa Pine antara FMZ dan Trading View.d = "1" >= 2
tidak akan melaporkan kesalahan pada FMZ, dan akan dijalankan dengan mengkonversi string ke nilai pertama dan kemudian membandingkan operasi. pada Trading View, akan melaporkan kesalahan.
Operator | Simbol Kode | Deskripsi |
---|---|---|
Tidak | Tidak | Operator Unary, bukan operasi |
dan | dan | Operator biner, dan operasi |
atau | atau | Operator biner, atau operasi |
Ketika datang ke operator logis, maka kita harus berbicara tentang tabel nilai sejati. sama seperti yang kita pelajari di sekolah menengah, di sini kita hanya menguji dan belajar dalam sistem backtesting kita:
a = 1 == 1 // An expression formed by using comparison operators, the result is a Boolean value
b = 1 != 1
c = not b // Logical not operators
d = not a // Logical not operators
runtime.log("test the logical operator:and", "#FF0000")
runtime.log("a:", a, ", c:", c, ", a and c:", a and c)
runtime.log("a:", a, ", b:", b, ", a and b:", a and b)
runtime.log("b:", b, ", c:", c, ", b and c:", b and c)
runtime.log("d:", d, ", b:", b, ", d and b:", d and b)
runtime.log("test the logical operator:or", "#FF0000")
runtime.log("a:", a, ", c:", c, ", a or c:", a or c)
runtime.log("a:", a, ", b:", b, ", a or b:", a or b)
runtime.log("b:", b, ", c:", c, ", b or c:", b or c)
runtime.log("d:", d, ", b:", b, ", d or b:", d or b)
runtime.error("stop")
Dalam rangka untuk tidak overprint pesan, kita membuang kesalahan denganruntime.error("stop")
Setelah itu, kita dapat mengamati informasi output, dan kita dapat menemukan bahwa isi yang dicetak sebenarnya sama dengan tabel nilai sebenarnya.
Ekspresi ternar menggunakan operator ternar? :
dikombinasikan dengan operandcondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalse
Kita juga telah menggunakannya dalam pelajaran sebelumnya. yang disebut ekspresi ternar, operator ternar berarti ada tiga operand di dalamnya.
Dalamcondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalse
, condition
adalah kondisi penilaian. Jika benar, nilai dari ungkapan adalah:valueWhenConditionIsTrue
. Jikacondition
adalah false, maka nilai dari ekspresi adalahvalueWhenConditionIsFalse
.
Contoh demonstrasi yang nyaman, meskipun tidak banyak digunakan secara praktis:
a = close > open
b = a ? "positive line" : "negative line"
c = not a ? "negative line" : "positive line"
plotchar(a, location=location.abovebar, color=color.red, char=b, overlay=true)
plotchar(not a, location=location.belowbar, color=color.green, char=c, overlay=true)
Apa yang harus dilakukan jika kita menemukan doji? Tidak masalah! Ekspresi ternar juga bisa bersarang, seperti yang kita lakukan di tutorial sebelumnya.
a = close > open
b = a ? math.abs(close-open) > 30 ? "positive line" : "doji" : math.abs(close-open) > 30 ? "negative line" : "doji"
c = not a ? math.abs(close-open) > 30 ? "negative line" : "doji" : math.abs(close-open) > 30 ? "positive line" : "doji"
plotchar(a, location=location.abovebar, color=color.red, char=b, overlay=true)
plotchar(not a, location=location.belowbar, color=color.green, char=c, overlay=true)
Bahkan, hal ini setara dengan menggantikanvalueWhenConditionIsTrue
danvalueWhenConditionIsFalse
dalamcondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalse
dengan ungkapan ternar lainnya.
Gunakan operator historis[]
untuk merujuk pada nilai historis pada seri waktu. nilai historis ini adalah nilai variabel pada K-line bar sebelum K-line bar saat ini ketika skrip sedang berjalan.[]
operator digunakan setelah variabel, ekspresi, dan panggilan fungsi.[]
kurung persegi adalah offset dari data historis yang ingin kita referensi dari K-line BAR saat ini. misalnya jika saya ingin mengutip harga penutupan dari K-line BAR terakhir, kita tulis sebagai:close[1]
.
Kita telah melihat sesuatu seperti ini dalam pelajaran sebelumnya:
high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)
Peraturan[]
operator hanya dapat digunakan sekali pada nilai yang sama, jadi salah untuk menulisnya seperti ini, dan kesalahan akan dilaporkan:
a = close[1][2] // error
Di sini, seseorang mungkin mengatakan bahwa operator[]
digunakan untuk struktur seri, tampaknya bahwa struktur seri (seri) mirip dengan array!
Mari kita gunakan contoh untuk menggambarkan perbedaan antara seri dan array dalam bahasa Pine.
strategy("test", overlay=true)
a = close
b = close[1]
c = b[1]
plot(a, title="a")
plot(b, title="b")
plot(c, title="c")
a = close[1][2]
akan melaporkan kesalahan, tetapi:
b = close[1]
c = b[1]
Tapi jika ditulis secara terpisah, itu tidak akan melaporkan kesalahan. jika kita memahaminya menurut array biasa, setelah penugasan darib = close [1]
, b harus menjadi nilai, tetapic = b[1]
, b masih dapat digunakan untuk merujuk pada nilai historis lagi dengan menggunakan operator sejarah. dapat dilihat bahwa konsep seri dalam bahasa Pine tidak sesederhana array. dapat dipahami sebagai nilai historis pada bar terakhir close (ditugaskan ke b), b juga merupakan struktur seri waktu (seri waktu), dan h