Tài nguyên đang được tải lên... tải...

Các nhà phát minh định lượng các hướng dẫn về ngôn ngữ PINE

Tác giả:Những nhà phát minh định lượng - những giấc mơ nhỏ, Tạo: 2022-05-30 16:23:43, Cập nhật: 2022-09-28 17:10:21

Ví dụ:

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)

Điểm quan trọng: biểu thức dùng để đánh giá, trả về giá trị Boolean. Chú ý là thu hẹp. Có thể chỉ có một nhánhelse tối đa. Tất cả các biểu thức nhánh không đúng và không có nhánhelse, trả về na.

x = if close > open
    close
plot(x, title="x")

Bởi vì khi K-line BAR là đường âm, tức là close < open, biểu thức sau câu if là false, không thực hiện khối mã bản địa của if.

Phương pháp chuyển đổi

Một câu lệnh switch cũng là một câu lệnh có cấu trúc nhánh, được sử dụng để thiết kế các hành trình khác nhau tùy thuộc vào một số điều kiện.

1, switch câu nói cũng có thể trả về giá trị như if câu nói. 2, không giống như các lệnh chuyển đổi trong các ngôn ngữ khác, khi thực hiện cấu trúc chuyển đổi, chỉ thực hiện một khối bản địa trong mã của nó, do đó tuyên bố break là không cần thiết (tức là không cần phải viết các từ khóa như break). 3, mỗi branching của switch có thể viết một local block, và cuối cùng của local block là return value (có thể là một tập hợp các giá trị); nếu không có branching nào được thực hiện, nó sẽ trả về na. 4, Quyết định vị trí biểu thức trong cấu trúc chuyển đổi, có thể viết chuỗi, biến, biểu thức hoặc gọi chức năng. 5, switch cho phép chỉ định một giá trị trả về, giá trị này là giá trị mặc định được sử dụng khi không có trường hợp nào khác trong cấu trúc được thực hiện.

Chúng ta sẽ xem từng ví dụ một để hiểu cách sử dụng chúng.

1 với biểu thứcswitchVí dụ:

// 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)

Trước đây chúng ta đã học các hàm input, và ở đây chúng ta tiếp tục học hai hàm tương tự như input:input.stringinput.intChức năng.input.stringVà chúng tôi sẽ sử dụng nó để trả lại các chuỗi.input.intChức năng này được sử dụng để trả lại các giá trị nguyên tố.optionsCác đối số được sử dụng như:optionsCác tham số có thể được truyền vào một mảng gồm các giá trị có thể chọn; ví dụ như trong ví dụoptions=["EMA", "SMA", "RMA", "WMA"]options=[5, 10, 20](Lưu ý rằng một là kiểu chuỗi, một là kiểu số) ; điều này làm cho các điều khiển trên giao diện chính sách không cần phải nhập các giá trị cụ thể, mà thay vào đó, điều khiển trở thành một khung kéo xuống, chọn các tùy chọn được cung cấp trong các tùy chọn.

Giá trị của biến func là một chuỗi, biến func là biểu thức của switch (có thể là biến, gọi chức năng, biểu thức) để xác định nhánh nào trong chuyển đổi được thực hiện. Nếu biến func không thể khớp với biểu thức trên bất kỳ nhánh nào trong chuyển đổi (tức là bằng nhau), thì thực hiện các khối mã nhánh mặc định, sẽ thực hiệnruntime.error("error")Chức năng gây ra các chính sách ném bất thường dừng.

Trong mã thử nghiệm của chúng tôi ở trên, sau dòng runtime.error cuối cùng của khối mã nhánh mặc định của Switch, chúng tôi không thêm mã như [na, na] để trả về giá trị tương thích, trong giao dịch view cần phải xem xét vấn đề này, nếu loại không phù hợp sẽ báo lỗi. Nhưng trên FMZ có thể bỏ qua mã tương thích này vì không có yêu cầu loại nghiêm ngặt.

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)

Không báo lỗi trên FMZ, báo lỗi trên trading view; vì if branch trả về kiểu không phù hợp.

2, không có biểu thứcswitch

Chúng ta sẽ xem.switchMột cách sử dụng khác của chữ "từ" là viết không có biểu thức.

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)

Trong ví dụ thử nghiệm, Switch sẽ khớp với một khối mã cục bộ thực theo điều kiện thực thi branch. Nói chung, các điều kiện branch sau câu lệnh switch phải phản đối lẫn nhau. Có nghĩa là up và down trong ví dụ không thể đúng cùng một lúc. Vì Switch chỉ thực thi một khối mã cục bộ của một branch, có thể đặt dòng này trong mã:up = close > open // up = close < openThay cho nội dung trong chú thích, xem xét lại kết quả. Bạn sẽ thấy branch switch chỉ thực hiện branch đầu tiên. Ngoài ra, bạn cũng cần phải cẩn thận để tránh viết các cuộc gọi chức năng trong branch của switch, các chức năng không thể được gọi trên mỗi BAR có thể gây ra một số vấn đề tính toán dữ liệu (trừ khi "có biểu thứcswitchTrong ví dụ này, nhánh thực thi được xác định và sẽ không bị thay đổi trong quá trình vận hành chiến lược).

