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

Tác giả:Giấc mơ nhỏ, Tạo: 2022-05-30 16:23:43, Cập nhật: 2022-09-28 17:10:21

[TOC]

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

Các video hướng dẫn:Quán hóa giao dịch quá khó để bắt đầu? sử dụng trade view ngôn ngữ Pine từ nhỏ trắng đến Quant-Goddess - Pine ngôn ngữ đầu tiên

Các nền tảng giao dịch định lượng của các nhà phát minh hỗ trợ các chính sách viết ngôn ngữ Pine, hỗ trợ truy cập lại, chạy chính sách ngôn ngữ Pine trên ổ đĩa thực, tương thích với các phiên bản thấp hơn của ngôn ngữ Pine.FMZ.COM),Quảng trường Chiến lượcTrong đó có rất nhiều chính sách của Pine để tìm kiếm, chuyển nhượng (scripts).

FMZ không chỉ hỗ trợ ngôn ngữ Pine mà còn hỗ trợ các chức năng đồ họa mạnh mẽ của ngôn ngữ Pine. Các tính năng trên nền tảng FMZ, các công cụ hữu ích phong phú, quản lý hiệu quả và dễ dàng, cũng tăng thêm khả năng sử dụng của chính sách Pine. FMZ dựa trên khả năng tương thích của ngôn ngữ Pine, đồng thời cũng mở rộng, tối ưu hóa và cắt giảm một số ngôn ngữ Pine.

Một cái nhìn ngắn gọn về một số điểm khác biệt rõ ràng:

  • 1, Chính sách Pine trên FMZ, mã đầu phiên bản//@versionvà bắt đầu với mãstrategyindicatorCâu nói không bắt buộc phải được viết, FMZ không hỗ trợimportNhậplibraryCác chức năng của các chương trình.

    Có thể thấy một số chiến lược được viết như sau:

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

    Có thể viết như sau:

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

    Trên FMZ, nó có thể được đơn giản hóa thành:

    src = close
    a = ta.sma(src, 5)
    b = ta.sma(src, 50)
    c = ta.cross(a, b)
    plot(a, color = color.blue, overlay=true)
    plot(b, color = color.black, overlay=true)
    plotshape(c, color = color.red, overlay=true)
    

    Hoặc:

    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)
    
  • 2, Chính sách (script) Một số cài đặt liên quan đến giao dịch được đặt bởi tham số "Pine language transaction library" trên giao diện chính sách FMZ.

    • Mô hình giá đóng cửa và mô hình giá thực tế Trong giao dịch xem, chúng ta có thể sử dụngstrategyCác hàmcalc_on_every_tickCác tham số để thiết lập kịch bản chiến lược thực hiện chiến lược logic trong thời gian thực mỗi khi giá thay đổi.calc_on_every_tickCác tham số được thiết lập làtrue◎ mặc địnhcalc_on_every_tickCác tham số làfalse, tức là chỉ thực hiện chiến lược logic khi chiến lược hiện tại K-line BAR hoàn toàn đi qua. Trên FMZ, các tham số của mẫu "Pine language exchange library" được đặt.

      img

    • Điều khiển số lượng chính xác như giá cả, số lượng đơn vị dưới khi thực hiện chiến lược cần được chỉ định trên FMZ Trong giao dịch xem, vì chỉ có thể thử nghiệm mô phỏng, do đó không có vấn đề về độ chính xác khi đặt hàng trên thực tế. Trên FMZ, bạn có thể chạy chính sách Pine trên thực tế. Sau đó, bạn cần chính sách có thể linh hoạt xác định các loại giao dịch, chính xác số lượng đặt hàng.

    • Mã hợp đồng tương lai Các loại giao dịch trên FMZ có hai thuộc tính nếu đó là hợp đồng. Các loại giao dịch là "cặp giao dịch" và "mã hợp đồng" và trong thực tế và kiểm tra lại, ngoài việc cần thiết lập các cặp giao dịch rõ ràng, cũng cần thiết lập mã hợp đồng cụ thể trong tham số "mã loại" của mẫu "Pine language trade library". Ví dụ: hợp đồng vĩnh cửu.swap, Mã hợp đồng là cụ thể để xem liệu sàn giao dịch có hợp đồng như vậy hay không. Ví dụ: một số giao dịch là tất cả các hợp đồng quý, bạn có thể điền ở đâyquarterCác mã hợp đồng này phù hợp với mã hợp đồng tương lai được xác định trên tài liệu API ngôn ngữ Javascript/python/c++ của FMZ.

    Các thiết lập khác, ví dụ như số lượng đơn tối thiểu, số lượng đơn mặc định, có thể được xem trong tài liệu ngôn ngữ Pine về"Pine Language Exchange Library" (Tổ điển giao dịch ngôn ngữ Pine)Các tham số được giới thiệu.

  • 3、runtime.debugruntime.logruntime.errorPhương thức mở rộng FMZ, dùng để chỉnh sửa.

    FMZ đã thêm 3 chức năng cho việc chỉnh sửa trên nền tảng.

    • runtime.debug: in controller print variable information, generally not used this function: không thể sử dụng chức năng này.

    • runtime.log: xuất nội dung trong nhật ký. FMZ PINE có chức năng đặc biệt.

      runtime.log(1, 2, 3, close, high, ...),可以传多个参数。
      
    • runtime.error: khi được gọi, sẽ gây ra lỗi khi chạy và mang theo thông báo lỗi được chỉ định trong các thông số message.

      runtime.error(message)
      
  • 4, phần được mở rộng trong các chức năng đồ họaoverlayCác tham số

    Ngôn ngữ Pine trên FMZ, biểu đồplotplotshapeplotcharvà tăngoverlayHỗ trợ các tham số cho phép chỉ định hình ảnh trong hình chủ đề hoặc hình phụ.overlayThiết lậptrueChụp trên sơ đồ chủ đề, đặt thànhfalseĐánh dấu trên phụ hình. Để chính sách Pine trên FMZ có thể chạy chủ đề, phụ hình cùng lúc vẽ.

  • 5、syminfo.mintickLấy giá trị của biến cố

    syminfo.mintickCác biến cố cố định là các giá trị nhỏ nhất của giống hiện tại.Đĩa thực/Kiểm tra lạiCác tham số mẫu trong thư viện giao dịch ngôn ngữ "Pine" trên giao diện có thể điều khiển giá trị này. Giá trị chính xác tiền tệ được đặt vào 2 để giá được chính xác đến vị trí thứ hai của dấu số nhỏ khi giao dịch, trong đó đơn vị biến động nhỏ nhất của giá là 0.01.syminfo.mintickGiá trị của nó là 0.01.

  • Giá trung bình trong FMZ PINE Script là giá bao gồm chi phí thủ tục

    Ví dụ: giá đặt hàng là 8000, hướng bán, số lượng 1 người (một, hai), giá trung bình sau giao dịch không phải là 8000, dưới 8000 (chi phí bao gồm phí thủ tục).

Cơ sở ngôn ngữ Pine

Khi bắt đầu học nền tảng của ngôn ngữ Pine, có thể có một số hướng dẫn, ngữ pháp mã trong ví dụ mà chúng ta không quen thuộc. Không quan trọng, chúng ta có thể quen thuộc với khái niệm trước, hiểu mục đích kiểm tra, hoặc có thể truy vấn tài liệu ngôn ngữ Pine của FMZ để xem hướng dẫn. Sau đó, hãy theo hướng dẫn từng bước để dần dần quen thuộc với các ngữ pháp, hướng dẫn, hàm, biến tích hợp.

