Tutorial Pengenalan Bahasa PINE Kuantitatif Penemu
Tutorial video:
Apakah sulit untuk memulai trading dengan trading view? Mulai dari bahasa Pine hingga Quant - Penginapan awal bahasa Pine
Inventor Quantum Trading Platform mendukung strategi penulisan bahasa Pine, mendukung feedback, menjalankan strategi bahasa Pine secara langsung, kompatibel dengan versi bahasa Pine yang lebih rendah.Strategi PersegiAda banyak strategi Pin yang dikumpulkan dan dipindahkan.
FMZ tidak hanya mendukung bahasa Pine, tetapi juga mendukung fitur gambar yang kuat dalam bahasa Pine. Fitur-fitur yang ada di platform FMZ, alat praktis yang kaya, manajemen yang efisien dan mudah, juga meningkatkan kepraktisan strategi Pine (script). FMZ didasarkan pada kompatibilitas dengan bahasa Pine, dan pada saat yang sama melakukan beberapa perluasan, pengoptimalan, dan pemotongan pada bahasa Pine.
Perbandingan ini dapat dilihat dari beberapa perbedaan yang jelas:
-
1 . Kebijakan Pine di FMZ, kode awal versi
//@versiondimulai dengan kodestrategy、indicatorPenjelasan tidak diwajibkan, sementara FMZ tidak mendukungimportImporlibraryfungsi.Mungkin Anda melihat beberapa strategi yang ditulis seperti ini:
pine//@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 seperti ini:
pine//@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)Di FMZ, ini bisa disimpulkan sebagai:
pinesrc = 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:
pinelongCondition = 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) -
2 , Strategi (script) Beberapa pengaturan yang terkait dengan transaksi diatur oleh parameter "Pine Language Transaction Class Library" di antarmuka kebijakan FMZ.
-
Model harga close out vs model harga real time
Dalam trading view, kita bisa melihatstrategyFungsicalc_on_every_tickParameter untuk mengatur skrip kebijakan untuk melakukan logika kebijakan secara real-time setiap kali harga berubah.calc_on_every_tickParameter harus disetel ketrueSecara defaultcalc_on_every_tickParameternya adalahfalseJadi, jika kita menggunakan Kbar, maka kita akan melakukan strategi logik hanya setelah Kbar yang ada pada saat itu selesai.
Pada FMZ, pengaturan dilakukan dengan menggunakan parameter dari template "Pine Language Exchange Class Repository". -
Akurasi pengendalian nilai-nilai seperti harga, jumlah pesanan, dan lain-lain pada saat pelaksanaan strategi perlu ditentukan di FMZ
Dalam trading view karena hanya dapat melakukan tes simulasi, sehingga tidak ada masalah akurasi real-time order. Dalam FMZ adalah real-time dapat menjalankan strategi pin. Maka diperlukan strategi yang dapat fleksibel menentukan jenis perdagangan harga akurasi, pesanan jumlah akurasi. -
Kode kontrak berjangka
Varian perdagangan di FMZ jika kontrak, ada 2 sifat. "pasangan perdagangan" dan "kode kontrak". Selain perlu mengatur pasangan perdagangan secara jelas di real time dan retrospeksi, Anda juga perlu mengatur kode kontrak tertentu dalam parameter "kode varietas" dari template "Pine Language Trading Classroom". Misalnya, kontrak berlanjut diisiswap, Kode kontrak Untuk melihat apakah ada kontrak seperti itu di bursa yang dioperasikan. Sebagai contoh, semua kontrak kuartal dari beberapa transaksi dapat diisi di siniquarterKode kontrak ini sesuai dengan kode kontrak berjangka yang didefinisikan pada dokumen API bahasa Javascript/python/c++ FMZ.
Pengaturan lain seperti minimum order, default order, dan lain-lain dapat dilihat dalam dokumentasi bahasa Pine tentang"Pine Language Exchange"Pengantar parameter.
-
-
3、
runtime.debug、runtime.log、runtime.errorFungsi dari ekstensi FMZ untuk debug 。Di platform FMZ, 3 fungsi baru ditambahkan untuk debugging.
-
runtime.debug: Fungsi ini biasanya tidak digunakan untuk mencetak informasi variabel di console. -
runtime.logFungsi khusus bahasa FMZ PINE.pineruntime.log(1, 2, 3, close, high, ...),可以传多个参数。 -
runtime.error: dapat menyebabkan kesalahan saat menjalankan dan membawa pesan kesalahan yang ditentukan dalam parameter message.pineruntime.error(message)
-
-
- Bagian yang diperluas dalam fungsi diagram
overlayparameter
Fungsi gambar pada bahasa Pine di FMZ
plot、plotshape、plotcharTambah lagioverlayDukungan parameter, memungkinkan untuk menentukan gambar pada gambar utama atau gambar kecil.overlaymendirikantrueGambar di gambar utama, setel menjadifalseMenggambar pada sub-gambar. Membuat strategi Pine di FMZ dapat menggambar gambar utama dan sub-gambar secara bersamaan. - Bagian yang diperluas dalam fungsi diagram
-
5、
syminfo.mintickMengambil nilai dari variabel internalsyminfo.mintickVariabel built-in didefinisikan sebagai nilai minimal dari varietas saat ini.Penawaran Tegas/Pengujian ulangPrecision Pricing Currency adalah parameter templat di Pine Language Trading Classroom yang dapat mengontrol nilai tersebut. Precision Pricing Currency set 2 adalah harga yang tepat pada saat transaksi hingga ke angka kecil kedua, saat ini unit perubahan harga minimal adalah 0.01syminfo.mintickJadi, nilai yang akan kita dapatkan adalah 0.01 <unk>. -
Harga rata-rata dalam FMZ PINE Script adalah harga yang mencakup biaya proses
Misalnya: harga pesanan adalah 8000, penjualan arah, jumlah 1 tangan ((satu, lembar), harga rata-rata setelah transaksi tidak 8000, kurang dari 8000 ((biaya termasuk biaya proses) <unk>)
Dasar-dasar bahasa Pine
Ketika kita mulai mempelajari dasar-dasar bahasa Pine, mungkin ada beberapa contoh instruksi, kode gramatika yang tidak kita kenal. Tidak masalah jika kita tidak mengerti, kita bisa terlebih dahulu membiasakan diri dengan konsep, memahami tujuan tes, atau kita dapat melihat dokumentasi bahasa Pine di FMZ untuk melihat petunjuk.
Pelaksanaan model
Pada awal belajar bahasa Pine, sangat penting untuk memahami konsep-konsep yang terkait seperti proses eksekusi skrip bahasa Pine. Strategi bahasa Pine dijalankan berdasarkan grafik, yang dapat dipahami sebagai serangkaian perhitungan dan operasi, yang dieksekusi pada grafik dengan urutan urutan waktu terdahulu yang dimulai dari data terdahulu yang telah dimuat di grafik.bar_indexMengutip indeks Bar pada K-line saat execution skrip Pine.
pine
plot(bar_index, "bar_index")
plotFungsi adalah salah satu fungsi yang akan kita gunakan di masa depan. Fungsinya sangat sederhana, yaitu menggambar garis pada grafik berdasarkan parameter yang kita masukkan, dan data yang kita masukkan adalahbar_indexGaris ini diberi namabar_indexAnda dapat melihat bahwa bar_index pada Bar pertama adalah 0, dan Bar bertambah 1 ke kanan.
Berbeda-beda tergantung pada pengaturan kebijakan, dan kebijakan model yang berbeda cara pelaksanaan, terbagi menjadi收盘价模型Dan实时价模型│ konsep model harga close-out, model harga real-time sebelumnya kami juga telah menjelaskan secara singkat│
-
Model Harga Penutupan
Pada saat kode strategi dijalankan, siklus K Bar saat ini telah selesai, dan saat K Bar ditutup, siklus K Bar telah berakhir. Pada saat ini, logika strategi Pine dijalankan sekali lagi, dan sinyal transaksi yang dipicu akan dilakukan pada saat Bar K Bar berikutnya dimulai.
-
Model harga waktu nyata
Ketika kode strategi dijalankan, Bar K saat ini akan melakukan logika strategi Pine setiap kali terjadi perubahan, terlepas dari apakah ditutup atau tidak, dan sinyal perdagangan yang dipicu akan segera dilakukan.
Ketika strategi bahasa Pine dilakukan dari kiri ke kanan pada grafik, Bar K pada grafik dibagi menjadi历史BarDan实时BarDari:
-
Sejarah Bar
Ketika strategi yang ditetapkan sebagai "Model Harga Saham Nyata" mulai dijalankan, semua Bar K pada grafik kecuali Bar K yang berada di sebelah kanan adalah
历史BarStrategi Logika pada setiap akar历史BarHanya dilakukan sekali.
Strategi yang disetel ke "model harga closeout" dimulai saat semua Bar di grafik adalah历史BarStrategi Logika pada setiap akar历史BarHanya dilakukan sekali.Perhitungan berdasarkan sejarah Bar:
Kode kebijakan dieksekusi satu kali pada keadaan tutup Bar Sejarah, lalu kode kebijakan dieksekusi di Bar Sejarah berikutnya sampai semua Bar Sejarah dieksekusi satu kali. -
Bar waktu nyata
Bar adalah realtime ketika strategi dijalankan pada Bar K terakhir di sebelah kanan. Bar ini akan berubah menjadi realtime bar setelah realtime bar ditutup. Setelah realtime bar ditutup, bar ini akan berubah menjadi realtime bar yang telah dilalui.
Strategi yang disetel ke "model harga real-time" akan mulai dieksekusi, dan setiap perubahan di bar real-time akan dieksekusi secara logis.
Strategi yang disetel ke "model harga closeout" tidak akan menampilkan real-time Bar pada grafik saat mulai dijalankan.Berdasarkan perhitungan Bar secara real-time:
Jika strategi yang ditetapkan sebagai "model harga closeout" tidak menampilkan real-time Bar, kode kebijakan hanya akan dieksekusi sekali pada saat closeout Bar saat ini.
Jika strategi yang ditetapkan sebagai "model harga saham nyata" dihitung pada Bar real-time dan sejarah Bar benar-benar berbeda, setiap perubahan di Bar real-time akan melakukan kode strategi. Misalnya, variabel built-inhigh、low、closeDalam sejarah Bar adalah pasti, dalam real-time Bar mungkin setiap saat perubahan situasi akan terjadi perubahan nilai-nilai tersebut. Jadi berdasarkan nilai-nilai yang dihitung indikator data juga akan berubah secara real-time. Dalam real-time Barclose"Saya tidak tahu apa-apa, saya tidak tahu apa-apa, saya tidak tahu apa-apa", katanya.highDanlowSelalu mewakili titik tertinggi dan terendah yang dicapai sejak awal Bar waktu nyata saat ini. Variabel-variabel ini mewakili nilai akhir saat Bar waktu nyata terakhir diperbarui.Mekanisme rollback saat melakukan strategi di Real-Time Bar (model harga real-time):
Dalam real-time Bar, setiap kali iterasi baru dari strategi dilakukan, variabel yang didefinisikan pengguna yang telah ditetapkan sebelumnya disebut rollback. Untuk memahami mekanisme rollback dengan contoh, berikut adalah kode uji.Melihat:
/*backtest ... .. . */Paket berisi informasi konfigurasi retrospektif yang disimpan dalam bentuk kode di platform FMZ.
pine/*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("n + 1之前, n:", n, " 当前bar_index:", bar_index) n := n + 1 runtime.log("n + 1之后, n:", n, " 当前bar_index:", bar_index) plot(n, title="n")Kami hanya melihat adegan yang dilakukan di Real Time Bar, jadi kami menggunakan
not barstate.ishistoryKeterbatasan ekspresi hanya dijumlahkan pada variabel n pada saat real-time Bar, dan digunakan sebelum dan sesudah melakukan operasi agregasiruntime.logFungsi output informasi dalam log kebijakan.plotGaris n yang digarisbawahi dapat dilihat bahwa n adalah 0 selama strategi berjalan di Bar Sejarah. Saat strategi dijalankan ke Bar Waktu Nyata, operasi n ditambah 1 dipicu, dan setiap kali strategi dijalankan di Bar Waktu Nyata, operasi n ditambah 1 dilakukan. Dari informasi log, dapat dilihat bahwa setiap kali kode strategi dieksekusi ulang, n akan disetel kembali ke nilai yang akhirnya diserahkan oleh strategi Bar Waktu Nyata sebelumnya.Di sini, saya ingin menyimpulkan:
1 , Kode kebijakan akan dieksekusi setiap kali update situasi terjadi ketika kebijakan mulai dieksekusi di Real-Time Bar .
2. Saat dieksekusi di Real-Time Bar, setiap kali kode kebijakan dieksekusi, variabel akan dibalikkan.
3 , Variabel yang dieksekusi di Real-Time Bar dikirimkan sekali pada saat pembaruan closeout .Operasi gambar seperti garis kurva pada grafik juga dapat menyebabkan penggambaran ulang, karena data bergulir, misalnya kita mengubah kode tes yang baru saja kita buat, tes hard disk:
pinevar n = 0 if not barstate.ishistory runtime.log("n + 1之前, n:", n, " 当前bar_index:", bar_index) n := open > close ? n + 1 : n runtime.log("n + 1之后, n:", n, " 当前bar_index:", bar_index) plot(n, title="n")Kami hanya mengubah kalimat ini:
n := open > close ? n + 1 : n, saat ini real waktu Bar adalah negatif ((yaitu, harga buka lebih tinggi dari harga tutup) hanya untuk n terakumulasi 1 . Anda dapat melihat di gambar pertama ((saat A) karena saat itu harga buka lebih tinggi dari harga tutup ((yang negatif) sehingga n terakumulasi 1, grafik kurva n menunjukkan nilai 5 . Kemudian perubahan tren, harga update seperti yang ditunjukkan dalam gambar kedua ((saat B) menunjukkan . Saat ini harga buka lebih rendah dari harga tutup ((yang negatif), n nilai bergulir kembali dan juga tidak terakumulasi 1 . -
Konteks variabel dalam fungsi
Di bawah ini kita akan mempelajari variabel dalam fungsi bahasa Pine. Berdasarkan deskripsi pada beberapa tutorial Pine, variabel dalam fungsi dan variabel di luar fungsi memiliki perbedaan sebagai berikut:
Sejarah variabel seri yang digunakan dalam fungsi Pine dibuat dengan setiap panggilan berturut-turut pada fungsi tersebut. Jika tidak ada fungsi yang dipanggil pada setiap kolom yang dijalankan dalam skrip, ini akan menyebabkan perbedaan antara nilai sejarah dalam blok lokal fungsi dan seri eksternal. Oleh karena itu, jika tidak ada fungsi yang dipanggil pada setiap kolom, seri yang menggunakan nilai indeks yang sama yang dirujuk di dalam dan di luar fungsi tidak akan merujuk pada titik sejarah yang sama.
Tidak masalah, kita bisa mengetahuinya dengan kode tes yang dijalankan di FMZ:
pine/*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)Pemutaran rekaman
Kode tes yang lebih sederhana, terutama untuk memeriksa data yang dikutip dalam dua cara, yaitu:
f(a) => a[1]Danf2() => close[1]。-
f(a) => a[1]Fungsi yang dikembalikan pada akhir menggunakan parametera[1]。 -
f2() => close[1]: Menggunakan variabel bawaan secara langsungcloseFungsi yang dikembalikan pada akhirclose[1]。
[]Simbol digunakan untuk operasi referensi pada nilai historis dari variabel seri data, close[1] yaitu data harga tutup pada Bar sebelum harga tutup saat ini.-
plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")
Gambarkan satu karakter A <unk>, berwarna merah, jika oneBarInTwo adalah benar, dan letaknya (atas sumbu Y) adalah:f(close)Nilai yang dikembalikan -
plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")
Gambarkan satu karakter B<unk>, berwarna hijau, jika oneBarInTwo adalah benar, dan letaknya (atas sumbu Y) adalah:f2()Nilai yang dikembalikan -
plot(close[2], title = "close[2]", color = color.red, overlay = true)
Garis yang digambar berwarna merah, dan posisi yang digambar (atas sumbu Y) adalah:close[2]yaitu harga penutupan pada Bar saat ini (dibarkan ke kiri) -
plot(close[1], title = "close[1]", color = color.green, overlay = true)
Garis yang digarisbawahi berwarna hijau, digarisbawahi sebagai:close[1]yaitu harga penutupan pada Bar saat ini (di depan Bar 1 (di sebelah kiri 1 (di sebelah kiri 1))
Sketsa berjalan melalui Retrospective Strategi dapat dilihat, meskipun fungsi yang digunakan untuk menggambar A
f(a) => a[1]Dan gambar fungsi yang digunakan untuk menandai Bf2() => close[1]Semua digunakan.[1] untuk merujuk data historis pada seri data, tetapi posisi penanda "A" dan "B" pada grafik sama sekali berbeda. Posisi penanda "A" selalu berada pada garis merah, yaitu kode dalam strategiplot(close[2], title = "close[2]", color = color.red, overlay = true)Garis-garis yang digambar menggunakan data adalahclose[2]。Ini adalah karena indeksasi melalui garis bar K, yaitu variabel yang ada di dalam
bar_indexPerhitungan apakah menggambar tanda "A" dan "B". "A" dan "B" tidak digambar pada setiap Bar garis K.f(a) => a[1]Nilai yang dikutip dengan cara ini, jika fungsi tidak dipanggil di setiap Bar, akan berhubungan dengan fungsif2() => close[1]Cara ini mengacu pada nilai yang berbeda, meskipun keduanya menggunakan[1] dengan indeks yang sama). -
-
Beberapa fungsi built-in perlu dihitung pada setiap Bar untuk menghitung hasilnya dengan benar
Contoh sederhana untuk menjelaskan hal ini:
pineres = close > close[1] ? ta.barssince(close < close[1]) : -1 plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)Kita akan memanggil fungsi dengan kode.
ta.barssince(close < close[1])Tuliskan dalam operator tiga dimensicondition ? value1 : value2Hal ini menyebabkan hanyaclose > close[1]Fungsi ta.barssince. dapat diputar.ta.barssinceFungsi yang dihitung dari terakhir kaliclose < close[1]Jumlah baris K pada saat terbentuk. Apabila fungsi ta.barssince dipanggil, maka fungsi close > close[1], yaitu saat harga close lebih besar dari harga close Bar sebelumnya, saat fungsi ta.barssince dipanggil dengan kondisi close < close[1] tidak didirikan, dan tidak ada lokasi terakhir didirikan.ta.barssince: Ketika dipanggil, fungsi ini akan mengembalikan na。 jika kondisi tersebut tidak pernah terpenuhi sebelum baris K saat ini.
Seperti yang ditunjukkan pada gambar:
Jadi ketika kita menggambar, kita hanya menggambar data ketika variabel res memiliki nilai ((-1) }}.
Untuk menghindari masalah ini, kita hanya menggunakan
ta.barssince(close < close[1])Panggilan fungsi diambil dari operator trivial dan ditulis di luar setiap cabang kondisional yang mungkin. Hal ini membuatnya melakukan perhitungan pada setiap Bar baris K.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)
Urutan waktu
Konsep urutan waktu sangat penting dalam bahasa Pine, dan merupakan konsep yang harus kita pahami saat kita belajar bahasa Pine. Karena urutan waktu bukanlah sebuah tipe melainkan sebuah struktur dasar untuk menyimpan nilai-nilai berurutan dari variabel-variabel yang terjadi dari waktu ke waktu, kita tahu bahwa skrip Pine didasarkan pada grafik, dan yang paling mendasar yang ditampilkan dalam grafik adalah grafik garis K.openadalah sebuah variabel built-in dari bahasa Pine yang terstruktur sebagai sebuah urutan waktu untuk menyimpan harga setiap K-line Bar yang dibuka.openStruktur urutan waktu ini mewakili harga mulai dari Bar pertama dari garis K saat ini hingga Bar yang dieksekusi oleh skrip saat ini. Jika garis K saat ini adalah periode 5 menit, maka kita akan menggunakan referensi dalam kode kebijakan Pine (atau)openJika Anda ingin menggunakan nilai sejarah dalam urutan waktu, Anda harus menggunakan nilai awal dari K-bar pada saat Anda menggunakan kode strategi.[]Operator <unk> digunakan ketika kebijakan Pine dieksekusi pada Bar baris K.open[1]Menampilkan referensiopenPada urutan waktu, harga pembukaan dari Bar K baris sebelumnya yang dieksekusi oleh skrip saat ini (yaitu, harga pembukaan dari siklus K baris sebelumnya).
-
Variabel dalam urutan waktu sangat mudah untuk dihitung
Kita menggunakan fungsi bawaan.ta.cumMisalnya: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.sumKode uji:
pinev1 = 1 v2 = ta.cum(v1) plot(v1, title="v1") plot(v2, title="v2") plot(bar_index+1, title="bar_index")Ada banyak hal yang sama.
ta.cumFungsi built-in seperti ini dapat langsung menangani data pada urutan waktu, misalnyata.cumIni adalah penjumlahan dari variabel yang masuk ke nilai yang sesuai pada setiap Bar K, dan kemudian kita menggunakan grafik untuk memudahkan pemahaman.Bar_index adalah variabel yang ada di dalam bar_index v1 dan v2
| - | - | - | - |
Strategi berjalan pada akar pertama K-bar 0 dan 1 dan 1.
Strategi berjalan pada garis K-bar kedua.
Strategi berjalan pada akar ketiga K-bar.
|...|...|...|...|
Strategi berjalan pada N + 1 akar K Bar dan N = 1 dan N + 1 danAnda dapat melihat bahwa v1, v2 dan bahkan bar_index adalah struktur berurutan waktu, dengan data yang sesuai pada setiap Bar. Kode tes ini tidak menggunakan "model harga real-time" atau "model harga closeout" yang berbeda hanya untuk menunjukkan Bar real-time pada grafik. Untuk mengukur kecepatan, kami menggunakan "model harga closeout" untuk menguji kembali.
Karena variabel v1 adalah 1 pada setiap bar.
ta.cum(v1)Karena hanya ada Bar pertama pada baris K pertama, fungsi tersebut dihitung sebagai 1, dan diberikan nilai pada variabel v2 <unk>.
Ketikata.cum(v1)Pada saat dilakukan pada Bar K baris kedua, sudah ada 2 Bar K baris ((bar_index dari variabel bawaan pertama adalah 0, bar_index dari variabel bawaan kedua adalah 1), sehingga hasil perhitungan adalah 2, memberikan nilai pada variabel v2, dan seterusnya. Sebenarnya dapat diamati bahwa v2 adalah jumlah Bar baris K dalam grafik, karena indeks baris Kbar_indexJika kita mulai dari nol, maka kita akan mendapatkanbar_index + 1Ini adalah jumlah garis Bar. Anda juga dapat melihat garis pada grafik.v2Danbar_indexIni adalah pertemuan.Saya juga bisa menggunakan
ta.cumFungsi built-in menghitung jumlah harga close out dari semua Bar pada grafik saat ini, dan hanya bisa ditulis sebagai:ta.cum(close), ketika strategi berjalan ke Bar Waktu Nyata di sebelah kananta.cum(close)Hasil yang dihitung adalah jumlah dari semua Bar yang ada di grafik (jika tidak dioperasikan ke sisi kanan, hanya ditambahkan ke Bar saat ini).Variabel pada urutan waktu juga dapat dihitung menggunakan operator, seperti kode:
ta.sma(high - low, 14)Mengubah variabel internalhigh(K garis Bar harga tertinggi) dikurangilow(K Line Bar Minimum Harga), penggunaan terakhirta.smaFungsi mencari nilai rata-rata. -
Hasil panggilan fungsi juga akan meninggalkan jejak nilai dalam urutan 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 tes ini dapat diamati saat tes berjalan pada pengukuran ulang.
v1Danv2Jika nilai dari suatu fungsi adalah sama, maka garis yang digambar pada grafiknya juga benar-benar bertepatan. Hasil dari perhitungan panggilan fungsi akan meninggalkan jejak nilai dalam urutan waktu, seperti kodeta.highest(high, 10)[1]Di antaranya adalahta.highest(high, 10)Hasil yang dihitung dari panggilan fungsi juga dapat digunakan[1] untuk mengutip nilai historisnya.ta.highest(high, 10)Hasilnya adalahta.highest(high[1], 10)Karena itu.ta.highest(high[1], 10)Danta.highest(high, 10)[1]Harga yang sama.Validasi informasi output menggunakan fungsi diagram yang berbeda:
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)Anda dapat melihat nilai variabel a dan variabel b dalam urutan waktu yang ditampilkan di atas dan di bawah Bar yang sesuai. Anda dapat menyimpan kode gambar ini dalam proses pembelajaran, karena mungkin sering perlu untuk mengekspor informasi pada grafik untuk pengamatan saat pengujian.
Struktur naskah
Struktur umum
Pada bagian awal tutorial, kami telah menguraikan beberapa perbedaan antara penggunaan bahasa Pine di FMZ dan bahasa Pine di Trading View.indicator()、strategy()Dan, sementara tidak mendukunglibrary()Tentu saja, untuk kompatibilitas dengan versi sebelumnya dari Pine script, strategi ditulis seperti://@version=5,indicator(),strategy()Anda juga bisa. Beberapa pengaturan kebijakan juga bisa dilakukan distrategy()Pengaturan parameter dalam fungsi.
<version>
<declaration_statement>
<code>
<version>Informasi kontrol versi dapat dihapus.
Catatan
Penggunaan bahasa Pine//Sebagai komentar satu baris, karena bahasa Pine tidak memiliki komentar multi baris./**/Untuk multi baris komentar.
Kode
Sebuah skrip tidak memiliki komentar atau perintah compiler, melainkan kalimat, yang mengimplementasikan algoritma skrip. Sebuah kalimat dapat menjadi salah satu dari hal-hal tersebut.
- Deklarasi Variabel
- Reassignment dari variabel
- Deklarasi Fungsi
- Pemanggilan fungsi built-in, pemanggilan fungsi yang didefinisikan pengguna
if,for,whileatauswitchStruktur lainnya
Pernyataan dapat disusun dengan berbagai cara
- Beberapa pernyataan dapat dituliskan dalam satu baris, seperti kebanyakan deklarasi variabel, yang hanya berisi satu baris panggilan fungsi atau deklarasi fungsi baris tunggal. Yang lain, seperti struktur, selalu membutuhkan lebih dari satu baris karena mereka membutuhkan satu blok lokal.
- Pernyataan dalam ruang lingkup global skrip (yaitu bagian yang tidak termasuk dalam blok lokal) tidak dapat dianggap sebagai
空格atau制表符(Tab) dimulai。 Karakter pertama mereka juga harus menjadi karakter pertama dari baris tersebut。 Baris yang dimulai pada posisi pertama dari baris, menurut definisi menjadi bagian dari ruang lingkup global dari skrip。 - Struktur atau deklarasi fungsi multi-baris selalu membutuhkan
local block。 Sebuah blok lokal harus disinkronkan ke dalam satu tanda baca atau empat ruang kosong (jika tidak, akan diuraikan ke dalam baris kode serialisasi sebelumnya, yang akan dianggap sebagai konten lanjutan dari baris kode sebelumnya), dan masing-masing blok lokal mendefinisikan sebuah ruang lingkup lokal yang berbeda。 - Beberapa kalimat tunggal dapat diurutkan dalam satu baris dengan menggunakan tanda koma ((,) sebagai pemisah.
- Satu baris bisa berisi komentar, atau hanya komentar.
- Baris juga bisa dibungkus (berlanjut pada beberapa baris) <unk>
Misalnya, termasuk tiga blok lokal, satu dalam deklarasi fungsi khusus dan dua menggunakan struktur if dalam deklarasi variabel, dengan kode sebagai berikut:
pine
indicator("", "", true) // 声明语句(全局范围),可以省略不写
barIsUp() => // 函数声明(全局范围)
close > open // 本地块(本地范围)
plotColor = if barIsUp() // 变量声明 (全局范围)
color.green // 本地块 (本地范围)
else
color.red // 本地块 (本地范围)
runtime.log("color", color = plotColor) // 调用一个内置函数输出日志 (全局范围)
Kode ganti baris
Baris panjang dapat dibagi dalam beberapa baris, atau "dibungkus". Baris yang dibungkus harus menyusut ke dalam jumlah ruang kosong, asalkan bukan kelipatan 4.
pine
a = open + high + low + close
Dapat dikemas dalam (perhatikan bahwa jumlah spasi yang dikurangi per baris bukanlah kelipatan dari 4):
pine
a = open +
high +
low +
close
Sebuah panggilan plot ((() yang panjang dapat dikemas menjadi。
pine
close1 = request.security(syminfo.tickerid, "D", close) // syminfo.tickerid 当前交易对的日线级别收盘价数据系列
close2 = request.security(syminfo.tickerid, "240", close) // syminfo.tickerid 当前交易对的240分钟级别收盘价数据系列
plot(ta.correlation(close, open, 100), // 一行长的plot()调用可以被包装
color = color.new(color.purple, 40),
style = plot.style_area,
trackprice = true)
Pernyataan dalam deklarasi fungsi yang didefinisikan pengguna juga dapat dikemas. Namun, karena blok lokal secara gramatikal harus dimulai dengan tanda kurung (((4 spasi atau 1 tanda kerja), ketika membagi-bagi ke baris berikutnya, bagian lanjutan dari pernyataan harus dimulai dengan satu atau lebih tanda kurung (((tidak sama dengan kelipatan 4 spasi) <unk>. Misalnya:
pine
test(c, o) =>
ret = c > o ?
(c > o+5000 ?
1 :
0):
(c < o-5000 ?
-1 :
0)
a = test(close, open)
plot(a, title="a")
Identifier dan operator
Identifikasi
Sebelum kita memahami variabel, kita harus memahami konsep dari tanda pengenal tanda baca.fungsiDanvariabelNama yang digunakan untuk menamai variabel, fungsi.fungsiDalam tutorial selanjutnya, kita akan belajar tentang pengidentifikasi lembu, yaitu <unk>▽.
-
- Identifikator harus ditulis dengan huruf kapital
(A-Z)atau huruf kecil(a-z)Huruf atau garis bawah(_)Awal, sebagai karakter pertama dari pengidentifikasi.
- Identifikator harus ditulis dengan huruf kapital
-
- Karakter berikutnya setelah karakter pertama identifier dapatAksara、Garis bawahatauAngka。
-
- Nama identifier ditulis dengan huruf besar dan kecil.
Sebagai contoh, identifier dengan nama-nama berikut:
pine
fmzVar
_fmzVar
fmz666Var
funcName
MAX_LEN
max_len
maxLen
3barsDown // 错误的命名!使用了数字字符作为标识符的开头字符
Seperti kebanyakan bahasa pemrograman lainnya, bahasa Pine juga memiliki rekomendasi penulisan.
-
- Semua huruf besar digunakan untuk menamai konstanta.
-
- GunakanAturan HumpbackNama yang digunakan untuk identifier lainnya.
pine
// 命名变量、常量
GREEN_COLOR = #4CAF50
MAX_LOOKBACK = 100
int fastLength = 7
// 命名函数
zeroOne(boolValue) => boolValue ? 1 : 0
Operator
Operator adalah beberapa simbol operator dalam bahasa pemrograman yang digunakan untuk membangun ekspresi, dan ekspresi adalah aturan perhitungan yang dirancang untuk tujuan perhitungan tertentu ketika kita menulis strategi. Operator dalam bahasa Pine diklasifikasikan berdasarkan fungsi sebagai:
Operator penentuan nilai, operator hitung, operator perbandingan, operator logika,? : Operator Triangular[]Operator referensi sejarah <unk>
Operator Aritmatika*Sebagai contoh, untuk membedakan jenis masalah yang disebabkan oleh pengembalian hasil operator bahasa Pine di Trading View, ada kode tes berikut:
pine
//@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)
Jika Anda ingin mengkompilasi skrip ini di Trading View, Anda dapat mengkompilasinya dengan kesalahan karena:adjustedLength = lenInput * factorSetelah kita perkalian hasilnya adalahseries intJenis (seri), namunta.emaParameter kedua dari fungsi tidak mendukung jenis ini. Namun, tidak ada batasan ketat seperti itu pada FMZ, kode di atas dapat berjalan dengan baik.
Di bawah ini kita akan melihat berbagai operator yang digunakan.
Operator Assignment
Ada dua jenis operator penugasan:=、:=Kami juga melihat beberapa contoh di bagian awal tutorial.
=Operator digunakan untuk menginisialisasi atau mendeklarasikan variabel.=Variabel yang diberikan setelah inisialisasi, deklarasi, dan penugasan akan dimulai dengan nilai tersebut pada setiap Bar berikutnya. Ini adalah deklarasi variabel yang valid:
a = close // 使用内置变量赋值给a
b = 10000 // 使用数值赋值
c = "test" // 使用字符串赋值
d = color.green // 使用颜色值赋值
plot(a, title="a")
plot(b, title="b")
plotchar(true, title="c", char=str.tostring(c), color=d, overlay=true)
Melihata = closeAssignment statement, di mana variabel a pada setiap Bar adalah harga penutupan Bar saat ini.b、c、dadalah tidak berubah, dapat diuji dalam sistem umpan balik pada FMZ, hasil dapat dilihat dari gambar.
:=digunakan untuk memberikan nilai baru pada variabel yang sudah ada, dapat dipahami sebagai penggunaan:=Operator digunakan untuk memodifikasi nilai variabel yang telah dinyatakan dan diinisialisasi.
Jika digunakan:=Operator memberi nilai pada variabel yang tidak diinisialisasi atau dinyatakan dapat menyebabkan kesalahan, seperti:
pine
a := 0
Jadi,:=Operator penugasan biasanya digunakan untuk penugasan ulang variabel yang sudah ada, misalnya:
pine
a = close > open
b = 0
if a
b := b + 1
plot(b)
Pertimbangan jikaclose > open(yaitu BAR saat ini adalah garis bujur), variabel a adalah nilai riil ((true)) ≠ akan melaksanakan kode dalam blok lokal dari pernyataan ifb := b + 1, menggunakan operator penugasan:=Berikan nilai baru untuk b, tambahkan 1 ≠ 1 dan kemudian gunakan fungsi plot untuk menggambar nilai variabel b pada setiap BAR dalam urutan waktu, dan menghubungkannya menjadi garis ≠ 1.
Apakah kita berpikir bahwa jika ada garis bujur BAR, b akan terus bertambah 1? Tentu tidak, di sini kita tidak menggunakan kata kunci apa pun untuk menyatakan variabel b, dan menginisialisasi menjadi 0.b=0Jadi kita bisa melihat bahwa hasil dari kode ini adalah setiap kali b di set ulang menjadi 0 jika a adalah benar maka akan sesuai denganclose > openJadi, pada saat menjalankan kode pada putaran ini, b akan bertambah 1, pada saat fungsi plot digambar, b adalah 1, tetapi pada saat menjalankan kode pada putaran berikutnya, b akan diberi nilai kembali menjadi 0.
Ada dua kata kunci yang perlu diperluas untuk operator asumsi:var、varip
-
var
Sebenarnya, kata kunci ini sudah kita lihat dan gunakan di tutorial sebelumnya, tapi tidak dibahas secara rinci.
var adalah kata kunci yang digunakan untuk mengalokasikan dan menginisialisasi variabel satu kali. Biasanya, sintaks pemberian nilai variabel tanpa kata kunci var akan menyebabkan nilai variabel ditutupi setiap kali data diperbarui. Sebaliknya, ketika menggunakan kata kunci var untuk mengalokasikan variabel, mereka dapat tetap berada di status yang sama meskipun data diperbarui
Kita masih menggunakan contoh ini, hanya saja ketika kita memberi nilai pada b
varKata Kunci:pinea = close > open var b = 0 if a b := b + 1 plot(b)varKata kunci membuat variabel b hanya melakukan penugasan pertama awalnya, setelah itu setiap kali menjalankan logika kebijakan tidak akan mengatur ulang b menjadi 0, sehingga garis yang digambar dari saat berjalan dapat diamati b yaitu jumlah garis yang muncul pada BAR saat garis K BAR saat ini.Variabel dalam deklarasi var tidak hanya dapat ditulis secara global, tetapi juga dapat ditulis dalam blok kode, seperti contoh ini:
pinestrategy(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 'a' mempertahankan harga penutupan dari pilar pertama dalam seri.
Variabel 'b' mempertahankan harga penutupan dari batang harga pertama dalam seri.
Variabel 'c' mempertahankan harga penutupan dari seri ke-10 dari kentang hijau. -
varip
varipIni adalah kata kunci yang pertama kali kita lihat, dan kita dapat melihat deskripsi kata kunci ini:varip ((var intrabar persist) adalah kata kunci yang digunakan untuk mengalokasikan dan menginisialisasi variabel satu kali. Kata kunci ini mirip dengan kata kunci var, tetapi variabel yang menggunakan deklarasi varip mempertahankan nilainya antara pembaruan K-line secara real-time.
Apakah lebih sulit untuk dimengerti? tidak apa-apa, kita akan menjelaskan dengan contoh, mudah untuk dimengerti.
strategy(overlay=true) // 测试 var varip var i = 0 varip ii = 0 // 将策略逻辑每轮改变的i、ii打印在图上 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) // 每轮逻辑执行都给i、ii递增1 i := i + 1 ii := ii + 1Kode tes ini bekerja secara berbeda pada model harga close out dan model harga real time:
Model harga real-time:
Ingatkah Anda bahwa strategi yang telah kami jelaskan sebelumnya dibagi menjadi periode BAR historis dan periode BAR real-time?var、varipVariabel yang dinyatakani、iiPada setiap putaran kode strategi, operasi incremental dilakukan. Jadi, dapat dilihat bahwa angka yang ditampilkan pada garis KBAR dari hasil pengukuran kembali masing-masing meningkat 1. Ketika tahap K baris sejarah berakhir, tahap K baris real-time dimulai.i := i + 1Danii := ii + 1Semua akan dieksekusi sekali. Perbedaannya adalah bahwa ii akan diubah setiap kali. Meskipun i juga diubah setiap kali, tetapi pada saat menjalankan strategi logis pada putaran berikutnya, nilai sebelumnya akan dikembalikan (ingat mekanisme pemutaran kembali yang kami jelaskan pada bab "Pelaksanaan Model" sebelumnya?), sampai saat ini KBAR berjalan selesai untuk memperbarui nilai yang ditentukan i (yaitu, pada saat menjalankan strategi logis pada putaran berikutnya, nilai sebelumnya tidak akan dikembalikan lagi).Model harga penutupan:
Karena model harga closeout hanya melakukan satu logika strategi setiap kali K line BAR selesai. Jadi dalam model harga closeout, fase K line historis dan fase K line real-time, variabel deklarasi var, varip berkinerja sama dalam contoh di atas, adalah setiap K line BAR berkinerja 1 .
Operator Aritmatika
| Operator | menjelaskan |
|---|---|
| + | Penambahan |
| - | Pengurangan |
| * | Perkalian |
| / | Penghapusan |
| % | Mencari Contoh |
+、-Operator dapat digunakan sebagai operator biner atau sebagai operator satuan. Operator aritmatika lainnya hanya dapat digunakan sebagai operator biner, jika digunakan sebagai operator satuan akan menimbulkan kesalahan.
- Operator aritmatika adalah kedua sisi dari tipe nilai numerik, hasilnya adalah tipe nilai numerik, integer atau floating point.
- Jika salah satu dari operandnya adalah string, maka operatornya adalah
+, hasilnya adalah string, nilai akan dikonversi ke dalam bentuk string, dan kemudian string akan disalin bersama-sama. Jika operator aritmatika lainnya, akan mencoba untuk mengubah string menjadi nilai, dan kemudian operasi. - Jika ada operasi na, maka hasil penghitungan adalah nilai nol na, yang akan ditampilkan pada saat mencetak pada FMZ NaN。
pine
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 dengan bahasa Pine di Trading View. Bahasa Pine di FMZ tidak terlalu keras dan ketat dalam hal persyaratan tipe variabel. Misalnya:
pine
a = 1 * "1.1"
b = "1" / "1.1"
c = 5 % "A"
plot(a)
plot(b)
plot(c)
Dalam FMZ dapat dijalankan, tetapi dalam trading view akan melaporkan kesalahan tipe. Untuk operator hitung kedua sisi operasi adalah string, sistem akan mengubah string menjadi nilai numerik dan kemudian menghitung. Jika string non-nilai tidak dapat dihitung, sistem operasi akan menghasilkan nilai kosong na.
Operator perbandingan
Operator perbandingan adalah operator biner.
| Operator | menjelaskan |
|---|---|
| < | Kurang dari |
| > | Lebih dari |
| <= | Kurang dari sama dengan |
| >= | Lebih besar dari sama dengan |
| == | Persamaan |
| != | Ketidakadilan |
Contoh pengujian:
pine
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 Anda lihat, operator perbandingan sangat mudah digunakan, tetapi ini adalah operator yang paling sering kita gunakan ketika kita menulis kebijakan. Anda dapat membandingkan nilai dan juga membandingkan variabel yang ada di dalamnya, seperticlose、openTunggu.
Seperti operator operasi, pada FMZ berbeda dengan Pin dari Trading View, FMZ tidak memiliki tipe persyaratan yang sangat ketat, jadi pernyataan seperti itud = "1" >= 2 Pada FMZ tidak akan ada kesalahan, string akan dikonversi menjadi nilai numerik dan kemudian dihitung. Pada Trading View akan ada kesalahan.
Operator logis
| Operator | Kode simbol | menjelaskan |
|---|---|---|
| Tidak | not | Operator unit, non-operator |
| Dan | and | Operator biner, dengan (dan) operasi |
| atau | or | Operator biner, atau operasi |
Berbicara tentang operator logis, maka kita harus berbicara tentang tabel nilai sebenarnya. Seperti yang kita pelajari di sekolah tinggi, hanya saja di sini kita menguji dan belajar dari sistem feedback:
pine
a = 1 == 1 // 使用比较运算符构成的表达式,结果为布尔值
b = 1 != 1
c = not b // 逻辑非操作符
d = not a // 逻辑非操作符
runtime.log("测试逻辑操作符: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("测试逻辑操作符: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")
Untuk menghindari dampak dari sistem yang terus menerus mencetak informasi, kami menggunakanruntime.error("stop")Pernyataan setelah melakukan pencetakan sekali lagi, maka akan ada kesalahan yang luar biasa sehingga pengetesan berhenti, setelah itu kita bisa melihat informasi yang keluar, kita dapat menemukan bahwa isi pencetakan dan tabel nilai sebenarnya sama.
Operator tiga dimensi
Menggunakan operator tiga dimensi? : Ekspresi trigonometri dengan kombinasi operasicondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseKita sudah membiasakannya di pelajaran sebelumnya. Ekspresi tiga dimensi, operator tiga dimensi berarti jumlah operasinya adalah tiga.
condition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseDi dalamconditionKondisi penilaian adalah jika nilai dari ungkapan yang benar adalah:valueWhenConditionIsTrueJikaconditionEkspresinya adalahvalueWhenConditionIsFalse。
Meskipun tidak banyak digunakan secara praktis, berikut adalah beberapa contoh yang mudah untuk didemonstrasikan:
pine
a = close > open
b = a ? "阳线" : "阴线"
c = not a ? "阴线" : "阳线"
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)
Jika Anda menemukan tanda silang, tidak masalah! Ekspresi trigonometrik juga dapat disematkan, seperti yang telah kita lakukan di tutorial sebelumnya.
pine
a = close > open
b = a ? math.abs(close-open) > 30 ? "阳线" : "十字星" : math.abs(close-open) > 30 ? "阴线" : "十字星"
c = not a ? math.abs(close-open) > 30 ? "阴线" : "十字星" : math.abs(close-open) > 30 ? "阳线" : "十字星"
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)
Ini sama saja dengancondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseDi dalamvalueWhenConditionIsTrue、valueWhenConditionIsFalse, juga menggunakan ekspresi trinitas lainnya sebagai gantinya.
Operator Sejarah
Menggunakan operator historis[]Referensi sejarah pada urutan waktu. Nilai sejarah adalah nilai pada baris K BAR sebelum baris K BAR saat skrip berjalan.[]Operator digunakan setelah variabel, ekspresi, dan fungsi dipanggil.[]Nilai dalam kurung persegi ini adalah jarak dari data historis yang ingin kita kutip dari garis BAR K saat ini. Sebagai contoh, jika saya ingin kutip harga penutupan garis BAR K sebelumnya, saya akan menuliskan sebagai:close[1]。
Kami telah melihat tulisan seperti ini di kursus sebelumnya:
pine
high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)
[]Operator hanya dapat digunakan sekali pada nilai yang sama, sehingga ditulis dengan cara ini adalah salah, akan melakukan kesalahan:
pine
a = close[1][2] // 错误
Anda mungkin melihat di sini, beberapa siswa akan mengatakan bahwa operator[]Ini adalah untuk struktur seri, yang tampaknya mirip dengan struktur seri (series) dan array!
Di bawah ini kita akan menggunakan sebuah contoh untuk menjelaskan bahwa seri dalam bahasa Pine tidak berbeda dengan array.
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")
Meskipun mengatakana = close[1][2]Saya tidak tahu apa yang harus saya lakukan, tapi saya akan menuliskannya di sini.
pine
b = close[1]
c = b[1]
Jika Anda menulisnya secara terpisah, Anda tidak akan salah, jika Anda memahaminya dalam bentuk array yang biasa.b = close[1]Setelah diberi nilai, b seharusnya menjadi nilai numerik, namunc = b[1], b masih dapat digunakan lagi dengan operator sejarah referensi nilai sejarah. terlihat bahwa dalam bahasa Pine konsep seri tidak semudah sebuah array. dapat dipahami sebagai nilai sejarah pada Bar yang lebih dekat (diasumsikan untuk b), b juga merupakan struktur urutan waktu (time series), dapat terus referensi nilai sejarahnya. Jadi kita melihat di tiga garis a, b, c yang digambar, b lebih lambat dari garis a satu BAR, garis b lebih lambat dari garis b satu BAR.
Kita bisa menarik grafik ke kiri, dan melihat bahwa pada baris pertama K, nilai b dan c adalah nilai nol ((na) <unk>). Itu karena ketika skrip dijalankan pada baris pertama K BAR, sejarah yang merujuk satu atau dua periode ke depan tidak ada, tidak ada. Jadi kita perlu sering memperhatikan ketika menulis kebijakan, apakah referensi sejarah data akan merujuk ke nilai nol, jika tidak hati-hati menggunakan nilai nol dapat menyebabkan serangkaian perbedaan perhitungan, bahkan dapat mempengaruhi waktu nyata.na、nzFungsi built-in untuk menilainz、naFungsi, ingat di bab apa?) yang secara khusus menangani nilai kosong, misalnya:
pine
close > nz(close[1], open) // 当引用close内置变量前一个BAR的历史值时,如果不存在,则使用open内置变量
Ini adalah pengolahan yang mungkin mengacu pada nilai nol ((na)).
Prioritas Operator
Kita telah mempelajari banyak operator dalam bahasa Pine yang membentuk ekspresi melalui berbagai kombinasi dari bilangan dan operasi. Jadi bagaimana prioritasnya ketika menghitung dalam ekspresi? Seperti halnya operasi empat baris yang kita pelajari di sekolah, ada perkalian dan pengurangan yang diutamakan, kemudian penjumlahan dan pengurangan.
| Prioritas | Operator |
|---|---|
| 9 | [] |
| 8 | Operator satuan + 、 - dan ```not `` |
| 7 | *、/、% |
| 6 | Operator biner +、 - |
| 5 | >、<、>=、<= |
| 4 | ==、!= |
| 3 | and |
| 2 | or |
| 1 | ?: |
Operasi dilakukan pada bagian ekspresi yang memiliki prioritas tinggi terlebih dahulu, dan jika prioritasnya sama, operasi dilakukan dari kiri ke kanan. Jika Anda ingin memaksakan operasi pada bagian tertentu terlebih dahulu, Anda dapat menggunakan()Membungkus ungkapan bagian yang harus dioperasikan terlebih dahulu.
variabel
Deklarasi Variabel
Kita sudah mempelajari konsep dari tanda pengenal variabel sebelumnya, tanda pengenal variabel adalah nama yang diberikan kepada variabel sebagai nama variabel. Jadi, variabel adalah tanda pengenal dari nilai yang disimpan. Lalu bagaimana mendeklarasikan sebuah variabel? Dan aturan apa yang ada pada deklarasi variabel?
-
Model pengumuman:
Ada tiga jenis model deklarasi variabel, yaitu:- Menggunakan kata kunci
var。 - Gunakan kata kunci
varip。 - Tidak menulis apa-apa.
var、varipKata kunci sebenarnya sudah kita pelajari di bab sebelumnya "Operator Assignment" dan tidak akan dibahas di sini. Jika model deklarasi variabel tidak ditulis apa-apa, misalnya kalimat:i = 1, dan kita telah mengatakan sebelumnya, bahwa variabel yang dinyatakan dan diberi nilai, akan dieksekusi pada setiap baris KBAR. - Menggunakan kata kunci
-
jenis
Bahasa Pine di FMZ tidak terlalu ketat untuk tipe, dan biasanya dapat dihapus. Namun, untuk kompatibilitas dengan strategi skrip di Trading View, variabel dapat diklaim dengan tipe.int i = 0 float f = 1.1Tipe pada Trading View lebih ketat, dan akan mengalami kesalahan jika menggunakan kode berikut di Trading View:
baseLine0 = na // compile time error! -
Identifikasi
Identifier adalah nama variabel, nama identifier telah dibahas di bab sebelumnya, dapat dilihat kembali: https://www.fmz.com/bbs-topic/9390#标识符
Sebagai kesimpulan, pernyataan tentang suatu variabel dapat ditulis sebagai:
// [<declaration_mode>] [<type>] <identifier> = value
声明模式 类型 标识符 = 值
Di sini, operator penugasan digunakan:=Variabel diberikan nilai pada saat deklarasi variabel. Nilai yang diberikan dapat berupa string, angka, ekspresi, panggilan fungsi, atau bentuk lainnya.if、 for、whileatauswitchStruktur dll (( struktur kata kunci, penggunaan kalimat kami akan menjelaskan secara rinci dalam pelajaran selanjutnya, sebenarnya kami telah belajar dalam pelajaran sebelumnya tentang pemberian nilai kalimat if sederhana, Anda dapat melihat kembali)
Fungsi input adalah salah satu fungsi yang sering kita gunakan dalam merancang strategi. Fungsi ini juga sangat penting dalam merancang strategi.
Fungsi input:
input函数,参数defval、title、tooltip、inline、group
Fungsi input pada FMZ dan pada Trading View sedikit berbeda, namun fungsi ini digunakan sebagai input penugasan parameter strategi. Di bawah ini kita akan menjelaskan penggunaan fungsi input pada FMZ dengan contoh:
pine
param1 = input(10, title="参数1名称", tooltip="参数1的描述信息", group="分组名称A")
param2 = input("close", title="参数2名称", tooltip="参数2的描述信息", group="分组名称A")
param3 = input(color.red, title="参数3名称", tooltip="参数3的描述信息", group="分组名称B")
param4 = input(close, title="参数4名称", tooltip="参数4的描述信息", group="分组名称B")
param5 = input(true, title="参数5名称", tooltip="参数5的描述信息", group="分组名称C")
ma = ta.ema(param4, param1)
plot(ma, title=param2, color=param3, overlay=param5)
Pada FMZ, fungsi input akan secara otomatis menarik kontrol yang digunakan untuk mengatur parameter kebijakan di antarmuka kebijakan FMZ. Kontrol yang didukung pada FMZ saat ini memiliki kotak input angka, kotak input teks, kotak dropdown, dan penyaringan nilai bullet. Selain itu, Anda dapat mengatur grup parameter kebijakan dan informasi teks yang diminta untuk mengatur parameter.
Berikut ini adalah beberapa parameter utama dari fungsi input:
- defval: Default value of the policy parameter option as an input function, supporting the built-in variables, numbers, and strings of the Pine language
- title: Nama parameter yang ditampilkan pada interface kebijakan yang terdeteksi/diukur ulang.
- tooltip: Pesan tentang parameter kebijakan, menampilkan informasi teks tentang pengaturan parameter ini ketika mouse mengayunkan mouse di atas parameter kebijakan.
- group: nama grup dari parameter kebijakan, dapat diberikan kepada grup dari parameter。
Selain deklarasi dan penugasan variabel secara terpisah, bahasa Pine juga menyatakan satu set variabel dan penugasan nilai:
[变量A,变量B,变量C] = 函数 或者 ```if```、 ```for```、```while```或```switch```等结构
Yang paling umum adalah kita menggunakanta.macdFungsi menghitung indikator MACD, karena indikator MACD adalah indikator multi-linear, menghitung tiga set data. Oleh karena itu, dapat ditulis sebagai:
pine
[dif,dea,column] = ta.macd(close, 12, 26, 9)
plot(dif, title="dif")
plot(dea, title="dea")
plot(column, title="column", style=plot.style_histogram)
Fungsi MACD dapat dengan mudah digambarkan dengan menggunakan kode di atas. Tidak hanya fungsi built-in yang dapat mengembalikan beberapa variabel, fungsi kustom yang ditulis juga dapat mengembalikan beberapa data.
pine
twoEMA(data, fastPeriod, slowPeriod) =>
fast = ta.ema(data, fastPeriod)
slow = ta.ema(data, slowPeriod)
[fast, slow]
[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)
Cara menulis struktur seperti if sebagai beberapa variabel yang diberi nilai juga mirip dengan cara fungsi kustom di atas, yang tertarik juga dapat mencoba.
[ema10, ema20] = if true
fast = ta.ema(close, 10)
slow = ta.ema(close, 20)
[fast, slow]
plot(ema10, title="ema10", color=color.fuchsia, overlay=true)
plot(ema20, title="ema20", color=color.aqua, overlay=true)
Struktur kondisional
Beberapa fungsi yang tidak dapat ditulis dalam blok kode lokal cabang kondisional, terutama beberapa fungsi berikut:
barcolor(), fill(), hline(), indicator(), plot(), plotcandle(), plotchar(), plotshape()
Trading View akan menyusun laporan kesalahan. Di FMZ, pembatasan tidak begitu ketat, tetapi juga disarankan untuk mengikuti spesifikasi yang ditulis di Trading View. Misalnya, meskipun tidak ada laporan kesalahan di FMZ, namun tidak disarankan untuk menulis seperti itu.
pine
strategy("test", overlay=true)
if close > open
plot(close, title="close")
else
plot(open, title="open")
kalimat if
Contoh:
pine
var lineColor = na
n = if bar_index > 10 and bar_index <= 20
lineColor := color.green
else if bar_index > 20 and bar_index <= 30
lineColor := color.blue
else if bar_index > 30 and bar_index <= 40
lineColor := color.orange
else if bar_index > 40
lineColor := color.black
else
lineColor := color.red
plot(close, title="close", color=n, linewidth=5, overlay=true)
plotchar(true, title="bar_index", char=str.tostring(bar_index), location=location.abovebar, color=color.red, overlay=true)
Penting: Ekspresi yang digunakan untuk menilai, mengembalikan nilai boolean. Perhatikan bahwa hanya ada satu cabang yang dapat dikurangi. Semua cabang ekspresi tidak benar, dan jika tidak ada cabang lain, maka dikembalikan na.
pine
x = if close > open
close
plot(x, title="x")
Karena jika garis K BAR adalah garis negatif, yaitu ketika close < open, maka if dinyatakan sebagai false, maka blok lokal dari if tidak dieksekusi. Pada saat ini tidak ada cabang else, dan if dikembalikan sebagai na. Oleh karena itu, x diberi nilai na.
Kata ganti
Pernyataan switch juga merupakan pernyataan dengan struktur cabang, yang digunakan untuk merancang jalan yang berbeda sesuai dengan kondisi tertentu. Pernyataan switch umumnya memiliki beberapa poin pengetahuan penting sebagai berikut:
- kalimat switch dan kalimat if dapat dikembalikan.
- Tidak seperti kata kunci switch dalam bahasa lain, struktur switch hanya mengeksekusi satu blok lokal dalam kodenya, sehingga deklarasi break tidak diperlukan (yaitu tidak perlu menulis kata kunci seperti break).
- Setiap cabang dari switch dapat menuliskan satu blok kode lokal, yang baris terakhir dari blok kode lokal tersebut adalah nilai yang dikembalikan (yang dapat menjadi sebuah subset dari nilai). Jika tidak ada cabang dari blok kode lokal yang dieksekusi, maka akan dikembalikan na.
4 , Ekspresi menentukan posisi dalam struktur switch, dapat menulis string, variabel, ekspresi atau fungsi panggilan 。 - switch memungkinkan untuk menentukan nilai yang akan dikembalikan sebagai nilai default yang digunakan ketika tidak ada kondisi lain dalam struktur.
Ada dua jenis switch, dan kita akan melihat contohnya satu per satu untuk mengetahui cara penggunaannya.
1 dengan ekspresiswitchContoh:
pine
// input.string: defval, title, options, tooltip
func = input.string("EMA", title="指标名称", tooltip="选择要使用的指标函数名称", options=["EMA", "SMA", "RMA", "WMA"])
// input.int: defval, title, options, tooltip
// param1 = input.int(10, title="周期参数")
fastPeriod = input.int(10, title="快线周期参数", options=[5, 10, 20])
slowPeriod = input.int(20, title="慢线周期参数", options=[20, 25, 30])
data = input(close, title="数据", tooltip="选择使用收盘价、开盘价、最高价...")
fastColor = color.red
slowColor = color.red
[fast, slow] = switch func
"EMA" =>
fastLine = ta.ema(data, fastPeriod)
slowLine = ta.ema(data, slowPeriod)
fastColor := color.red
slowColor := color.red
[fastLine, slowLine]
"SMA" =>
fastLine = ta.sma(data, fastPeriod)
slowLine = ta.sma(data, slowPeriod)
fastColor := color.green
slowColor := color.green
[fastLine, slowLine]
"RMA" =>
fastLine = ta.rma(data, fastPeriod)
slowLine = ta.rma(data, slowPeriod)
fastColor := color.blue
slowColor := color.blue
[fastLine, slowLine]
=>
runtime.error("error")
plot(fast, title="fast" + fastPeriod, color=fastColor, overlay=true)
plot(slow, title="slow" + slowPeriod, color=slowColor, overlay=true)
Sebelumnya kita telah mempelajari fungsi input, dan di sini kita melanjutkan dengan dua fungsi yang mirip dengan input:input.string、input.intfungsi.
input.stringJika Anda ingin mengunduh aplikasi, Anda dapat mengunduh aplikasi dari Google Play Store.input.intFungsi yang digunakan untuk mengembalikan nilai integer. Dalam contoh ini sebenarnya ada tambahanoptionsCara menggunakan parameter,optionsParameter dapat ditransfer ke dalam sebuah array yang terdiri dari nilai-nilai yang dapat dipilih.options=["EMA", "SMA", "RMA", "WMA"]Danoptions=[5, 10, 20](Perhatikan bahwa satu adalah tipe string dan satu adalah tipe nilai numerik). Dengan demikian, pengendali pada antarmuka kebijakan tidak perlu memasukkan nilai numerik tertentu, tetapi pengendali berubah menjadi kotak bawah, memilih opsi yang disediakan dalam parameter options.
Variabel func diberi nilai sebagai string, dengan variabel func sebagai ekspresi switch (bisa berupa variabel, panggilan fungsi, atau ekspresi), untuk menentukan cabang mana dalam switch yang akan dijalankan. Jika variabel func tidak dapat cocok dengan ekspresi pada cabang manapun dalam switch (yaitu setara), maka blok kode cabang default yang akan dijalankanruntime.error("error")Fungsi menyebabkan kebijakan untuk membuang pengecualian berhenti.
Dalam kode tes kami di atas, setelah runtime.error pada baris terakhir dari blok kode cabang default switch, kami tidak menambahkan[Kode seperti na, na] untuk kompatibel dengan nilai yang dikembalikan, di trading view perlu untuk mempertimbangkan masalah ini, jika jenis tidak sesuai akan mendapat kesalahan. Tetapi di FMZ karena tidak ada tipe yang sangat diperlukan, maka dapat dihilangkan kode kompatibilitas ini. Jadi di FMZ tidak perlu mempertimbangkan masalah kompatibilitas tipe if, switch cabang yang mengembalikan nilai.
pine
strategy("test", overlay=true)
x = if close > open
close
else
"open"
plotchar(true, title="x", char=str.tostring(x), location=location.abovebar, color=color.red)
Tidak ada kesalahan pada FMZ, tetapi ada kesalahan pada trading view. Karena jenis if yang dikembalikan tidak konsisten.
- Tidak ada ekspresi
switch
Mari kita lihat.switchPenggunaan lain dari kata ini adalah tanpa ekspresi.
pine
up = close > open // up = close < open
down = close < open
var upOfCount = 0
var downOfCount = 0
msgColor = switch
up =>
upOfCount += 1
color.green
down =>
downOfCount += 1
color.red
plotchar(up, title="up", char=str.tostring(upOfCount), location=location.abovebar, color=msgColor, overlay=true)
plotchar(down, title="down", char=str.tostring(downOfCount), location=location.belowbar, color=msgColor, overlay=true)
Dalam contoh kode tes ini, kita dapat melihat bahwa switch akan mencocokkan blok kode lokal yang benar dengan syarat pemenuhan cabang. Secara umum, syarat cabang setelah kalimat switch harus saling menolak. Artinya, dalam contoh ini, up dan down tidak dapat menjadi benar pada saat yang sama. Karena switch hanya dapat menjalankan blok kode lokal dari satu cabang, orang yang tertarik dapat menggunakan kalimat berikut dalam kode:up = close > open // up = close < open Ubah ke dalam komentar, ulangi hasil pengamatan. Anda akan menemukan bahwa cabang switch hanya dapat melakukan cabang pertama. Selain itu, perlu diperhatikan bahwa fungsi tidak dapat dipanggil pada setiap BAR yang dapat menyebabkan beberapa masalah perhitungan data.switchDalam contoh ini, implementasi cabang ditentukan dan tidak akan diubah dalam operasi strategi.
Struktur siklus
kalimat for
返回值 = for 计数 = 起始计数 to 最终计数 by 步长
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
kalimat for sangat mudah digunakan, loop for dapat akhirnya mengembalikan satu nilai (() atau mengembalikan beberapa nilai, untuk[a, b, c] seperti) 。 Variabel yang diberi nilai pada posisi "pengembalian" seperti dalam kode palsu di atas。 for statement diikuti dengan variabel "count" yang digunakan untuk mengontrol jumlah siklus, referensi nilai lain, dan sebagainya。 Variabel "count" diberikan nilai sebagai "count awal" sebelum siklus dimulai, kemudian bertumbuh sesuai dengan pengaturan "langkah", dan siklus berhenti ketika variabel "count" lebih besar dari "count akhir"。
digunakan dalam siklus forbreakKata Kunci: Ketika dilakukanbreakSetelah kalimat, lingkaran berhenti.
digunakan dalam siklus forcontinueKata Kunci: Ketika dilakukancontinueSetelah kalimat, lingkaran akan mengabaikancontinueKode berikutnya, langsung melakukan putaran berikutnya. For kembali nilai yang dikembalikan pada putaran terakhir. Jika tidak ada kode yang dilakukan, maka kembali nol.
Di bawah ini adalah contoh sederhana:
pine
ret = for i = 0 to 10 // 可以增加by关键字修改步长,暂时FMZ不支持 i = 10 to 0 这样的反向循环
// 可以增加条件设置,使用continue跳过,break跳出
runtime.log("i:", i)
i // 如果这行不写,就返回空值,因为没有可返回的变量
runtime.log("ret:", ret)
runtime.error("stop")
Untuk ... dalam kalimat
for ... inAda dua bentuk kalimat, dengan kode pseudo berikut.
返回值 = for 数组元素 in 数组
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Perbedaan utama antara dua bentuk ini adalah apa yang diikuti oleh kata kunci for, yaitu menggunakan variabel sebagai referensi untuk elemen array. Yang pertama adalah menggunakan struktur yang berisi variabel indeks, variabel array untuk referensi. Yang lainnya adalah aturan nilai kembali, menggunakan break, continue, dan aturan lain yang sesuai dengan siklus for.
pine
testArray = array.from(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for ele in testArray // 修改成 [i, ele]的形式:for [i, ele] in testArray , runtime.log("ele:", ele, ", i:", i)
runtime.log("ele:", ele)
runtime.error("stop")
Jika Anda ingin mengindeks, gunakan saja.for [i, ele] in testArrayBahasa Indonesia
Untuk aplikasi siklus
Ketika Anda dapat menggunakan fungsi built-in yang disediakan oleh bahasa Pine untuk melakukan beberapa perhitungan logis lingkaran, Anda dapat menggunakan struktur lingkaran untuk menulisnya secara langsung, atau Anda dapat menggunakan fungsi built-in untuk memprosesnya. Mari kita ambil dua contoh.
1 , menghitung rata-rata
Ketika menggunakan desain struktur lingkaran:
pine
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
sum = 0
for ele in a
sum += ele
avg = sum / length
plot(avg, title="avg", overlay=true)
Dalam contoh ini, kita menggunakan for loop addition, dan kemudian menghitung rata-rata.
Hitung garis rata-rata langsung dengan fungsi built-in:
pine
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Menggunakan fungsi built-in secara langsungta.smaUntuk menghitung indikator garis rata-rata, jelas lebih mudah menggunakan fungsi bawaan untuk menghitung garis rata-rata. Hasil perhitungan dapat dilihat secara konsisten dalam perbandingan pada grafik.
- Penjumlahan
Atau gunakan contoh di atas untuk menjelaskan.
Ketika menggunakan desain struktur lingkaran:
pine
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
sum = 0
for ele in a
sum += ele
avg = sum / length
plot(avg, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Untuk menghitung jumlah semua elemen dari sebuah array dapat diproses dengan loop, atau dengan fungsi built-in.array.sumUntuk menghitung.
Perhitungan penjumlahan langsung menggunakan fungsi built-in:
pine
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
plot(array.sum(a) / length, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Data yang dihitung dapat dilihat dengan menggunakan gambar plot yang ditampilkan secara konsisten pada grafik.
Jika Anda dapat melakukan semua ini dengan fungsi bawaan, mengapa Anda harus membuat loop?
- Untuk beberapa operasi, perhitungan dari array.
- Mengingat kembali sejarah, misalnya, mencari tahu berapa banyak titik tinggi masa lalu yang lebih tinggi dari titik tinggi BAR saat ini. Karena titik tinggi BAR saat ini hanya diketahui pada BAR yang dijalankan oleh skrip, sebuah loop diperlukan untuk kembali dan menganalisis BAR masa lalu.
- Fungsi built-in yang menggunakan bahasa Pine tidak dapat menyelesaikan perhitungan BAR yang lalu.
Pernyataan while
whileSentensi membuat kode bagian loop terus dijalankan sampai kondisi pertimbangan dalam struktur while adalah false (false) <unk>.
返回值 = while 判断条件
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Aturan lain dari while mirip dengan loop for, di mana baris terakhir dari blok kode lokal loop adalah nilai yang dikembalikan, yang dapat mengembalikan lebih dari satu nilai. Apabila "kondisi loop" adalah waktu yang benar untuk melakukan loop, dan berhenti ketika kondisi adalah palsu. Anda juga dapat menggunakan kalimat break, continue dalam loop.
Saya akan memberikan contoh dengan menghitung garis rata-rata:
pine
length = 10
sma(data, length) =>
i = 0
sum = 0
while i < 10
sum += data[i]
i += 1
sum / length
plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Anda dapat melihat bahwa menggunakan while loop juga sangat sederhana, dan Anda dapat merancang beberapa logika komputasi yang tidak dapat digantikan dengan fungsi built-in, seperti menghitung perkalian pangkat:
pine
counter = 5
fact = 1
ret = while counter > 0
fact := fact * counter
counter := counter - 1
fact
plot(ret, title="ret") // ret = 5 * 4 * 3 * 2 * 1
Kelompok
Array dalam bahasa Pine mirip dengan definisi array dalam bahasa pemrograman lainnya. Array Pine adalah sebuah array berdimensi. Array ini biasanya digunakan untuk menyimpan serangkaian data yang berurutan. Array yang menyimpan data tunggal disebut elemen array, dan jenis elemen tersebut dapat berupa: integer, float, string, nilai warna, nilai bul.[]Tapi perlu digunakan.array.get()danarray.set()Fungsi △ adalah urutan indeks elemen dalam array dengan indeks elemen pertama dari array adalah 0, indeks elemen berikutnya meningkat 1 △.
Kami menjelaskan dengan kode sederhana:
pine
var a = array.from(0)
if bar_index == 0
runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 1
array.push(a, bar_index)
runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 2
array.push(a, bar_index)
runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2])
else if bar_index == 3
array.push(a, bar_index)
runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2], ", 向前数3根BAR上的a,即a[3]值:", a[3])
else if bar_index == 4
// 使用array.get 按索引获取元素,使用array.set按索引修改元素
runtime.log("数组修改前:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
array.set(a, 1, 999)
runtime.log("数组修改后:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
Deklarasi Array
menggunakanarray<int> a、float[] bArray yang diklaim atau hanya diklaim satu variabel dapat diberi nilai array, misalnya:
pine
array<int> a = array.new(3, bar_index)
float[] b = array.new(3, close)
c = array.from("hello", "fmz", "!")
runtime.log("a:", a)
runtime.log("b:", b)
runtime.log("c:", c)
runtime.error("stop")
Penggunaan umum untuk inisialisasi variabel arrayarray.newDanarray.fromFungsi . . Banyak fungsi lain dalam bahasa Pine yang terkait dengan tipe yang mirip dengan array.new:array.new_int()、array.new_bool()、array.new_color()、array.new_string()Tunggu.
Kata kunci var juga dapat bekerja dengan mode deklarasi array, menggunakan kata kunci var yang menyatakan bahwa array hanya diinisialisasi pada BAR pertama.
pine
var a = array.from(0)
b = array.from(0)
if bar_index == 1
array.push(a, bar_index)
array.push(b, bar_index)
else if bar_index == 2
array.push(a, bar_index)
array.push(b, bar_index)
else if barstate.islast
runtime.log("a:", a)
runtime.log("b:", b)
runtime.error("stop")
Kita dapat melihat bahwa perubahan dari array a terus-menerus ditentukan, tanpa diset ulang. Array b diinisialisasi pada setiap BAR.barstate.islastUntuk waktu nyata, hanya ada satu elemen yang dicetak, yaitu angka 0.
Membaca dan menulis elemen dalam array
Gunakan array.get untuk mendapatkan elemen yang mengindeks posisi di array, gunakan array.set untuk mengubah elemen yang mengindeks posisi di array.
Array.get dengan argumen pertama adalah array yang akan diproses, dan argumen kedua adalah indeks yang ditentukan.
Argumen pertama array.set adalah array yang akan diproses, argumen kedua adalah indeks yang ditentukan, dan argumen ketiga adalah elemen yang akan ditulis.
Contoh sederhana berikut ini akan menjelaskan:
pine
lookbackInput = input.int(100)
FILL_COLOR = color.green
var fillColors = array.new(5)
if barstate.isfirst
array.set(fillColors, 0, color.new(FILL_COLOR, 70))
array.set(fillColors, 1, color.new(FILL_COLOR, 75))
array.set(fillColors, 2, color.new(FILL_COLOR, 80))
array.set(fillColors, 3, color.new(FILL_COLOR, 85))
array.set(fillColors, 4, color.new(FILL_COLOR, 90))
lastHiBar = - ta.highestbars(high, lookbackInput)
fillNo = math.min(lastHiBar / (lookbackInput / 5), 4)
bgcolor(array.get(fillColors, int(fillNo)), overlay=true)
plot(lastHiBar, title="lastHiBar")
plot(fillNo, title="fillNo")
Contoh ini menginisialisasi warna dasar hijau, menyatakan dan menginisialisasi sebuah array untuk menyimpan warna, dan kemudian memberikan transparansi yang berbeda pada nilai warna (dengan menggunakan fungsi color.new). Dengan menghitung jarak dari BAR saat ini ke nilai tertinggi dalam 100 siklus percobaan, perhitungkan peringkat warna.
Menjelajahi elemen array
Bagaimana kita bisa menjelajahi sebuah array dengan menggunakan for/for in/while yang kita pelajari sebelumnya?
pine
a = array.from(1, 2, 3, 4, 5, 6)
for i = 0 to (array.size(a) == 0 ? na : array.size(a) - 1)
array.set(a, i, i)
runtime.log(a)
runtime.error("stop")
pine
a = array.from(1, 2, 3, 4, 5, 6)
i = 0
while i < array.size(a)
array.set(a, i, i)
i += 1
runtime.log(a)
runtime.error("stop")
pine
a = array.from(1, 2, 3, 4, 5, 6)
for [i, ele] in a
array.set(a, i, i)
runtime.log(a)
runtime.error("stop")
Ketiga metode ini memiliki hasil yang sama.
Array dapat dinyatakan dalam batas global skrip, atau dapat dinyatakan dalam batas lokal fungsi atau cabang if
Sumber data sejarah
Untuk penggunaan elemen dalam array, cara berikut ini adalah ekuivalen, kita dapat melihat dengan contoh di bawah ini bahwa pada diagram, dua kelompok garis digambar, dua baris di setiap kelompok, dan dua baris di setiap kelompok memiliki nilai yang sama persis.
pine
a = array.new_float(1)
array.set(a, 0, close)
closeA1 = array.get(a, 0)[1]
closeB1 = close[1]
plot(closeA1, "closeA1", color.red, 6)
plot(closeB1, "closeB1", color.black, 2)
ma1 = ta.sma(array.get(a, 0), 20)
ma2 = ta.sma(close, 20)
plot(ma1, "ma1", color.aqua, 6)
plot(ma2, "ma2", color.black, 2)
Fungsi operasi penambahan dan penghapusan dari array
- Fungsi yang berhubungan dengan operasi penambahan dari array:
array.unshift()、array.insert()、array.push()。
- Fungsi yang terkait dengan penghapusan array:
array.remove()、array.shift()、array.pop()、array.clear()。
Kami menggunakan contoh berikut untuk menguji fungsi operasi penambahan dan penghapusan dari array tersebut.
pine
a = array.from("A", "B", "C")
ret = array.unshift(a, "X")
runtime.log("数组a:", a, ", ret:", ret)
ret := array.insert(a, 1, "Y")
runtime.log("数组a:", a, ", ret:", ret)
ret := array.push(a, "D")
runtime.log("数组a:", a, ", ret:", ret)
ret := array.remove(a, 2)
runtime.log("数组a:", a, ", ret:", ret)
ret := array.shift(a)
runtime.log("数组a:", a, ", ret:", ret)
ret := array.pop(a)
runtime.log("数组a:", a, ", ret:", ret)
ret := array.clear(a)
runtime.log("数组a:", a, ", ret:", ret)
runtime.error("stop")
Menambahkan, menghapus aplikasi: Array sebagai Queue
Dengan menggunakan array, dan beberapa fungsi penambahan dan penghapusan dari array, kita dapat membangun sebuah struktur data "array". Array dapat digunakan untuk menghitung nilai rata-rata bergerak dari harga tick, dan mungkin ada yang bertanya, "Kenapa kita harus membangun sebuah struktur array? Bukankah kita bisa menghitung nilai rata-rata dari array sebelumnya?"
Sebuah antrian adalah struktur yang sering digunakan dalam bidang pemrograman, dengan karakteristik sebagai berikut:
Unsur yang masuk ke antrian pertama, keluar dari antrian pertama.
Dengan cara ini, Anda dapat memastikan bahwa data yang ada dalam antrian adalah data terbaru dan tidak akan membesar sampai batas tak terbatas (kode yang membesar sampai batas tak terbatas hanya dapat ditulis pada waktu tengah hari, karena ini akan menjadi masalah di pagi hari dan malam hari).
Dalam contoh di bawah ini, kita menggunakan struktur antrian untuk mencatat harga setiap tick, menghitung moving average pada tingkat tick, dan kemudian membandingkannya dengan moving average pada tingkat K-line selama 1 menit.
pine
strategy("test", overlay=true)
varip a = array.new_float(0)
var length = 10
if not barstate.ishistory
array.push(a, close)
if array.size(a) > length
array.shift(a)
sum = 0.0
for [index, ele] in a
sum += ele
avgPrice = array.size(a) == length ? sum / length : na
plot(avgPrice, title="avgPrice")
plot(ta.sma(close, length), title="ta.sma")
Perhatikan bahwa ketika kita menyatakan array a, kita menentukan mode deklarasi, menggunakan kata kunci.varipDengan demikian, setiap perubahan harga akan dicatat dalam sebuah array.
Fungsi penghitungan dan operasi array yang umum digunakan
Untuk menghitung fungsi yang terkait:
array.avg()Carilah nilai rata-rata dari semua elemen dalam array.array.min()Carilah elemen terkecil dalam array.array.max()Carilah elemen terbesar dari array.array.stdev()Carilah perbedaan standar dari semua elemen dalam array.array.sum()Tentukan jumlah semua elemen dalam array.
Fungsi yang terkait:
array.concat()Merger atau menghubungkan dua array.
array.copy()Menyalin array.
array.joinHubungkan semua elemen dalam array menjadi sebuah string.
array.sort()Urutan urutan naik atau turun.
array.reverse()Array pembalikan
array.slice()Potong array tersebut.
array.includes()Elemen penilaian
array.indexof()Mengembalikan indeks yang pertama kali muncul dari nilai yang diimpor oleh parameter tersebut. Jika tidak ditemukan, maka dikembalikan -1
array.lastindexof()Menemukan nilai yang muncul terakhir
Contoh tes untuk fungsi terkait perhitungan array:
pine
a = array.from(3, 2, 1, 4, 5, 6, 7, 8, 9)
runtime.log("数组a的算数平均:", array.avg(a))
runtime.log("数组a中的最小元素:", array.min(a))
runtime.log("数组a中的最大元素:", array.max(a))
runtime.log("数组a中的标准差:", array.stdev(a))
runtime.log("数组a的所有元素总和:", array.sum(a))
runtime.error("stop")
Ini adalah fungsi penghitungan array yang lebih umum.
Contoh fungsi yang berhubungan dengan operasi:
pine
a = array.from(1, 2, 3, 4, 5, 6)
b = array.from(11, 2, 13, 4, 15, 6)
runtime.log("数组a:", a, ", 数组b:", b)
runtime.log("数组a,数组b连接在一起:", array.concat(a, b))
c = array.copy(b)
runtime.log("复制一个数组b,赋值给变量c,变量c:", c)
runtime.log("使用array.join处理数组c,给每个元素中间增加符号+,连接所有元素结果为字符串:", array.join(c, "+"))
runtime.log("排序数组b,按从小到大顺序,使用参数order.ascending:", array.sort(b, order.ascending)) // array.sort函数修改原数组
runtime.log("排序数组b,按从大到小顺序,使用参数order.descending:", array.sort(b, order.descending)) // array.sort函数修改原数组
runtime.log("数组a:", a, ", 数组b:", b)
array.reverse(a) // 此函数修改原数组
runtime.log("反转数组a中的所有元素顺序,反转之后数组a为:", a)
runtime.log("截取数组a,索引0 ~ 索引3,遵循左闭右开区间规则:", array.slice(a, 0, 3))
runtime.log("在数组b中搜索元素11:", array.includes(b, 11))
runtime.log("在数组a中搜索元素100:", array.includes(a, 100))
runtime.log("将数组a和数组b连接,搜索其中第一次出现元素2的索引位置:", array.indexof(array.concat(a, b), 2), " , 参考观察 array.concat(a, b):", array.concat(a, b))
runtime.log("将数组a和数组b连接,搜索其中最后一次出现元素6的索引位置:", array.lastindexof(array.concat(a, b), 6), " , 参考观察 array.concat(a, b):", array.concat(a, b))
runtime.error("stop")
fungsi
Fungsi Khusus
Bahasa Pine dapat mendesain fungsi kustom, dan pada umumnya fungsi kustom dalam bahasa Pine memiliki aturan berikut:
- Semua fungsi didefinisikan dalam ruang lingkup global skrip. Tidak dapat mendeklarasikan fungsi dalam fungsi lain.
- Fungsi tidak diizinkan untuk memanggil dirinya sendiri dalam kode sendiri.
- Pada prinsipnya semua bahasa PINE memiliki fungsi gambar bawaan
barcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) tidak dapat dipanggil dalam fungsi kustom. - Fungsi dapat ditulis dalam bentuk baris tunggal, maupun baris ganda. Nilai yang dikembalikan dari kalimat terakhir adalah nilai yang dikembalikan oleh fungsi saat ini, dan nilai yang dikembalikan dapat dikembalikan dalam bentuk unsur.
Dalam tutorial sebelumnya, kita telah menggunakan fungsi kustom beberapa kali, seperti fungsi kustom yang dirancang dalam satu baris:
pine
barIsUp() => close > open
Fungsi ini mengembalikan apakah BAR saat ini adalah garis bujur.
Desain fungsi kustom multi baris:
pine
sma(data, length) =>
i = 0
sum = 0
while i < 10
sum += data[i]
i += 1
sum / length
plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Fungsi yang kita lakukan sendiri dengan fungsi kustom kita adalah sebuah fungsi sma rata-rata.
Anda juga dapat mengembalikan contoh fungsi kustom dari dua variabel:
pine
twoEMA(data, fastPeriod, slowPeriod) =>
fast = ta.ema(data, fastPeriod)
slow = ta.ema(data, slowPeriod)
[fast, slow]
[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)
Sebuah fungsi dapat menghitung garis cepat, garis lambat, dua indikator EMA rata-rata.
Fungsi bawaan
Fungsi built-in dapat dengan mudah diFMZ PINE Script DokumentasiPencarian di:
Fungsi bawaan bahasa Pine diklasifikasikan sebagai:
- Fungsi pengolahan string
str.Serial - Fungsi pengolahan nilai warna
color.Serial
3 , fungsi input parameterinput.Serial - Fungsi penghitungan indikator
ta.Serial - Fungsi gambar
plot.Serial - Fungsi pengolahan array
array.Serial
7 . Fungsi terkait transaksistrategy.Serial - Fungsi yang berhubungan dengan operasi matematika
math.Serial
9, fungsi lain ((pengolahan waktu, non-plot seri gambar fungsi,request.Fungsi seri, fungsi pengolahan tipe, dan lain-lain).
Fungsi transaksi
strategy.Fungsi seri adalah fungsi yang sering kita gunakan dalam desain strategi, yang terkait dengan fungsi dan strategi yang dijalankan untuk melakukan operasi transaksi.
1、strategy.entry
strategy.entryFungsi adalah fungsi perintah yang sangat penting dalam penulisan kebijakan, beberapa parameter yang sangat penting adalah:id, direction, qty, whenTunggu.
parameter:
id: dapat diartikan sebagai nama pertama yang digunakan untuk merujuk pada suatu posisi perdagangan. dapat merujuk pada id ini untuk membatalkan, memodifikasi pesanan, atau posisi kosong.direction: Jika arah pesanan adalah melakukan lebih banyak ((beli) parameter ini diteruskanstrategy.longVariabel internal ini akan dikirim jika Anda ingin melakukan short sale.strategy.shortVariabel iniqty: Tentukan jumlah pesanan, jika tidak memberikan parameter ini digunakan adalah jumlah pesanan default.whenKondisi eksekusi: Anda dapat menentukan parameter ini untuk mengontrol apakah operasi perintah saat ini dipicu atau tidak.limit: Tentukan harga order limit.stopHarga Stop Loss:
strategy.entryDetail pelaksanaan fungsistrategyPengendalian pengaturan parameter pada panggilan fungsi juga dapat dilakukan dengan"Parameter modeling perpustakaan kelas pertukaran bahasa Pine"Untuk lebih jelasnya tentang pengaturan kontrol, dan kontrol parameter modeling dari Pine Language Transaction Class Library, lihat dokumen yang tercantum di bawah ini.
Ini adalah salah satu dari beberapa hal penting yang dapat saya sampaikan.strategyDalam fungsi,pyramiding、default_qty_valueParameter ≠ Test menggunakan kode berikut:
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)
ema10 = ta.ema(close, 10)
findOrderIdx(idx) =>
if strategy.opentrades == 0
false
else
ret = false
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == idx
ret := true
break
ret
if not findOrderIdx("long1")
strategy.entry("long1", strategy.long)
if not findOrderIdx("long2")
strategy.entry("long2", strategy.long, 0.2, when = close > ema10)
if not findOrderIdx("long3")
strategy.entry("long3", strategy.long, 0.2, limit = low[1])
strategy.entry("long3", strategy.long, 0.3, limit = low[1])
if not findOrderIdx("long4")
strategy.entry("long4", strategy.long, 0.2)
plot(ema10, title="ema10", color=color.red)
Kode awal/*backtest ... */Bagian paket adalah pengaturan pengembalian, untuk mencatat informasi seperti waktu pengaturan pengembalian pada saat itu, untuk memudahkan debug, bukan kode kebijakan.
Dalam kode:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)Ketika kita menunjukpyramidingJika parameternya adalah 3, maka kita bisa mengatur untuk melakukan transaksi dalam satu arah paling banyak 3 kali. Jadi dalam contoh ini 4 kali.strategy.entryOperasi perintah di bawah ini tidak dijalankan.default_qty_valueParameter adalah 0,1, jadi ID yang diidentifikasi sebagai <unk>long1<unk> kali inistrategy.entryOperasi perintah berikutnya adalah perintah yang disetel secara default 0.1.strategy.entryFungsi yang kita pilih saat kita memanggildirectionadalahstrategy.longJadi, semua pesanan harus dibayar untuk tes ulang.
Perhatikan kodestrategy.entry("long3", ...Operasi perintah berikut dipanggil dua kali, untuk ID yang sama: <unk>long3<unk>strategy.entryOperasi berikutnya tidak berhasil, panggilan keduastrategy.entryFungsi untuk memodifikasi pesanan dengan ID ini ((data yang ditampilkan pada saat pengujian pengembalian juga dapat melihat bahwa pesanan dengan harga yang dibatasi ini telah dimodifikasi untuk 0.3)). Dalam kasus lain, misalnya jika ID pertama kali melakukan transaksi dengan pesanan dengan ID yang diperdagangkan, terus menggunakan ID yang diperdagangkan dengan ID yang diperdagangkanstrategy.entryFungsi yang dipesan, maka posisi pesanan akan terakumulasi pada ID<unk>long3<unk>.
2、strategy.close
strategy.closeFungsi ini digunakan untuk posisi kosong untuk menentukan posisi masuk yang identik dengan ID. Parameter utama adalah:id,when,qty,qty_percent。
parameter:
idSaya tidak tahu apa yang harus saya lakukan, tapi saya ingin tahu apa yang harus saya lakukan.strategy.entryID yang ditentukan pada saat fungsi pesanan masuk dan membuka posisi.whenKondisi pelaksanaan:qtyJumlah saham kosong:qty_percentPersentase posisi kosong.
Untuk lebih jelasnya, lihat contoh berikut:
Dalam kode/*backtest ... */Ini adalah informasi konfigurasi FMZ.COM International Station Retest, yang dapat dihapus, mengatur informasi seperti pasar, varietas, dan rentang waktu yang Anda butuhkan untuk diuji.
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("close Demo", pyramiding=3)
var enableStop = false
if enableStop
runtime.error("stop")
strategy.entry("long1", strategy.long, 0.2)
if strategy.opentrades >= 3
strategy.close("long1") // 多个入场订单,不指定qty参数,全部平仓
// strategy.close() // 不指定id参数,会平掉当前的持仓
// strategy.close("long2") // 如果指定一个不存在的id则什么都不操作
// strategy.close("long1", qty=0.15) // 指定qty参数平仓
// strategy.close("long1", qty_percent=50) // qty_percent设置50即为平掉long1标识仓位的50%持仓
// strategy.close("long1", qty_percent=80, when=close<open) // 指定when参数,修改为close>open就不触发了
enableStop := true
Strategi pengujian menunjukkan mulai dengan tiga kali masuk berturut-turut, dengan ID masuk masing-masing adalah <unk>long1<unk>, dan kemudian menggunakanstrategy.closeHasil yang berbeda dari fungsi yang diukur kembali saat parameter yang berbeda diatur pada posisi kosong.strategy.closeFungsi ini tidak memiliki parameter untuk menentukan harga pelunasan, fungsi ini terutama digunakan untuk segera melakukan pelunasan dengan harga pasar saat ini.
3、strategy.close_all
strategy.close_allFungsi ini digunakan untuk meratakan semua posisi saat ini, karena skrip bahasa Pine hanya dapat memegang posisi dalam satu arah, yaitu jika ada sinyal yang memicu posisi saat ini dengan arah yang berlawanan dari posisi saat ini, maka posisi akan diratakan dan kemudian dipicu oleh sinyal tersebut.strategy.close_allPada saat dipanggil, semua posisi di arah saat ini akan dihapus.strategy.close_allParameter utama dari fungsi ini adalah:when。
parameter:
whenKondisi pelaksanaan:
Kami menggunakan contoh untuk mengamati:
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("closeAll Demo")
var enableStop = false
if enableStop
runtime.error("stop")
strategy.entry("long", strategy.long, 0.2, when=strategy.position_size==0 and close>open)
strategy.entry("short", strategy.short, 0.3, when=strategy.position_size>0 and close<open)
if strategy.position_size < 0
strategy.close_all()
enableStop := true
Kode tes dimulai dengan posisi 0...strategy.position_size==0adalah benar), sehingga hanya melakukan ID sebagai long<unk> jika memenuhi kondisi yang ditetapkan oleh whenstrategy.entryFungsi masuk: Setelah memegang beberapa posisistrategy.position_sizeJika ID lebih besar dari 0, maka fungsi masuk untuk short akan dieksekusi, karena ada posisi yang lebih besar, maka sinyal inversi shorting yang muncul akan menyebabkan posisi yang lebih besar dihapus dan kemudian dibalikkan.strategy.position_size < 0Ketika, yaitu ketika memegang posisi kosong tutup semua posisi yang memegang arah saat ini.enableStop := true│Menghentikan pelaksanaan kebijakan agar dapat melihat lognya.│
dapat ditemukanstrategy.close_allFungsi ini tidak memiliki parameter untuk menentukan harga pelunasan, fungsi ini terutama digunakan untuk segera melakukan pelunasan dengan harga pasar saat ini.
4、strategy.exit
strategy.exitFungsi ini digunakan untuk melakukan operasi posisi kosong untuk masuk dan memegang posisi, berbeda dengan fungsi ini adalahstrategy.closeDanstrategy.close_allFungsi ini adalah untuk segera melunasi posisi dengan harga pasar saat ini.strategy.exitFungsi akan melakukan perencanaan posisi kosong berdasarkan pengaturan parameter.
parameter:
id: ID pesanan untuk setoran saat ini.from_entry: ID entri yang digunakan untuk menentukan operasi yang akan dilakukan.qtyJumlah saham kosong:qty_percent: Persentase posisi kosong, kisaran: 0 ~ 100 ◦profitTarget laba, dalam poin.loss: Stop Loss Target, dalam poin.limitTarget laba, ditentukan dengan harga.stop: Stop loss target, dengan harga yang ditentukan.whenKondisi pelaksanaan:
Gunakan strategi tes untuk memahami penggunaan parameter.
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/
strategy("strategy.exit Demo", pyramiding=3)
varip isExit = false
findOrderIdx(idx) =>
ret = -1
if strategy.opentrades == 0
ret
else
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == idx
ret := i
break
ret
strategy.entry("long1", strategy.long, 0.1, limit=1, when=findOrderIdx("long1") < 0)
strategy.entry("long2", strategy.long, 0.2, when=findOrderIdx("long2") < 0)
strategy.entry("long3", strategy.long, 0.3, when=findOrderIdx("long3") < 0)
if not isExit and strategy.opentrades > 0
// strategy.exit("exitAll") // 如果仅仅指定一个id参数,则该退场订单无效,参数profit, limit, loss, stop等出场条件也至少需要设置一个,否则也无效
strategy.exit("exit1", "long1", profit=50) // 由于long1入场订单没有成交,因此ID为exit1的出场订单也处于暂待状态,直到对应的入场订单成交才会放置exit1
strategy.exit("exit2", "long2", qty=0.1, profit=100) // 指定参数qty,平掉ID为long2的持仓中0.1个持仓
strategy.exit("exit3", "long3", qty_percent=50, limit=strategy.opentrades.entry_price(findOrderIdx("long3")) + 1000) // 指定参数qty_percent,平掉ID为long3的持仓中50%的持仓
isExit := true
if bar_index == 0
runtime.log("每点价格为:", syminfo.mintick) // 每点价格和Pine语言模板参数上「定价货币精度」参数设置有关
Dengan menggunakan real-time model harga test feedback, strategi tes ini dimulai dengan melakukan 3 operasi masuk (strategy.entryFungsi), long1 sengaja disetellimitParameter, harga 1 membuat tidak dapat diperdagangkan. Kemudian tes kondisi keluar dari fungsistrategy.exit❚ Menggunakan stop-loss berdasarkan jumlah poin, stop-loss berdasarkan harga, menggunakan posisi dengan jumlah tetap, menggunakan posisi dengan persentase. ❚ Hanya menunjukkan stop-loss dalam contoh perpanjangan. Operasi stop-loss juga sama.strategy.exitFungsi ini juga memiliki parameter tracking stop loss yang lebih kompleks:trail_price、trail_points、trail_offsetAnda juga dapat mencoba untuk mempelajari cara menggunakannya dalam contoh ini.
5、strategy.cancel
strategy.cancelFungsi yang digunakan untuk membatalkan/menunda semua perintah untuk daftar pendahuluan.strategy.order, strategy.entry , strategy.exitFungsi ini dapat menghasilkan ID masuk. Parameter utamanya adalah:id、when。
parameter:
idID yang harus dibatalkan:whenKondisi pelaksanaan:
Fungsi ini dipahami dengan baik, yaitu untuk membatalkan perintah masuk yang tidak bertransaksi.
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("strategy.cancel Demo", pyramiding=3)
var isStop = false
if isStop
runtime.error("stop")
strategy.entry("long1", strategy.long, 0.1, limit=1)
strategy.entry("long2", strategy.long, 0.2, limit=2)
strategy.entry("long3", strategy.long, 0.3, limit=3)
if not barstate.ishistory and close < open
strategy.cancel("long1")
strategy.cancel("long2")
strategy.cancel("long3")
isStop := true
6、strategy.cancel_all
strategy.cancel_allFungsi danstrategy.cancelFungsi serupa ◦ membatalkan/membatalkan semua preload order order ◦ dapat ditentukanwhenParameter
parameter:
whenKondisi pelaksanaan:
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("strategy.cancel Demo", pyramiding=3)
var isStop = false
if isStop
runtime.error("stop")
strategy.entry("long1", strategy.long, 0.1, limit=1)
strategy.entry("long2", strategy.long, 0.2, limit=2)
strategy.entry("long3", strategy.long, 0.3, limit=3)
if not barstate.ishistory and close < open
strategy.cancel_all()
isStop := true
7、strategy.order
strategy.orderFungsi fungsi, pengaturan parameter, dan lain-lain hampir sama denganstrategy.entryPersamaan, perbedaan antarastrategy.orderFungsi tidak terlindungistrategyFungsipyramidingPengaturan parameter berdampak, tidak ada batasan jumlah pesanan.
parameter:
id: dapat diartikan sebagai nama pertama yang digunakan untuk merujuk pada suatu posisi perdagangan. dapat merujuk pada id ini untuk membatalkan, memodifikasi pesanan, atau posisi kosong.direction: Jika arah pesanan adalah melakukan lebih banyak ((beli) parameter ini diteruskanstrategy.longVariabel internal ini akan dikirim jika Anda ingin melakukan short sale.strategy.shortVariabel iniqty: Tentukan jumlah pesanan, jika tidak memberikan parameter ini digunakan adalah jumlah pesanan default.whenKondisi eksekusi: Anda dapat menentukan parameter ini untuk mengontrol apakah operasi perintah saat ini dipicu atau tidak.limit: Tentukan harga order limit.stopHarga Stop Loss:
Kita akan menggunakanstrategy.orderTidak ada batasan pada jumlah baris yang akan ditampilkan.strategy.exitFungsi Keluar Kondisi. Membangun skrip yang mirip dengan transaksi grid. Contoh sangat sederhana, hanya untuk belajar:
pine
/*backtest
start: 2021-03-01 00:00:00
end: 2022-08-30 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["ZPrecision",0,358374]]
*/
varip beginPrice = -1
if not barstate.ishistory
if beginPrice == -1 or (math.abs(close - beginPrice) > 1000 and strategy.opentrades == 0)
beginPrice := close
for i = 0 to 20
strategy.order("buy"+i, strategy.long, 0.01, limit=beginPrice-i*200, when=(beginPrice-i*200)<close)
strategy.exit("coverBuy"+i, "buy"+i, qty=0.01, profit=200)
strategy.order("sell"+i, strategy.short, 0.01, limit=beginPrice+i*200, when=(beginPrice+i*200)>close)
strategy.exit("coverSell"+i, "sell"+i, qty=0.01, profit=200)
Contoh kebijakan
Contoh strategi dalam tutorial ini hanya digunakan untuk strategi pengajaran, strategi bimbingan desain ide, tidak melakukan apa-apa perdagangan bimbingan, rekomendasi. Strategi pengajaran jangan langsung.
Strategi Indeks Tren Super
pine
strategy("supertrend", overlay=true)
[supertrend, direction] = ta.supertrend(input(5, "factor"), input.int(10, "atrPeriod"))
plot(direction < 0 ? supertrend : na, "Up direction", color = color.green, style=plot.style_linebr)
plot(direction > 0 ? supertrend : na, "Down direction", color = color.red, style=plot.style_linebr)
if direction < 0
if supertrend > supertrend[2]
strategy.entry("entry long", strategy.long)
else if strategy.position_size < 0
strategy.close_all()
else if direction > 0
if supertrend < supertrend[3]
strategy.entry("entry short", strategy.short)
else if strategy.position_size > 0
strategy.close_all()
Strategi tren yang ditulis dalam bahasa Pine sangatlah sederhana, di sini kita merancang strategi pelacakan tren yang sederhana dengan indikator tren super. Mari kita analisa kode sumber strategi ini.
Pertama, mulailah menggunakan kode strategi.strategyFungsi melakukan beberapa pengaturan sederhana:strategy("supertrend", overlay=true)Jadi, jika Anda ingin membuat sebuah strategi, Anda hanya perlu membuat sebuah strategi dengan judul "supertrend".overlayParameternya adalahtrueKita membuat strategi Pine atau kita belajar sebuah skrip strategi Pine. Pertama kita lihat pada desain parameter interface strategi, kita lihat pada kode sumber dari strategi indikator super trend, di antaranya ada yang kita pelajari di kursus sebelumnya.inputfungsi
[supertrend, direction] = ta.supertrend(input(5, "factor"), input.int(10, "atrPeriod"))
inputFungsi panggilan langsung digunakan sebagaita.supertrendParameter dari fungsi indikator digunakan untuk menghitung indikator supertrend. Di antaranya:
- input(5, "factor")
- input.int(10, "atrPeriod")
Fungsi secara default akan mengatur dua kontrol parameter pada antarmuka kebijakan bahasa Pine, seperti gambar:
Anda dapat melihat bahwa default pada controller adalahinputFungsi daninputFungsi seri adalahinput.intFungsi kedua ini dapat kita setel di interface kebijakan. Fungsi kedua ini dapat kita setel di interface kebijakan.ta.supertrendParameter dari fungsi tersebut adalah . Fungsi indikator super trend menghitung data hargasupertrendDan satu arah datadirection◦ Lalu gunakanplotFungsi gambar, perhatikan bahwa ketika menggambar adalah berdasarkan arah dari indikator tren super, hanya menggambar arah saat ini.directionJadi, jika trend trend saat ini adalah ke arah atas, maka trend saat ini adalah ke arah atas.directionJadi kita bisa melihat bahwa pada saat ini, kita sedang berada di posisi yang lebih rendah, dan pada saat ini kita sedang berada di posisi yang lebih rendah.plotFungsinya adalah untuk menentukan waktu untuk menggambar.directionLebih besar dari, kurang dari 0.
Selanjutnyaif ... else ifLogika adalah penilaian dari sinyal perdagangan, ketika ekspresidirection < 0Ini adalah indikator real-time yang menunjukkan bahwa pasar saat ini berada dalam fase naik, di mana jika data harga dalam indikator supertrendsupertrendLebih tinggi dari harga indikator super trend pada 2 BAR ke depan (yaitusupertrend[2],还记得历史操作符引用某个变量历史数据吧Jika ada posisi saat ini, maka pada saat ini, panggilan fungsi reverse order akan menghapuskan posisi sebelumnya, dan kemudian membuka posisi sesuai dengan arah perdagangan saat ini.supertrend > supertrend[2]Kondisi tidak tercapai, hanya saja saat inistrategy.position_size < 0Ini juga dapat memicu risiko yang lebih besar untuk investor yang memiliki posisi kosong.strategy.close_all()Eksekusi fungsi, melakukan seluruh posisi kosong.
direction > 0Pada fase downtrend juga sama, jika ada banyak pemegang posisi, semuanya akan terhapus, dan kemudian memenuhi syarat.supertrend < supertrend[3]Ini adalah salah satu alasan mengapa Anda harus mengaturnya sebagai[3]Bagaimana dengan referensi data harga indikator supertrend pada BAR ke-3? Mungkin ini adalah maksud dari penulis strategi, karena di beberapa pasar seperti pasar kontrak perdagangan, risiko shorting sedikit lebih besar daripada risiko over.
untukta.supertrendApakah ada teman-teman yang tertarik dengan indikator ini, dan bagaimana cara menentukan apakah tren saat ini naik atau turun?
Indikator ini juga dapat diimplementasikan dalam bentuk fungsi khusus dalam bahasa Pine:
pine
pine_supertrend(factor, atrPeriod) =>
src = hl2
atr = ta.atr(atrPeriod)
upperBand = src + factor * atr
lowerBand = src - factor * atr
prevLowerBand = nz(lowerBand[1])
prevUpperBand = nz(upperBand[1])
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
int direction = na
float superTrend = na
prevSuperTrend = superTrend[1]
if na(atr[1])
direction := 1
else if prevSuperTrend == prevUpperBand
direction := close > upperBand ? -1 : 1
else
direction := close < lowerBand ? 1 : -1
superTrend := direction == -1 ? lowerBand : upperBand
[superTrend, direction]
Fungsi kustom ini adalah fungsi built-in.ta.supertrendAlgoritma yang sama, tentu saja data indikator yang dihitung juga sama.
Dari algoritma fungsi kustom ini kita dapat melihat bahwa indikator supertrend yang ada di dalam Pine digunakan untuk menghitunghl2Variabel internal ((harga tertinggi, harga terendah ditambah kemudian dibagi dengan 2, yaitu rata-rata harga tertinggi dan harga terendah), kemudian menghitung indikator ATR untuk periode tertentu berdasarkan parameteratrPeriod ((amplitude)) Kemudian menggunakan hl2 dan ATR untuk membangun up-track, down-track.
Pembaruan berdasarkan ekspresi trigonometri dalam kodelowerBandDanupperBand。
pine
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
lowerBand: garis bawah, digunakan untuk menentukan apakah ada perubahan tren ke atas. upperBand: garis atas, digunakan untuk menentukan apakah ada perubahan tren ke bawah. lowerBand dan upperBand terus dihitung, hanya pada fungsi yang disesuaikan ini akhirnya menentukan arah tren saat ini.
pine
else if prevSuperTrend == prevUpperBand
direction := close > upperBand ? -1 : 1
else
direction := close < lowerBand ? 1 : -1
Jadi, jika nilai dari supertrend di BAR sebelumnya adalahprevUpperBand, yaitu garis atas, yang menunjukkan tren saat ini adalah tren ke bawah.closeLebih dariupperBandHarga terobosan, yang berarti bahwa saat ini tren bergeser, berubah menjadi tren naik.directionJika Anda tidak melihat perubahan arah dalam strategi supertrend, maka Anda akan melihat perubahan arah dalam strategi supertrend. Jadi jika Anda melihat perubahan arah dalam strategi supertrend, Anda akan melihat perubahan arah dalam strategi supertrend.if direction < 0Saat itu, kondisi sinyal memicu lebih banyak.direction > 0Saat, kondisi sinyal menyalakan dan kemudian kosongkan.
pine
superTrend := direction == -1 ? lowerBand : upperBand
[superTrend, direction]
Akhirnya, data harga indikator supertrend dan data arah dipilih berdasarkan arah.
Strategi Keseimbangan Dinamis
pine
/*backtest
start: 2021-03-01 00:00:00
end: 2022-09-08 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["v_input_1",4374],["v_input_2",3],["v_input_3",300],["ZPrecision",0,358374]]
*/
varip balance = input(50000, "balance")
varip stocks = input(0, "stocks")
maxDiffValue = input(1000, "maxDiffValue")
if balance - close * stocks > maxDiffValue and not barstate.ishistory
// more balance , open long
tradeAmount = (balance - close * stocks) / 2 / close
strategy.order("long", strategy.long, tradeAmount)
balance := balance - tradeAmount * close
stocks := stocks + tradeAmount
runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)
else if close * stocks - balance > maxDiffValue and not barstate.ishistory
// more stocks , open short
tradeAmount = (close * stocks - balance) / 2 / close
strategy.order("short", strategy.short, tradeAmount)
balance := balance + tradeAmount * close
stocks := stocks - tradeAmount
runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)
plot(balance, title="balance value(quoteCurrency)", color=color.red)
plot(stocks*close, title="stocks value(quoteCurrency)", color=color.blue)
Kami terus mempelajari beberapa contoh desain strategi bahasa Pine, kali ini kita akan melihat strategi keseimbangan dinamis.BaseCurrencyJumlah (varietas yang diperdagangkan) danQuoteCurrencyJika harga relatif dari suatu aset meningkat, nilai yang dipegang di akun meningkat, maka akan dijual aset mana. Jika harga relatif dari suatu aset menurun, nilai yang dipegang di akun berkurang, maka akan dibeli aset tersebut. Ini adalah strategi yang disebut strategi keseimbangan dinamis.
Kelemahan strategi ini seperti yang ditunjukkan pada grafik pengukuran strategi ini, pada fase tren harga besar naik (atau turun) strategi ini lebih besar. Jadi strategi ini baik untuk strategi tunai, dan menggunakan strategi berjangka membutuhkan pengendalian risiko.
Mari kita lihat desain kode strategi:
Kami menggunakan desain sederhana untuk mensimulasikan strategibalance(yaitu jumlah aset QuoteCurrency) danstocks(yaitu jumlah aset BaseCurrency) informasi keseimbangan. Kita tidak membaca jumlah aset yang sebenarnya dalam rekening, kita hanya menggunakan jumlah simulasi untuk menghitung pembelian dan penjualan yang sesuai.maxDiffValue, parameter ini adalah kriteria untuk melakukan keseimbangan. Pada harga saat ini, hanya jikaBaseCurrencyDanQuoteCurrencyKecurangan melebihimaxDiffValueIni adalah waktu untuk menyeimbangkan, menjual aset yang lebih mahal, membeli aset yang lebih murah, dan menyeimbangkan kembali aset.
Trigger sinyal perdagangan strategi harus masuk akal pada tahap BAR real-time, sehingga kondisi perdagangan strategi diatur dalam penilaian ifnot barstate.ishistory◦ Jika dihitung berdasarkan harga saat ini,balanceNilai lebih daristocksPembelian dilakukan pada saat nilai. Sebaliknya, operasi penjualan dilakukan. Pembaruan dilakukan setelah pernyataan transaksibalanceDanstocksVariabel, dan kemudian menanti pemicu keseimbangan berikutnya.
Informasi yang ada di atas adalah harga varietas pada saat penelusuran dimulai, yaitu harga 1458, jadi saya sengaja mengatur parameterbalanceJadi: 43741458*3), pengaturan parameterstocksUntuk: 3. Pastikan aset berada dalam keadaan seimbang pada awalnya.
Strategi Supertrend dengan Pelacakan Stop Loss
Dalam pelajaran sebelumnya kita telah belajar bahwastrategy.exitFungsi out of position, dimana fungsi tracking stop loss stop we have no examples to explain. Dalam contoh desain strategi ini kita akan menggunakanstrategy.exitFungsi Tracking Stop Loss Stop function untuk mengoptimalkan strategi supertrend.
Pertama kita lihat.strategy.exitParameter Stop Loss Tracking untuk fungsi:
1、trail_priceParameter: memicu penempatan tracking stop loss stop loss pada posisi yang sesuai dengan tindakan logis (diposisi yang ditentukan dengan harga).
2、trail_offsetParameter: Setelah melakukan tindakan tracking stop loss, jarak yang ditempatkan dari satuan posisi kosong dari harga tertinggi ((waktu melakukan banyak) atau harga terendah ((waktu melakukan kosong))
3、trail_pointsParameter: samatrail_priceParameter, hanya ditunjuk sebagai posisi dengan jumlah keuntungan.
Tidak masalah jika itu sulit untuk dipahami, kita bisa memahaminya dengan mempertimbangkan sebuah skenario, yang sebenarnya sangat sederhana.
pine
/*backtest
start: 2022-09-23 00:00:00
end: 2022-09-23 08:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/
strategy("test", overlay = true)
varip a = na
varip highPrice = na
varip isTrade = false
varip offset = 30
if not barstate.ishistory and not isTrade
strategy.entry("test 1", strategy.long, 1)
strategy.exit("exit 1", "test 1", 1, trail_price=close+offset, trail_offset=offset)
a := close + offset
runtime.log("每点价格为:", syminfo.mintick, ",当前close:", close)
isTrade := true
if close > a and not barstate.ishistory
highPrice := na(highPrice) ? close : highPrice
highPrice := close > highPrice ? close : highPrice
plot(a, "trail_price 触发线")
plot(strategy.position_size>0 ? highPrice : na, "当前最高价")
plot(strategy.position_size>0 ? highPrice-syminfo.mintick*offset : na, "移动止损触发线")
Strategi ini dimulai dengan segera multi-headed entry, dan kemudian segera berikutnyastrategy.exitPerintah keluar ((menentukan parameter tracking stop loss), mulai menjalankan logika tracking stop loss ketika harga naik melebihi garis pemicu trail_price, stop loss line ((biru)) mulai mengikuti perubahan harga tertinggi, posisi garis biru adalah harga yang memicu stop loss untuk posisi terdepan, dan akhirnya ketika harga turun di bawah garis biru untuk posisi terdepan. Dengan demikian, garis yang digambar pada grafik tidak mudah dipahami.
Jadi kita menggunakan fitur ini untuk mengoptimalkan strategi supertrend, kita hanya memberikan satu entry order untuk strategi.strategy.exitPada daftar jadwal, Anda dapat menambahkan fitur tracking dan stop loss.
pine
if not barstate.ishistory and findOrderIdx("open") >= 0 and state == 1
trail_price := strategy.position_size > 0 ? close + offset : close - offset
strategy.exit("exit", "open", 1, trail_price=trail_price, trail_offset=offset)
runtime.log("每点价格为:", syminfo.mintick, ",当前close:", close, ",trail_price:", trail_price)
state := 2
tradeBarIndex := bar_index
Kode strategi lengkap:
pine
/*backtest
start: 2022-05-01 00:00:00
end: 2022-09-27 00:00:00
period: 1d
basePeriod: 5m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/
varip trail_price = na
varip offset = input(50, "offset")
varip tradeBarIndex = 0
// 0 : idle , 1 current_open , 2 current_close
varip state = 0
findOrderIdx(idx) =>
ret = -1
if strategy.opentrades == 0
ret
else
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == idx
ret := i
break
ret
if strategy.position_size == 0
trail_price := na
state := 0
[superTrendPrice, dir] = ta.supertrend(input(2, "atr系数"), input(20, "atr周期"))
if ((dir[1] < 0 and dir[2] > 0) or (superTrendPrice[1] > superTrendPrice[2])) and state == 0 and tradeBarIndex != bar_index
strategy.entry("open", strategy.long, 1)
state := 1
else if ((dir[1] > 0 and dir[2] < 0) or (superTrendPrice[1] < superTrendPrice[2])) and state == 0 and tradeBarIndex != bar_index
strategy.entry("open", strategy.short, 1)
state := 1
// 反向信号,全平
if strategy.position_size > 0 and dir[2] < 0 and dir[1] > 0
strategy.cancel_all()
strategy.close_all()
runtime.log("趋势反转,多头全平")
else if strategy.position_size < 0 and dir[2] > 0 and dir[1] < 0
strategy.cancel_all()
strategy.close_all()
runtime.log("趋势反转,空头全平")
if not barstate.ishistory and findOrderIdx("open") >= 0 and state == 1
trail_price := strategy.position_size > 0 ? close + offset : close - offset
strategy.exit("exit", "open", 1, trail_price=trail_price, trail_offset=offset)
runtime.log("每点价格为:", syminfo.mintick, ",当前close:", close, ",trail_price:", trail_price)
state := 2
tradeBarIndex := bar_index
plot(superTrendPrice, "superTrendPrice", color=dir>0 ? color.red : color.green, overlay=true)
- 1




