Cơ cấu chu kỳ

Câu nói for

返回值 = for 计数 = 起始计数 to 最终计数 by 步长
    语句                                            // 注释:语句里可以有break,continue
    语句                                            // 注释:最后一条语句为返回值

Sử dụng câu nói for rất đơn giản, vòng lặp for có thể trả về cuối cùng một giá trị ((hoặc trả về nhiều giá trị, dưới dạng như [a, b, c]); như trong mã giả trên, các biến được gán cho vị trí "lấy lại giá trị". Sau câu nói for, một biến "đếm" được sử dụng để kiểm soát số lần lặp, trích dẫn các giá trị khác, v.v. Các biến "đếm" được gán giá trị "đếm ban đầu" trước khi vòng lặp bắt đầu, sau đó chuyển theo cài đặt "tăng dần", và vòng lặp dừng lại khi số "đếm" lớn hơn số "đếm cuối cùng".

for được sử dụng trong chu trìnhbreakTừ khóa: Khi thực hiệnbreakSau câu nói, chu kỳ dừng lại. for được sử dụng trong chu trìnhcontinueTừ khóa: Khi thực hiệncontinueSau câu, vòng lặp sẽ bị bỏ qua.continueMã sau đó, thực hiện trực tiếp vòng lặp tiếp theo. Câu lệnh for trả về giá trị khi vòng lặp cuối cùng được thực hiện. Nếu không có mã nào được thực hiện, trả về giá trị trống.

Dưới đây là một ví dụ đơn giản:

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")

For... in câu

for ... inCó hai hình thức câu nói, các mã giả dưới đây cho thấy.

返回值 = for 数组元素 in 数组 
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值 

Có thể thấy sự khác biệt chính giữa hai hình thức là nội dung sau từ khóa for, một là sử dụng một biến để tham khảo các yếu tố matrix. Một là sử dụng một cấu trúc chứa các biến chỉ mục, các biến của các yếu tố matrix để tham khảo. Các quy tắc khác về giá trị trả về, sử dụng các quy tắc như break, tiếp tục và vòng lặp for phù hợp.

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")

Khi cần sử dụng chỉ mục, hãy sử dụngfor [i, ele] in testArrayCó một người đàn ông ở đây.

for ứng dụng tuần hoàn

Khi một số tính toán logic vòng lặp có thể được thực hiện bằng các hàm tích hợp được cung cấp bằng ngôn ngữ Pine, nó có thể được viết trực tiếp bằng cấu trúc vòng lặp hoặc xử lý bằng các hàm tích hợp. Chúng tôi đưa ra hai ví dụ.

1, tính trung bình

Khi sử dụng thiết kế cấu trúc tuần hoàn:

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)

Trong ví dụ này, sử dụng tổng hợp vòng tròn for, sau đó tính toán giá trị bình quân.

Sử dụng hàm tích hợp trực tiếp để tính đường ngang:

plot(ta.sma(close, length), title="ta.sma", overlay=true)

Sử dụng trực tiếp các hàm được xây dựngta.sma, tính toán chỉ số đường thẳng, rõ ràng là đơn giản hơn để tính toán đường thẳng bằng cách sử dụng các hàm tích hợp. Trong biểu đồ, so sánh có thể thấy kết quả tính toán hoàn toàn phù hợp.

2, cộng

Bạn có thể sử dụng ví dụ trên để minh họa.

Khi sử dụng thiết kế cấu trúc tuần hoàn:

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)

Đối với tất cả các phần tử của một toán matrix, và có thể sử dụng vòng lặp để xử lý, cũng có thể sử dụng các hàm tích hợparray.sumHãy tính toán nhé. Sử dụng hàm tích hợp trực tiếp để tính toán tổng cộng:

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)

Bạn có thể thấy dữ liệu được tính toán, sử dụng đồ họa phác thảo để hiển thị hoàn toàn phù hợp trên biểu đồ.

Vì vậy, tại sao lại thiết kế vòng lặp nếu bạn có thể thực hiện những công việc này bằng các hàm tích hợp? 1, một số hoạt động cho các mảng, tính toán. 2, xem lại lịch sử, ví dụ như tìm ra bao nhiêu điểm cao trong quá khứ cao hơn điểm cao của BAR hiện tại. Vì điểm cao của BAR hiện tại chỉ được biết đến trên BAR mà kịch bản đang chạy, nên cần một vòng lặp để quay lại và phân tích BAR trong quá khứ. 3, Trường hợp các hàm được xây dựng bằng ngôn ngữ Pine không thể thực hiện tính toán về BAR trong quá khứ.

while

whileCâu lệnh cho phép mã của phần vòng lặp được thực hiện cho đến khi điều kiện phán đoán trong cấu trúc while là false.

返回值 = while 判断条件
    语句                    // 注释:语句里可以有break,continue
    语句                    // 注释:最后一条语句为返回值

Các quy tắc khác của while tương tự như vòng lặp for, dòng cuối cùng của khối mã bản địa của vòng lặp là giá trị trả về, và có thể trả về nhiều giá trị. Khi "quy tắc vòng lặp" thực hiện vòng lặp trong thời gian thực, điều kiện dừng vòng lặp trong thời gian giả.