Thực hiện mô hình

Khi bắt đầu học ngôn ngữ Pine, điều quan trọng là phải hiểu các khái niệm liên quan như quá trình thực hiện chương trình kịch bản ngôn ngữ Pine. Các chiến lược ngôn ngữ Pine dựa trên biểu đồ, có thể hiểu là một loạt các tính toán và các hoạt động được thực hiện trên biểu đồ theo thứ tự thời gian từ dữ liệu đầu tiên đã được tải trên biểu đồ. Số lượng dữ liệu được tải ban đầu trên biểu đồ có giới hạn.bar_indexĐề cập đến giá trị chỉ mục của K-LineBar hiện tại khi kịch bản Pine được thực hiện.

plot(bar_index, "bar_index")

img

plotCác hàm là một trong những hàm mà chúng ta sẽ sử dụng nhiều hơn trong tương lai. Sử dụng rất đơn giản, đó là vẽ một đường trên biểu đồ dựa trên các tham số được truyền, dữ liệu được truyền làbar_indexĐường dây được đặt tên làbar_indexBạn có thể thấy giá trị của dòng được gọi là bar_index ở trên tên Bar đầu tiên là 0, và Bar tăng lên bên phải tăng lên 1.

Theo thiết lập của chiến lược, mô hình thực hiện chiến lược cũng khác nhau, được chia thành:收盘价模型实时价模型◎ Các khái niệm về mô hình giá đóng cửa, mô hình giá thực tế đã được giới thiệu một cách ngắn gọn trước đây.

  • Mô hình giá đóng cửa

    Khi mã chính sách được thực hiện, chu kỳ của K-LineBar hiện tại được thực hiện hoàn toàn và chu kỳ của K-LineBar đã kết thúc khi K-Line đóng. Khi thực hiện lại logic chính sách Pine, tín hiệu giao dịch được kích hoạt sẽ được thực hiện khi K-LineBar tiếp theo bắt đầu.

  • Mô hình giá thời gian thực

    Khi mã chiến lược được thực hiện, K-bar hiện tại sẽ được thực hiện một lần nữa theo logic chính sách của Pine với mỗi thay đổi thị trường, bất kể là đóng hay không, và tín hiệu giao dịch được kích hoạt sẽ được thực hiện ngay lập tức.

