Jadi kita lihat bahwa pada tiga garis a, b, dan c, garis b adalah satu BAR lebih lambat dari garis a, dan garis c adalah satu BAR lebih lambat dari garis b.
Kita dapat menarik grafik ke kiri jauh dan mengamati bahwa pada garis K pertama, kedua nilai b dan c adalah nol (na). Ini karena ketika skrip dijalankan pada garis K pertama BAR, tidak ada ketika merujuk pada nilai historis satu atau dua periode ke depan, yang tidak ada. Oleh karena itu, kita perlu berhati-hati ketika menulis strategi untuk memeriksa apakah referensi data historis akan menghasilkan nilai nol. Jika nilai nol digunakan dengan ceroboh, itu akan menyebabkan serangkaian perbedaan perhitungan, dan bahkan dapat mempengaruhi BAR real-time. Biasanya kita akan menggunakan fungsi built-inna
, nz
untuk menilai dalam kode (sebenarnya, kita juga telah menemukannz
, ```na `` dalam video kami sebelumnya, apakah Anda ingat bab mana itu?) menangani kasus nilai nol, misalnya:
close > nz(close[1], open) // When referencing the historical value of the previous BAR of the close built-in variable, if it does not exist, the open built-in variable is used
Ini adalah cara untuk menangani kemungkinan referensi ke nilai nol (na).
Kita telah belajar banyak operator dalam bahasa Pine. Operator ini membentuk ekspresi melalui berbagai kombinasi dengan operand. Jadi apa prioritas operasi ini ketika mengevaluasi dalam ekspresi? Sama seperti aritmatika yang kita pelajari di sekolah, perkalian dan pembagian dihitung terlebih dahulu, diikuti dengan penjumlahan dan pengurangan. Hal yang sama berlaku untuk ekspresi dalam bahasa Pine.
Prioritas | Operator |
---|---|
9 | [] |
8 | + 、- dannot dalam operator unary |
7 | * 、/ 、% |
6 | + 、- dalam operator biner |
5 | > 、< 、>= 、<= |
4 | == 、!= |
3 | and |
2 | or |
1 | ?: |
Ekspresi prioritas tinggi dihitung terlebih dahulu, dan jika prioritasnya sama, dievaluasi dari kiri ke kanan.()
untuk membungkus ekspresi untuk memaksa bagian yang akan dievaluasi terlebih dahulu.
Kita sudah mempelajari konsep
Mode Deklarasi:
Hal pertama yang harus ditulis saat mendeklarasikan variabel adalah
var
.varip
.Peraturanvar
danvarip
kata kunci telah benar-benar dipelajari dalam bab kami sebelumnya padaAssignment Operators
Jika tidak ada yang ditulis untuk mode deklarasi variabel, seperti pernyataan:i = 1
, seperti yang telah kami sebutkan sebelumnya, variabel tersebut dinyatakan dan ditugaskan dijalankan pada setiap K-line BAR.
Jenis Bahasa Pine pada FMZ tidak ketat tentang jenis, dan umumnya dapat dihilangkan. Namun, untuk kompatibel dengan strategi skrip pada Trading View, variabel juga dapat dinyatakan dengan jenis.
int i = 0
float f = 1.1
Persyaratan tipe pada Trading View cukup ketat, dan kesalahan akan dilaporkan jika kode berikut digunakan pada Trading View:
baseLine0 = na // compile time error!
Penanda Penanda adalah nama variabel. Penamaan penanda telah disebutkan dalam bab-bab sebelumnya, sehingga Anda dapat meninjau di sini:https://www.fmz.com/bbs-topic/9637#markers
Singkatnya, mendeklarasikan variabel dapat ditulis sebagai:
// [<declaration_mode>] [<type>] <marker> = value
declaration mode type marker = value
Operator penugasan digunakan di sini:=
menugaskan nilai untuk variabel ketika dinyatakan. Saat menugaskan nilai dapat menjadi string, angka, ekspresi, panggilan fungsi,if
, for
, while
, atauswitch
dan struktur lainnya (kata kunci struktural dan penggunaan pernyataan ini akan dijelaskan secara rinci dalam kursus berikutnya.
Di sini kita fokus pada fungsi input, yang merupakan fungsi yang akan kita gunakan sering ketika merancang dan menulis strategi.
Fungsi input:
input function, parameters: defval、title、tooltip、inline、group
Fungsi input pada FMZ agak berbeda dari pada Trading View, tetapi fungsi ini digunakan sebagai input penugasan parameter strategi.
param1 = input(10, title="name of param1", tooltip="description for param1", group="group name A")
param2 = input("close", title="name of param2", tooltip="description for param2", group="group name A")
param3 = input(color.red, title="name of param3", tooltip="description for param3", group="group name B")
param4 = input(close, title="name of param4", tooltip="description for param4", group="group name B")
param5 = input(true, title="name of param5", tooltip="description for param5", group="group name C")
ma = ta.ema(param4, param1)
plot(ma, title=param2, color=param3, overlay=param5)
Fungsi input sering digunakan untuk menetapkan nilai pada variabel saat mendeklarasinya. Fungsi input pada FMZ menarik kontrol untuk mengatur parameter strategi secara otomatis di antarmuka strategi FMZ. Kontrol yang didukung pada FMZ saat ini termasuk kotak input numerik, kotak input teks, kotak drop-down, dan kotak centang Boolean. Dan Anda dapat mengatur pengelompokan parameter strategi, mengatur pesan teks prompt parameter dan fungsi lainnya.
Kami memperkenalkan beberapa parameter utama dari fungsi input:
Selain deklarasi dan penugasan variabel individu, ada juga cara untuk mendeklarasikan sekelompok variabel dan menugaskannya dalam bahasa Pine:
[Variable A, Variable B, Variable C] = function or structure, such as ```if```, ```for```, ```while``` or ```switch```
Yang paling umum adalah ketika kita menggunakanta.macd
fungsi untuk menghitung indikator MACD, karena indikator MACD adalah indikator multi-line, tiga set data dihitung.
[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)
Kita dapat menggambar grafik MACD menggunakan kode di atas dengan mudah. Tidak hanya fungsi built-in dapat kembali ke beberapa variabel, tetapi juga fungsi kustom tertulis dapat kembali ke beberapa data.
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)
Metode menulis menggunakan if dan struktur lain sebagai penugasan variabel ganda juga mirip dengan fungsi kustom di atas, dan Anda dapat mencobanya jika Anda tertarik.
[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)
Beberapa fungsi tidak dapat ditulis dalam blok kode lokal dari cabang bersyarat, terutama termasuk fungsi berikut:
barcolor ((), fill ((), hline ((), indicator ((), plot ((), plotcandle ((), plotchar ((), plotshape (()
Trading View akan mengkompilasi dengan kesalahan, FMZ tidak begitu membatasi, tetapi disarankan untuk mengikuti spesifikasi Trading View.
strategy("test", overlay=true)
if close > open
plot(close, title="close")
else
plot(open, title="open")
Contoh penjelasan:
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)
Poin penting: Ekspresi yang digunakan untuk penilaian yang mengembalikan nilai Boolean. Perhatikan indentasi. Ada paling banyak satu cabang lain. Jika semua ekspresi cabang tidak benar dan tidak ada cabang lain, kembali ke na.
x = if close > open
close
plot(x, title="x")
Pernyataan switch juga merupakan pernyataan terstruktur cabang, yang digunakan untuk merancang jalur yang berbeda untuk dieksekusi sesuai dengan kondisi tertentu.
Ada dua bentuk switch, mari kita lihat contohnya satu per satu untuk memahami penggunaannya.
switch
dengan ekspresi - contoh penjelasan:// input.string: defval, title, options, tooltip
func = input.string("EMA", title="indicator name", tooltip="select the name of the indicator function to be used", options=["EMA", "SMA", "RMA", "WMA"])
// input.int: defval, title, options, tooltip
// param1 = input.int(10, title="period parameter")
fastPeriod = input.int(10, title="fastPeriod parameter", options=[5, 10, 20])
slowPeriod = input.int(20, title="slowPeriod parameter", options=[20, 25, 30])
data = input(close, title="data", tooltip="select the closing price, opening price, highest price...")
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)
Kita belajar fungsi input sebelumnya, di sini kita terus belajar dua fungsi yang mirip dengan input:input.string
, input.int
functions.
input.string
digunakan untuk mengembalikan string, daninput.int
fungsi digunakan untuk mengembalikan nilai bilangan bulat. Dalam contoh, ada penggunaan baru darioptions
parameter.options
parameter dapat dilewati array dari nilai opsional, sepertioptions=["EMA", "SMA", "RMA", "WMA"]
danoptions=[5, 10, 20]
Dengan cara ini, kontrol pada antarmuka strategi tidak perlu memasukkan nilai tertentu, tetapi kontrol menjadi kotak drop-down untuk memilih opsi yang disediakan dalam parameter opsi.
Nilai dari variabel func adalah string, dan variabel func digunakan sebagai ekspresi untuk switch (yang bisa menjadi variabel, panggilan fungsi, atau ekspresi) untuk menentukan cabang mana di switch yang dieksekusi.runtime.error("error")
fungsi akan dieksekusi, menyebabkan strategi untuk melemparkan pengecualian dan berhenti.
Dalam kode uji kami di atas, setelah baris terakhir runtime.error di blok kode cabang default switch, kami tidak menambahkan kode seperti [na, na] untuk kompatibel dengan nilai return. Masalah ini perlu dipertimbangkan di Trading View. Jika tipe tidak konsisten, kesalahan akan dilaporkan. Tetapi di FMZ, karena tipe tidak benar-benar diperlukan, kode kompatibilitas ini dapat dihilangkan. Oleh karena itu, tidak perlu mempertimbangkan kompatibilitas tipe dari nilai return if dan switch branches di FMZ.
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 yang akan dilaporkan pada FMZ, tetapi kesalahan akan dilaporkan pada trading view. Karena tipe yang dikembalikan oleh if branch tidak konsisten.
switch
tanpa ekspresiSelanjutnya, mari kita lihat cara lain untuk menggunakanswitch
, yaitu, tanpa ekspresi.
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)
Seperti yang dapat kita lihat dari contoh kode uji, switch akan sesuai dengan eksekusi blok kode lokal yang benar pada kondisi cabang. Secara umum, kondisi cabang setelah pernyataan switch harus saling eksklusif. Artinya, atas dan bawah dalam contoh tidak dapat benar pada saat yang sama. Karena switch hanya dapat mengeksekusi blok kode lokal dari satu cabang, jika Anda tertarik, Anda dapat mengganti baris ini dalam kode:up = close > open // up = close < open
Anda akan menemukan bahwa switch branch hanya dapat mengeksekusi branch pertama. Selain itu perlu untuk memperhatikan untuk tidak menulis panggilan fungsi di branch switch sebanyak mungkin, fungsi tidak dapat dipanggil pada setiap BAR dapat menyebabkan beberapa masalah perhitungan data (kecuali seperti dalam contoh "switch
dengan ekspresi", cabang eksekusi adalah deterministik dan tidak akan diubah selama operasi strategi).
return value = for count = start count to final count by step length
statement // Note: There can be break and continue in the statement
statement // Note: The last statement is the return value
Pernyataan for sangat sederhana untuk digunakan, loop for akhirnya dapat mengembalikan nilai (atau beberapa nilai, dalam bentuk [a, b, c]). Seperti variabel yang ditugaskan ke posisi
Peraturanbreak
kata kunci yang digunakan dalam loop for: loop berhenti ketikabreak
pernyataan dieksekusi.
Peraturancontinue
Kata kunci yang digunakan dalam loop for:continue
pernyataan dijalankan, loop akan mengabaikan kode setelahcontinue
dan mengeksekusi putaran berikutnya dari loop secara langsung. pernyataan for kembali ke nilai kembali dari eksekusi terakhir loop. dan kembali null jika tidak ada kode yang dijalankan.
Kemudian kita menunjukkan dengan contoh sederhana:
ret = for i = 0 to 10 // We can increase the keyword by to modify the step length, FMZ does not support reverse loops such as i = 10 to 0 for now
// We can add condition settings, use continue to skip, use break to jump out
runtime.log("i:", i)
i // If this line is not written, it will return null because there is no variable to return
runtime.log("ret:", ret)
runtime.error("stop")
Peraturanfor ... in
pernyataan memiliki dua bentuk, kita akan menggambarkan mereka dalam pseudocode berikut.
return value = for array element in array
statement // Note: There can be break and continue in the statement
statement // Note: The last statement is the return value
Return value = for [index variable, array element corresponding to index variable] in array
statement // Note: There can be break and continue in the statement
statement // Note: The last statement is the return value
Kita dapat melihat bahwa perbedaan utama antara kedua bentuk adalah konten yang mengikuti kata kunci for, satu adalah menggunakan variabel sebagai variabel yang mengacu pada elemen array, yang lain adalah menggunakan struktur yang berisi variabel indeks, tuples variabel elemen array sebagai referensi. Untuk aturan nilai return lainnya, seperti menggunakan break, continue, dll, konsisten dengan untuk loop.
testArray = array.from(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for ele in testArray // Modify it to the form of [i, ele]: for [i, ele] in testArray, runtime.log("ele:", ele, ", i:", i)
runtime.log("ele:", ele)
runtime.error("stop")
Ketika perlu menggunakan indeks, gunakan tata bahasafor [i, ele] in testArray
.
Aplikasi untuk loop
Kita dapat menggunakan fungsi built-in yang disediakan dalam bahasa Pine untuk menyelesaikan beberapa perhitungan logika loop, baik ditulis dengan menggunakan struktur loop secara langsung atau diproses dengan menggunakan fungsi built-in.
Saat merancang dengan struktur lingkaran:
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)
Contoh menggunakan loop for untuk menghitung jumlah dan kemudian menghitung nilai rata-rata.
Menghitung rata-rata bergerak langsung menggunakan fungsi built-in:
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Gunakan fungsi built-inta.sma
dengan menggunakan indikator rata-rata bergerak secara langsung. jelas, lebih sederhana untuk menggunakan fungsi built-in untuk menghitung rata-rata bergerak. dengan membandingkan pada grafik, dapat dilihat bahwa hasil yang dihitung persis sama.
Kami masih menggunakan contoh di atas untuk menggambarkan.
Saat merancang dengan struktur lingkaran:
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 dalam array, kita dapat menggunakan loop untuk memprosesnya, atau menggunakan fungsi built-inarray.sum
untuk menghitung.
Menghitung jumlah langsung menggunakan fungsi built-in:
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)
Kita dapat melihat data yang dihitung adalah persis sama dengan yang ditampilkan pada grafik menggunakan plot.
Jadi mengapa mendesain loop ketika kita bisa melakukan semua ini dengan fungsi built-in? penggunaan loop terutama didasarkan pada penerapan 3 poin ini:
Peraturanwhile
pernyataan menjaga kode dalam bagian loop yang dijalankan sampai kondisi penilaian dalam while struktur adalah false.
return value = while judgment condition
statement // Note: There can be break and continue in the statement
statement // Note: The last statement is the return value
Aturan lain while mirip dengan yang untuk loop. baris terakhir dari blok kode lokal dari tubuh loop adalah nilai return, yang dapat mengembalikan beberapa nilai. Mengeksekusi loop ketika
Kita masih akan menggunakan contoh perhitungan rata-rata bergerak untuk demonstrasi:
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)
Kita dapat melihat bahwa loop sementara juga sangat sederhana untuk digunakan, dan juga mungkin untuk merancang beberapa logika perhitungan yang tidak dapat digantikan oleh fungsi built-in, seperti menghitung faktorial:
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
Definisi array dalam bahasa Pine mirip dengan bahasa pemrograman lainnya. Array Pine adalah array satu dimensi. Biasanya digunakan untuk menyimpan serangkaian data berkelanjutan. Data tunggal yang disimpan dalam array disebut elemen array, dan jenis elemen ini dapat: integer, floating point, string, nilai warna, nilai boolean. Bahasa Pine pada FMZ tidak terlalu ketat tentang jenis, dan bahkan dapat menyimpan string dan angka dalam array pada saat yang sama. Karena struktur dasar array juga merupakan struktur seri, jika operator historis digunakan untuk merujuk pada keadaan array pada BAR sebelumnya.[]
untuk merujuk pada elemen dalam array, kita perlu menggunakan fungsiarray.get()
danarray.set()
Urutan indeks elemen dalam array adalah bahwa indeks elemen pertama array adalah 0, dan indeks elemen berikutnya ditingkatkan dengan 1.
Kami mengilustrasikannya dengan kode sederhana:
var a = array.from(0)
if bar_index == 0
runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1])
else if bar_index == 1
array.push(a, bar_index)
runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1])
else if bar_index == 2
array.push(a, bar_index)
runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1], ", a on the last second BAR, i.e. the value of a[2]:", a[2])
else if bar_index == 3
array.push(a, bar_index)
runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1], ", a on the last second BAR, i.e. the value of a[2]:", a[2], ", a on the last third BAR, i.e. the value of a[3]:", a[3])
else if bar_index == 4
// Obtain elements by index using array.get, modify elements by index using array.set
runtime.log("Before array modification:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
array.set(a, 1, 999)
runtime.log("After array modification:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
Penggunaanarray<int> a
, float[] b
untuk mendeklarasikan array atau hanya mendeklarasikan variabel yang dapat ditugaskan array, misalnya:
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")
Variabel array diinisialisasi dengan menggunakanarray.new
danarray.from
Ada juga banyak fungsi yang berhubungan dengan jenis yang mirip denganarray.newdalam bahasa Pine:array.new_int()
, array.new_bool()
, array.new_color()
, array.new_string()
, dll.
Kata kunci var juga bekerja dengan mode deklarasi array. Array yang dinyatakan dengan kata kunci var hanya diinisialisasi pada BAR pertama. Mari kita amati dengan contoh:
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 array a telah terus ditentukan dan belum diatur kembali. array b diinisialisasi pada setiap BAR. Akhirnya, ketikabarstate.islast
adalah benar, masih ada hanya satu elemen dicetak dengan nilai 0.
Gunakan array.get untuk mendapatkan elemen di posisi indeks yang ditentukan dalam array, dan gunakan array.set untuk memodifikasi elemen di posisi indeks yang ditentukan dalam array.
Parameter pertama array.get adalah array yang akan diproses, dan parameter kedua adalah indeks yang ditentukan. Parameter pertama array.set adalah array yang akan diproses, parameter kedua adalah indeks yang ditentukan, dan parameter ketiga adalah elemen yang akan ditulis.
Kami menggunakan contoh sederhana berikut untuk menggambarkan:
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 menginisialisasi warna dasar hijau, menyatakan dan menginisialisasi array untuk menyimpan warna, dan kemudian menetapkan nilai transparansi yang berbeda untuk warna (dengan menggunakancolor.newTingkat warna dihitung dengan menghitung jarak BAR saat ini dari nilai maksimum tinggi dalam 100 periode lookback. Semakin dekat jarak ke nilai maksimum HIGH dalam 100 siklus lookback terakhir, semakin tinggi peringkat dan semakin gelap (transparansi lebih rendah) nilai warna yang sesuai. Banyak strategi serupa menggunakan metode ini untuk mewakili tingkat harga saat ini dalam N periode lookback.
Cara mengulangi melalui array, kita bisa menggunakan for/for in/while statement yang kita pelajari sebelumnya.
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")
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")
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 traversal ini memiliki hasil eksekusi yang sama.
Array dapat dinyatakan dalam ruang lingkup global skrip, atau dalam ruang lingkup lokal fungsi atau jika cabang.
Untuk penggunaan elemen dalam array, cara berikut ini setara. kita dapat melihat dengan contoh berikut bahwa dua set garis digambar pada bagan, dua di setiap set, dan dua garis di setiap set memiliki nilai yang sama persis.
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)
array.unshift()
, array.insert()
, array.push()
.
array.remove()
, array.shift()
, array.pop()
, array.clear()
.
Kami menggunakan contoh berikut untuk menguji fungsi operasi penjumlahan dan penghapusan array ini.
a = array.from("A", "B", "C")
ret = array.unshift(a, "X")
runtime.log("array a:", a, ", ret:", ret)
ret := array.insert(a, 1, "Y")
runtime.log("array a:", a, ", ret:", ret)
ret := array.push(a, "D")
runtime.log("array a:", a, ", ret:", ret)
ret := array.remove(a, 2)
runtime.log("array a:", a, ", ret:", ret)
ret := array.shift(a)
runtime.log("array a:", a, ", ret:", ret)
ret := array.pop(a)
runtime.log("array a:", a, ", ret:", ret)
ret := array.clear(a)
runtime.log("array a:", a, ", ret:", ret)
runtime.error("stop")
Aplikasi penambahan, penghapusan: array sebagai antrian
Kita dapat membangun struktur data
Antrian adalah struktur yang sering digunakan dalam bidang pemrograman, karakteristik antrian adalah:
Elemen yang masuk ke antrian pertama, meninggalkan antrian pertama.
Dengan cara ini, ia memastikan bahwa data dalam antrian adalah data terbaru, dan bahwa panjang antrian tidak akan berkembang tanpa batas.
Dalam contoh berikut, kita menggunakan struktur antrian untuk mencatat harga setiap tik, menghitung harga rata-rata bergerak pada tingkat tik, dan kemudian membandingkannya dengan rata-rata bergerak pada tingkat garis K 1 menit.
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 mendeklarasikan array a, kita menentukan mode deklarasi dan menggunakan kata kuncivariant
Dengan cara ini, setiap perubahan harga akan dicatat dalam array a.
Menghitung fungsi korelasi:
array.avg()
menghitung nilai rata-rata dari semua elemen dalam array,array.min()
menghitung elemen terkecil dalam array,array.max()
menghitung elemen terkecil dalam array,array.stdev()
menghitung standar deviasi dari semua elemen dalam array,array.sum()
menghitung standar deviasi dari semua elemen dalam array.
Fungsi yang berhubungan dengan operasi:array.concat()
untuk menggabungkan atau konkaten dua array.array.copy()
untuk menyalin array.array.join
untuk mengkonkaten semua elemen array ke dalam string.array.sort()
untuk menyortir dengan naik atau turun urutan.array.reverse()
untuk membalikkan array.array.slice()
untuk memotong array.array.includes()
untuk menilai elemen.array.indexof()
untuk kembali ke indeks kejadian pertama dari nilai yang diteruskan sebagai parameter. Jika nilai tidak ditemukan, -1 akan dikembalikan.array.lastindexof()
untuk menemukan kejadian terakhir dari nilai.
Contoh pengujian fungsi terkait perhitungan array:
a = array.from(3, 2, 1, 4, 5, 6, 7, 8, 9)
runtime.log("Arithmetic average of the array a:", array.avg(a))
runtime.log("The minimum element in the array a:", array.min(a))
runtime.log("The maximum element in the array a:", array.max(a))
runtime.log("Standard deviation in array a:", array.stdev(a))
runtime.log("Sum of all elements of the array a:", array.sum(a))
runtime.error("stop")
Ini adalah fungsi perhitungan array yang umum digunakan.
Contoh fungsi yang terkait dengan operasi:
a = array.from(1, 2, 3, 4, 5, 6)
b = array.from(11, 2, 13, 4, 15, 6)
runtime.log("array a: ", a, ", array b: ", b)
runtime.log("array a, array b is concatenated with:", array.concat(a, b))
c = array.copy(b)
runtime.log("Copy an array b and assign it to the variable c, variable c:", c)
runtime.log("use array.join to process the array c, add the symbol + to the middle of each element, concatenating all elements results in a string:", array.join(c, "+"))
runtime.log("Sort the array b, in order from smallest to largest, using the parameter order.ascending:", array.sort(b, order.ascending)) // array.sort function modifies the original array
runtime.log("Sort the array b, in order from largest to smallest, using the parameter order.descending:", array.sort(b, order.descending)) // array.sort function modifies the original array
runtime.log("array a:", a, ", array b:", b)
array.reverse(a) // This function modifies the original array
runtime.log("reverse the order of all elements in the array a, after reversing, the array a is:", a)
runtime.log("Intercept array a, index 0~index 3, and follow the rule of left-closed and right-open interval:", array.slice(a, 0, 3))
runtime.log("Search for element 11 in array b:", array.includes(b, 11))
runtime.log("Search for element 100 in array a:", array.includes(a, 100))
runtime.log("Connect array a and array b, and search the index position of the first occurrence of element 2:", array.indexof(array.concat(a, b), 2), " , observe array.concat(a, b):", array.concat(a, b))
runtime.log("Connect array a and array b, and search the index position of the last occurrence of element 6:", array.lastindexof(array.concat(a, b), 6), " , observe array.concat(a, b):", array.concat(a, b))
runtime.error("stop")
Bahasa Pine dapat dirancang dengan fungsi kustom. Secara umum, aturan berikut diterapkan pada fungsi kustom dalam bahasa Pine:
barcolor(), fill(), hline(), plot(), plotbar(), plotcandle()
) tidak dapat dipanggil dalam fungsi kustom.Kami juga telah menggunakan fungsi kustom untuk banyak kali dalam tutorial kami sebelumnya, seperti yang dirancang sebagai satu baris:
barIsUp() => close > open
Apakah BAR saat ini adalah garis positif ketika fungsi kembali.
Fungsi khusus yang dirancang untuk menjadi beberapa baris:
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)
Kami menggunakan fungsi khusus untuk mewujudkan fungsi perhitungan rata-rata sma.
Selain itu, dua contoh fungsi kustom yang bisa kita kembalikan:
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)
Satu fungsi dapat menghitung garis cepat, garis lambat dan dua rata-rata EMA.
Fungsi built-in dapat dengan mudah ditemukan diDokumen skrip FMZ PINE.
Klasifikasi fungsi bawaan dalam bahasa Pine:
str.
series.color.
series.input.
series.ta.
series.plot.
series.array.
series.strategy.
series.math.
series.request.
fungsi seri, fungsi penanganan tipe, dll.)Peraturanstrategy.
Serangkaian fungsi adalah fungsi yang sering kita gunakan dalam desain strategi, dan fungsi ini terkait erat dengan pelaksanaan operasi perdagangan ketika strategi berjalan secara khusus.
strategy.entry
strategy.entry
fungsi adalah fungsi yang lebih penting ketika kita menulis strategi untuk menempatkan pesanan, beberapa parameter penting untuk fungsi adalah:id
, direction
, qty
, when
, dll.
Parameter:
id
: Ini dapat dipahami sebagai memberikan nama untuk posisi perdagangan untuk referensi.direction
: Jika arah pesanan panjang (beli), masukkan variabel bawaanstrategy.long
, dan jika Anda ingin pergi pendek (menjual), lulus dalam variabelstrategy.short
.qty
: Tentukan jumlah pesanan yang akan ditempatkan, jika parameter ini tidak dilewati, jumlah pesanan default akan digunakan.when
: Kondisi eksekusi, Anda dapat menentukan parameter ini untuk mengontrol apakah operasi order saat ini dipicu atau tidak.limit
: Tentukan harga batas pesanan.stop
Harga stop loss.Rincian pelaksanaan khususstrategy.entry
fungsi dikendalikan oleh pengaturan parameter ketikastrategy
fungsi disebut, dan juga dapat dikendalikan oleh [
Kami fokus padapyramiding
, default_qty_value
parameter dalamstrategy
Kami menggunakan kode berikut untuk tes:
/*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)
Bagian di awal kode/* backtest... */
adalah pengaturan backtest, yang digunakan untuk merekam waktu pengaturan backtest dan informasi lain pada saat itu untuk debugging, bukan kode startup.
Dalam kode:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)
, ketika kita menentukanpyramiding
parameter sebagai 3, kita mengatur jumlah maksimum perdagangan ke arah yang sama ke 3.strategy.entry
Operasi order dalam contoh tidak dijalankan.default_qty_value
parameter menjadi 0,1, inistrategy.entry
Operasi dengan IDlong1
memiliki ukuran pesanan default 0,1.strategy.entry
fungsi panggilan ketika kita menentukandirection
sebagaistrategy.long
, jadi semua pesanan uji backtest adalah pesanan beli.
Perhatikan bahwa operasi orderstrategy.entry("long3", ...
dalam kode dipanggil dua kali, untuk ID yang sama:long3
, yang pertamastrategy.entry
operasi pesanan tidak diisi, dan panggilan kedua kestrategy.entry
fungsi adalah untuk memodifikasi urutan untuk ID ini (data yang ditunjukkan dalam tes backtest juga menunjukkan bahwa kuantitas urutan untuk urutan batas ini dimodifikasi menjadi 0,3).strategy.entry
fungsi untuk menempatkan pesanan sesuai dengan ID
strategy.close
Peraturanstrategy.close
fungsi digunakan untuk menutup posisi masuk dengan ID identifikasi yang ditentukan. Parameter utama adalah:id
, when
, qty
, qty_percent
.
Parameter:
id
: ID entri yang perlu ditutup adalah ID yang kita tentukan ketika kita membuka posisi menggunakan fungsi order entry, sepertistrategy.entry
.when
: Kondisi pelaksanaan.qty
: Jumlah posisi tertutup.qty_percent
: Persentase posisi tertutup.Mari kita membiasakan diri dengan rincian penggunaan fungsi ini melalui contoh:
Peraturan/*backtest ... */
dalam kode adalah informasi konfigurasi untukFMZ.COMsitus web internasional backtest, Anda dapat menghapus dan mengatur pasar, varietas, rentang waktu dan informasi lain yang Anda butuhkan untuk menguji.
/*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") // Multiple entry orders, no qty parameters specified, close all
// strategy.close() // Without specifying the id parameter, the current position will be closed
// strategy.close("long2") // If a non-existent id is specified then nothing is done
// strategy.close("long1", qty=0.15) // Specify qty parameters to close a position
// strategy.close("long1", qty_percent=50) // qty_percent is set to 50 to close 50% of the positions marked by long1
// strategy.close("long1", qty_percent=80, when=close<open) // Specify the parameter when, change it to close>open and it won't trigger
enableStop := true
Strategi uji menunjukkan tiga entri panjang berturut-turut dengan ID entri strategy.close
fungsi untuk mengatur hasil yang berbeda dari backtest ketika menutup posisi.strategy.close
fungsi tidak memiliki parameter untuk menentukan harga pesanan untuk menutup posisi, fungsi ini terutama digunakan untuk menutup posisi segera pada harga pasar saat ini.
strategy.close_all
Fungsistrategy.close_all
digunakan untuk menutup semua posisi saat ini, karena posisi skrip bahasa Pine hanya dapat memiliki arah, yaitu, jika ada sinyal dipicu dalam arah yang berlawanan dari posisi saat ini akan menutup posisi saat ini dan kemudian membukanya sesuai dengan pemicu sinyal.strategy.close_all
akan menutup semua posisi dalam arah saat ini ketika dipanggil.strategy.close_all
Fungsi adalah:when
.
Parameter:
when
: Kondisi pelaksanaan.Mari kita gunakan contoh untuk mengamati:
/*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 uji dimulai dengan nomor posisi 0 (yaitustrategy.position_size==0
adalah benar), jadi ketika kondisi yang ditetapkan oleh ketika parameter dipenuhi, hanyastrategy.entry
fungsi entri dengan ID strategy.position_size
jika nilai nilai dari posisi long yang dipegang oleh trader adalah lebih besar dari 0, maka fungsi entry dengan ID strategy.position_size < 0
, yaitu ketika memegang posisi pendek, semua posisi di arah memegang saat ini akan ditutup.enableStop := true
. Menghentikan pelaksanaan strategi sehingga log dapat diamati.
Hal ini dapat ditemukan bahwa fungsistrategy.close_all
tidak memiliki parameter untuk menentukan harga penutupan pesanan, fungsi ini terutama digunakan untuk segera menutup posisi pada harga pasar saat ini.
strategy.exit
Peraturanstrategy.exit
Fungsi ini digunakan untuk menutup posisi masuk.strategy.close
danstrategy.close_all
fungsi menutup posisi segera pada harga pasar saat ini.strategy.exit
fungsi akan menutup posisi sesuai dengan pengaturan parameter.
Parameter:
id
: ID pengidentifikasi order dari order kondisi penutupan saat ini.from_entry
: Digunakan untuk menentukan ID entri posisi yang akan ditutup.qty
: Jumlah posisi tertutup.qty_percent
: Persentase posisi tertutup, kisaran: 0 ~ 100.profit
: Target keuntungan, dinyatakan dalam poin.loss
: Target stop loss, dinyatakan dalam poin.limit
: Target keuntungan, ditentukan oleh harga.stop
: Target stop loss, ditentukan oleh harga.when
: Kondisi pelaksanaan.Gunakan strategi uji untuk memahami penggunaan parameter.
/*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") // If only one id parameter is specified, the exit order is invalid, and the parameters profit, limit, loss, stop and other exit conditions also need to be set at least one, otherwise it is also invalid
strategy.exit("exit1", "long1", profit=50) // Since the long1 entry order is not filled, the exit order with ID exit1 is also on hold until the corresponding entry order is filled before exit1 is placed
strategy.exit("exit2", "long2", qty=0.1, profit=100) // Specify the parameter qty to close 0.1 positions in the position with ID long2
strategy.exit("exit3", "long3", qty_percent=50, limit=strategy.opentrades.entry_price(findOrderIdx("long3")) + 1000) // Specify the parameter qty_percent to close 50% of the positions in the position with ID long3
isExit := true
if bar_index == 0
runtime.log("The price per point:", syminfo.mintick) // The price per point is related to the "Pricing Currency Precision" parameter setting on the Pine language template parameters
Kami menggunakan model harga real-time untuk backtest, strategi tes dimulai dengan 3 operasi entri (strategy.entry
fungsi), danlong1
sengaja diatur denganlimit
parameter dengan harga order tertunda 1, sehingga tidak dapat diisi.strategy.exit
Kami menggunakan strategy.exit
Fungsi ini juga memiliki parameter trailing stop yang lebih kompleks:trail_price
, trail_points
, trail_offset
juga dapat diuji dalam contoh ini untuk belajar penggunaannya.
strategy.cancel
Peraturanstrategy.cancel
fungsi digunakan untuk membatalkan / menghentikan semua pesanan yang belum selesai.strategy.order
, strategy.entry
, strategy.exit
dapat menghasilkan ID entri. Parameter utama dari fungsi ini adalah:id
, when
.
Parameter:
id
: ID masuk dibatalkan.when
: Kondisi pelaksanaan.Fungsi ini mudah dipahami, dan digunakan untuk membatalkan pesanan masuk yang tidak diisi.
/*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