FMZ PINE Script 文档

Author: 雨幕(youquant), Created: 2022-05-10 10:18:57, Updated: 2024-02-23 15:11:55

[TOC]

img

关键字、语法、设置简介

代码结构

Pine中代码遵循的一般结构:

<version>
<declaration_statement>
<code>

注释

FMZ的Pine语言支持的注释符号:单行注释//、多行注释/* */,例如以下例子中的注释写法:

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

版本

以下形式的编译器指令告诉编译器该脚本是用哪个版本的Pine编写的:

//@version=5

默认为v5版本,代码中可以省略//@version=5

声明语句

  • indicator()
  • strategy()

声明语句确定脚本的类型,这又决定了其中允许哪些内容,以及如何使用和执行。设置脚本的关键属性,比如它的名称,当它被添加到图表中时,它将出现在哪里,它所显示的数值的精度和格式,以及管理其运行时行为的某些数值,比如它将在图表中显示的最大绘图对象数量。对于策略,属性包括控制回测的参数,如初始资本、佣金、滑点等。FMZ的Pine不要求一个策略代码中必须包含indicator()或者strategy()声明语句。

代码

脚本中不是注释或编译器指令的行是语句,它实现了脚本的算法。一个语句可以是这些内容之一。

  • 变量声明
  • 变量的重新赋值
  • 函数声明
  • 内置函数调用,用户定义的函数调用
  • ifforwhileswitch等结构

语句可以以多种方式排列

  • 有些语句可以用一行来表达,比如大多数变量声明、只包含一个函数调用的行或单行函数声明。其他的,像结构,总是需要多行,因为它们需要一个局部的块。
  • 脚本的全局范围内的语句(即不属于局部块的部分)不能以空格制表符(tab键)开始。它们的第一个字符也必须是该行的第一个字符。在行的第一个位置开始的行,根据定义成为脚本的全局范围的一部分。
  • 结构或多行函数声明总是需要一个local block。一个本地块必须缩进一个制表符或四个空格(否则,会被解析为上一行的串联代码,即被判定为上一行代码的连续内容),每个局部块定义了一个不同的局部范围。
  • 多个单行语句可以通过使用逗号(,)作为分隔符在一行中串联起来。
  • 一行中可以包含注释,也可以只是注释。
  • 行也可以被包起来(在多行上继续)。

例如,包括三个局部块,一个在自定义函数声明中,两个在变量声明中使用if结构,如下代码:

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

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

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

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

换行代码

长行可以被分割在多行上,或被 "包裹 "起来。被包裹的行必须缩进任何数量的空格,只要它不是4的倍数(这些边界用于缩进局部块)。

a = open + high + low + close

可以被包装成(注意每行缩进的空格数量都不是4的倍数):

a = open +
      high +
          low +
             close

一个长的plot()调用可以被包装成。

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)

用户定义的函数声明中的语句也可以被包装。但是,由于局部块在语法上必须以缩进开始(4个空格或1个制表符),当把它分割到下一行时,语句的延续部分必须以一个以上的缩进开始(不等于4个空格的倍数)。比如说:

test(c, o) =>
    ret = c > o ?
       (c > o+5000 ? 
          1 :
              0):
       (c < o-5000 ? 
          -1 : 
              0)

a = test(close, open)
plot(a, title="a")

时间序列

时间序列并不是一种数据类型或者格式,时间序列是PINE语言中一种基本结构的概念。用来储存时间上连续变动的值,每个值都对应一个时间点。时间序列这种概念的结构很适合应用于处理、记录随时间变化的一系列数据。 以内置变量open为例,open内置变量记录了每一根K线BAR的开盘价,如果这个open是5分钟K线周期的数据。那么这个open变量中记录的就是每个5分钟K线BAR(柱)的开盘价。当你的策略程序在执行时,代码中引用open即引用了当前所在K线BAR的开盘价。为了引用时间序列中之前的值(过去的值),我们使用[]历史操作符,当策略在某个K线BAR上执行时,open[1]的意思就是引用当前K线BAR的前一根K线BAR的开盘价。

虽然时间序列很容易让人想起「数组」这种数据结构,虽然PINE语言也有数组类型。但是它们和时间序列是完全不同的概念。

PINE语言这样设计时间序列,可以在策略代码中很轻松地计算收盘价的累计值,而且不需要使用for之类的循环结构,只用使用PINE语言的内置函数ta.cum(close)。再举个例子,我们需要计算最后14个K线BAR(即距离代码执行时的当前时刻最近的14根K线BAR)的最高价与最低价差值的平均值可以写为:ta.sma(high - low, 14)