Khi các công cụ ngôn ngữ Pine được thực hiện từ trái sang phải trên biểu đồ, K-lineBar trên biểu đồ được chia thành历史Bar实时BarCác bạn có thể tham khảo:

  • Lịch sử Bar

    Khi chính sách được đặt thành "Mô hình giá thực" bắt đầu thực hiện, tất cả các K-Line Bar trên biểu đồ ngoại trừ K-Line Bar ở phía bên phải nhất sẽ là历史Bar◎ Logic chiến lược trong mọi thứ历史BarChỉ thực hiện một lần. Khi chiến lược được thiết lập để "mô hình giá đóng cửa" bắt đầu thực hiện, tất cả các Bar trên biểu đồ là历史Bar◎ Logic chiến lược trong mọi thứ历史BarChỉ thực hiện một lần.

    Tính toán dựa trên lịch sử Bar: Mã chiến lược được thực hiện một lần trong trạng thái đóng cửa History Bar, sau đó mã chiến lược tiếp tục được thực hiện trong History Bar tiếp theo cho đến khi tất cả các History Bar được thực hiện một lần.

  • LiveBar

    Khi chiến lược được thực hiện trên K-line Bar cuối cùng ở bên phải, Bar sẽ trở thành Real-Time Bar. Khi Real-Time Bar đóng, Bar sẽ trở thành Real-Time Bar (trở thành History Bar).

    Khi chiến lược được đặt là "mô hình giá thời gian thực" bắt đầu thực hiện, một chiến lược logic sẽ được thực hiện cho mỗi sự thay đổi thị trường trên Bar thời gian thực. Khi bắt đầu thực hiện, Bar không hiển thị trên biểu đồ trong thời gian thực.

    Theo tính toán thực tế của Bar: Nếu đặt chính sách là "Mô hình giá đóng cửa" và biểu đồ không hiển thị Bar trong thời gian thực, mã chính sách sẽ chỉ được thực hiện một lần khi Bar hiện tại đóng cửa. Nếu đặt chính sách là "Mô hình giá thực" thì tính toán trên Bar thực và lịch sử Bar hoàn toàn khác nhau, trong đó mỗi thay đổi thị trường trên Bar thực sẽ thực hiện một mã chính sách; ví dụ như biến tích hợp.highlowcloseTrong Bar lịch sử là xác định, trong Bar thời gian thực có thể mỗi khi thị trường thay đổi, các giá trị này sẽ thay đổi. Vì vậy, dữ liệu như các chỉ số được tính toán dựa trên các giá trị này cũng sẽ thay đổi trong thời gian thực. Trong Bar thời gian thựccloseTrong khi đó, một số người cho rằng giá cả của sản phẩm này là cao hơn so với các sản phẩm khác.highlowLuôn luôn đại diện cho mức cao nhất và thấp nhất đạt được kể từ khi bắt đầu Realtime Bar hiện tại. Các biến tích hợp này đại diện cho giá trị cuối cùng khi Realtime Bar được cập nhật cuối cùng.

    Cơ chế quay trở lại khi thực hiện chiến lược trên Bar trong thời gian thực (mô hình giá trong thời gian thực): Khi thực hiện Bar trong thời gian thực, các biến định nghĩa người dùng được đặt lại trước khi thực hiện mỗi lần lặp lại của chính sách được gọi là quay lại. Để hiểu cơ chế quay lại, chúng ta hãy thử nghiệm bằng một ví dụ dưới đây.

    Lưu ý:

    /*backtest 
    ...
    ..
    .
    */
    

    Nội dung của gói là thông tin cấu hình kiểm tra lại được lưu trữ dưới dạng mã trên nền tảng FMZ.

    /*backtest
    start: 2022-06-03 09:00:00
    end: 2022-06-08 15:00:00
    period: 1m
    basePeriod: 1m
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */
    
    var n = 0
    if not barstate.ishistory
        runtime.log("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")
    

    img

    img

    Chúng tôi chỉ xem xét các cảnh thực hiện trong thời gian thực Bar, vì vậy chúng tôi sử dụngnot barstate.ishistoryHạn chế biểu thức chỉ được sử dụng trước và sau khi thực hiện phép tích lũy trên các biến n trong thời gian thực Barruntime.logCác hàm xuất thông tin trong nhật ký chính sách.plotCác đường cong n được vẽ cho thấy n luôn là 0 khi chính sách đang chạy trong lịch sử Bar. Các hoạt động n + 1 được kích hoạt khi thực hiện đến Bar trong thời gian thực, và các hoạt động n + 1 được thực hiện mỗi lần thực hiện chính sách trên Bar trong thời gian thực. Có thể thấy từ thông tin nhật ký rằng n được đặt lại với giá trị cuối cùng của chính sách thực hiện trước đó mỗi lần thực hiện lại.

    Một số người cho rằng: Khi chính sách bắt đầu thực thi trong thời gian thực, mỗi lần cập nhật, một mã chính sách được thực hiện. 2, Khi thực hiện trên Bar trong thời gian thực, biến sẽ được xoay lại trước mỗi lần thực hiện mã chính sách. 3, khi thực hiện trên Bar trong thời gian thực, các biến được gửi một lần khi cập nhật kết thúc.

    Do dữ liệu lật ngược, các thao tác đồ họa như đường cong trên biểu đồ cũng có thể gây ra việc vẽ lại, ví dụ như chúng ta đã sửa đổi mã thử nghiệm, thử nghiệm thực tế:

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

    Hình ảnh của khoảnh khắc Aimg

    Hình ảnh của thời điểm Bimg

    Chúng tôi chỉ thay đổi câu này:n := open > close ? n + 1 : nTrong biểu đồ đầu tiên, bạn có thể thấy rằng tại thời điểm A, giá mở cao hơn giá đóng, vì vậy n được thêm vào 1, giá trị được hiển thị trên đường cong n là 5; sau đó, biến động, cập nhật giá được hiển thị như trong biểu đồ thứ hai, giá mở thấp hơn giá đóng, n quay trở lại và không thêm 1 trên biểu đồ. Các đường cong n cũng được vẽ lại ngay lập tức, khi n trên đường cong là 4; vì vậy các tín hiệu cho thấy trên Bar trong thời gian thực là không chắc chắn và có thể thay đổi.

  • Các biến trong hàm trong ngữ cảnh

    Dưới đây chúng ta cùng nhau nghiên cứu các biến trong hàm ngôn ngữ Pine. Theo mô tả trong một số bài học của Pine, các biến trong hàm khác với các biến ngoài hàm như sau:

    Lịch sử của các biến hàng được sử dụng trong hàm Pine được tạo ra bởi mỗi lần gọi liên tục vào hàm. Nếu không gọi hàm trên mỗi cột mà kịch bản chạy, điều này sẽ dẫn đến sự khác biệt giữa giá trị lịch sử bên trong và cột lịch sử bên ngoài của cột. Do đó, nếu không gọi hàm trên mỗi cột, thì các chuỗi dùng cùng một giá trị chỉ mục bên trong và bên ngoài của hàm sẽ không tham chiếu đến cùng một điểm lịch sử.

    Không sao, chúng tôi đã giải quyết vấn đề này bằng một đoạn mã thử nghiệm chạy trên FMZ:

    /*backtest
    start: 2022-06-03 09:00:00
    end: 2022-06-08 15:00:00
    period: 1m
    basePeriod: 1m
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */
      
    f(a) => a[1]
    f2() => close[1]  
    
    oneBarInTwo = bar_index % 2 == 0
    plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")   
    plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")   
    plot(close[2], title = "close[2]", color = color.red, overlay = true)
    plot(close[1], title = "close[1]", color = color.green, overlay = true)
    

    Trình chiếu chạy thử

    img

    Mã kiểm tra khá đơn giản, chủ yếu là để xem xét dữ liệu được trích dẫn theo hai cách:f(a) => a[1]f2() => close[1]

    • f(a) => a[1]Cách sử dụng các tham số truyền, các hàm cuối cùng trở lạia[1]

    • f2() => close[1]Sử dụng các biến tích hợp trực tiếp:closeChế độ trả về cuối cùngclose[1]

    []Biểu tượng được sử dụng để tham chiếu các hoạt động về giá trị lịch sử của các biến trong chuỗi dữ liệu, close[1] là tham chiếu dữ liệu giá đóng trước giá đóng hiện tại Bar; mã thử nghiệm của chúng tôi vẽ tổng cộng 4 dữ liệu trên biểu đồ:

    • plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")Vẽ một ký tự A, màu đỏ, chỉ vẽ khi oneBarInTwo là đúng, và vị trí vẽ ((trên trục Y) là:f(close)Các giá trị được trả về.

    • plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")Vẽ một ký tự B, màu xanh lá cây, chỉ được vẽ khi oneBarInTwo là đúng, và vị trí được vẽ (trên trục Y) là:f2()Các giá trị được trả về.

    • plot(close[2], title = "close[2]", color = color.red, overlay = true)Đường vẽ, màu đỏ, vị trí được vẽ (trên trục Y):close[2]Đó là giá đóng cửa trên Bar trước số 2 của Bar hiện tại.

    • plot(close[1], title = "close[1]", color = color.green, overlay = true)Đường vẽ màu xanh lá cây, vị trí vẽ (trên trục Y) là:close[1]Đó là giá đóng cửa trên Bar trước số Bar hiện tại.

    Một màn hình chạy bằng cách tìm kiếm lại chính sách có thể thấy, mặc dù hình ảnh A đánh dấu các chức năng được sử dụngf(a) => a[1]và các hàm được sử dụng để đánh dấu hình Bf2() => close[1]Cả hai đều được sử dụng[1] để tham chiếu dữ liệu lịch sử trên chuỗi dữ liệu, nhưng vị trí đánh dấu "A" và "B" trên biểu đồ hoàn toàn khác nhau.plot(close[2], title = "close[2]", color = color.red, overlay = true)Dữ liệu được sử dụng trên đường vẽ làclose[2]

    img

    Và điều đó là bởi vì chúng ta có thể sử dụng chỉ số của K-lineBar, một biến tích hợp.bar_indexTính toán liệu có vẽ dấu "A" và "B" không. Các dấu "A" và "B" không vẽ biểu đồ trên mỗi đường KBar.f(a) => a[1]Các giá trị được tham chiếu theo cách này sẽ được gọi với các hàm nếu không phải ở mỗi Bar.f2() => close[1]Các giá trị được trích dẫn theo cách này không giống nhau (ngay cả khi sử dụng cùng một chỉ mục như [1]).

  • Một số hàm tích hợp cần tính trên mỗi Bar để tính ra kết quả của chúng một cách chính xác

    Một ví dụ đơn giản cho thấy điều này:

    res = close > close[1] ? ta.barssince(close < close[1]) : -1
    plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)
    

    Chúng ta sẽ gọi hàm bằng mã.ta.barssince(close < close[1])Viết trong một toán tử 3condition ? value1 : value2Điều này dẫn đến việc chỉ cóclose > close[1]时去调用ta.barssince函数。可偏偏ta.barssinceChức năng là tính từ lần gần đây nhất.close < close[1]Số lượng các dòng K được tạo ra; khi gọi hàm ta.barssince là close > close[1], tức là giá đóng cửa hiện tại lớn hơn giá đóng cửa của Bar trước đó, hàm ta.barssince khi được gọi không có điều kiện close < close[1] và không có vị trí được tạo gần đây nhất.

    ta.barssince: Khi gọi, hàm trả về na nếu điều kiện này chưa bao giờ được đáp ứng trước dòng K hiện tại.

    Dưới đây là hình:

    img

    Vì vậy, khi vẽ đồ họa, chỉ vẽ dữ liệu khi biến res có giá trị ((-1)).

    Để tránh vấn đề này, chúng ta chỉ cần sử dụngta.barssince(close < close[1])Các cuộc gọi hàm được lấy ra từ các toán tử 3 và được viết bên ngoài các nhánh của bất kỳ điều kiện nào có thể.

    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)
    

    img

