4
tập trung vào
1076
Người theo dõi

FMZ PINE Script tài liệu

Được tạo ra trong: 2022-05-06 14:27:06, cập nhật trên: 2025-01-23 10:19:06
comments   18
hits   13761

[TOC]

Từ khóa, ngữ pháp, cấu hình

Cấu trúc mã

Cấu trúc chung của mã trong Pine:

<version>
<declaration_statement>
<code>

Ghi chú

Ghi chú được hỗ trợ bởi ngôn ngữ Pine của FMZ: Ghi chú một dòng//Các dòng chú thích/* */Ví dụ, cách viết chú thích trong ví dụ sau:

[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)  // 计算MACD指标

/*
plot函数在图表上画出指标线
*/
plot(macdLine, color = color.blue, title='macdLine')
plot(signalLine, color = color.orange, title='signalLine')
plot(histLine, color = color.red, title='histLine')

Phiên bản

Hướng dẫn trình biên dịch dưới dạng sau cho trình biên dịch biết kịch bản này được viết bằng phiên bản Pine:

//@version=5

Bản v5 mặc định, có thể bỏ qua trong mã//@version=5

Tuyên bố

  • indicator()
  • strategy()

Các câu tuyên bố xác định loại kịch bản, và điều này quyết định những gì trong đó được phép, và cách sử dụng và thực hiện. Thiết lập các thuộc tính quan trọng của kịch bản, chẳng hạn như tên của nó, nơi nó sẽ xuất hiện khi nó được thêm vào biểu đồ, độ chính xác và định dạng của các giá trị mà nó hiển thị, và các giá trị số để quản lý một số hành vi khi nó chạy, chẳng hạn như số lượng đối tượng vẽ tối đa mà nó sẽ hiển thị trong biểu đồ. Đối với chiến lược, thuộc tính bao gồm các tham số được kiểm soát ngược, chẳng hạn như vốn đầu tiên, hoa hồng, điểm trượt, v.v.indicator()hoặcstrategy()Lời tuyên bố:

Một câu lệnh có thể là một trong những nội dung này.

  • Tuyên bố biến
  • Đặt lại giá trị của biến
  • Tuyên bố hàm
  • Gọi hàm được xây dựng, gọi hàm được định nghĩa bởi người dùng
  • ifforwhilehoặcswitchCấu trúc

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

  • Một số câu lệnh 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 tuyên bố hàm một dòng. Những người 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 trong phạm vi toàn cầu của kịch bản (tức là những phần không thuộc khối địa phương) không thể được coi là空格hoặc制表符(Tab) bắt đầu. Các 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 trở thành 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 hay một hàm đa dòng luôn cần mộtlocal blockMột khối địa phương phải được thu nhỏ thành một dấu biểu thức hoặc bốn khoảng trống (trừ khi nó được phân tích thành chuỗi liên kết của dòng trước, tức là được coi là nội dung liên tục của dòng trước), mỗi khối địa phương xác định một phạm vi địa phương khác nhau.
  • Nhiều câu đơn hàng có thể được nối tiếp trong một dòng bằng cách sử dụng dấu chấm ký ức ((,) làm dấu phân cách.
  • Một dòng có thể chứa các chú thích, hoặc chỉ là chú thích.
  • Các dòng cũng có thể được gói lại (như tiếp tục trên nhiều dòng).

Ví dụ, bao gồm ba khối địa phương, một trong các tuyên bố hàm tùy chỉnh và hai trong các tuyên bố biến sử dụng cấu trúc if, như sau:

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

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

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

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

Thay đổi mã

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

a = open + high + low + close

Có thể được đóng gói thành (lưu ý rằng số khoảng trống mỗi dòng không phải là nhân của 4):

a = open +
      high +
          low +
             close

Một cuộc gọi plot (()) dài có thể được đóng gói thành ▽.

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)