Tôi sẽ trình bày bằng cách sử dụng ví dụ về đường thẳng:

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)

Bạn có thể thấy rằng sử dụng vòng lặp while cũng rất đơn giản, và bạn có thể thiết kế một số logic tính toán không thể thay thế bằng các hàm tích hợp, chẳng hạn như tính toán bậc:

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

Đội số

Các mảng trong ngôn ngữ Pine có định nghĩa tương tự như các mảng trong các ngôn ngữ lập trình khác. Mảng Pine là một mảng một chiều. Nó thường được sử dụng để lưu trữ một loạt dữ liệu liên tục. Mảng mà các dữ liệu đơn lẻ được lưu trữ trong đó được gọi là các yếu tố của mảng. Các loại của các yếu tố này có thể là: nguyên dạng, kiểu phẩy, chuỗi, giá trị màu, giá trị boolean. Ngôn ngữ Pine trên FMZ không đòi hỏi loại rất nghiêm ngặt, thậm chí có thể lưu trữ cả chuỗi và số trong một mảng.[]Chúng ta cần phải sử dụngarray.get()array.set()Các hàm.. trong một mảng có thứ tự chỉ mục của các phần tử như là chỉ mục của phần tử đầu tiên của mảng là 0, chỉ mục của phần tử tiếp theo tăng lên 1..

Chúng tôi sẽ sử dụng một đoạn mã đơn giản để giải thích:

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))

Mảng tuyên bố

Sử dụngarray<int> afloat[] bMột mảng được tuyên bố hoặc chỉ tuyên bố một biến có thể được gán cho mảng, ví dụ:

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")

Việc khởi tạo biến số cho ma trận được sử dụng chungarray.newarray.from函数。Pine语言中还有很多和类型相关的与array.new类似的函数:array.new_int()array.new_bool()array.new_color()array.new_string()Và rồi.

Từ khóa var cũng có thể hoạt động với mô hình tuyên bố của mảng, mảng được khai báo bằng từ khóa var chỉ được khởi tạo trên mảng BAR đầu tiên. Chúng ta thấy bằng một ví dụ:

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")

Bạn có thể thấy rằng thay đổi của a được xác định liên tục và không được đặt lại. b được khởi tạo ở mỗi BAR.barstate.islastKhi in trong thời gian thực, vẫn chỉ có một phần tử, giá trị 0 ≠ 0.

Đọc, ghi vào các phần tử trong mảng

Sử dụng array.get để lấy các phần tử chỉ định vị trí chỉ mục trong một mảng, sử dụng array.set để sửa đổi các phần tử chỉ định vị trí chỉ mục trong một mảng.

Các đối số đầu tiên của array.get là các mảng để xử lý, và các đối số thứ hai là các chỉ mục được chỉ định. Các đối số đầu tiên của array.set là các mảng để xử lý, các đối số thứ hai là các chỉ mục được chỉ định, và các đối số thứ ba là các phần tử để viết.

Hãy dùng ví dụ đơn giản sau đây:

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")

Ví dụ này khởi tạo màu xanh lá cây nền, tuyên bố và khởi tạo một mảng để lưu trữ màu sắc, sau đó gán độ minh bạch khác nhau cho giá trị màu sắc (sử dụng hàm color.new); tính cấp độ màu bằng cách tính khoảng cách lớn nhất của giá trị high trong 100 chu kỳ xem hiện tại BAR; càng gần mức tối đa high trong 100 chu kỳ xem gần nhất, cấp độ cao hơn, giá trị màu tương ứng càng sâu (thanh minh bạch thấp); nhiều chiến lược tương tự được sử dụng theo cách này để biểu thị mức giá trong N chu kỳ xem hiện tại.

Đi qua các phần tử ma trận

Làm thế nào để đi qua một mảng, chúng ta có thể thực hiện bằng cách sử dụng các câu nói for / for in / while mà chúng ta đã học trước đây.

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")

Những cách này đều có kết quả tương tự.

Các mảng có thể được tuyên bố trong phạm vi toàn cầu của kịch bản, hoặc được tuyên bố trong phạm vi cục bộ của hàm hoặc if branch

Dữ liệu lịch sử

Đối với việc sử dụng các phần tử trong mảng, cách sau đây là tương đương, chúng ta có thể thấy bằng ví dụ sau đây rằng hai nhóm đường được vẽ trên biểu đồ, mỗi nhóm hai đường và mỗi nhóm hai đường có giá trị hoàn toàn giống nhau.

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)

Thêm Array, xóa hàm vận hành

1, các hàm liên quan đến các hoạt động gia tăng của mảng:

array.unshift()array.insert()array.push()

2, các hàm liên quan đến các hoạt động xóa của các mảng:

array.remove()array.shift()array.pop()array.clear()

Chúng ta dùng các ví dụ sau đây để kiểm tra các hàm phép tính thêm, loại bỏ.

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")

Ứng dụng thêm, xóa: mảng như hàng

Một số bạn có thể hỏi: Tại sao chúng ta nên xây dựng một cấu trúc hàng? Chúng ta có thể tạo ra một cơ cấu dữ liệu "đường hàng". Đường hàng có thể được sử dụng để tính trung bình động của giá tick.