Dòng thời gian

Khái niệm chuỗi thời gian rất quan trọng trong ngôn ngữ Pine, và là một khái niệm mà chúng ta phải hiểu khi học ngôn ngữ Pine. Các chuỗi thời gian không phải là một loại mà là cấu trúc cơ bản của giá trị liên tục của các biến được lưu trữ theo thời gian. Chúng ta biết rằng các kịch bản Pine dựa trên biểu đồ, và những gì cơ bản nhất được hiển thị trong biểu đồ là biểu đồ K.openlà một biến tích hợp trong ngôn ngữ Pine, cấu trúc của nó là để lưu trữ chuỗi thời gian giá mở cửa của mỗi dòng KBar.openCấu trúc chuỗi thời gian này đại diện cho giá khởi điểm của tất cả các K-stringBar trong K-string hiện tại từ Bar đầu tiên khi bắt đầu đến Bar khi kịch bản hiện tại được thực hiện. Nếu K-string hiện tại là chu kỳ 5 phút, thì chúng ta trích dẫn (hoặc sử dụng) trong mã chính sách Pine.openKhi đó là giá mở của K-lineBar khi sử dụng mã chính sách đang được thực hiện. Nếu cần sử dụng giá trị lịch sử trong chuỗi thời gian để tham khảo.[]Người vận hành. Khi chính sách Pine được thực hiện trên một K-lineBar, sử dụngopen[1]Đánh dấu tham chiếuopenGiá mở của K-LineBar trước đó của K-LineBar mà kịch bản hiện tại đang thực hiện trên chuỗi thời gian (tức là giá mở của chu kỳ K-Line trước đó).

  • Các biến trong chuỗi thời gian rất dễ sử dụng để tính toán. Chúng ta có một hàm tích hợp.ta.cumVí dụ:

    ta.cum
    
    Cumulative (total) sum of `source`. In other words it's a sum of all elements of `source`.
    ta.cum(source) → series float
    RETURNS
    Total sum series.
    ARGUMENTS
    source (series int/float)
    SEE ALSO
    math.sum
    

    Mã kiểm tra:

    v1 = 1
    v2 = ta.cum(v1)
    plot(v1, title="v1")
    plot(v2, title="v2")
    plot(bar_index+1, title="bar_index")
    

    Có rất nhiều.ta.cumCác hàm tích hợp như vậy có thể xử lý trực tiếp dữ liệu trên chuỗi thời gian, chẳng hạn nhưta.cumSau đó, chúng ta sẽ sử dụng một biểu đồ để giúp bạn dễ dàng hiểu.

    Chiến lược vận hành Biến đổi mặc định bar_index v1 v2
    Chiến lược chạy ở root 1 K Bar 0 1 1
    Chiến lược chạy trên root 2 K-bar 1 1 2
    Chiến lược chạy trên đường K 3Bar 2 1 3
    Chiến lược chạy trên n + 1 root K Bar N 1 N+1

    Bạn có thể thấy rằng v1, v2 và thậm chí bar_index là các cấu trúc chuỗi thời gian, với dữ liệu tương ứng trên mỗi Bar. Mã kiểm tra này phân biệt giữa "mô hình giá thời gian thực" và "mô hình giá đóng cửa" chỉ bằng cách hiển thị Bar thời gian thực trên biểu đồ. Để kiểm tra tốc độ, chúng tôi sử dụng "mô hình giá đóng cửa" để kiểm tra lại.

    img

    Vì v1 là 1 trên mỗi Bar.ta.cum(v1)Khi thực hiện hàm trên Bar đầu tiên của K, kết quả là 1, vì chỉ có Bar đầu tiên. Variable v2 được gán. Khita.cum(v1)Khi thực hiện trên K-Line Bar thứ hai, đã có 2 K-LineBar (thứ nhất là bar_index tương ứng là 0, và thứ hai là bar_index tương ứng là 1), vì vậy kết quả là 2, gán cho biến v2, và như vậy. Thực tế, bạn có thể thấy rằng v2 là số lượng Bar trong K-Line trong biểu đồ, do chỉ số của K-Line.bar_indexNếu chúng ta bắt đầu từ 0 và tăng lên,bar_index + 1Trong biểu đồ quan sát, bạn cũng có thể thấy các đường.v2bar_indexCó một số người nói rằng, "Đó là một điều không thể làm được".

    img

    Tôi cũng có thể sử dụng nó.ta.cumCác hàm tích hợp tính toán tổng giá đóng cửa của tất cả các Bar trên biểu đồ hiện tại, sau đó chỉ có thể viết như sau:ta.cum(close), khi chiến lược chạy đến Bar thời gian thực ở bên phảita.cum(close)Kết quả tính toán là tổng giá đóng cửa của tất cả các Bar trên biểu đồ (không chạy đến bên phải, chỉ thêm vào Bar hiện tại).

    Các biến trong chuỗi thời gian cũng có thể được tính toán bằng các toán tử, ví dụ như mã:ta.sma(high - low, 14)Và chúng ta có thể sử dụng các biến tích hợphigh(K Bar giá cao nhất) trừlow(K Bar giá thấp nhất), sử dụng cuối cùngta.smaChức năng tìm kiếm giá trị trung bình.

  • Kết quả gọi hàm cũng sẽ để lại dấu vết giá trị trong chuỗi thời gian.

    v1 = ta.highest(high, 10)[1]
    v2 = ta.highest(high[1], 10)
    plot(v1, title="v1", overlay=true)
    plot(v2, title="v2", overlay=true)
    

    Mã thử nghiệm này chạy thử nghiệm khi kiểm tra lại, bạn có thể quan sátv1v2Các giá trị của các giá trị tương tự, các đường được vẽ trên biểu đồ cũng hoàn toàn trùng lặp. Kết quả được tính toán khi gọi hàm sẽ để lại dấu vết của giá trị trong chuỗi thời gian, ví dụ như mã.ta.highest(high, 10)[1]Một trong số đóta.highest(high, 10)Kết quả được tính từ cuộc gọi của hàm cũng có thể được sử dụng[1] để tham khảo giá trị lịch sử của nó.ta.highest(high, 10)Kết quả là:ta.highest(high[1], 10)Vì vậy.ta.highest(high[1], 10)ta.highest(high, 10)[1]Một số người cho rằng,

    Sử dụng một hàm vẽ khác để xuất thông tin xác minh:

    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)
    

    Bạn có thể thấy giá trị của biến a và biến b trong chuỗi thời gian được hiển thị ở phía trên và phía dưới Bar tương ứng. Bạn có thể giữ mã đồ họa này trong quá trình học, vì trong quá trình kiểm tra, thử nghiệm có thể thường xuyên cần phải xuất thông tin trên biểu đồ để quan sát.

    img

Cấu trúc kịch bản

Cấu trúc chung

Trong phần đầu của bài học, chúng tôi đã tóm tắt một số điểm khác nhau về việc sử dụng ngôn ngữ Pine trên FMZ và sử dụng ngôn ngữ Pine trên Trading View.indicator()strategy()Và tạm thời không hỗ trợ.library()│ Tất nhiên, để tương thích với các phiên bản trước của kịch bản Pine, các chính sách được viết như://@version=5indicator()strategy()Có thể. Một số cài đặt chính sách cũng có thể được cài đặt trênstrategy()Chế độ truyền tham số trong hàm.