在时间序列上调用函数的结果也会在时间序列上留下痕迹,同样可以使用[]历史操作符引用之前的值。例如,测试当前的K线BAR的收盘价是否超过最后10根K线BAR中的最高价的最大值时(不包括当前的K线BAR)。我们可以写为breach = close > ta.highest(close, 10)[1],同样也可以写成breach = close > ta.highest(close[1], 10)。所以ta.highest(close, 10)[1]ta.highest(close[1], 10)是等价的。

可以用以下代码验证:

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)

以上测试代码会将a和b在每个BAR上输出其对应的时间序列上的值,可以看到a和b值一直都是相等的,所以这两种表示方法等价。

Pine语言交易类库模版参数

PINE策略的内置模板「Pine语言交易类库」的参数设置说明。

交易设置

  • 执行方式 收盘价模型:当前BAR走完才执行模型,在下根BAR开始的时候执行交易。 实时价模型:每次价格变动都执行模型,有信号立即执行交易。
  • 默认开仓手数:如果交易指令不指定交易数量时,按照该设置的数量执行交易。
  • 最大单次交易下单量:根据实际盘口,结合该参数设置,确定每次下单最大的数量,避免冲击盘面。
  • 滑价点数:根据定价货币精度参数和该参数确定下单时的滑价。例如,定价货币精度设置2,即精确到小数点第二位,精确到0.01。那么滑价点数每一点代表0.01个定价单位。此时滑价点数设置5,下单时的滑价就是0.05(滑价指下单时为了更好和盘口订单成交溢出的价格部分)。
  • 变量最长周期数:影响图表K线BAR数量,与javascript策略中调用SetMaxBarLen函数作用相同。

期货选项

  • 品种代码:合约代码,交易所对象为非现货交易所对象时才需要设置。
  • 最小合约张数:下单时,合约的最小交易量。

实盘选项

  • 自动恢复进度:自动恢复上次策略停止前的状态。
  • 下单重试次数:订单没有成交会撤销订单,重新下单尝试交易,该参数用来限定最大的重试次数。
  • 网络轮询间隔(毫秒):只对REST协议有效,控制网络请求间隔,避免请求过于频繁,超出交易所限制。
  • 账户同步时间(秒):同步账户数据的时间周期。
  • 开仓后仓位同步时间(毫秒):只针对一些交易所数据延迟导致的重复开仓,同步时间设置大一些可以缓解此类问题。
  • 杠杆倍数:设置杠杆倍数。

现货交易、其它设置

  • 一手交易量:默认一手的交易量,只针对现货有效。
  • 最小交易量:最小交易量。
  • 定价货币精度:价格精度,即价格的小数位数。
  • 交易品种精度:下单量精度,即下单量的小数位数。
  • 手续费:根据该设置对一些数据进行计算,0.002指千分之2。
  • 盈亏统计间隔:仅在实盘显示盈亏统计使用。
  • 失败重试(毫秒):网络请求失败时重试间隔。
  • 使用代理:只针对REST协议有效。
  • 隐藏常见网络错误:在日志区域隐藏常见错误日志。
  • 切换基地址:只针对REST协议有效。
  • 推送通知:推送消息到邮箱等。

下单交易

开仓

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

平仓