Một queue là một cấu trúc thường được sử dụng trong lĩnh vực lập trình.

Các yếu tố vào hàng đầu, hàng đầu đi.

Điều này đảm bảo rằng dữ liệu trong hàng là dữ liệu mới nhất, và chiều dài hàng không bị mở rộng vô hạn (mã mở rộng vô hạn chỉ có thể được viết vào giữa trưa, vì có thể xảy ra vấn đề sớm hoặc muộn).

Ví dụ dưới đây chúng ta sử dụng một cấu trúc hàng để ghi lại giá mỗi lần tick, tính toán giá trung bình di chuyển ở cấp độ tick, sau đó so sánh với mức trung bình di chuyển ở cấp độ đường K trong 1 phút.

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")

Lưu ý, khi tuyên bố a, chúng ta chỉ định mô hình tuyên bố, sử dụng từ khóavaripVì vậy, mỗi lần thay đổi giá sẽ được ghi lại trong một mảng a.

Công thức toán số phổ biến, chức năng vận hành

Tính toán các hàm liên quan:

array.avg()Đặt giá trị trung bình của tất cả các phần tử trong một chuỗi.array.min()Các phần tử nhỏ nhất trong một chuỗi số.array.max()Một phần tử lớn nhất trong một chuỗi sốarray.stdev()Các yếu tố trong một chuỗi số có độ sai tiêu chuẩn.array.sum()Tổng của tất cả các phần tử trong một toán tử.

Các chức năng liên quan đến hoạt động:array.concat()Kết hợp hoặc kết nối hai mảng.array.copy()Phân bản các mảng.array.joinKết nối tất cả các phần tử trong mảng thành một chuỗi.array.sort()Lưu ý: Các bài viết trên trang web của chúng tôi được đăng trên trang web của chúng tôi.array.reverse()Các số được đảo ngược.array.slice()Cắt các số.array.includes()Đánh giá các yếu tố.array.indexof()Trả về chỉ mục mà giá trị được nhập vào lần đầu tiên. Nếu không tìm thấy, trả về -1.array.lastindexof()Tìm giá trị xuất hiện cuối cùng.

Ví dụ thử nghiệm về các hàm liên quan đến toán số:

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")

Đây là các hàm toán toán số được sử dụng phổ biến hơn.

Ví dụ về các chức năng liên quan:

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")

Chức năng

Chức năng tùy chỉnh

Ngôn ngữ Pine có thể thiết kế các hàm tùy chỉnh, nói chung các hàm tùy chỉnh của ngôn ngữ Pine có các quy tắc sau:

1, tất cả các hàm được định nghĩa trong phạm vi toàn cầu của kịch bản. Không thể tuyên bố một hàm trong một hàm khác. 2, không cho phép hàm gọi chính nó trong mã của nó. 3, về cơ bản tất cả các ngôn ngữ PINE đều có chức năng đồ họa được xây dựngbarcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) không thể được gọi trong các chức năng tùy chỉnh. 4, hàm có thể được viết như một dòng, nhiều dòng. Giá trị trả về của câu cuối cùng là giá trị trả về của hàm hiện tại, giá trị trả về có thể trở lại dạng phân tử.

Trong các bài học trước, chúng ta đã sử dụng các chức năng tùy chỉnh nhiều lần, ví dụ như thiết kế các chức năng tùy chỉnh một dòng:

barIsUp() => close > open

Chức năng này trả về BAR hiện tại là ánh sáng mặt trời.

Được thiết kế thành các hàm tùy chỉnh nhiều dòng:

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)

Một hàm mà chúng ta tự thực hiện với các hàm tùy chỉnh là một hàm mà được tính theo đường trung bình SMA.

Ngoài ra, bạn có thể trả về một ví dụ về các hàm tùy chỉnh với hai biến:

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)

Một hàm có thể tính ra đường nhanh, đường chậm, hai chỉ số EMA đường thẳng.

Chức năng tích hợp

Các chức năng được xây dựng rất dễ dàngFMZ PINE Script tài liệuTrong truy vấn.

Phân loại các hàm được xây dựng trong ngôn ngữ Pine:

1, hàm xử lý chuỗistr.Bộ phim. 2, hàm xử lý giá trị màucolor.Bộ phim. 3, hàm nhập tham sốinput.Bộ phim. 4, hàm tính toán chỉ sốta.Bộ phim. 5, Chế độ vẽplot.Bộ phim. 6, hàm xử lý sốarray.Bộ phim. 7. Các chức năng liên quan đến giao dịchstrategy.Bộ phim. 8. Các chức năng liên quan đến toán họcmath.Bộ phim. 9, Các chức năng khác (đối với xử lý thời gian, các chức năng vẽ đồ họa không theo chuỗi phác thảo,request.Các hàm chuỗi, các hàm xử lý kiểu, v.v.) ‖

Chức năng giao dịch

strategy.Các hàm chuỗi là những hàm mà chúng ta thường sử dụng trong các chiến lược thiết kế, và các hàm này và các chiến lược này rất liên quan đến việc thực hiện các giao dịch khi chúng được thực hiện cụ thể.