<version>
<declaration_statement>
<code>

<version>Thông tin kiểm soát phiên bản có thể bị bỏ qua.

Phản hồi

Ngôn ngữ Pine//Là một ký tự một dòng, vì ngôn ngữ Pine không có nhiều dòng ký tự. FMZ mở rộng ký tự/**/Có thể sử dụng nhiều dòng chú thích.

Các dòng không phải là chú thích hoặc hướng dẫn trình biên dịch trong kịch bản là câu nói, nó thực hiện các thuật toán của kịch bản. Một câu nói có thể là một trong số đó.

  • Tuyên bố biến
  • Đặt lại giá trị của biến
  • Tuyên bố hàm
  • Gọi hàm tích hợp, gọi hàm được xác định bởi người dùng
  • ifforwhileHoặcswitchcấu trúc tương tự

Câu nói có thể được sắp xếp theo nhiều cách

  • Một số câu nói có thể được thể hiện bằng một dòng, chẳng hạn như hầu hết các tuyên bố biến, chỉ chứa một dòng gọi hàm hoặc một dòng tuyên bố hàm; những câu khác, như cấu trúc, luôn cần nhiều dòng vì chúng cần một khối địa phương.
  • Các câu nói toàn cầu của kịch bản (tức là những phần không thuộc về các phần) không thể được sử dụng để viết một câu nói toàn cầu.空格Hoặc制表符(tab key) bắt đầu. Chữ ký tự đầu tiên của chúng cũng phải là ký tự đầu tiên của dòng. Các dòng bắt đầu ở vị trí đầu tiên của dòng, theo định nghĩa là một phần của phạm vi toàn cầu của kịch bản.
  • Một cấu trúc hoặc một tuyên bố chức năng nhiều dòng luôn cần mộtlocal blockMột khối địa phương phải được thu hẹp thành một biểu mẫu hoặc bốn không gian (nếu không, nó sẽ được phân tích thành dòng mã chuỗi trước đó, nghĩa là được xác định là nội dung liên tục của dòng mã trước đó), và mỗi khối địa phương xác định một phạm vi địa phương khác.
  • Nhiều câu đơn hàng có thể được nối liền trong một dòng bằng cách sử dụng dấu chấm (,) làm dấu phân cách.
  • Một dòng có thể bao gồm chú thích hoặc chỉ là chú thích.
  • Dòng cũng có thể được gói lại (tiếp tục trên nhiều dòng).

Ví dụ, bao gồm ba phần tử, một trong tuyên bố chức năng tùy chỉnh, hai trong tuyên bố biến sử dụng cấu trúc if, mã như sau:

indicator("", "", true)             // 声明语句(全局范围),可以省略不写

barIsUp() =>                        // 函数声明(全局范围)
    close > open                    // 本地块(本地范围)

plotColor = if barIsUp()            // 变量声明 (全局范围)
    color.green                     // 本地块 (本地范围)
else
    color.red                       // 本地块 (本地范围)

runtime.log("color", color = plotColor)  // 调用一个内置函数输出日志 (全局范围)

Đổi mã

Dòng dài có thể được chia thành nhiều dòng, hoặc được "bọc" lên. Dòng được bọc phải thu hẹp vào bất kỳ số lượng không gian nào, miễn là nó không phải là số lần của 4 (các ranh giới này được sử dụng để thu hẹp các phần tử).

a = open + high + low + close

Có thể được đóng gói như sau (lưu ý rằng không có số lượng không gian co lại cho mỗi dòng là số lần của 4):

a = open +
      high +
          low +
             close

Một cuộc gọi dài có thể được đóng gói thành một cuộc gọi dài.

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)

Một câu nói trong một tuyên bố chức năng được xác định bởi người dùng cũng có thể được đóng gói. Tuy nhiên, vì một phần tử địa phương phải bắt đầu bằng cách rút ngắn (tương đương 4 không gian hoặc 1 ký tự), khi chia nó sang dòng tiếp theo, phần tiếp theo của câu nói phải bắt đầu bằng nhiều hơn một lần rút ngắn (không bằng số lần của 4 không gian). Ví dụ:

test(c, o) =>
    ret = c > o ?
       (c > o+5000 ? 
          1 :
              0):
       (c < o-5000 ? 
          -1 : 
              0)
           
                   
a = test(close, open)
plot(a, title="a")

Nhãn hiệu và toán tử

Nhãn hiệu

Trước khi hiểu được các biến, chúng ta phải hiểu khái niệm về các ký hiệu.Chức năngCác biếnTên của (được sử dụng để đặt tên cho biến, hàm) ⇒Chức năngTrong bài học tiếp theo, chúng ta sẽ tìm hiểu, trước tiên, chúng ta hãy học các ký hiệu chữ cái.

  • 1, mã số phải được viết lớn(A-Z)Hoặc viết nhỏ(a-z)chữ cái hoặc dấu phẩy(_)Đầu tiên, là ký tự đầu tiên của biểu tượng.
  • 2, ký tự tiếp theo sau ký tự đầu tiên của ID có thể làchữ cáiĐường biên dướiHoặcSố liệu
  • 3, Tên của các biểu tượng được viết bằng chữ viết nhỏ và chữ viết lớn.

Ví dụ, các biểu tượng có tên như sau:

fmzVar
_fmzVar
fmz666Var
funcName
MAX_LEN
max_len
maxLen
3barsDown  // 错误的命名!使用了数字字符作为标识符的开头字符

Như hầu hết các ngôn ngữ lập trình khác, ngôn ngữ Pine cũng có đề xuất viết. Thông thường đề nghị khi đặt tên cho các biểu tượng:

  • 1, tất cả các chữ cái đều được viết to để đặt tên cho hằng số.
  • 2. Sử dụngQuy tắc nhỏTên được sử dụng cho các biểu tượng khác.
// 命名变量、常量
GREEN_COLOR = #4CAF50
MAX_LOOKBACK = 100
int fastLength = 7

// 命名函数
zeroOne(boolValue) => boolValue ? 1 : 0

Các toán tử

Các toán tử là một số ký hiệu hoạt động được sử dụng trong ngôn ngữ lập trình để xây dựng biểu thức, và biểu thức là các quy tắc tính toán được thiết kế cho một số mục đích tính toán khi chúng ta viết chính sách. Các toán tử trong ngôn ngữ Pine được phân loại theo chức năng như:

Các toán tử gán giá trị, toán tử số, toán tử so sánh, toán tử logic,? :Các toán tử ba chữ cái[]Chữ tham chiếu lịch sử.

Các toán tử số*Ví dụ, các loại vấn đề khác nhau từ các toán tử ngôn ngữ Pine trên Trading View trả về kết quả có mã kiểm tra sau:

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

Khi chạy kịch bản này trên Trading View, nó sẽ biên soạn thông báo lỗi vì:adjustedLength = lenInput * factorSau khi nhân, kết quả là:series intLoại ((series), tuy nhiênta.emaCác tham số thứ hai của hàm không hỗ trợ loại này. Tuy nhiên, không có hạn chế nghiêm ngặt như vậy trên FMZ, và mã trên có thể hoạt động bình thường.

Dưới đây chúng ta cùng xem các phép tính khác nhau được sử dụng.


Các toán tử gán giá trị

Có hai loại toán tử gán:=:=Chúng ta đã thấy một vài ví dụ trong phần đầu của bài học.

=Các toán tử được sử dụng để gán giá trị khi khởi tạo hoặc tuyên bố các biến.=Initialization, các biến sau khi tuyên bố gán sẽ bắt đầu với giá trị này trên mỗi Bar sau đó. Đây là các tuyên bố biến hiệu quả:

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)