strategy(title = "close long example", pyramiding = 2)                              // pyramiding 允许的同方向下单的次数
strategy.entry("long1", strategy.long, 1)                                           // 市价开多仓,指定分组标签为long1
strategy.entry("long2", strategy.long, 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%持仓

交易机制

PINE语言的持仓机制类似于单向持仓。举例子,当持有多头方向的头寸时(多头持仓),如果有卖出操作的订单、计划单等(相对于持仓方向反方向的)订单触发执行,此时会先平掉多头方向的头寸(平掉所有多头持仓),然后再执行触发的(相对于平仓前持仓方向反方向的)订单。

计划单

使用下单指令下单时,如果不指定任何价格,默认为市价单。除了市价单还可以通过计划单下单,计划单并不会立即操作下单。计划单在没有触发时存在程序的计划委托队列中,可以在实盘/回测时状态信息(即策略运行时的状态栏)的「计划订单」表格分页中看到。当市场实时价格满足条件触发这些计划单时系统才会真正下单。所以这些订单在成交价格上存在略微偏差属于正常情况。使用strategy.entry函数下单时,我们可以指定limitstop参数。

var isTrade = false 
if not barstate.ishistory and not isTrade
    isTrade := true 
    strategy.entry("test 1", strategy.long, 1, stop=close*1.3, comment="test 1 order")                     // stop
    strategy.entry("test 2", strategy.long, 2, limit=close*0.7, comment="test 2 order")                    // limit
    strategy.entry("test 3", strategy.short, 3, stop=close*0.6, limit=close*1.4, comment="test 3 order")   // stop-limit    
  • limit 订单

    设置订单的限价,当订单为买单时(即direction参数为strategy.long),只有市场当前价格低于该价格时,订单才会触发。 当订单为卖单时(即direction参数为strategy.short),只有市场当前价格高于该价格时,订单才会触发。

  • stop 订单

    设置订单的止损价,当订单为买单时,只有市场当前价格高于该价格时,订单才会触发。 当订单为卖单时,只有市场当前价格低于该价格时,订单才会触发。

  • stop-limit 订单

    可以同时设置limitstop参数,订单在首先符合条件的价格触发。

声明、逻辑结构关键字

var

var 是用于分配和一次性初始化变量的关键字。 通常,不包含关键字var的变量赋值语法会导致每次更新数据时都会覆盖变量的值。 与此相反,当使用关键字var分配变量时,尽管数据更新,它们仍可以“保持状态”,只有在满足if-expressions中的条件时才更改它。

var variable_name = expression

说明:

  • variable_name - Pine Script中允许的用户变量的任何名称(可以包含大写和小写的拉丁字符,数字和下划线(_),但不能以数字开头)。
  • expression - 任何算术表达式,就像定义常规变量一样。 将计算表达式并将其分配给变量一次。

例子

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

变量’a’保持系列中每个柱线的第一根柱线的收盘价。 变量’b’保持系列中第一个“绿色”价格棒的收盘价。 变量’c’保持系列中第十个“绿色”条的收盘价。

在FMZ上,分为实时价模型、收盘价模型,对于varvarip声明的变量我们使用以下代码测试。

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
  • 实时价模型 以上测试代码在执行时分为两个阶段:1、历史K线阶段。2、实时K线阶段。当在实时价模型、历史K线阶段时,varvarip声明的变量i、ii在策略代码每轮执行时都会执行递增操作(因为if true所以肯定执行对应的条件代码块)。所以可以看到回测结果K线BAR上显示的数字逐个都是递增1的。当历史K线阶段结束,开始实时K线阶段。varvarip声明的变量则开始发生不同的变化。因为是实时价模型,在一根K线BAR内每次价格变动都会执行一遍策略代码,i := i + 1ii := ii + 1都会执行一次。区别是ii每次都修改。i虽然每次也修改,但是下一轮执行策略逻辑时会恢复之前的值,直到当前K线BAR走完才更新确定i的值(即下一轮执行策略逻辑时不再恢复之前的值)。所以可以看到变量i依然是每根BAR增加1。但是变量ii每根BAR就累加了好几次。

  • 收盘价模型 由于收盘价模型是每根K线BAR走完时才执行一次策略逻辑。所以在收盘价模型时,历史K线阶段和实时K线阶段,varvarip声明的变量在以上例子中递增表现完全一致,都是每根K线BAR递增1。

varip

varip(var intrabar persist)是用于分配和一次性初始化变量的关键词。它与var关键词相似,但是使用varip声明的变量在实时K线更新之间保留其值。

varip variable_name = expression

说明:

  • variable_name - Pine脚本中允许的用户变量的任何名称(可以包含大写和小写拉丁字符、数字和下划线(_),但不能以数字开头)。
  • expression - 任何算术表达式,就像定义常规变量时一样。在第一根K线上,表达式仅计算一次并将其分配给变量一次。

例子

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

使用var时,绘图将返回bar_index的值。使用varip,在历史K线上会发生相同的行为,但是在实时K线上,该图将返回一个值,该值对于每一tick都增加一。

备注 只能与简单类型,例如float、int、bool、string,和这些类型的阵列一起使用。

true

表示一个布尔类型变量的值,或者当表达式使用比较逻辑运算符时可以计算的值。

备注 请参阅比较运算符和逻辑运算符的描述。

另见 bool

false

表示一个布尔类型变量的值,以及比较操作、逻辑操作的结果。

备注 请参阅比较运算符和逻辑运算符的描述。

另见 bool

if

If语句定义了在满足表达式条件时必须执行的语句块。第4版的Pine脚本语言允许您使用“else if”语法。

通用编码来自:

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

备注 var_declarationX - 此变量获取if语句的值 condition - 如果条件为true,则使用语句块then中的逻辑(var_decl_then0var_decl_then1等)。如果条件为false,则使用语句块else if或者else中的逻辑(var_decl_else0var_decl_else1等)。 return_expression_then , return_expression_else - 模块中的最后一个表达式或者来自块else的表达式将返回语句的最终值。 如果变量的声明在最后,它的值将是结果值。

if语句的返回值的类型取决于return_expression_thenreturn_expression_else类型。TradingView上运行时,它们的类型必须匹配:当你在else块中有一个字符串值时,不可能从then语句块返回一个整数值。在FMZ上运行时,以下例子不会报错,当y值取值"open"时,plot画图时的数值为n/a。

例子

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

可以省略else块。在这种情况下,如果条件为false,则会为var_declarationX变量分配一个“empty”值(na、false 或“”):

例子

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

可以使用多个“else if”块或根本不使用。“then”、“else if”、“else”的块被移动四个空格:

例子

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

可以忽略if语句的结果值(“var_declarationX=”可以省略)。如果您需要表达式的副作用,它可能很有用,例如在策略交易中:

例子

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

If语句可以相互包含:

例子

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

for

'for’结构允许重复执行多个语句:

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

var_declaration - 一个可选的变数声明,它将被指派为回圈的 return_expression 的值。 counter - 保存回圈计数器值的变数,在回圈的每次迭代中递增/递减 1 或 step_num 值。 from_num - 计数器的起始值。允许使用“series int/float”值/表达式。 to_num - 计数器的最终值。当计数器大于to_num(或小于to_num在from_num > to_num的情况下)时,循环中断。允许使用“series int/float”值/表达式,但它们仅在循环的第一次迭代时进行评估。 step_num - 计数器的递增/递减值。它是可选的。默认值为+1或-1,具体取决于from_num或to_num中最大的一个。使用值时,计数器也会根据from_num或to_num中最大的那个而递增/递减,因此step_num的+/-符号是可选的。 statements | continue | break - 任意数量的语句,或’continue’或’break’关键字,缩进4个空格或一次 tab。 return_expression - 循环的返回值,如果存在,则分配给var_declaration中的变量。 如果循环由于“continue”或“break”关键字而退出,则循环的返回值是在循环退出之前分配值的最后一个变量的返回值。 continue - 只能在回圈中使用的关键字。它导致回圈的下一次迭代被执行。 break - 退出回圈的关键字。

例子

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

另见 for...in while

for…in

for...in 结构允许为数组中的每个元素重复执行多个语句。它可以与任一参数一起使用:array_element,或与两个参数一起使用:[index, array_element]。 第二种形式不影响循环的功能。它在元组的第一个变量中跟踪当前迭代的索引。

[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 - 一个可选的变量声明,将被赋予循环的 return_expression 的值。 index - 跟踪当前迭代索引的可选变量。索引从 0 开始。变量在循环体中是不可变的。使用时,它必须包含在一个也包含 array_element 的元组中。 array_element - 包含要在循环中处理的每个连续阵列元素的变量。该变量在循环体中是不可变的。 array_id - 回圈迭代的阵列ID。 statements | continue | break - 任意数量的语句,或’continue’或’break’关键字,缩进4个空格或一次 tab。 return_expression - 循环的返回值分配给 var_declaration 中的变量,如果存在的话。 如果循环由于’continue’或’break’关键字而退出,则循环的返回值是循环退出前最后一个赋值的变量。 continue - 只能在回圈中使用的关键字。它导致回圈的下一次迭代被执行。 break - 退出回圈的关键字。

允许在循环内修改阵列的元素或其大小。 在这里,我们使用 for...in 的单参数形式来确定在每个K线上,有多少K线的OHLC值大于’close’值的SMA:

例子

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

在这里,我们使用for…in的两个参数形式将我们的 isPos 数组的值设置为 true,当它们在我们的 valuesArray 数组中的对应值为正时:

例子

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

另见 for while array.sum array.min array.max

while

while语句允许本地代码块的条件迭代。

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

说明: variable_declaration - 可选的变量声明。return expression可以为这个变量提供初始化值。 boolean_expression - 如果为true,则执行while语句的本地块。如果为false,则在while语句之后继续执行脚本。 continue - continue 关键字导致循环分支到下一次迭代。 break - break 关键字导致循环终止。脚本的执行在 while 语句之后恢复。 return_expression - 提供 while 语句返回值的可选行。

例子

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

备注 初始 while 行之后的本地代码块必须缩进四个空格或一个制表符。要终止 while 循环,while 后面的布尔表达式必须最终变为 false,或者必须执行 break

switch

switch运算符根据条件和表达式的值将控制权转移到几个语句之一。

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

例子

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

例子

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)

返回值 执行的本地语句块中最后一个表达式的值。

备注 只能执行local_block实例或default_local_block之一。default_local_block仅与=>标记一起引入,并且仅在没有执行前面的块时才执行。如果switch语句的结果被分配给一个变量并且没有指定default_local_block,如果没有执行local_block,则该语句返回na。将switch语句的结果分配给变量时,所有local_block实例必须返回相同类型的值。

另见 if ?:

series

series是一个关键字,表示数据系列类型。显式使用 series 关键字通常是不必要的。

运算符

=

用于给变量赋值,但仅在声明变量时(第一次使用)。

:=

赋值运算符,给左侧变量赋值。用于为先前声明的变量赋值。

!=

不等于。适用于任何类型的表达式。

expr1 != expr2

返回值 布尔值,或一系列布尔值。

%

模数(整数余数)。 适用于数值表达式。

expr1 % expr2

返回值 整数或浮点值,或一系列值。

备注 在Pine脚本中,当计算整数的余数时,商将被截断。 即,将其四舍五入到最小绝对值。 所得值将具有与股息相同的符号。

示例:-1 % 9 = -1 - 9 * truncate(-1/9) = -1 - 9 * truncate(-0.111) = -1 - 9 * 0 = -1。

%=

模数指派。适用于数值表达式。

expr1 %= expr2

例子

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

返回值 整数或浮点值,或一系列值。

*

乘法。适用于数值表达式。

expr1 * expr2

返回值 整数或浮点值,或一系列值。

*=

乘法指派。适用于数值表达式。

expr1 *= expr2

例子

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

返回值 整数或浮点值,或一系列值。

+

添加或一元正号。适用于数值表达式或字符串。

expr1 + expr2
+ expr

返回值 字符串的二进制+返回expr1和expr2的合并 数字返回整数或浮点值,或一系列值: 二进制’+'返回expr1加expr2。 一元“+”返回expr(对一元运算符对称不添加任何内容)。

备注 您可以使用带数字的算术运算符以及变量数列。 在使用数列的情况下,操作符应用于元素。

+=

加法指派。适用于数值表达式或字符串。

expr1 += expr2

例子

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

返回值 对于字符串,返回expr1和expr2的串联。对于数字,返回整数或浮点值,或一系列值。

备注 您可以使用带数字的算术运算符以及变量数列。 在使用数列的情况下,操作符应用于元素。

-

减法或一元负号。 适用于数值表达式。

expr1 - expr2
- expr

返回值 返回整数或浮点值,或一系列值: 二进制’+'返回expr1减expr2。 一元的-返回expr的否定式。

备注 您可以使用带数字的算术运算符以及变量数列。 在使用数列的情况下,操作符应用于元素。

-=

减法指派。适用于数值表达式。

expr1 -= expr2

例子

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

返回值 整数或浮点值,或一系列值。

/

除法。适用于数值表达式。

expr1 / expr2

返回值 整数或浮点值,或一系列值。

/=

除法指派。适用于数值表达式。

expr1 /= expr2

例子

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

返回值 整数或浮点值,或一系列值。

<

小于。适用于数值表达式。

expr1 < expr2

返回值 布尔值,或一系列布尔值。

<=

小于或等于。适用于数值表达式。

expr1 <= expr2

返回值 布尔值,或一系列布尔值。

==

等于。 适用于任何类型的表达。

expr1 == expr2

返回值 布尔值,或一系列布尔值。

=>

'=>'运算符用于用户定义的函数声明和switch语句中。

函数声明语法是:

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

一个<local_block>是零个或多个Pine语句。 <function_result>是一个变量、一个表达式或一个元组。

例子

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

备注 您可以在用户手册的声明函数和脚本库页面中了解有关用户定义函数的更多信息。

>

大于。适用于数值表达式。

expr1 > expr2

返回值 布尔值,或一系列布尔值。

>=

大于或等于。适用于数值表达式。

expr1 >= expr2

返回值 布尔值,或一系列布尔值。

?:

三元条件运算符。

expr1 ? expr2 : expr3

例子

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

返回值 如果expr1被评估为true,则expr2,否则为expr3。 零值(0和NaN,+ Infinity,-Infinity)被视为false,其他值皆为true。

备注 如果您不需要,请使用na作为“else”分支。 您可以结合使用两个或多个?:运算符,以实现类似于“switch”的语句(请参见上面的示例)。 您可以使用带数字的算术运算符以及变量数列。 在使用数列的情况下,操作符应用于元素。

另见 na

[]

系列下标。 提供对expr1系列的以前值的访问。 expr2是过去k线的数目,必须是数值。 浮动将被向下舍入。

expr1[expr2]

例子

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

返回值 一系列数值。

另见 math.floor

and

逻辑 AND。适用于布尔表达式。

expr1 and expr2

返回值 布尔值,或一系列布尔值。

or

逻辑 OR。适用于布尔表达式。

expr1 or expr2

返回值 布尔值,或一系列布尔值。

not

逻辑求反(NOT)。 适用于布尔表达式。

not expr1

返回值 布尔值,或一系列布尔值。

数据类型关键字

bool

用于显式声明变量或参数的“bool”(布尔)类型的关键字。"Bool"变量的值可以是true、false或na。

例子

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

备注 在变量声明中明确提及类型是可选的,除非它是用na初始化的。在 类型系统的用户手册页面中了解有关Pine类型的更多信息。

另见 var varip int float color string true false

int

用于显式声明变量或参数的“int”(整数)类型的关键字。

例子

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

备注 在变量声明中明确提及类型是可选的,除非它是用na初始化的。在 类型系统的用户手册页面中了解有关Pine类型的更多信息。

另见 var varip float bool color string

float

用于显式声明变量或参数的“float”(浮点)类型的关键字。

例子

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

备注 在变量声明中明确提及类型是可选的,除非它是用na初始化的。

另见 var varip int bool color string

string

用于显式声明变量或参数的"string"类型的关键字。

例子

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

备注 在变量声明中明确提及类型是可选的,除非它是用na初始化的。在 类型系统的用户手册页面中了解有关Pine类型的更多信息。

另见 var varip int float bool str.tostring str.format

color

用于显式声明变量或参数的"color"类型的关键字。

例子

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

备注 颜色文字具有以下格式:#RRGGBB 或 #RRGGBBAA。 字母对代表00到FF的十六进制值(十进制的0到255),其中RR、GG和BB对是颜色的红色、绿色和蓝色分量的值。AA是颜色透明度(或alpha分量)的可选值,其中00不可见,FF不透明。 当没有提供AA对时,使用FF。十六进制字母可以是大写或小写。 在变量声明中明确提及类型是可选的,除非它是用na初始化的。在 类型系统的用户手册页面中了解有关Pine类型的更多信息。

另见 var varip int float string color.rgb color.new

array

用于显式声明变量或参数的“阵列”类型的关键字。可以使用array.new<type>,array.from函数创建阵列对象(或ID)。

例子

// array
array<float> a = na
a := array.new<float>(1, close)
plot(array.get(a, 0))

备注 阵列对象总是“系列”形式。

另见 var array.new array.from

内置函数

调用函数时传参数,可以指定参数名赋值,可以在对应的参数位置直接传入变量,也支持混合使用。例如:

plot(close, title="test plot")     // 直接传参数 close ;指定参数 title ,赋值字符串"test plot"

指定参数名赋值之后,就不能再直接传变量作为参数了,之后的传参都必须写成参数名赋值的形式。

// plot(close, title="test", color.red)    // 虽然plot第三个参数是颜色值,但是这样写就会报错
plot(close, title="test", color=color.red) // 正确写法
plot(close, "test", color.red)             // 正确写法

timeframe

timeframe.in_seconds

将传递给 timeframe 参数的时间周期转换为秒。

timeframe.in_seconds(timeframe)

例子

// Get chart timeframe:
i_tf = input.timeframe("1D")

// Convert timeframe to the int value (number of seconds in 1 Day):
tf = timeframe.in_seconds(i_tf)

plot(tf)

返回值 timeframe 的一根K线中的秒数的 int 表示形式。

参数

  • timeframe (simple string) 时间周期。可选。默认值为timeframe.period。

备注 对于 timeframe >= ‘1M’ 函数根据一个月中的 30.4167 (365/12) 天计算秒数。

另见 input.timeframe timeframe.period

ticker

ticker.heikinashi

创建一个代码标识符请求平滑平均K线值。

ticker.heikinashi(symbol)

例子

heikinashi_close = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, close)