1、strategy.entry

strategy.entryMột hàm là một hàm phụ quan trọng hơn khi chúng ta viết chính sách, và nó quan trọng hơn một vài tham số:id, direction, qty, whenVà rồi.

Các thông số:

  • id: có thể hiểu là một cái tên cho một vị trí giao dịch được sử dụng để tham khảo. Có thể tham khảo id này hủy bỏ, sửa đổi lệnh, thanh toán.
  • direction: Nếu hướng đặt hàng là mua () thì tham số này được truyền đistrategy.longCác biến tích hợp này sẽ được truyền nếu bạn muốn bán.strategy.shortCác biến này.
  • qty: chỉ định số lượng đặt hàng, nếu không truyền tham số này sẽ được sử dụng là số lượng đơn hàng mặc định.
  • when: điều kiện thực hiện, bạn có thể chỉ định tham số này để kiểm soát việc kích hoạt hoặc không các hoạt động dưới lệnh hiện tại.
  • limitĐặt giá đặt hàng giới hạn.
  • stopĐánh giá: giá dừng lỗ.

strategy.entryCác chi tiết thực hiện cụ thể của hàmstrategyĐiều khiển cài đặt tham số khi gọi chức năng cũng có thể được thực hiện bằng cách"Pine Language Exchange Library Template Parameters" (Các tham số mẫu của thư viện ngôn ngữ Pine)Các chi tiết chi tiết về các giao dịch được kiểm soát trong các tài liệu có thể được xem tại đây.

Đây là những điểm nhấn.strategyTrong các hàm,pyramidingdefault_qty_valueCác tham số. Sử dụng mã sau để kiểm tra:

/*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)

Mã bắt đầu/*backtest ... */Phần gói được thiết lập để kiểm tra lại, để ghi lại thông tin như thời gian kiểm tra lại, dễ dàng điều chỉnh, chứ không phải là mã chính sách.

Trong mã:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)Khi chúng ta chỉ địnhpyramidingKhi tham số là 3, chúng ta đặt giao dịch theo cùng một hướng tối đa 3 lần.strategy.entryMột trong những thao tác dưới đây đã không được thực hiện.default_qty_valueCác tham số là 0.1, vì vậy ID sẽ là 1long trong lần nàystrategy.entrySố lượng đơn hàng của các hoạt động đơn hàng được đặt theo mặc định là 0.1.strategy.entryChúng ta chỉ định khi gọi hàm.directionĐúng làstrategy.longTrong khi đó, các nhà nghiên cứu cũng cho rằng, việc kiểm tra lại các bài kiểm tra là một việc phải trả tiền.