Chú ý.a = closeCâu lệnh gán, trên mỗi Bar, biến a là giá đóng cửa hiện tại của Bar. Các biến khácbcdCó thể thử nghiệm trong hệ thống đo lường lại trên FMZ, kết quả có thể được nhìn thấy từ hình vẽ.

:=Sử dụng để tái gán giá trị cho một biến hiện có, có thể được hiểu đơn giản như là sử dụng:=Các toán tử được sử dụng để sửa đổi các giá trị của các biến đã được tuyên bố, khởi tạo. Nếu sử dụng:=Các toán tử sẽ tạo ra lỗi cho các phép gán biến chưa được khởi tạo hoặc đã được tuyên bố, ví dụ:

a := 0

Vì vậy,:=Các toán tử gán thường được sử dụng để gán lại các biến đã có, ví dụ:

a = close > open 
b = 0 
if a
    b := b + 1

plot(b)

Nếuclose > open(i.e. BAR hiện tại là đường dương xích), a biến là giá trị đúng (true); sẽ thực hiện mã trong khối cục bộ của câu ifb := b + 1, sử dụng các toán tử gán:=Đặt lại giá trị cho b, thêm một 1; và sau đó sử dụng hàm plot để vẽ giá trị của biến b trên các BAR của chuỗi thời gian trên biểu đồ, nối các đường dây.

Có phải chúng ta nghĩ rằng một đường dương xích BAR xuất hiện, b sẽ tiếp tục cộng thêm 1 không? Tất nhiên không, ở đây chúng ta đã tuyên bố cho biến b, không sử dụng bất kỳ từ khóa nào khi khởi tạo thành 0.b=0Có thể thấy rằng kết quả của việc chạy mã này là mỗi lần đặt lại biến b là 0, nếu biến a là giá trị thực, nó sẽ phù hợp.close > openVậy là b sẽ được thêm 1 khi thực hiện mã trong vòng này, nhưng b sẽ được gán lại 0 khi thực hiện mã trong vòng tiếp theo. Đây cũng là nơi mà người mới sử dụng ngôn ngữ Pine dễ bị ngã xuống.

Về các toán tử gán, chúng ta phải mở rộng giải thích hai từ khóa:varvarip

  • var

    Trong thực tế, từ khóa này, chúng ta đã thấy và sử dụng trong các bài học trước đây, nhưng không được thảo luận chi tiết vào thời điểm đó.

    var là một từ khóa được sử dụng để phân bổ và khởi tạo một lần các biến. Thông thường, ngữ pháp gán biến mà không bao gồm từ khóa var sẽ dẫn đến việc giá trị của biến sẽ bị che phủ mỗi khi dữ liệu được cập nhật. Ngược lại, khi sử dụng từ khóa var, các biến được phân bổ, mặc dù dữ liệu được cập nhật, chúng vẫn có thể giữ trạng thái.

    Chúng ta vẫn sử dụng ví dụ này, nhưng chúng ta chỉ sử dụng nó khi gán cho b.varTừ khóa:

    a = close > open 
    var b = 0 
    if a
        b := b + 1
    
    plot(b)
    

    varTừ khóa cho phép biến b chỉ thực hiện định nghĩa đầu tiên ban đầu, sau đó không đặt lại b thành 0 mỗi lần thực hiện logic chiến lược, do đó, các đường được vẽ từ khi chạy có thể quan sát được b là số lượng đường sợi BAR xuất hiện tại đường K hiện tại BAR.

    Các biến được tuyên bố var không chỉ có thể được viết trên phạm vi toàn cầu mà còn có thể được viết trong các khối mã, ví dụ như ví dụ này:

    strategy(overlay=true)
    var a = close
    var b = 0.0
    var c = 0.0
    var green_bars_count = 0
    if close > open
        var x = close
        b := x
        green_bars_count := green_bars_count + 1
        if green_bars_count >= 10
            var y = close
            c := y
    plot(a, title = "a")
    plot(b, title = "b")
    plot(c, title = "c")
    

    Chất biến a giữ giá đóng cửa của đường cột đầu tiên trong chuỗi. Các biến số b giữ giá đóng cửa của thanh giá n màu xanh lá cây n đầu tiên trong loạt n. Các biến c giữ giá đóng cửa của con số 10 trong loạt các con số.

  • khác nhau

    varipChúng ta thấy từ khóa này lần đầu tiên, và chúng ta có thể xem mô tả của từ khóa này:

    varip (var intrabar persist) là một từ khóa dùng để phân bổ và khởi tạo một lần các biến. Nó tương tự như từ khóa var, nhưng các biến được sử dụng trong tuyên bố varip giữ giá trị giữa các bản cập nhật dòng K trong thời gian thực.

    Có phải nó khó hiểu hơn không? Không sao, chúng ta sẽ giải thích bằng một ví dụ và nó sẽ dễ dàng hiểu.

    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 + 1
    

    Mã thử nghiệm này biểu hiện khác nhau trên mô hình giá đóng cửa và mô hình giá thực tế:

    Mô hình giá thực tế: Hãy nhớ rằng chúng ta đã nói về các chiến lược thực hiện trong giai đoạn BAR lịch sử và giai đoạn BAR thời gian thực.varvaripCác biến trong tuyên bốiiiCác hoạt động tăng dần được thực hiện mỗi lần thực hiện mã chiến lược. Vì vậy, bạn có thể thấy rằng các số được hiển thị trên kết quả K-Line BAR đều tăng lên một lần. Khi giai đoạn K-Line lịch sử kết thúc, giai đoạn K-Line thực tế bắt đầu. Các biến trong tuyên bố var, varip bắt đầu thay đổi.i := i + 1ii := ii + 1Có một sự khác biệt là i sẽ được thay đổi mỗi lần. Tuy nhiên, i vẫn sẽ được thay đổi, nhưng giá trị trước đó sẽ được khôi phục lại vào vòng thực thi kế hoạch kế hoạch tiếp theo. (Hãy nhớ cơ chế quay trở lại mà chúng tôi đã giải thích trong chương "Hành động mô hình" trước đây?), Giá trị của i sẽ không được xác định cho đến khi dòng K hiện tại BAR chạy ra khỏi bản cập nhật.

    Mô hình giá đóng cửa: Vì mô hình giá đóng là một chiến lược logic chỉ được thực hiện một lần khi mỗi K-line BAR đi qua. Vì vậy, trong mô hình giá đóng, giai đoạn K-line lịch sử và giai đoạn K-line thời gian thực, các biến của tuyên bố var, varip diễn ra hoàn toàn đồng bộ trong các ví dụ trên, mỗi K-line BAR tăng 1.


Các toán tử số
Các toán tử Giải thích
+ Pháp
- Giảm luật
* Nhân
/ Ngoại trừ
% Hình mẫu

