脚本结构
Pine 脚本遵循以下一般结构:
版本
以下形式的编译器注释告诉编译器该脚本是用哪个版本的 Pine Script™ 编写的 :
//@version=5
- 版本号可以是1至5。
- 编译器注释不是强制性的。省略时,假定为版本 1。强烈建议始终使用最新版本的语言。
- 虽然将版本编译器注释放在脚本的任何位置在语法上都是正确的,但当它出现在脚本的顶部时,对读者来说更有用。
Pine Script™ 当前版本的显著变化已记录在发行说明中。
声明
所有 Pine 脚本都必须包含一个声明语句,它是对以下函数之一的调用:
宣告文說明:
- 识别脚本的类型,进而决定其中允许哪些内容,以及如何使用和执行脚本。
- 设置脚本的关键属性,例如其名称、添加到图表时显示的位置、其显示值的精度和格式,以及控制其运行时行为的某些值,例如其在图表上显示的最大绘图对象数量。对于策略,属性包括控制回测的参数,例如初始资本、佣金、滑点等。
每种类型的脚本都有不同的要求:
- 指标必须至少包含一个在图表上产生输出的函数调用(例如, plot()、 plotshape()、 barcolor()、 line.new()等)。
- 策略必须至少包含一个
strategy.*()
调用,例如 strategy.entry()。 - 库必须至少包含一个导出 函数 或用户定义类型。
代码
脚本中除 注释 或 编译器注解之外的行都是语句,用于实现脚本的算法。语句可以是以下之一:
语句可以按多种方式排列:
- 有些语句可以用一行来表达,例如大多数变量声明、仅包含函数调用的行或单行函数声明。行也可以 换行(继续在多行上)。可以使用逗号作为分隔符将多个单行语句连接在一行上。
- 其他语句(例如结构或多行函数声明)总是需要多行,因为它们需要 局部块。局部块必须以制表符或四个空格缩进。每个局部块定义一个不同的局部范围。
- 脚本全局范围内的语句(即不属于本地块的语句)不能以空格(空格或制表符)开头。它们的第一个字符也必须是行的第一个字符。从行的第一个位置开始的行按定义成为脚本全局范围的一部分。
可以通过使用“打开”按钮并选择“新建空白指标”在 Pine Script™ 编辑器中生成一个简单有效的 Pine Script™ v5 指标:
//@version=5
indicator("My Script")
plot(close)
该指示符包括三个局部块,一个在函数声明中,另外两个在使用iff()
结构的变量声明中
:
//@version=5
indicator("", "", true) // Declaration statement (global scope)
barIsUp() => // Function declaration (global scope)
close > open // Local block (local scope)
plotColor = if barIsUp() // Variable declaration (global scope)
color.green // Local block (local scope)
else
color.red // Local block (local scope)
bgcolor(color.new(plotColor, 70)) // Call to a built-in function (global scope)
您可以通过选择“新建空白策略”来调出一个简单的 Pine Script™ v5 策略:
//@version=5
strategy("My Strategy", overlay=true, margin_long=100, margin_short=100)
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)
评论
双斜杠 ( //
) 在 Pine Script™ 中定义注释。注释可以在行中的任何位置开始。它们也可以跟在同一行的 Pine Script™ 代码之后:
//@version=5
indicator("")
// This line is a comment
a = close // This is also a comment
plot(a)
Pine 编辑器具有用于注释/取消注释行的键盘快捷键:
ctrl
+ /
。您可以先突出显示多行,然后使用它。
换行
较长的行可以拆分成多行,或“换行”。换行的行必须缩进任意数量的空格,但不能是 4 的倍数(这些边界用于缩进本地块):
a = open + high + low + close
可以包装为:
a = open +
high +
low +
close
较长的 plot() 调用可以包装为:
plot(ta.correlation(src, ovr, length),
color = color.new(color.purple, 40),
style = plot.style_area,
trackprice = true)
用户定义函数声明中的语句也可以换行。但是,由于局部块在语法上必须以缩进(4 个空格或 1 个制表符)开头,因此在将其拆分到下一行时,语句的延续必须以多个缩进开头(不等于 4 个空格的倍数)。例如:
updown(s) =>
isEqual = s == s[1]
isGrowing = s > s[1]
ud = isEqual ?
0 :
isGrowing ?
(nz(ud[1]) <= 0 ?
1 :
nz(ud[1])+1) :
(nz(ud[1]) >= 0 ?
-1 :
nz(ud[1])-1)
您可以在换行中使用注释:
//@version=5
indicator("")
c = open > close ? color.red :
high > high[1] ? color.lime : // A comment
low < low[1] ? color.blue : color.black
bgcolor(c)
编译器注释
编译器注释是 针对脚本发出特殊指令的注释:
//@version=
指定编译器将使用的 PineScript™ 版本。此注释中的数字不应与脚本的版本号混淆,该版本号会在每次保存代码更改时更新。//@description
为使用library() 声明语句的脚本设置自定义描述 。//@function
,//@param
并在函数声明上方添加用户定义的函数或方法//@returns
、其参数及其结果的自定义描述。//@type
当放置在类型声明上方时,为用户定义类型 (UDT)添加自定义描述。//@enum
当放置在枚举声明上方时,为枚举类型添加自定义描述。//@field
当放置在类型或枚举声明上方时,为用户定义类型(UDT)或枚举类型的字段添加自定义描述。//@variable
当放置在变量声明上方时,为变量添加自定义描述。//@strategy_alert_message
为策略脚本提供默认消息,以预填充警报创建对话框中的“消息”字段。
Pine 编辑器还具有两个专门的注释,//#region
和//#endregion
,用于创建可折叠的代码区域。单击行旁边的下拉箭头//#region
可折叠该行与其下方最近的注释之间的所有代码//#endregion
。
此示例使用图表上三个交互选择的点绘制三角形。该脚本说明了如何使用编译器和编辑器注释来记录代码并使其更易于导航:
//@version=5
indicator("Triangle", "", true)
//#region ———————————————————— Constants and inputs
int TIME_DEFAULT = 0
float PRICE_DEFAULT = 0.0
x1Input = input.time(TIME_DEFAULT, "Point 1", inline = "1", confirm = true)
y1Input = input.price(PRICE_DEFAULT, "", inline = "1", tooltip = "Pick point 1", confirm = true)
x2Input = input.time(TIME_DEFAULT, "Point 2", inline = "2", confirm = true)
y2Input = input.price(PRICE_DEFAULT, "", inline = "2", tooltip = "Pick point 2", confirm = true)
x3Input = input.time(TIME_DEFAULT, "Point 3", inline = "3", confirm = true)
y3Input = input.price(PRICE_DEFAULT, "", inline = "3", tooltip = "Pick point 3", confirm = true)
//#endregion
//#region ———————————————————— Types and functions
// @type Used to represent the coordinates and color to draw a triangle.
// @field time1 Time of first point.
// @field time2 Time of second point.
// @field time3 Time of third point.
// @field price1 Price of first point.
// @field price2 Price of second point.
// @field price3 Price of third point.
// @field lineColor Color to be used to draw the triangle lines.
type Triangle
int time1
int time2
int time3
float price1
float price2
float price3
color lineColor
//@function Draws a triangle using the coordinates of the `t` object.
//@param t (Triangle) Object representing the triangle to be drawn.
//@returns The ID of the last line drawn.
drawTriangle(Triangle t) =>
line.new(t.time1, t.price1, t.time2, t.price2, xloc = xloc.bar_time, color = t.lineColor)
line.new(t.time2, t.price2, t.time3, t.price3, xloc = xloc.bar_time, color = t.lineColor)
line.new(t.time1, t.price1, t.time3, t.price3, xloc = xloc.bar_time, color = t.lineColor)
//#endregion
//#region ———————————————————— Calculations
// Draw the triangle only once on the last historical bar.
if barstate.islastconfirmedhistory
//@variable Used to hold the Triangle object to be drawn.
Triangle triangle = Triangle.new()
triangle.time1 := x1Input
triangle.time2 := x2Input
triangle.time3 := x3Input
triangle.price1 := y1Input
triangle.price2 := y2Input
triangle.price3 := y3Input
triangle.lineColor := color.purple
drawTriangle(triangle)
//#endregion