Chú ý trong mãstrategy.entry("long3", ...Các thao tác dưới đây được gọi hai lần, cho cùng một ID: long3.strategy.entryLệnh sau không được thực hiện, gọi lần thứ haistrategy.entryChức năng này được sử dụng để thay đổi ID của đơn đặt hàng (dữ liệu được hiển thị khi kiểm tra lại cũng có thể thấy rằng số lượng đơn đặt hàng dưới lệnh giới hạn này đã được thay đổi thành 0.3). Một trường hợp khác, ví dụ: nếu khi lần đầu tiên ID đã được giao dịch cho các đơn đặt hàng của long3, tiếp tục sử dụng theo ID giao dịch này long3.strategy.entryCác chức năng đặt hàng, sau đó các vị trí được đặt hàng sẽ được tích lũy trên ID Long 3 Long.


2、strategy.close

strategy.closeChức năng này được sử dụng để chỉ định ID nhận dạng giao dịch. Các tham số chính là:idwhenqtyqty_percent

Các thông số:

  • idBạn có thể sử dụng một số mã thông báo khác như:strategy.entryID được chỉ định khi mở giao dịch.
  • whenĐiều kiện thực hiện:
  • qty: Số lượng giao dịch.
  • qty_percent: tỷ lệ ngang hàng.

Để làm quen với các chi tiết sử dụng của hàm này, hãy xem ví dụ: Trong mã/*backtest ... */是FMZ.COM国际站回测时的配置信息,可以删掉,设置自己需要测试的市场、品种、时间范围等信息。

/*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

Chiến lược thử nghiệm cho thấy bắt đầu nhiều lần truy cập liên tục, ID truy cập là 1 long, sau đó sử dụngstrategy.closeCác kết quả khác nhau được tìm thấy khi các tham số khác nhau của hàm được đặt ngang hàng.strategy.closeChức năng này không có các tham số để chỉ định giá đặt hàng, và chủ yếu được sử dụng để đặt hàng ngay lập tức với giá thị trường hiện tại.


3、strategy.close_all

strategy.close_allChức năng này được sử dụng để làm phẳng tất cả các vị thế hiện tại, vì kịch bản Pine chỉ có thể làm phẳng một hướng, tức là nếu có một tín hiệu kích hoạt ngược lại với hướng giữ hiện tại, nó sẽ làm phẳng vị trí hiện tại và kích hoạt vị trí dựa trên tín hiệu.strategy.close_allKhi được gọi, tất cả các cổ phiếu theo hướng hiện tại sẽ được cân bằng.strategy.close_allCác tham số chính của hàm là:when

Các thông số:

  • whenĐiều kiện thực hiện:

Chúng ta hãy sử dụng một ví dụ để quan sát:

/*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 

Khi mã thử nghiệm bắt đầu, số lượng lưu trữ là 0 (tức làstrategy.position_size==0Đúng), vì vậy chỉ thực hiện ID là con đường dài khi đáp ứng các điều kiện đặt trong tham số whenstrategy.entryChức năng nhập.strategy.position_sizeNếu số lượng các vị trí được chọn là lớn hơn 0, thì chỉ có thể thực hiện các hàm nhập vào của ID cho các vị trí được chọn ngắn hơn.strategy.position_size < 0Khi nắm giữ một cổ phiếu trống, bạn sẽ có thể giữ tất cả các cổ phiếu theo hướng nắm giữ hiện tại.enableStop := true⇒ Dừng chính sách để dễ dàng quan sát nhật ký.

Bạn có thể tìm thấystrategy.close_allChức năng này không có các tham số để chỉ định giá đặt hàng, và chủ yếu được sử dụng để đặt hàng ngay lập tức với giá thị trường hiện tại.


4、strategy.exit

strategy.exitChức năng này được sử dụng cho các hoạt động giao dịch giao dịch trong giao dịch mua cổ phiếu, khác với chức năng này làstrategy.closestrategy.close_allChức năng này được đặt ngay tại giá thị trường hiện tại.strategy.exitChức năng sẽ lập kế hoạch ngang hàng theo cài đặt tham số.

Các thông số:

  • id: ID đặt hàng cho danh sách điều kiện giao dịch hiện tại.
  • from_entry: được sử dụng để chỉ định ID nhập để thực hiện các hoạt động giao dịch.
  • qty: Số lượng giao dịch.
  • qty_percent: Tỷ lệ ngang hàng, phạm vi: 0 ~ 100.
  • profitMục tiêu lợi nhuận, được thể hiện bằng các điểm.
  • lossNhững người tham gia cuộc thi này đã có những câu trả lời rất thú vị.
  • limitMục tiêu lợi nhuận được xác định theo giá cả.
  • stopNhững người tham gia cuộc thi này đã được mời đến tham dự.
  • whenĐiều kiện thực hiện:

Sử dụng một chiến lược thử nghiệm để hiểu các tham số được sử dụng.

/*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语言模板参数上「定价货币精度」参数设置有关

Sử dụng thử nghiệm trả lại mô hình giá thực tế, chiến lược thử nghiệm này bắt đầu thực hiện 3 hoạt động nhập vào.strategy.entryPhương thức), long1 được đặt cố tìnhlimitCác tham số, giá đặt hàng là 1 làm cho nó không thể giao dịch. Sau đó kiểm tra các điều kiện ra khỏi hàmstrategy.exit; sử dụng stop stop theo số điểm, stop stop theo giá, sử dụng số lượng vị trí cố định, sử dụng tỷ lệ phần trăm. Vì chỉ chứng minh stop stop trong ví dụ trên, stop stop cũng tương tự.strategy.exitChức năng này cũng có các tham số dừng mất tích theo dõi phức tạp hơn:trail_pricetrail_pointstrail_offsetBạn cũng có thể kiểm tra để tìm hiểu cách sử dụng nó trong ví dụ này.


5、strategy.cancel

strategy.cancelCác hàm được sử dụng để hủy / tắt tất cả các lệnh trên danh sách chờ.strategy.order, strategy.entry , strategy.exitCó thể tạo ID nhập. Các tham số chính của hàm là:idwhen

Các thông số:

  • idCác bạn có thể tham gia vào chương trình này.
  • whenĐiều kiện thực hiện:

Chức năng này rất dễ hiểu, nó được sử dụng để hủy lệnh nhập mà không có giao dịch.

/*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_allChức năng vàstrategy.cancelChức năng tương tự như: ⇒ hủy/tắt tất cả các lệnh đặt hàng trước.whenCác tham số.

Các thông số:

  • whenĐiều kiện thực hiện:
/*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.orderCác chức năng của hàm, cài đặt các tham số, v.v. gần giống nhưstrategy.entryNhìn chung, phân biệtstrategy.orderChức năng không đượcstrategyCác hàmpyramidingCác tham số cài đặt ảnh hưởng, không có giới hạn lần lượt.

Các thông số:

  • id: có thể hiểu là một cái tên cho một vị trí giao dịch được sử dụng để tham khảo. Có thể tham khảo id này hủy bỏ, sửa đổi lệnh, thanh toán.
  • direction: Nếu hướng đặt hàng là mua () thì tham số này được truyền đistrategy.longCác biến tích hợp này sẽ được truyền nếu bạn muốn bán.strategy.shortCác biến này.
  • qty: chỉ định số lượng đặt hàng, nếu không truyền tham số này sẽ được sử dụng là số lượng đơn hàng mặc định.
  • when: điều kiện thực hiện, bạn có thể chỉ định tham số này để kiểm soát việc kích hoạt hoặc không các hoạt động dưới lệnh hiện tại.
  • limitĐặt giá đặt hàng giới hạn.
  • stopĐánh giá: giá dừng lỗ.

Chúng ta sử dụngstrategy.orderKhông có giới hạn về số lần tiếp theo, kết hợpstrategy.exitChức năng thoát điều kiện. Một kịch bản tương tự như giao dịch lưới. Một ví dụ rất đơn giản chỉ dùng để học:

/*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)

Các mô hình chiến lược

Các ví dụ về chiến lược trong hướng dẫn này chỉ được sử dụng để giảng dạy chiến lược, hướng dẫn các ý tưởng thiết kế chiến lược, không làm bất kỳ hướng dẫn giao dịch, đề xuất.

Chiến lược chỉ số siêu xu hướng

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()

Sử dụng ngôn ngữ Pine để viết các chiến lược xu hướng rất đơn giản, ở đây chúng ta sẽ thiết kế một chiến lược theo dõi xu hướng đơn giản với một siêu chỉ số xu hướng.

Đầu tiên là sử dụng mã chiến lược.strategyCác chức năng đã thực hiện một số cài đặt đơn giản:strategy("supertrend", overlay=true), chỉ cần đặt một chiến lược tiêu đề supertrend .overlayCác tham số làtrue, để các nội dung như đường chỉ báo được vẽ ra được hiển thị trên sơ đồ chính. Chúng ta thiết kế một chiến lược Pine hoặc học một kịch bản chiến lược Pine.inputChức năng

[supertrend, direction] = ta.supertrend(input(5, factor),input.int(10, trPeriod))

inputCác cuộc gọi hàm được sử dụng trực tiếpta.supertrendCác tham số của hàm chỉ số được sử dụng để tính các chỉ số siêu xu hướng.

Các hàm sẽ mặc định đặt hai điều khiển tham số trên giao diện chính sách ngôn ngữ Pine, như sau:

img

Và bạn có thể thấy rằng mặc định của điều khiển làinputChức năng vàinputChức năng chuỗi ((đây làinput.intCác hàm này có thể được đặt trên giao diện chiến lược.ta.supertrendCác tham số của hàm. Các hàm siêu xu hướng tính toán một dữ liệu giá.supertrendvà dữ liệu một hướngdirectionVà rồi sử dụng nó.plotBiểu đồ hàm, lưu ý khi vẽ biểu đồ theo hướng của chỉ số siêu xu hướng, chỉ vẽ hướng hiện tại; khidirectionTrong khi đó, thị trường hiện nay có xu hướng tăng khidirectionVì vậy, chúng ta có thể thấy rằng thị trường hiện tại đang có xu hướng giảm.plotXác định khi vẽ biểu đồ hàmdirectionLớn hơn, nhỏ hơn 0.

Tiếp theoif ... else ifLogic là sự phán đoán về tín hiệu giao dịch, khi biểu thứcdirection < 0Thời gian thực cho thấy thị trường hiện tại đang ở giai đoạn tăng trưởng, khi đó nếu dữ liệu giá trong chỉ số siêu xu hướngsupertrendGiá của chỉ số siêu xu hướng trên 2 BAR trước đó (tức làsupertrend[2],还记得历史操作符引用某个变量历史数据吧Bạn có nhớ không? Nếu hiện tại có nắm giữ, tại thời điểm này thực hiện một cuộc gọi đơn chức năng ngược xuống sẽ làm giảm trước đó nắm giữ, và sau đó mở lệnh theo hướng giao dịch hiện tại.supertrend > supertrend[2]Điều kiện không đạt được, chỉ cần thời điểm này.strategy.position_size < 0Có thể bạn sẽ thấy một số người đang cố gắng để làm điều đó.strategy.close_all()Chế độ thực hiện hàm, thực hiện tất cả các giao dịch ngang hàng.

direction > 0Khi ở giai đoạn xu hướng giảm cũng tương tự, nếu có nhiều cổ phiếu được giữ tất cả đều được giữ, thì điều kiện phù hợp.supertrend < supertrend[3]Tại sao nó được thiết lập như vậy?[3]Có lẽ đó là ý định của các nhà chiến lược, sau khi tất cả các thị trường, chẳng hạn như các thị trường giao dịch hợp đồng, có rủi ro nhỏ hơn nhiều.

Đối vớita.supertrendChỉ số, có một số học sinh quan tâm đến nó như thế nào để xác định xu hướng hiện tại là tăng hay giảm?

Trên thực tế, chỉ số này cũng có thể được thực hiện dưới dạng các hàm tùy chỉnh của ngôn ngữ 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]

Chức năng này là một hàm tự động và một hàm tích hợp.ta.supertrendCác thuật toán tương tự, tất nhiên dữ liệu chỉ số được tính toán cũng giống nhau. Từ thuật toán tùy biến này, chúng ta có thể thấy rằng tính toán siêu xu hướng của Pine được sử dụnghl2Các biến cố tích hợp (đối với giá cao nhất, giá thấp nhất cộng với giá thấp nhất và chia cho 2, tức là giá trung bình của giá thấp nhất và giá cao nhất) sau đó tính toán các chỉ số ATR của một chu kỳ nhất định (mức sóng) theo tham số trPeriod; sau đó sử dụng hl2 và ATR để xây dựng đường ray, đường ray.

Cập nhật dựa trên biểu thức ba chữ trong mãlowerBandupperBand

    lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
    upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand

lowerBand: đường downtrend, dùng để xác định xu hướng tăng hay không. upperBand: đường uptrend, dùng để xác định xu hướng giảm hay không. lowerBand và upperBand luôn được tính toán, chỉ cần xác định cuối cùng xu hướng hiện tại trong hàm tùy chỉnh này.

    else if prevSuperTrend == prevUpperBand
        direction := close > upperBand ? -1 : 1
    else
        direction := close < lowerBand ? 1 : -1

Ở đây, giá trị của siêu xu hướng trên thanh cuối cùng làprevUpperBandTrong khi đó, các nhà nghiên cứu cho biết, các đường dây trên đường cao đang có xu hướng đi xuống.closehơnupperBandTrong khi đó, một số nhà đầu tư cho rằng giá đã vượt qua một bước ngoặt và chuyển sang xu hướng tăng.directionCác biến định hướng được thiết lập là -1 (trends upwards); nếu không vẫn được thiết lập là 1 (trends downwards); vì vậy bạn sẽ thấy trong chiến lược siêu xu hướngif direction < 0Khi điều kiện tín hiệu được kích hoạt, hãy làm nhiều hơn.direction > 0Khi các điều kiện tín hiệu được kích hoạt, bạn sẽ không có dấu hiệu nào.

    superTrend := direction == -1 ? lowerBand : upperBand
    [superTrend, direction]

Cuối cùng, dữ liệu về giá và hướng của các chỉ số siêu xu hướng cụ thể được chọn theo hướng.

Chiến lược cân bằng năng động

/*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)

img

img

Chúng ta tiếp tục học một số mô hình thiết kế chính sách của ngôn ngữ Pine, lần này chúng ta sẽ xem xét một chiến lược cân bằng động.BaseCurrencySố tiền vàQuoteCurrencySố tiền luôn được xử lý cân bằng. Giá tương đối của bất kỳ tài sản nào tăng, giá trị được giữ trong tài khoản tăng, tài sản nào được bán. Nếu giá tương đối của một tài sản giảm, giá trị được giữ trong tài khoản giảm, bạn mua tài sản đó. Đây là chiến lược cân bằng động.

Nhược điểm của chiến lược này là, như biểu đồ ngược của chiến lược này cho thấy, trong giai đoạn xu hướng giá lớn tăng (hoặc giảm lớn), chiến lược nổi sẽ có lỗ lớn hơn. Vì vậy, chiến lược này cũng tốt cho chiến lược hiện tại, sử dụng trong tương lai cần phải kiểm soát rủi ro.

Chúng ta hãy nhìn vào các chiến lược trong việc thiết kế mã:

Chúng tôi đã sử dụng một thiết kế đơn giản để mô phỏng một chiến lượcbalance(tức là số lượng tài sản QuotCurrency) vàstocks(tức là số lượng tài sản cơ bản) thông tin cân bằng. Chúng tôi không đọc số lượng tài sản thực sự trong tài khoản, chúng tôi chỉ sử dụng số tiền giả định để tính toán mua và bán phù hợp.maxDiffValueTrong khi đó, giá hiện tại là giá trị duy nhất của một giá trị hiện tại.BaseCurrencyQuoteCurrencySự sai lệchmaxDiffValueTrong khi đó, một số nhà đầu tư đang tìm kiếm cách làm cho các tài sản của họ trở nên cân bằng, bán các tài sản có giá cao và mua các tài sản có giá thấp.

Các tín hiệu giao dịch chiến lược phải được kích hoạt trong giai đoạn BAR thời gian thực, vì vậy các điều kiện giao dịch chiến lược được đặt ra trong quyết định ifnot barstate.ishistoryTrong khi đó, một số người cho rằng giá cả của các sản phẩm này là rất thấp.balanceGiá trị vượt quástocksMua khi giá trị; bán ngược lại; cập nhật sau khi thực hiện lệnh giao dịchbalancestocksMột số người cho rằng, việc tạo ra một sự cân bằng mới là điều cần thiết để tạo ra sự cân bằng.

Những thông tin về chiến lược quay trở lại ở trên chứa giá của giống từ thời điểm bắt đầu của chiến lược quay trở lại, giá là 1458, vì vậy tôi cố tình đặt các tham sốbalanceĐặt tham số cho: 4374 ((1458*3)stocksVì vậy, bạn có thể sử dụng các công cụ như:

Chiến lược siêu xu hướng theo dõi dừng lỗ và dừng tăng

Trong bài học trước, chúng ta đã học đượcstrategy.exitCác chức năng thoát khỏi vị trí, trong đó theo dõi stop-loss stop-loss functionality chúng tôi không có ví dụ giải thích.strategy.exitCác chức năng theo dõi stop-loss stop-gap để tối ưu hóa một chiến lược siêu xu hướng.

Trước tiên chúng ta hãy xem.strategy.exitTracking stop-loss stop-loss parameter của hàm:

1、trail_priceCác tham số: kích hoạt vị trí đặt theo dõi lệnh giao dịch dừng và dừng lỗ hành vi logic này (được chỉ định theo giá)


Thêm nữa