+-Các toán tử có thể được sử dụng như một toán tử nhị phân hoặc một toán tử nguyên tố. Các toán tử số liệu khác chỉ có thể được sử dụng như một toán tử hai và sẽ trả lại lỗi nếu được sử dụng như một toán tử nguyên tố.

1, các toán tử toán học ở cả hai bên đều là các loại giá trị, kết quả là các loại giá trị, kiểu toàn phần hoặc các số trôi tùy thuộc vào kết quả của hoạt động. Nếu một số trong số đó là một chuỗi, thì chúng ta có thể sử dụng một số trong số đó.+, thì kết quả tính toán là một chuỗi, giá trị sẽ được chuyển đổi thành dạng chuỗi, và sau đó các chuỗi được ghép lại. Nếu là các toán tử số khác, chúng sẽ cố gắng chuyển đổi chuỗi thành giá trị số, và sau đó thực hiện. 3, nếu một trong số các số hoạt động là na, kết quả tính toán là giá trị trống na, hiển thị NaN khi in trên FMZ.

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

Ngôn ngữ Pine trên FMZ có một chút khác biệt với ngôn ngữ Pine trên Trading View, ngôn ngữ Pine trên FMZ không quá khắt khe về yêu cầu loại biến; ví dụ:

a = 1 * "1.1"
b = "1" / "1.1"
c = 5 % "A" 

plot(a)
plot(b)
plot(c)

Có thể chạy trên FMZ, nhưng sẽ báo cáo lỗi loại trong giao dịch. Đối với các toán tử, hệ thống sẽ tính toán sau khi chuyển đổi các chuỗi thành các giá trị. Nếu các chuỗi không phải số không thể tính toán, hệ thống sẽ tính toán với giá trị trống na.


Chế độ so sánh

Các toán tử so sánh đều là các toán tử nhị phân.

Các toán tử Giải thích
< Ít hơn
> lớn hơn
<= Ít hơn bằng
>= lớn hơn bằng
== Tương đương
!= Không bình đẳng

Ví dụ thử nghiệm:

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

Như bạn có thể thấy, phép so sánh rất đơn giản, nhưng đây cũng là phép so sánh được sử dụng nhiều nhất khi viết chính sách.closeopenVâng. Cũng như các toán tử, FMZ khác với Pine trên Trading View, FMZ không có loại yêu cầu đặc biệt nghiêm ngặt, vì vậy các câu nói như vậyd = "1" >= 2Không báo lỗi trên FMZ, trước khi thực hiện, các chuỗi được chuyển đổi thành các giá trị số, sau đó so sánh các hoạt động.


Các toán tử logic
Các toán tử Biểu tượng mã Giải thích
Không không Đơn vị vận hành, không vận hành
Các toán tử nhị phân, hoạt động với ()
Hoặc hoặc Các toán tử nhị phân, hoặc các hoạt động

Khi nói về các toán tử logic, thì chúng ta phải nói về các bảng giá trị thực. Cũng giống như chúng ta đã học ở trường trung học, nhưng ở đây chúng ta đang thử nghiệm trong hệ thống kiểm tra lại, học:

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

Để không để những thông tin in liên tục của hệ thống kiểm tra lại ảnh hưởng đến quan sát, chúng tôi sử dụngruntime.error("stop")Sau khi thực hiện một lần in, câu lệnh sẽ bị lỗi bất thường để dừng kiểm tra lại, sau đó bạn có thể xem thông tin đầu ra, bạn có thể thấy nội dung được in và bảng giá trị thực là giống nhau.


Các toán tử 3 đô la

Sử dụng các toán tử ba? :và các biểu thức 3 phần tử kết hợp với các số vận hànhcondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseChúng ta cũng đã quen thuộc trong các bài học trước đây. Những biểu thức ba chữ cái, các toán tử ba chữ cái có nghĩa là có tổng cộng ba số toán tử trong đó.

condition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseTrongconditionNếu đúng, thì giá trị của biểu thức là:valueWhenConditionIsTrueNếuconditionGiá trị của biểu thức giả định làvalueWhenConditionIsFalse

Một ví dụ đơn giản cho việc chứng minh, mặc dù không có nhiều mục đích thực tế:

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)

Nếu bạn gặp phải một ngôi sao chéo, điều đó là không quan trọng! biểu thức ba chữ cái cũng có thể được ghép, như chúng ta đã làm trong bài học trước đây.

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)

Nó cũng giống như việccondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseTrongvalueWhenConditionIsTruevalueWhenConditionIsFalse, cũng được thay thế bằng một biểu thức ba chữ khác.


Chữ toán lịch sử

Sử dụng toán tử lịch sử[]Các giá trị lịch sử trên chuỗi thời gian. Các giá trị lịch sử này là giá trị trên K-line BAR trước K-line BAR hiện tại khi kịch bản chạy.[]Các toán tử được sử dụng sau khi gọi biến, biểu thức, hàm.[]Các giá trị trong dấu ngoặc là khoảng cách của dữ liệu lịch sử mà chúng ta muốn trích dẫn với đường K BAR hiện tại. Ví dụ, nếu tôi muốn trích dẫn giá đóng cửa của một đường K BAR trước, chúng tôi viết:close[1]

Chúng ta đã thấy những dòng chữ như thế này trong các bài học trước đây:

high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)

[]Các toán tử chỉ có thể được sử dụng một lần trên cùng một giá trị, vì vậy viết sai như vậy sẽ trả lại lỗi:

a = close[1][2]   // 错误

Bạn có thể thấy ở đây, và một số bạn sẽ nói rằng,[]Một trong những điều quan trọng nhất của chúng tôi là chúng ta có thể sử dụng các cấu trúc chuỗi, và chúng trông giống như một chuỗi và một mảng. Dưới đây là một ví dụ cho thấy sự khác biệt giữa chuỗi và mảng trong ngôn ngữ 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")

Mặc dùa = close[1][2]Có thể viết sai, nhưng:

b = close[1]
c = b[1]

Trong khi đó, nếu chúng ta sử dụng một số thuật toán khác nhau, thì chúng ta sẽ không có lỗi nếu chúng được hiểu theo các toán học thông thường.b = close[1]Sau khi gán, b nên là một giá trị, tuy nhiênc = b[1], b vẫn có thể được sử dụng để tham khảo giá trị lịch sử một lần nữa bằng cách sử dụng các toán tử lịch sử. Dường như khái niệm series trong ngôn ngữ Pine không đơn giản như các số. Có thể hiểu là giá trị lịch sử trên Bar gần trước đó được gán cho b, b cũng là một cấu trúc chuỗi thời gian và có thể tiếp tục tham khảo giá trị lịch sử của nó. Vì vậy, chúng ta thấy trong ba đường a, b và c được vẽ, đường b chậm hơn đường a một BAR, đường c chậm hơn đường b một BAR. C chậm hơn đường a hai BAR.