Các câu trong tuyên bố hàm được định nghĩa bởi người dùng cũng có thể được đóng gói. Tuy nhiên, vì khối địa phương phải bắt đầu bằng dấu rút gọn theo ngữ pháp ((4 khoảng trống hoặc 1 biểu tượng), khi chia nó thành hàng tiếp theo, phần tiếp tục của câu phải bắt đầu bằng một hoặc nhiều dấu rút gọn ((không bằng số nhân của 4 khoảng trống). 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")

Dòng thời gian

Dòng thời gian không phải là một loại dữ liệu hoặc định dạng, dãy thời gian là một khái niệm về cấu trúc cơ bản trong ngôn ngữ PINE. Nó được sử dụng để lưu trữ các giá trị thay đổi liên tục theo thời gian, mỗi giá trị tương ứng với một thời điểm. Các biến tích hợpopenVí dụ:openCác biến tích hợp ghi lại giá mở của mỗi dòng K BAR, nếuopenlà 5 phút của K.openCác biến được ghi lại là giá mở mỗi 5 phút K dòng BAR ((cột)). Khi chương trình chiến lược của bạn được thực hiện, các tham chiếu trong mãopenVí dụ, giá mở cửa của dòng K BAR hiện tại được trích dẫn. Để trích dẫn các giá trị trước trong chuỗi thời gian, chúng tôi sử dụng[]Hình thức này được sử dụng khi thực hiện chiến lược trên một dòng KBAR.open[1]Nghĩa là giá mở đầu của Kbar trước Kbar hiện tại.

Mặc dùDòng thời gianNó dễ dàng gợi nhớ đến cấu trúc dữ liệu “mảng”, mặc dù ngôn ngữ PINE cũng có các loại mảng. Tuy nhiên, chúng là những khái niệm hoàn toàn khác với chuỗi thời gian.

Ngôn ngữ PINE được thiết kế theo trình tự thời gian, có thể dễ dàng tính toán giá trị tích lũy của giá đóng cửa trong mã chiến lược, và không cần sử dụng cấu trúc vòng lặp như for, chỉ sử dụng hàm tích hợp trong ngôn ngữ PINEta.cum(close)Để lấy một ví dụ khác, chúng ta cần tính trung bình giá trị chênh lệch giữa giá trị cao nhất và giá trị thấp nhất của 14 dòng K BAR cuối cùng (tức là 14 dòng K BAR gần nhất từ thời điểm hiện tại khi code được thực hiện) có thể được viết là:ta.sma(high - low, 14)

Kết quả của việc gọi hàm trên chuỗi thời gian cũng sẽ để lại dấu vết trên chuỗi thời gian, cũng có thể sử dụng[]Ví dụ, khi kiểm tra xem giá trị đóng cửa của dòng K BAR hiện tại có vượt quá giá trị tối đa của giá trị cao nhất trong 10 dòng K BAR cuối cùng (không bao gồm dòng K BAR hiện tại) không. Chúng ta có thể viết làbreach = close > ta.highest(close, 10)[1]Cũng có thể viết:breach = close > ta.highest(close[1], 10)Vì thế.ta.highest(close, 10)[1]ta.highest(close[1], 10)Đương đương.

Có thể xác nhận bằng mã sau:

strategy("test pine", "test", true) 

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)
plotchar(true, title="b", char=str.tostring(b), location=location.belowbar, color=color.green)

Các mã thử nghiệm trên sẽ đưa ra giá trị của a và b trên mỗi BAR theo trình tự thời gian tương ứng của chúng, và có thể thấy rằng giá trị của a và b luôn luôn bằng nhau, vì vậy hai cách biểu thị này là tương đương.

Đề cập dữ liệu lịch sử

Trading View có giới hạn về số lượng truy cập vào dữ liệu lịch sử (tối đa 5000 truy cập), ví dụ như mã:

//@version=6
indicator("test")

ema = ta.ema(close, 10000)      // 报错:Error on bar 0: The 'ema'->'sum' function references too many historical candles (10000), the limit is 5000.
plot(ema, "ema")

// pre10000 = ema[10000]        // 报错:Invalid number of bars back specified in the history-referencing operator. It accepts a value between 0 and 5000.
// plot(pre10000, "pre10000")

Thiết lập giao dịch trong thư viện giao dịch ngôn ngữ Pine, tham số: “số chu kỳ dài nhất của biến” thiết lập cụ thể số lượng lớn nhất của dữ liệu có thể tham khảo được trên FMZ.

FMZ PINE Script tài liệu

indicator("test")

ema = ta.ema(close, 1000)  // ema = ta.ema(close, 3000) 则报错:Invalid number 3000 of bars back specified in the history-referencing operator. It accepts a value between 0 and 2000.
plot(ema, "ema")

Các tham số “chiều dài nhất của biến” không nên được thiết lập quá lớn, trong phạm vi tham chiếu dữ liệu trong chính sách phù hợp có thể.

Các tham số mô hình của thư viện lớp giao dịch ngôn ngữ Pine

Hướng dẫn cài đặt tham số cho “Pine Language Transaction Class Library”, một mẫu được xây dựng trong chính sách PINE.

FMZ PINE Script tài liệu

Cài đặt giao dịch

  • Thực hiện Mô hình giá đóng cửa: mô hình được thực hiện khi BAR hiện tại kết thúc, giao dịch được thực hiện khi BAR gốc bắt đầu. Mô hình giá thực tế: Mô hình được thực hiện mỗi khi giá thay đổi, có tín hiệu để thực hiện giao dịch ngay lập tức.
  • Lệnh mở vị trí mặc định: Nếu lệnh giao dịch không chỉ định số lượng giao dịch, hãy thực hiện giao dịch theo số lượng được thiết lập.
  • Số đơn đặt hàng tối đa cho mỗi lần giao dịch: dựa trên mức bán thực tế, kết hợp với cài đặt tham số này, xác định số lượng lớn nhất cho mỗi lần đặt hàng, tránh va chạm với mặt phẳng.
  • Điểm giá trượt:定价货币精度Các tham số và tham số này xác định giá trượt tại thời điểm đặt hàng. Ví dụ, nếu định giá tiền tệ được đặt chính xác là 2, tức là chính xác đến số ký tự thứ hai, chính xác đến 0.01. Vậy thì mỗi điểm giá trượt đại diện cho 0.01 đơn vị định giá. Nếu định giá trượt là 5, giá trượt tại thời điểm đặt hàng là 0.05.
  • Số chu kỳ dài nhất của biến: số BAR của dòng K ảnh hưởng đến biểu đồ, vàjavascriptGọi trong chiến lượcSetMaxBarLenChức năng tương tự.

Tùy chọn tương lai

  • Mã giống: mã hợp đồng, chỉ cần thiết lập khi đối tượng giao dịch là đối tượng giao dịch không có mặt hàng.
  • Số lượng hợp đồng tối thiểu: Số lượng giao dịch tối thiểu của hợp đồng khi đặt hàng.

Tùy chọn thực tế

  • Tự động khôi phục tiến độ: tự động khôi phục trạng thái trước khi chiến lược cuối cùng dừng lại.
  • Số lần thử lại đặt hàng: Nếu lệnh không được giao dịch, lệnh sẽ bị hủy và đặt hàng lại để thử giao dịch, tham số này được sử dụng để giới hạn số lần thử lại tối đa.
  • Khoảng cách thăm dò mạng ((millisecond): Chỉ có hiệu lực đối với giao thức REST, kiểm soát khoảng cách yêu cầu mạng, tránh yêu cầu quá thường xuyên, vượt quá giới hạn của sàn giao dịch.
  • Thời gian đồng bộ hóa tài khoản (giây): chu kỳ thời gian đồng bộ hóa dữ liệu tài khoản
  • Thời gian đồng bộ hóa vị trí sau khi mở vị trí ((milliseconds): chỉ đối với một số giao dịch mở vị trí lặp lại do chậm dữ liệu, thiết lập thời gian đồng bộ lớn hơn có thể làm giảm bớt các vấn đề như vậy.
  • Tỷ lệ đòn bẩy: thiết lập tỷ lệ đòn bẩy.

Giao dịch trực tiếp, các thiết lập khác

  • Số lượng giao dịch một tay: Số lượng giao dịch một tay mặc định, chỉ có hiệu lực đối với hàng mặt hàng.
  • Số lượng giao dịch tối thiểu: Số lượng giao dịch tối thiểu.
  • Độ chính xác định giá tiền tệ: Độ chính xác giá, tức là số chữ số nhỏ của giá.
  • Tính chính xác của hàng hóa: Tính chính xác của đơn hàng tiếp theo, tức là số nhỏ của đơn hàng tiếp theo.
  • Phí xử lý: Tính toán một số dữ liệu dựa trên thiết lập này, 0.002 là 2 phần nghìn.
  • Thống kê lỗ hổng: Chỉ sử dụng thống kê lỗ hổng hiển thị trên ổ đĩa thực.
  • Thử lại thất bại ((ms): Khoảng thời gian thử lại khi yêu cầu mạng thất bại.
  • Sử dụng proxy: Chỉ có hiệu lực với giao thức REST.
  • Hide common network errors: Hide common error logs in the log area. Hide common error logs in the log area.
  • Địa chỉ chuyển đổi: chỉ có hiệu lực với giao thức REST.
  • Thông báo đẩy: Gửi tin nhắn đến hộp thư, v.v.

Đặt hàng

Khởi đầu

strategy(title = "open long example", pyramiding = 3)                                // pyramiding 允许的同方向下单的次数
strategy.entry("long1", strategy.long, 0.01)                                         // 市价开多仓,指定分组标签为long1
strategy.entry("long2", strategy.long, 0.02, when = close > ta.ema(close, 10))       // 条件触发,执行下单,市价开多仓
strategy.entry("long3", strategy.long, 0.03, limit = 30000)                          // 指定(较低的)价格,计划下买单订单,等待成交开仓,限价开仓

Cổ phiếu bằng phẳng

strategy(title = "close long example", pyramiding = 2)                              // pyramiding 允许的同方向下单的次数
strategy.entry("long1", strategy.long, 0.1)                                         // 市价开多仓,指定分组标签为long1
strategy.entry("long2", strategy.long, 0.1)                                         // 市价开多仓,指定分组标签为long2
strategy.close("long1", when = strategy.position_size > 0.1, qty_percent = 50, comment = "close buy entry for 50%")   // 平仓,指定平掉分组标签为long1的仓位的50%持仓
strategy.close("long2", when = strategy.position_size > 0.1, qty_percent = 80, comment = "close buy entry for 80%")   // 平仓,指定平掉分组标签为long2的仓位的80%持仓

Cơ chế giao dịch

Cơ chế giữ vị trí của ngôn ngữ PINE tương tự như giữ vị trí một chiều. Ví dụ: khi giữ vị trí theo nhiều hướng (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((

Kế hoạch

Sử dụng lệnh đặt hàng để đặt hàng, nếu không chỉ định bất kỳ giá nào, thì giá thị trường được mặc định. Ngoài giá thị trường, bạn có thể đặt hàng thông qua bảng kế hoạch, và bảng kế hoạch sẽ không hoạt động ngay lập tức.Đĩa thật / Đánh giá lạiThông tin trạng thái thời gian (tức là trạng thái của chiến lược khi chạy) được nhìn thấy trong bảng xếp hạng “Lệnh kế hoạch”. Hệ thống sẽ thực sự đặt hàng chỉ khi các đơn kế hoạch này được kích hoạt khi thị trường đáp ứng các điều kiện giá theo thời gian thực. Vì vậy, các đơn đặt hàng này có một chút sai lệch về giá giao dịch là điều bình thường.strategy.entryChúng ta có thể chỉ địnhlimitstopCác tham số.

var isTrade = false 
if not barstate.ishistory and not isTrade
    isTrade := true 
    strategy.entry("test 1", strategy.long, 0.1, stop=close*1.3, comment="test 1 order")                     // stop
    strategy.entry("test 2", strategy.long, 0.2, limit=close*0.7, comment="test 2 order")                    // limit
    strategy.entry("test 3", strategy.short, 0.3, stop=close*0.6, limit=close*1.4, comment="test 3 order")   // stop-limit    
  • Lệnh giới hạn

Thiết lập giá giới hạn của đơn đặt hàng, khi đơn đặt hàng là mua (tức làdirectionCác thông số làstrategy.long), chỉ khi giá hiện tại của thị trường thấp hơn giá đó thì lệnh sẽ được kích hoạt. Khi đơn đặt hàng là bán hàng đơn (tức làdirectionCác thông số làstrategy.short), chỉ khi giá hiện tại trên thị trường cao hơn giá đó thì lệnh sẽ được kích hoạt.

  • Lệnh dừng

Đặt giá dừng của lệnh, khi lệnh là mua, chỉ khi giá thị trường hiện tại cao hơn giá đó, lệnh sẽ được kích hoạt. Khi đặt hàng là bán hàng, chỉ khi giá hiện tại của thị trường thấp hơn giá đó, lệnh sẽ được kích hoạt.

  • Lệnh stop-limit

Có thể thiết lập cùng một lúclimitstopCác tham số, đặt hàng được kích hoạt với giá đầu tiên phù hợp.

Tỷ lệ phần trăm quyền lợi

//@version=5
strategy("Percent of Equity Order", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)  

// 简单的均线交叉策略
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))  

// 如果均线交叉条件满足,则买入或卖出
if (longCondition)
    strategy.entry("Long", strategy.long)  

if (shortCondition)
    strategy.entry("Short", strategy.short)
  

Chỉ địnhdefault_qty_type=strategy.percent_of_equitySau đó, thiết lậpdefault_qty_valueNhư một số phần trăm ((0 ~ 100), 1 là 1%. Theo số lượng đồng tiền định giá trong tài khoản, đặt hàng được tính. Ví dụ: Tài khoản hiện tại có 10000 USDT, đặt hàng 1%, nghĩa là đặt hàng theo quy mô 100 USDT ((theo giá hiện tại khi bán).

Tuyên bố, cấu trúc logic từ khóa

var

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

var variable_name = expression

Giải thích:

  • variable_name- Bất kỳ tên biến người dùng nào được phép trong Pine Script có thể bao gồm các ký tự Latinh lớn và nhỏ, số và dấu gạch dưới_), nhưng không được bắt đầu bằng số) 。
  • expression- Bất kỳ biểu thức toán học nào cũng giống như định nghĩa biến thường.

Ví dụ

// Var keyword example
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")

Biến số ‘a’ duy trì giá đóng cửa của mỗi cột đầu tiên trong chuỗi. Biến số ‘b’ giữ giá đóng cửa của thanh giá thạch anh xanh đầu tiên trong chuỗi. Biến số ‘c’ giữ giá đóng cửa của 10 quả khoai tây xanh trong chuỗi.

Trong FMZ, có mô hình giá thời gian thực, mô hình giá đóng cửa, mô hình giá đóng cửa, mô hình giá đóng cửa, mô hình giá đóng cửa.varvaripCác biến trong tuyên bố được kiểm tra bằng cách sử dụng mã:

strategy("test pine", "test 1", 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
if true
    i := i + 1
    ii := ii + 1
  • Mô hình giá thời gian thực Các mã thử nghiệm trên được thực hiện trong hai giai đoạn: giai đoạn K-line lịch sử, giai đoạn K-line thực tế, và giai đoạn K-line lịch sử.varvaripCác biến i, ii của tuyên bố sẽ thực hiện các hoạt động gia tăng mỗi lần thực thi mã chính sách (bởi vìif trueVì vậy, chắc chắn sẽ thực hiện các khối mã điều kiện tương ứng) ❚ Vì vậy, bạn có thể thấy rằng các con số được hiển thị trên kết quả kiểm tra lại K-line BAR được tăng dần 1 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. ❚varvaripCác biến trong tuyên bố bắt đầu thay đổi. Vì đây là mô hình giá thời gian thực, mỗi lần thay đổi giá trong một K-line BAR sẽ thực hiện một lần mã chiến lược, và các biến trong tuyên bố sẽ thay đổi theo thời gian.i := i + 1ii := ii + 1Tất cả đều được thực hiện một lần. Sự khác biệt là ii được sửa đổi mỗi lần. Mặc dù i cũng được sửa đổi mỗi lần, nhưng giá trị trước đó sẽ được khôi phục khi thực hiện chiến lược logic vòng tiếp theo, và giá trị của i sẽ được xác định lại cho đến khi dòng K hiện tại BAR đã hết ((tức là giá trị trước đó không được khôi phục khi thực hiện chiến lược logic vòng tiếp theo). Vì vậy, có thể thấy biến i vẫn là mỗi BAR tăng 1. Tuy nhiên, biến ii tích lũy mỗi BAR nhiều lần.

  • Mô hình giá đóng cửa Vì mô hình giá đóng cửa chỉ thực hiện một logic chiến lược khi mỗi K-line BAR đi qua. Vì vậy, trong mô hình giá đóng cửa, giai đoạn K-line lịch sử và giai đoạn K-line thực tế,varvaripCác biến được tuyên bố tăng lên trong các ví dụ trên là hoàn toàn phù hợp, mỗi dòng K tăng 1 BAR.

varip

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

varip variable_name = expression

Giải thích:

  • variable_name- Bất kỳ tên biến người dùng nào được cho phép trong kịch bản Pine ((có thể bao gồm các ký tự Latin lớn và nhỏ, số và dấu gạch dưới))_), nhưng không được bắt đầu bằng số) 。
  • expression- Bất kỳ biểu thức toán học nào, giống như khi định nghĩa biến thường. Trên dòng K đầu tiên, biểu thức chỉ được tính một lần và được phân bổ cho biến một lần.

Ví dụ

// varip
varip int v = -1
v := v + 1
plot(v)

Khi sử dụng var, bản đồ sẽ trả về giá trị của bar_index. Sử dụng varip, hành vi tương tự xảy ra trên đường K lịch sử, nhưng trên đường K thời gian thực, bản đồ sẽ trả về một giá trị tăng lên một cho mỗi tick.

Ghi chú Chỉ sử dụng với các kiểu đơn giản như float, int, bool, string, và các kiểu của các loại này.

true

thể hiện giá trị của một biến kiểu Boolean, hoặc khi biểu thức được sử dụngSo sánhhoặcLogicCác giá trị có thể tính toán khi toán tử ≠

Ghi chú Xem thêmSo sánhCác toán tử vàLogicMô tả của toán tử.

Xem thêm bool

false

Hiển thị giá trị của một biến kiểu Boolean, và kết quả của các thao tác so sánh, logic.

Ghi chú Xem thêmSo sánhCác toán tử vàLogicMô tả của toán tử.

Xem thêm bool

if

Các câu lệnh if xác định các khối câu lệnh phải được thực hiện khi đáp ứng các điều kiện biểu thức. Ngôn ngữ kịch bản Pine phiên bản 4 cho phép bạn sử dụng ngữ pháp else if.

Mã chung được lấy từ:

var_declarationX = if condition
    var_decl_then0
    var_decl_then1
    ...
    var_decl_thenN
    return_expression_then
else if [optional block]
    var_decl_else0
    var_decl_else1
    ...
    var_decl_elseN
    return_expression_else
else
    var_decl_else0
    var_decl_else1
    ...
    var_decl_elseN
    return_expression_else

Ghi chú var_declarationX- biến này lấy giá trị của câu if condition- Nếu điều kiện là true, sử dụng khối câu lệnhthenLogic trongvar_decl_then0var_decl_then1Nếu điều kiện là false, sử dụng khối câuelse ifhoặcelseLogic trongvar_decl_else0var_decl_else1(Cười) return_expression_then , return_expression_else- biểu thức cuối cùng trong mô-đun hoặc biểu thức từ khốielse sẽ trả về giá trị cuối cùng của câu nói. Nếu biến được tuyên bố ở cuối, giá trị của nó sẽ là giá trị kết quả.

Loại giá trị trả về của câu if phụ thuộc vàoreturn_expression_thenreturn_expression_elseLoại 。 Khi chạy trên TradingView, các loại của chúng phải phù hợp: Khi bạn có một giá trị chuỗi trong khối else, không thể trả về một giá trị số nguyên từ khối câu then。 Khi chạy trên FMZ, ví dụ sau sẽ không bị lỗi, khi giá trị y được lấy giá trị “open”, giá trị khi vẽ plot là n/a。

Ví dụ

// This code compiles
x = if close > open
    close
else
    open  

// This code doesn’t compile by trading view
// y = if close > open
//     close
// else
//     "open"
plot(x)

Có thể bỏ quaelseBảng . Trong trường hợp này, nếu điều kiện là false, biến var_declarationX sẽ được gán một giá trị empty (na, false hoặc ):

Ví dụ

// if
x = if close > open
    close
// If current close > current open, then x = close.
// Otherwise the x = na.
plot(x)

Có thể sử dụng nhiều khối else if hoặc không sử dụng then, else if, else được di chuyển bốn khoảng trống:

Ví dụ

// if
x = if open > close
    5
else if high > low
    close
else
    open
plot(x)

Có thể bỏ quaifGiá trị kết quả của câu lệnh ((var_declarationX= có thể bỏ qua) . Nó có thể hữu ích nếu bạn cần các tác dụng phụ của biểu thức, chẳng hạn như trong giao dịch chiến lược:

Ví dụ

if (ta.crossover(high, low))
    strategy.entry("BBandLE", strategy.long, stop=low)
else
    strategy.cancel(id="BBandLE")

Các câu lệnh If có thể chứa các câu lệnh:

Ví dụ

// if
float x = na
if close > open
    if close > close[1]
        x := close
    else
        x := close[1]
else
    x := open
plot(x)

for

Cấu trúc ‘for’ cho phép thực hiện nhiều câu lặp lại:

[var_declaration =] for counter = from_num to to_num [by step_num]
    statements | continue | break
    return_expression

var_declaration- Một tuyên bố biến tùy chọn, nó sẽ được gán cho giá trị return_expression của vòng quay. counter- Các biến của giá trị bộ đếm vòng quay được lưu, tăng/giảm 1 hoặc giá trị step_num trong mỗi lần lặp vòng quay. from_num- Giá trị bắt đầu của bộ đếm. Cho phép sử dụng giá trị giảm giá / biểu thức int / float. to_num- Giá trị cuối cùng của bộ đếm. Loop bị ngắt khi bộ đếm lớn hơn to_num (hoặc nhỏ hơn to_num trong trường hợp from_num > to_num). step_num- Giá trị tăng/giảm của bộ đếm. Nó là tùy chọn. Giá trị mặc định là +1 hoặc -1, tùy thuộc vào số lớn nhất trong from_num hoặc to_num. statements | continue | break- Bất kỳ số lượng câu nói, hoặc ‘continue’ hoặc ‘break’ từ khóa, thu nhỏ vào 4 khoảng trống hoặc một tab. return_expression- Giá trị trả về của vòng tròn, nếu có, được phân bổ cho biến trong var_declaration. Nếu vòng tròn thoát ra do từ khóa continue hoặc break, giá trị trả về của vòng tròn là giá trị trả về của biến cuối cùng được phân bổ trước khi vòng tròn thoát ra. continue- Từ khóa chỉ được sử dụng trong vòng lặp. Nó dẫn đến việc lặp lại vòng lặp tiếp theo được thực hiện. break- Từ khóa để thoát khỏi vòng tròn.

Ví dụ

// Here, we count the quantity of bars in a given 'lookback' length which closed above the current bar's close
qtyOfHigherCloses(lookback) =>
    int result = 0
    for i = 1 to lookback
        if close[i] > close
            result += 1
    result
plot(qtyOfHigherCloses(14))

Xem thêm for...in while

for…in

for...inCấu trúc cho phép thực hiện nhiều lệnh lặp lại cho mỗi phần tử trong mảng. Nó có thể được sử dụng với bất kỳ tham số nào:array_element, hoặc sử dụng với hai tham số:[index, array_element]。 Hình thức thứ hai không ảnh hưởng đến chức năng của vòng tròn。 Nó theo dõi chỉ số của sự lặp lại hiện tại trong biến số đầu tiên của mô-tô。

[var_declaration =] for array_element in array_id
    statements | continue | break
    return_expression

[var_declaration =] for [index, array_element] in array_id
    statements | continue | break
    return_expression

var_declaration- Một tuyên bố biến tùy chọn, sẽ được trao cho vòng lặpreturn_expressionGiá trị của index- Các biến tùy chọn theo dõi chỉ số thời gian hiện tại. Chỉ số bắt đầu từ 0. Các biến không thể thay đổi trong vòng lặp.array_elementTrong nhóm array_element- Bao gồm các biến của mỗi thành phần của mảng liên tiếp được xử lý trong vòng lặp. Các biến này là không thay đổi trong vòng lặp. array_id- ID của mảng lặp vòng tròn. statements | continue | break- Bất kỳ số lượng câu nói, hoặc ‘continue’ hoặc ‘break’ từ khóa, thu nhỏ vào 4 khoảng trống hoặc một tab. return_expression- giá trị trả về của vòng lặp được phân bổ chovar_declarationCác biến trong vòng lặp, nếu có. Nếu vòng lặp thoát vì từ khóa ‘continue’ hoặc ‘break’, thì giá trị trả về của vòng lặp là biến được gán cuối cùng trước khi vòng lặp thoát. continue- Từ khóa chỉ được sử dụng trong vòng lặp. Nó dẫn đến việc lặp lại vòng lặp tiếp theo được thực hiện. break- Từ khóa để thoát khỏi vòng tròn.

Cho phép thay đổi các phần tử hoặc kích thước của mảng trong vòng lặp. Ở đây, chúng tôi sử dụngfor...inHình thức đơn tham số để xác định trên mỗi dòng K, có bao nhiêu giá trị OHLC của dòng K lớn hơn giá trị SMA của ‘close’:

Ví dụ

// Here we determine on each bar how many of the bar's OHLC values are greater than the SMA of 'close' values
float[] ohlcValues = array.from(open, high, low, close)
qtyGreaterThan(value, array) =>
    int result = 0
    for currentElement in array
        if currentElement > value
            result += 1
        result
plot(qtyGreaterThan(ta.sma(close, 20), ohlcValues))

Ở đây, chúng ta sử dụng hai dạng tham số của for…in để đưa cho chúng taisPosCác giá trị của mảng được đặt thành trueKhi chúng ở trong tay chúng ta.valuesArrayCác giá trị tương ứng trong mảng là đúng thời gian:

Ví dụ

// for...in
var valuesArray = array.from(4, -8, 11, 78, -16, 34, 7, 99, 0, 55)
var isPos = array.new_bool(10, false)  

for [index, value] in valuesArray
    if value > 0
        array.set(isPos, index, true)  

if barstate.islastconfirmedhistory
    runtime.log(str.tostring(isPos))

Xem thêm for while array.sum array.min array.max

while

whileCụm từ cho phép lặp lại điều kiện của khối mã địa phương.

variable_declaration = while boolean_expression
    ...
    continue
    ...
    break
    ...
    return_expression

Giải thích: variable_declaration- Tuyên bố biến có thể chọn.return expressionBạn có thể cung cấp giá trị khởi tạo cho biến này. boolean_expression- Nếu đúng, thực thiwhileNếu là false, thì trongwhileTiếp tục thực hiện kịch bản sau khi nói. continue - continueTừ khóa dẫn đến vòng lặp phân nhánh đến lần lặp tiếp theo. break - breakTừ khóa dẫn đến kết thúc vòng lặp.whileSau khi nói xong, chúng tôi quay lại. return_expression- Cung cấp.whileCác dòng tùy chọn trả về giá trị của câu lệnh.

Ví dụ

// This is a simple example of calculating a factorial using a while loop.
int i_n = input.int(10, "Factorial Size", minval=0)
int counter   = i_n
int factorial = 1
while counter > 0
    factorial := factorial * counter
    counter   := counter - 1

plot(factorial)

Ghi chú Bắt đầuwhileCác khối mã cục bộ sau hàng phải được thu nhỏ vào bốn khoảng trống hoặc một ký tự đếm.whileVòng luân hồiwhileCác biểu thức Boolean sau đó phải trở thành false, hoặc phải được thực hiện.break

switch

Hoạt động chuyển đổi chuyển quyền kiểm soát sang một trong số các câu lệnh tùy thuộc vào điều kiện và giá trị của biểu thức.

[variable_declaration = ] switch expression
    value1 => local_block
    value2 => local_block
    ...
    => default_local_block

[variable_declaration = ] switch
    boolean_expression1 => local_block
    boolean_expression2 => local_block
    ...
    => default_local_block

Switch có biểu thức:

Ví dụ

// Switch using an expression

string i_maType = input.string("EMA", "MA type", options = ["EMA", "SMA", "RMA", "WMA"])

float ma = switch i_maType
    "EMA" => ta.ema(close, 10)
    "SMA" => ta.sma(close, 10)
    "RMA" => ta.rma(close, 10)
    // Default used when the three first cases do not match.
    => ta.wma(close, 10)

plot(ma)

Switch không có biểu thức:

Ví dụ

strategy("Switch without an expression", overlay = true)

bool longCondition  = ta.crossover( ta.sma(close, 14), ta.sma(close, 28))
bool shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))

switch
    longCondition  => strategy.entry("Long ID", strategy.long)
    shortCondition => strategy.entry("Short ID", strategy.short)

Trả giá trị Giá trị của biểu thức cuối cùng trong khối lệnh địa phương được thực thi.

Ghi chú Chỉ có thể thực hiệnlocal_blockVí dụ hoặcdefault_local_blockMột.default_local_blockChỉ với=>Các ký hiệu được đưa vào cùng với nhau và chỉ được thực hiện khi không có khối trước đó được thực hiện. NếuswitchKết quả của câu lệnh được gán cho một biến và không được chỉ địnhdefault_local_blockNếu không thực hiện,local_block, thì câu trả lời làna- Không.switchKhi kết quả của câu lệnh được phân bổ cho biến, tất cảlocal_blockCác trường hợp phải trả về các giá trị cùng loại.

Xem thêm if ?:

series

series là một từ khóa cho biết kiểu chuỗi dữ liệu.seriesTừ khóa thường không cần thiết.

Máy tính

=

Nó được sử dụng để gán giá trị cho biến, nhưng chỉ khi tuyên bố biến ((được sử dụng lần đầu tiên))

:=

Hoạt động gán giá trị, gán giá trị cho biến bên trái. Được dùng để gán giá trị cho biến đã được khai báo trước đó.

!=

Không tương đương với ≠ ≠ ≠ ≠ ≠

expr1 != expr2

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

%

Số mô-đun ((số nguyên dư)

expr1 % expr2

Trả giá trị Số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị.

Ghi chú Trong kịch bản Pine, khi tính số dư của một số nguyên, doanh nghiệp sẽ bị cắt. Đó là, đưa nó vào vòng tròn đến giá trị tuyệt đối nhỏ nhất. Giá trị thu được sẽ có ký hiệu tương tự như cổ tức.

Ví dụ: -1 % 9 = -1 - 9 * truncate ((-19) = -1 - 9 * truncate ((-0.111) = -1 - 9 * 0 = -1。

%=

Định nghĩa mô-đun áp dụng cho biểu thức số

expr1 %= expr2

Ví dụ

// Equals to expr1 = expr1 % expr2.
a = 3
b = 3
a %= b
// Result: a = 0.
plot(a)

Trả giá trị Số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị.

*

Phương thức nhân áp dụng cho các biểu thức số

expr1 * expr2

Trả giá trị Số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị.

*=

Định nghĩa phép nhân. Sử dụng trong biểu thức số.

expr1 *= expr2

Ví dụ

// Equals to expr1 = expr1 * expr2.
a = 2
b = 3
a *= b
// Result: a = 6.
plot(a)

Trả giá trị Số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị.

+

Thêm hoặc một số dương. áp dụng cho biểu thức số hoặc chuỗi.

expr1 + expr2
+ expr

Trả giá trị Binary String+Trả về sự kết hợp của express1 và express2 Số trả về một số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị: Binary ‘+’ trả về express1 cộng với express2。 Một nhân + một nhân trả về expr ((không thêm bất cứ điều gì vào đối xứng của một nhân))

Ghi chú Bạn có thể sử dụng các toán tử toán học với số và các chuỗi biến. Trong trường hợp sử dụng chuỗi, các toán tử được áp dụng cho các phần tử.

+=

Chức năng bổ sung ≠ áp dụng cho biểu thức số hoặc chuỗi ≠

expr1 += expr2

Ví dụ

// Equals to expr1 = expr1 + expr2.
a = 2
b = 3
a += b
// Result: a = 5.
plot(a)

Trả giá trị Đối với chuỗi, trả về chuỗi expr1 và expr2. Đối với số, trả về số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị.

Ghi chú Bạn có thể sử dụng các toán tử toán học với số và các chuỗi biến. Trong trường hợp sử dụng chuỗi, các toán tử được áp dụng cho các phần tử.

-

Phương pháp trừ hoặc số trừ một. áp dụng cho biểu thức số.

expr1 - expr2
- expr

Trả giá trị Trả về số nguyên hoặc giá trị điểm nổi, hoặc một chuỗi giá trị: Binary ‘+’ trả về express1 trừ express2。 Một đồng.-Trả về từ chối của expres ≠

Ghi chú Bạn có thể sử dụng các toán tử toán học với số và các chuỗi biến. Trong trường hợp sử dụng chuỗi, các toán tử được áp dụng cho các phần tử.

-=

Phương pháp trừ ≠ áp dụng cho biểu thức số ≠

expr1 -= expr2

Ví dụ

// Equals to expr1 = expr1 - expr2.
a = 2
b = 3
a -= b
// Result: a = -1.
plot(a)

Trả giá trị Số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị.

/

Ngoại lệ áp dụng cho biểu thức số

expr1 / expr2

Trả giá trị Số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị.

/=

Việc chỉ định loại trừ. áp dụng cho biểu thức số.

expr1 /= expr2

Ví dụ

// Equals to expr1 = expr1 / expr2.
a = 3
b = 3
a /= b
// Result: a = 1.
plot(a)

Trả giá trị Số nguyên hoặc giá trị điểm nổi, hoặc một loạt các giá trị.

<

Nhỏ hơn ◄ áp dụng cho biểu thức số ◄

expr1 < expr2

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

<=

< hoặc bằng ≠. áp dụng cho biểu thức số ≠.

expr1 <= expr2

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

==

Tương đương với ≠ ≠ ≠ ≠ ≠ ≠ ≠ ≠ ≠ ≠ ≠ ≠ ≠

expr1 == expr2

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

=>

’=>’ được sử dụng để tuyên bố hàm được định nghĩa bởi người dùng vàswitchTrong câu nói.

Định nghĩa của hàm là:

<identifier>([<parameter_name>[=<default_value>]], ...) =>
    <local_block>
    <function_result>

Một.<local_block>Không có câu Pine hoặc nhiều hơn. <function_result>là một biến, một biểu thức hoặc một nhóm.

Ví dụ

// single-line function
f1(x, y) => x + y
// multi-line function
f2(x, y) => 
    sum = x + y
    sumChange = ta.change(sum, 10)
    // Function automatically returns the last expression used in it
plot(f1(30, 8) + f2(1, 3))

Ghi chú Bạn có thể tìm hiểu thêm về các hàm được định nghĩa bởi người dùng trong hướng dẫn sử dụng của bạn trên trang hàm tuyên bố và thư viện kịch bản.

>

Lớn hơn ◄ áp dụng cho biểu thức số ◄

expr1 > expr2

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

>=

Lớn hơn hoặc bằng áp dụng cho biểu thức số

expr1 >= expr2

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

?:

Hoạt động điều kiện ba phương.

expr1 ? expr2 : expr3

Ví dụ

// Draw circles at the bars where open crosses close
s2 = ta.cross(open, close) ? math.avg(open,close) : na
plot(s2, style=plot.style_circles, linewidth=2, color=color.red)  

// Combination of ?: operators for 'switch'-like logic
c = timeframe.isintraday ? color.red : timeframe.isdaily ? color.green : timeframe.isweekly ? color.blue : color.gray
plot(hl2, color=c)

Trả giá trị Nếu expr1 được đánh giá là true, thì expr2 và nếu không thì expr3. Các giá trị 0 ((0 và NaN +, Infinity, -Infinity) được coi là false, các giá trị khác là true.

Ghi chú Nếu bạn không cần, hãy sử dụng na như là một nhánh của xelse. Bạn có thể kết hợp sử dụng hai hoặc nhiều điều khiển: để thực hiện các câu tương tự như switch (xem ví dụ trên) . Bạn có thể sử dụng các toán tử toán học với số và các chuỗi biến. Trong trường hợp sử dụng chuỗi, các toán tử được áp dụng cho các phần tử.

Xem thêm na

[]

Series suborder cung cấp quyền truy cập vào các giá trị trước của series expr1 expr2 là số của k dòng trước, phải là giá trị số floating sẽ được xoay xuống

expr1[expr2]

Ví dụ

// [] can be used to "save" variable value between bars
a = 0.0 // declare `a`
a := a[1] // immediately set current value to the same as previous. `na` in the beginning of history
if high == low // if some condition - change `a` value to another
    a := low
plot(a)

Trả giá trị Một chuỗi các giá trị.

Xem thêm math.floor

and

Logic AND ≠ áp dụng cho các biểu thức Boolean ≠

expr1 and expr2

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

or

Logic OR ≠ áp dụng cho các biểu thức Boolean ≠

expr1 or expr2

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

not

Logical inversion ((NOT) áp dụng cho các biểu thức Boolean

not expr1

Trả giá trị Một giá trị, hoặc một chuỗi giá trị.

Từ khóa kiểu dữ liệu

bool

Từ khóa của kiểu bool (bool) để khai báo một biến hoặc tham số rõ ràng. Các giá trị của biến “Bool” có thể là true, false hoặc na.

Ví dụ

// bool
bool b = true    // Same as `b = true`
b := na
plot(b ? open : close)

Ghi chú Việc đề cập rõ ràng đến kiểu trong tuyên bố biến là tùy chọn, trừ khi nó được khởi tạo bằng na. Tìm hiểu thêm về kiểu Pine trên trang hướng dẫn sử dụng của hệ thống kiểu.

Xem thêm var varip int float color string true false

int

Từ khóa của kiểu int ((integer)) dùng để khai báo một biến hoặc tham số một cách rõ ràng.

Ví dụ

// int
int i = 14    // Same as `i = 14`
i := na
plot(i)

Ghi chú Việc đề cập rõ ràng đến kiểu trong tuyên bố biến là tùy chọn, trừ khi nó được khởi tạo bằng na. Tìm hiểu thêm về kiểu Pine trên trang hướng dẫn sử dụng của hệ thống kiểu.

Xem thêm var varip float bool color string

float

Từ khóa của kiểu float () của biến hoặc tham số tuyên bố rõ ràng.

Ví dụ

// float
float f = 3.14    // Same as `f = 3.14`
f := na
plot(f)

Ghi chú Việc đề cập rõ ràng đến kiểu trong tuyên bố biến là tùy chọn, trừ khi nó được khởi tạo bằng na.

Xem thêm var varip int bool color string

string

Từ khóa kiểu “string” dùng để khai báo một biến hoặc tham số rõ ràng.

Ví dụ

// string
string s = "Hello World!"    // Same as `s = "Hello world!"`
// string s = na // same as "" 
plot(na, title=s)

Ghi chú Việc đề cập rõ ràng đến kiểu trong tuyên bố biến là tùy chọn, trừ khi nó được khởi tạo bằng na. Tìm hiểu thêm về kiểu Pine trên trang hướng dẫn sử dụng của hệ thống kiểu.

Xem thêm var varip int float bool str.tostring str.format

color

Từ khóa kiểu “color” dùng để khai báo một biến hoặc tham số trong biểu thức.

Ví dụ

// color
color textColor = color.green
if barstate.islastconfirmedhistory
    runtime.log("test", textcolor = textColor)

Ghi chú Chữ màu có định dạng sau: #RRGGBB hoặc #RRGGBBAA. Các cặp chữ cái đại diện cho giá trị mười sáu ký tự từ 00 đến FF ((giá mười ký tự từ 0 đến 255), trong đó RR, GG và BB là giá trị của phân số màu đỏ, xanh lá cây và xanh dương. AA là độ trong suốt của màu sắc (hoặc phân số alpha), trong đó 00 không thể nhìn thấy, FF không minh bạch. Việc đề cập rõ ràng đến kiểu trong tuyên bố biến là tùy chọn, trừ khi nó được khởi tạo bằng na. Tìm hiểu thêm về kiểu Pine trên trang hướng dẫn sử dụng của hệ thống kiểu.

Xem thêm var varip int float string color.rgb color.new

array

Các từ khóa của kiểu phím mảng phím được sử dụng để khai báo một biến hoặc tham số một cách rõ ràng