heikinashi_aapl_60_close = request.security(ticker.heikinashi(syminfo.tickerid), "60", close)
plot(heikinashi_close)
plot(heikinashi_aapl_60_close)

返回值 股票代码的字符串值,可以提供给request.security函数。

参数

  • symbol (simple string) 商品代码标识符。

另见 syminfo.tickerid syminfo.ticker request.security

request

request.data

请求外部数据。

request.data(url, attribute)

例子

/*backtest
start: 2022-01-26 09:00:00
end: 2024-02-01 15:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/

// 图表地址https://www.datadata.cn/queries/a10ea45c-1674-48ef-b414-cc17a7e4a548
var chart_data = "https://www.datadata.cn/api/v1/query/a10ea45c-1674-48ef-b414-cc17a7e4a548/data"
add_investor = request.data(chart_data, "$.add_investor")
idx_price = request.data(chart_data, "$.close_price")

plot(add_investor, "股市新增人口")
plot(idx_price, "股指价格")
// 反指交易
avg_investor = ta.ema(add_investor[1], 30)
if strategy.position_size == 0
    if add_investor > avg_investor*1.1
        runtime.log("新增人口:", add_investor, "近30天平均:", avg_investor, "#ff0000")
        strategy.entry("Enter Short", strategy.short)
    else if add_investor < avg_investor*0.9
        runtime.log("新增人口:", add_investor, "近30天平均:", avg_investor, "#ff0000")
        strategy.entry("Enter Long", strategy.long)

返回值 参数attribute指定的数据系列。

参数

  • url (simple string) 请求的数据源url,数据源应答的数据格式需要符合要求(至少包含time、data属性):{"data": [], "schema": ["time", "data"]}。可以参考例子中的数据格式:
    {
        "data": [
            [1430438400000, "2015年04月", "{\"add_investor\" : 497.53, \"close_price\" : 4441.655}"],
            [1433116800000, "2015年05月", "{\"add_investor\" : 415.87, \"close_price\" : 4611.744}"]
            // ...
        ],
        "schema": ["time", "date", "data"]
    }  
    
  • attribute (simple string) 指定属性名,返回所需的数据。例如:"$.add_investor",使用$.作为前缀,属性名与请求数据源时应答的数据中data字段中的属性保持一致

request.security

要求另一个品种/解析度。

request.security(symbol, timeframe, expression, gaps, lookahead, ignore_invalid_symbol, currency) 

例子

s = request.security(syminfo.tickerid, "D", close)   // 1 Day
plot(s)

expr = ta.sma(close, 10)
s1 = request.security(syminfo.tickerid, "240", expr) // 240 Minutes
plot(s1)

// To avoid difference in calculation on history/realtime you can request not latest values and use merge strategy flags as follows:
s2 = request.security(syminfo.tickerid, "D", close[1], barmerge.gaps_off, barmerge.lookahead_on)
plot(s2)
f() => [open, high]
[o, h] = request.security(syminfo.tickerid, "D", f())
[l, c] = request.security(syminfo.tickerid, "D", [low, close])
plot((o + h + l + c) / 4)

返回值 要求系列

参数

  • symbol (simple string) 商品代码。
  • timeframe (simple string) 时间周期。空字符串将被解释为图表的当前时间周期。
  • expression (series int/float/bool/color) 可以从request.security调用计算并返回一个表达式。它可以是一个系列或一个包含可以转换为系列的元素的元组。
  • gaps (barmerge_gaps) 给所请求的数据合并策略(要求数据自动与主要系列OHLC数据合并)。 可能的值:barmerge.gaps_on,barmerge.gaps_off。 barmerge.gaps_on - 请求的数据与可能差距合并(na值)。 barmerge.gaps_off - 请求的数据连续不间断地合并,所有的差距都填满了之前最近的现有值。 默认值为barmerge.gaps_off。
  • lookahead (barmerge_lookahead) 给所请求的数据合并策略。可能的值:barmerge.lookahead_on,barmerge.lookahead_off。 从版本3开始,默认值为barmerge.lookahead_off。请注意,行为与实时相同,仅在历史上不同。
  • ignore_invalid_symbol (const bool) 一个可选参数。如果未找到指定的商品,则确定函数的行为:如果为 false,脚本将停止并返回运行时错误; 如果为true,函数将返回na并继续执行。默认值为false。
  • currency (simple string) 将商品的货币相关值(例如 OHLC)转换成的货币。然后根据转换后的值计算“expression”。使用的转换率基于FX_IDC对的前一天的每日汇率(相对于进行计算的K线)。可选。默认值为syminfo.currency。可能的值:带有 ISO 4217格式的货币代码(例如“USD”)的三字母字符串或 currency.* 命名空间中的常量之一,例如currency.USD。

备注 使用此功能的PineScript代码可以对历史记录和实时数据进行不同的计算。 如果您想为请求的商品指定附加参数,例如交易时段或调整类型,您可以使用ticker.new()函数。 无法使用’ticker’变量将点差传递给此函数。您可以使用’ticker.new’变量或股票代码的字符串表示形式,例如“AAPL+MSFT*TSLA”。 目前,一个脚本中最多可以有40个request.security调用。 请注意,使用此变量/函数可能会导致指标重新绘制。 分辨率参数允许值为: 1S,5S,15S,30S - 秒间隔(图表周期应小于或等于请求的周期) 从1到1440分钟 从1D到365D天 从1W到52W几周 从1M到12M几个月

另见 syminfo.ticker syminfo.tickerid timeframe.period ta.correlation barmerge.lookahead_off barmerge.lookahead_on

str

str.contains

如果source字符串包含str子字符串,则返回true,否则返回false。

str.contains(source, str)

例子

// If the current chart is a continuous futures chart, e.g “BTC1!”, then the function will return true, false otherwise.
var isFutures = str.contains(syminfo.tickerid, "!")
plot(isFutures ? 1 : 0)

返回值 如果在source字符串中找到 str,则为true ,否则为false。

参数

  • source (series string) 来源字符串
  • str (series string) 要搜索的子字符串。

另见 str.pos str.match

str.endswith

如果source字符串以str中指定的子字符串结尾,则返回true,否则返回false。

str.endswith(source, str)

返回值 如果source字符串以str中指定的子字符串结尾,则为true,否则为false。

参数

  • source (series string) 来源字符串
  • str (series string) 要搜索的子字符串。

另见 str.startswith

str.startswith

如果source字符串以str中指定的子字符串开头,则返回true,否则返回false。

str.startswith(source, str)

返回值 如果source字符串以str中指定的子字符串开头,则为true,否则为false。

参数

  • source (series string) 来源字符串
  • str (series string) 要搜索的子字符串。

另见 str.endswith

str.substring

返回一个新字符串,它是source字符串的子字符串。子字符串以begin_pos 指定的索引处的字符开始,并扩展到source 字符串的’end_pos - 1’。

str.substring(source, begin_pos)
str.substring(source, begin_pos, end_pos)

例子

sym= "EXCHANGE_NAME:SYMBOL_NAME"
pos = str.pos(sym, ":")        // Get position of ":" character
tkr= str.substring(sym, pos+1) // "SYMBOL_NAME"
if barstate.islastconfirmedhistory
    runtime.log(tkr)

返回值 从源字符串中提取的子字符串。

参数

  • source (series string) 从中提取子字符串的源字符串。
  • begin_pos (series int) 提取的子串的起始位置。它是独占的(提取的子字符串包括该位置的字符)。
  • end_pos (series int) 结束位置。它是独占的(提取的字符串不包括该位置的字符)。可选。默认值为source字符串的长度。

备注 字符串索引从0开始。如果begin_pos等于end_pos,函数返回一个空字符串。

另见 str.contains str.pos str.match

str.tonumber

str.tonumber(string)

返回值 如果包含有效数字,为字符串的浮点型,否则为na。

参数

  • string (series string) int或float的字符串表现形式。

str.format

将格式字符串和值转换为格式化字符串。格式字符串可以包含文字文本和每个要格式化的值的大括号{}中的一个占位符。每个占位符包括将替换它的必需参数的指数(从0开始) ,以及一个可选的格式说明符。索引表示该参数在str.format参数列表中的位置。

str.format(formatString, arg0, arg1, ...)

例子

// The format specifier inside the curly braces accepts certain modifiers:
// - Specify the number of decimals to display:
s1 = str.format("{0,number,#.#}", 1.34) // returns: 1.3
runtime.log(s1)

// - Round a float value to an integer:
s2 = str.format("{0,number,integer}", 1.34) // returns: 1
runtime.log(s2)

// - Display a number in currency:
s3 = str.format("{0,number,currency}", 1.34) // returns: $1.34
runtime.log(s3)

// - Display a number as a percentage:
s4 = str.format("{0,number,percent}", 0.5) // returns: 50%
runtime.log(s4)

// EXAMPLES WITH SEVERAL ARGUMENTS
// returns: Number 1 is not equal to 4
s5 = str.format("Number {0} is not {1} to {2}", 1, "equal", 4)
runtime.log(s5)

// returns: 1.34 != 1.3
s6 = str.format("{0} != {0, number, #.#}", 1.34)
runtime.log(s6)

// returns: 1 is equal to 1, but 2 is equal to 2
s7 = str.format("{0, number, integer} is equal to 1, but {1, number, integer} is equal to 2", 1.34, 1.52)
runtime.log(s7)

// returns: The cash turnover amounted to $1,340,000.00
s8 = str.format("The cash turnover amounted to {0, number, currency}", 1340000)
runtime.log(s8)

// returns: Expected return is 10% - 20%
s9 = str.format("Expected return is {0, number, percent} - {1, number, percent}", 0.1, 0.2)
runtime.log(s9)

返回值 格式化的字符串。

参数

  • formatString (series string) 格式字符串。
  • arg0, arg1, ... (series int/float/bool/string/na/int[]/float[]/bool[]/string[]) 要格式化的值。

备注 未引用样式中的所有花括号必须保持平衡。例如,“ab {0} de"和"ab ‘}’ de"是有效的样式 ,但是"ab {0’}’ de”, “ab } de"和”’’{’’"不是有效样式。

str.length

返回与该字符串中的字符数相对应的整数。

str.length(string)

返回值 源字符串中的字符数。

参数

  • string (series string) 来源字符串

str.lower

返回一个所有字母都转换为小写的新字符串。

str.lower(source)

返回值 所有字母都转换为小写的新字符串。

参数

  • source (series string) 要转换的字符串。

另见 str.upper

str.upper

返回一个所有字母都转换为大写的新字符串。

str.upper(source)

返回值 所有字母都转换为大写的新字符串。

参数

  • source (series string) 要转换的字符串。

另见 str.lower

str.match

如果匹配regex正则表达式,则返回source字符串的新子字符串,否则返回’na’。

str.match(source, regex) 

例子

s = input.string("It's time to sell some EXCHANGE_NAME:SYMBOL_NAME!")

// finding first substring that matches regular expression "[\w]+:[\w]+"
var string tickerid = str.match(s, "[\\w]+:[\\w]+")

if barstate.islastconfirmedhistor

更多内容