Chúng ta có thể kéo biểu đồ về phía bên trái nhất và thấy rằng trên đường K đầu tiên, giá trị của b và c đều là giá trị trống ((na)). Đó là bởi vì khi kịch bản được thực hiện trên đường K đầu tiên BAR, một, hai chu kỳ giá trị lịch sử không có, nó không tồn tại. Vì vậy, khi viết chính sách, chúng ta cần phải thường xuyên xem xét liệu chúng ta có tham chiếu đến giá trị trống khi tham khảo dữ liệu lịch sử hay không, nếu không cẩn thận, việc sử dụng giá trị trống sẽ gây ra một loạt các tính toán khác biệt, thậm chí có thể ảnh hưởng đến thời gian thực BAR. Chúng ta thường sử dụng trong mã.nanzChúng ta đã từng học về cách phân tích các hàm tích hợp (trên thực tế, chúng ta đã học về các hàm tích hợp trước đây).nznaCác hàm, bạn có nhớ chương nào không?) đặc biệt xử lý các trường hợp không có giá trị, ví dụ:

close > nz(close[1], open)    // 当引用close内置变量前一个BAR的历史值时,如果不存在,则使用open内置变量

Đây là một cách xử lý những gì có thể tham chiếu đến giá trị không ((na)).


Ưu tiên toán tử

Chúng ta đã học được rất nhiều toán tử của ngôn ngữ Pine, chúng tạo thành các biểu thức bằng cách kết hợp với các số toán tử khác nhau. Vậy ưu tiên của các toán tử này là gì khi tính trong biểu thức?

Ưu tiên Các toán tử
9 []
8 Một số toán tử trong thời gian+-not
7 */%
6 Các toán tử nhị phân+-
5 ><>=<=
4 ==!=
3 and
2 or
1 ?:

Phần biểu thức có ưu tiên cao được thực hiện trước, nếu ưu tiên giống nhau thì được thực hiện từ trái sang phải.()Các biểu thức này có thể được sử dụng cho các biểu thức khác nhau.

Các biến

Tuyên bố biến

Chúng ta đã học được khái niệm về dấu hiệu ký hiệu ký hiệu, và dấu hiệu ký hiệu ký hiệu ký hiệu là tên của một biến. Vì vậy, chúng ta cũng có thể nói: biến là ký hiệu lưu trữ giá trị. Vậy làm thế nào để tuyên bố một biến?

  • Mô hình tuyên bố: Khi tuyên bố một biến, thứ đầu tiên bạn viết là "hình thức tuyên bố", và có ba kiểu tuyên bố của biến: 1, sử dụng từ khóavar❖ 2. Sử dụng từ khóavarip❖ 3, không viết gì cả.

    varvaripCác từ khóa mà chúng ta đã học được trong phần "Động tác viên gán" trước đây sẽ không được mô tả ở đây. Nếu mô hình tuyên bố của biến không viết gì, ví dụ như câu:i = 1Trong thực tế, chúng ta đã nói trước đây rằng các biến được tuyên bố như vậy và gán giá trị, được thực hiện trên mỗi dòng KBAR.

  • Loại Ngôn ngữ Pine trên FMZ không nghiêm ngặt về yêu cầu kiểu và thường có thể bỏ qua. Tuy nhiên, để tương thích với chính sách kịch bản trên Trading View, các biến có thể được tuyên bố với kiểu. Ví dụ:

    int i = 0 
    float f = 1.1
    

    Các loại trên Trading View là yêu cầu nghiêm ngặt hơn, và sẽ trả lại lỗi nếu sử dụng các mã sau đây trên Trading View:

    baseLine0 = na          // compile time error!
    
  • Nhãn hiệu Nhãn hiệu là tên của biến, tên của mã đã được đề cập trong chương trước, bạn có thể xem lại:https://www.fmz.com/bbs-topic/9390#标识符

Tóm lại, tuyên bố một biến có thể được viết như sau:

// [<declaration_mode>] [<type>] <identifier> = value 
   声明模式             类型     标识符       = 值

Đây là một số hoạt động được sử dụng trong việc tạo ra các phép tính:=Đặt giá trị cho một biến trong khi tuyên bố một biến. Khi gán, giá trị có thể là một chuỗi, một số, một biểu thức, một cuộc gọi chức năng, hoặc một số khác.ifforwhileHoặcswitchCác cấu trúc khác nhau (các cấu trúc từ khóa và cách sử dụng câu sẽ được giải thích chi tiết trong bài học tiếp theo của chúng tôi, trong thực tế chúng tôi đã học được một bài học trước đây về việc gán các câu if đơn giản, chúng ta có thể xem lại).

Ở đây, chúng ta tập trung vào các hàm input, một hàm mà chúng ta thường sử dụng trong việc thiết kế các chính sách.

Chức năng input:

input函数,参数defval、title、tooltip、inline、group

Các hàm đầu vào trên FMZ có một chút khác biệt so với trong Trading View, mặc dù các hàm này được sử dụng như là đầu vào gán giá trị cho các tham số chiến lược. Dưới đây chúng ta sẽ mô tả chi tiết về việc sử dụng các hàm đầu vào trên FMZ bằng một ví dụ:

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)

Trong FMZ, hàm input sẽ tự động vẽ ra các điều khiển để đặt các tham số chính sách trên giao diện chính sách FMZ. Các điều khiển được hỗ trợ trên FMZ hiện có các hộp nhập số, hộp nhập văn bản, hộp kéo xuống, chọn giá trị và các chức năng khác.

img

Chúng ta đã giới thiệu một vài tham số chính của hàm input:

  • defval: giá trị mặc định của các tùy chọn tham số chính sách được đặt trong hàm đầu vào, hỗ trợ các biến, số, chuỗi được xây dựng trong ngôn ngữ Pine
  • title: tên của một tham số được hiển thị trên giao diện chính sách trên đĩa thực / kiểm tra lại.
  • tooltip: lời khuyên về các tham số chính sách, khi chuột dừng trên các tham số chính sách sẽ hiển thị thông tin văn bản về cài đặt tham số này.
  • group: tên nhóm cho các tham số chính sách, có thể cho các tham số nhóm.

Ngoài việc tuyên bố và gán các biến riêng biệt, ngôn ngữ Pine còn tuyên bố một tập các biến và gán một cách viết:

[变量A,变量B,变量C] = 函数 或者 ```if```、 ```for```、```while```或```switch```等结构

Chúng ta thường sử dụngta.macdKhi tính toán chỉ số MACD, các hàm tính toán ba tập dữ liệu; vì chỉ số MACD là một chỉ số đa tuyến, chúng ta có thể viết:

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

Chúng ta có thể dễ dàng vẽ biểu đồ MACD bằng cách sử dụng mã trên, không chỉ các hàm tích hợp có thể trả về nhiều biến mà các hàm tùy chỉnh được viết cũng có thể trả về nhiều dữ liệu.

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)

Sử dụng các cấu trúc như if để gán nhiều biến tương tự như cách viết các hàm tùy chỉnh ở trên, bạn cũng có thể thử.

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

Cấu trúc điều kiện

Một số hàm không thể được viết trong các khối mã bản địa mà không có chi nhánh điều kiện, chủ yếu là các hàm sau:

barcolor ((), fill ((), hline ((), indicator ((), plot ((), plotcandle ((), plotchar ((), plotshape (())

Trading View sẽ biên soạn báo cáo lỗi; FMZ không bị hạn chế nghiêm ngặt, nhưng cũng nên làm theo các quy định viết trên Trading View. Ví dụ như điều này không được đề nghị trong FMZ, nhưng không nên viết như vậy.

strategy("test", overlay=true)
if close > open 
    plot(close, title="close")
else 
    plot(open, title="open")

If


Thêm nữa