类型系统
介绍
Pine Script™ 类型系统决定了脚本值与各种函数和操作的兼容性。虽然可以在不了解类型系统的情况下编写简单的脚本,但对类型系统的合理理解对于达到语言熟练程度是必不可少的,而对其细微之处的深入了解可以让程序员充分发挥其潜力。
Pine Script™ 使用类型对所有值进行分类,并使用限定符来确定值和引用是常量、在第一次脚本执行时建立还是在执行过程中动态变化。该系统适用于所有 Pine 值和引用,包括文字、变量、表达式、函数返回和函数参数。
类型系统与 Pine 的 执行模型和 时间序列概念紧密相关。理解这三者对于充分利用 Pine Script™ 的强大功能至关重要。
资格赛
Pine Script™限定符识别脚本何时可以访问值:
- 限定为const 的值和引用 是在编译时建立的(即,在 Pine 编辑器中保存脚本或将其添加到图表时)。
- 符合 输入条件的值是在输入时确定的(即,根据用户输入确认值时,主要从“设置/输入”选项卡)。
- 简单的值 是在零条处(即第一次脚本执行)建立的。
- 符合系列要求的值 可以在整个脚本执行过程中发生变化。
Pine Script™ 根据以下层次结构确定类型限定符的主导地位:const < input < simple < series,其中 “const” 是最弱的限定符,而 “series” 是最强的。限定符层次结构转化为以下规则:只要变量、函数或操作与特定的限定类型兼容, 则也允许使用具有较弱限定符的值。
脚本始终根据 其计算中的主导限定符限定其表达式的返回类型。例如,评估涉及“输入”和“系列”值的表达式将返回一个被限定为“系列”的值。此外,脚本无法将值的限定符更改为层次结构中较低的限定符。如果某个值获得了更强的限定符(例如,最初推断为“简单”的值在脚本执行过程中后来变为“系列”),则该状态是不可逆的。
需要注意的是,“series”值是唯一可以在脚本执行过程中发生变化的值,包括来自各种内置函数(例如 close 和 volume )的值,以及涉及“series”值的表达式的结果。所有限定为“const”、“input”或“simple”的值在所有脚本执行过程中都保持一致。
常量
被限定为“const”的值或引用在编译时(即脚本开始执行之前) 建立。编译最初发生在将脚本保存在 Pine Editor 中时,这不需要它在图表上运行。带有“const”限定符的值或引用在脚本执行之间永远不会改变,即使在第一次执行时也不会改变。
所有文字值以及仅涉及“const”限定值的表达式返回的结果都会自动采用“const”限定符。
以下是一些文字值的示例:
- 文字int :
1
,,-1
42
- 文字浮点数:
1.
,1.0
,3.14
,6.02E-23
,3e8
- 文字布尔值:
true
,false
- 字面颜色:
#FF55C6
,#FF55C6ff
- 文字字符串:
"A text literal"
,,"Embedded single quotes 'text'"
'Embedded double quotes "text"'
我们的样式指南 建议使用大写 SNAKE_CASE 命名“const”变量以提高可读性。虽然不是必需的,但也可以在声明“const”变量时使用 var 关键字,以便脚本仅在数据集的 第一条上初始化它们。有关更多信息,请参阅我们的用户手册的此部分。
下面是在indicator()
和
plot()函数中使用“const”值的示例
,它们都需要“const string”限定类型的值作为其title
参数:
//@version=5
// The following global variables are all of the "const string" qualified type:
//@variable The title of the indicator.
INDICATOR_TITLE = "const demo"
//@variable The title of the first plot.
var PLOT1_TITLE = "High"
//@variable The title of the second plot.
const string PLOT2_TITLE = "Low"
//@variable The title of the third plot.
PLOT3_TITLE = "Midpoint between " + PLOT1_TITLE + " and " + PLOT2_TITLE
indicator(INDICATOR_TITLE, overlay = true)
plot(high, PLOT1_TITLE)
plot(low, PLOT2_TITLE)
plot(hl2, PLOT3_TITLE)
以下示例将引发编译错误,因为它使用了 syminfo.ticker,它返回一个“简单”值,因为它依赖于仅在脚本第一次执行后才可访问的图表信息:
//@version=5
//@variable The title in the `indicator()` call.
var NAME = "My indicator for " + syminfo.ticker
indicator(NAME, "", true) // Causes an error because `NAME` is qualified as a "simple string".
plot(close)
const
关键字允许使用常
量值赋值来声明变量和参数。使用此关键字声明变量会指示脚本禁止对其使用重新赋值和复合赋值
操作。例如,此脚本使用关键字声明变量,然后尝试使用加法赋值运算符 ( += )为变量分配新的“浮点”值,从而导致编译错误:myVar
//@version=5
indicator("Cannot reassign const demo")
//@variable A "float" variable declared as `const`, preventing reassignment.
const float myVar = 0.0
myVar += 1.0 // Causes an error. Reassignment and compound assignments are not allowed on `const` variables.
plot(myVar)
需要注意的是,使用 const 关键字声明变量会强制其保持对特定表达式返回值的常量引用,但这不一定定义所赋值的性质。例如,脚本可以声明一个 const变量,该变量保持对返回特殊类型ID的 表达式的常量引用。虽然脚本无法重新分配变量,但分配的 ID 是一个“系列”值:
//@version=5
indicator("Constant reference to 'series' ID demo")
//@variable A `label` variable declared as `const`, preventing reassignment.
// Although the reference is constant, the ID of the `label` is a "series" value.
const label myVar = label.new(bar_index, close)
输入
大多数被限定为“输入”的值都是通过函数初始化后建立的input.*()
。这些函数产生的值可供用户在脚本设置的“输入”选项卡中修改。当更改此选项卡中的任何值时,脚本将从图表历史记录的开头重新启动,以确保其输入在整个执行过程中保持一致。Pine 的一些内置变量(例如
chart.bg_color)
也使用“输入”限定符,即使函数不返回它们,因为脚本在输入时input.*()
接收它们的值。
sourceInput
以下脚本根据
symbolInput
和上下文绘制 a 的值timeframeInput
。
request.security()
调用在此脚本中有效,因为其symbol
和timeframe
参数允许“简单字符串”参数,这意味着它们也可以接受“输入字符串”值,因为“输入”限定符
在层次结构中较低:
//@version=5
indicator("input demo", overlay = true)
//@variable The symbol to request data from. Qualified as "input string".
symbolInput = input.symbol("AAPL", "Symbol")
//@variable The timeframe of the data request. Qualified as "input string".
timeframeInput = input.timeframe("D", "Timeframe")
//@variable The source of the calculation. Qualified as "series float".
sourceInput = input.source(close, "Source")
//@variable The `sourceInput` value from the requested context. Qualified as "series float".
requestedSource = request.security(symbolInput, timeframeInput, sourceInput)
plot(requestedSource)
简单的
被认定为“简单”的值在第一次脚本执行时可用,并且在后续执行中保持一致。
simple
用户可以通过在声明中包含关键字来明确定义接受“简单”值的变量和参数。
许多内置变量返回“简单”限定值,因为它们依赖于脚本在图表上开始运行时才能获得的信息。此外,许多内置函数需要不会随时间变化的“简单”参数。只要脚本允许“简单”值,它也可以接受限定为“输入”或“const”的值。
此脚本突出显示背景,以警告用户他们正在使用非标准图表类型。它使用
chart.is_standard的值
来计算isNonStandard
变量,然后使用该变量的值来计算warningColor
也引用“简单”值的变量。bgcolor ()color
的参数
允许使用“系列颜色”参数,这意味着它也可以接受“简单颜色”值,因为“简单”在层次结构中较低:
//@version=5
indicator("simple demo", overlay = true)
//@variable Is `true` when the current chart is non-standard. Qualified as "simple bool".
isNonStandard = not chart.is_standard
//@variable Is orange when the the current chart is non-standard. Qualified as "simple color".
simple color warningColor = isNonStandard ? color.new(color.orange, 70) : na
// Colors the chart's background to warn that it's a non-standard chart type.
bgcolor(warningColor, title = "Non-standard chart color")
系列
符合“系列”要求的值在脚本中提供了最大的灵活性,因为它们可以在执行过程中发生变化。
series
用户可以通过在声明中包含关键字来明确定义接受“系列”值的变量和参数。
内置变量(例如 open、 high、 low、 close、 volume、 time和 bar_index)以及使用此类内置变量的任何表达式的结果均被限定为“系列”。任何返回动态值的函数或操作的结果将始终是“系列”,使用历史引用运算符 [] 访问历史值的结果也是如此。只要脚本允许“系列”值,它也会接受带有任何其他限定符的值,因为“系列”是层次结构中的最高限定符。
此脚本显示
横线
的最高值
和
最低值。分配给和变量的值属于“系列浮点数”限定类型,因为它们可以在脚本执行过程中发生变化:sourceInput
lengthInput
highest
lowest
//@version=5
indicator("series demo", overlay = true)
//@variable The source value to calculate on. Qualified as "series float".
series float sourceInput = input.source(close, "Source")
//@variable The number of bars in the calculation. Qualified as "input int".
lengthInput = input.int(20, "Length")
//@variable The highest `sourceInput` value over `lengthInput` bars. Qualified as "series float".
series float highest = ta.highest(sourceInput, lengthInput)
//@variable The lowest `sourceInput` value over `lengthInput` bars. Qualified as "series float".
lowest = ta.lowest(sourceInput, lengthInput)
plot(highest, "Highest source", color.green)
plot(lowest, "Lowest source", color.red)
类型
Pine Script™类型对值进行分类并确定其兼容的功能和操作。它们包括:
- 基本类型: int、 float、 bool、 color和string
- 特殊类型: plot、 hline、 line、 linefill、 box、 polyline、 label、 table、 chart.point、 array、 matrix和 map
- 用户定义类型 (UDT)
- 枚举
- 空白
基本类型是指值的底层性质,例如,值 1 属于“int”类型,1.0 属于“float”类型,“AAPL”属于“string”类型,等等。特殊类型和用户定义类型使用引用特定类型对象的ID。例如,“label”类型的值包含一个 ID,该 ID 充当 指向“label”对象的指针。“void”类型是指不返回可用值的函数或方法的输出。
Pine Script™ 可以自动将某些类型的值转换为其他类型。自动转换规则为:int → float → bool。 有关更多信息,请参阅本页的类型转换部分。
在大多数情况下,Pine Script™ 可以自动确定值的类型。但是,我们也可以使用类型关键字来明确指定类型,以提高可读性,并用于需要明确定义的代码(例如,声明分配给na 的变量 )。例如:
//@version=5
indicator("Types demo", overlay = true)
//@variable A value of the "const string" type for the `ma` plot's title.
string MA_TITLE = "MA"
//@variable A value of the "input int" type. Controls the length of the average.
int lengthInput = input.int(100, "Length", minval = 2)
//@variable A "series float" value representing the last `close` that crossed over the `ma`.
var float crossValue = na
//@variable A "series float" value representing the moving average of `close`.
float ma = ta.sma(close, lengthInput)
//@variable A "series bool" value that's `true` when the `close` crosses over the `ma`.
bool crossUp = ta.crossover(close, ma)
//@variable A "series color" value based on whether `close` is above or below its `ma`.
color maColor = close > ma ? color.lime : color.fuchsia
// Update the `crossValue`.
if crossUp
crossValue := close
plot(ma, MA_TITLE, maColor)
plot(crossValue, "Cross value", style = plot.style_circles)
plotchar(crossUp, "Cross Up", "▲", location.belowbar, size = size.small)
整数
“int”类型的值表示整数,即没有任何小数的整数。
整数文字是以十进制表示的数值。例如:
1
-1
750
内置变量如 bar_index、 time、 timenow、 dayofmonth和 strategies.wintrades 均返回“int”类型的值。
漂浮
“float”类型的值表示浮点数,即可以包含整数和小数的数字。
浮点文字是用.
分隔符书写的数值。它们也可能包含符号e
或E
(表示“10 的 X 次方”,其中 X 是e
或E
符号后面的数字)。例如:
3.14159 // Rounded value of Pi (π)
- 3.0
6.02e23 // 6.02 * 10^23 (a very large value)
1.6e-19 // 1.6 * 10^-19 (a very small value)
Pine Script™ 中“浮点”值的内部精度为 1e-16。
内置变量如 close、 hlcc4、 volume、 ta.vwap和 strategies.position_size 均返回“float”类型的值。
布尔值
“bool”类型的值表示比较或条件的真值,脚本可以在 条件结构和其他表达式中使用它。
只有两个文字代表布尔值:
true // true value
false // false value
当“bool”类型的表达式返回
na时,脚本会将其值视为false
评估条件语句和运算符时的值。
内置变量如 barstate.isfirst、 chart.is_heikinashi、 session.ismarket和 timeframe.isdaily 均返回“bool”类型的值。
颜色
颜色文字具有以下格式:#RRGGBB
或#RRGGBBAA
。字母对代表和之间的十六进制值(十进制为 0 到 255),其中:00
FF
RR
、GG
和BB
对分别代表颜色的红色、绿色和蓝色成分的值。AA
是颜色不透明度(或alpha 分量)的可选值,其中00
是不可见且FF
不透明的。当文字不包含AA
对时,脚本会将其视为完全不透明(与使用 相同FF
)。- 文字中的十六进制字母可以是大写或小写。
这些是“颜色”文字的示例:
#000000 // black color
#FF0000 // red color
#00FF00 // green color
#0000FF // blue color
#FFFFFF // white color
#808080 // gray color
#3ff7a0 // some custom color
#FF000080 // 50% transparent red color
#FF0000ff // same as #FF0000, fully opaque red color
#FF000000 // completely transparent red color
Pine Script™ 还具有
内置颜色常量,包括
color.green、
color.red、
color.orange、
color.blue
(函数中的默认颜色和绘图类型plot*()
中的许多默认颜色相关属性
)等。
使用内置颜色常量时,可以通过 color.new() 函数向其添加透明度信息。
请注意,在color.*()
函数中指定红色、绿色或蓝色分量时,我们使用值介于 0 到 255 之间的“int”或“float”参数。指定透明度时,我们使用介于 0 到 100 之间的值,其中 0 表示完全不透明,100 表示完全透明。例如:
//@version=5
indicator("Shading the chart's background", overlay = true)
//@variable A "const color" value representing the base for each day's color.
color BASE_COLOR = color.rgb(0, 99, 165)
//@variable A "series int" value that modifies the transparency of the `BASE_COLOR` in `color.new()`.
int transparency = 50 + int(40 * dayofweek / 7)
// Color the background using the modified `BASE_COLOR`.
bgcolor(color.new(BASE_COLOR, transparency))
有关在脚本中使用颜色的更多信息,请参阅用户手册中的颜色页面。
细绳
“字符串”类型的值表示字母、数字、符号、空格和其他字符的序列。
Pine 中的字符串文字是用单引号或双引号括起来的字符。例如:
"This is a string literal using double quotes."
'This is a string literal using single quotes.'
在 Pine Script™ 中,单引号和双引号功能相同。双引号内的“字符串”可以包含任意数量的单引号,反之亦然:
"It's an example"
'The "Star" indicator'
脚本可以使用反斜杠字符 ( )转义“字符串”中的分隔符\
。例如:
'It\'s an example'
"The \"Star\" indicator"
我们可以创建包含换行符( )的“字符串”值,用于使用和绘图类型
的函数和对象
\n
显示多行文本。例如:plot*()
log.*()
"This\nString\nHas\nOne\nWord\nPer\nLine"
我们可以使用 +运算符来连接“字符串”值:
"This is a " + "concatenated string."
命名空间中的内置函数str.*()
使用专门的操作创建“字符串”值。例如,此脚本创建一个格式化的字符串来表示“浮点”价格值,并使用标签显示结果:
//@version=5
indicator("Formatted string demo", overlay = true)
//@variable A "series string" value representing the bar's OHLC data.
string ohlcString = str.format("Open: {0}\nHigh: {1}\nLow: {2}\nClose: {3}", open, high, low, close)
// Draw a label containing the `ohlcString`.
label.new(bar_index, high, ohlcString, textcolor = color.white)
有关从脚本显示“字符串”值的更多信息,请参阅我们的用户手册中的 文本和形状页面。
内置变量(例如 syminfo.tickerid、 syminfo.currency和 timeframe.period) 返回“字符串”类型的值。
绘图和线
Pine Script™ 的 plot() 和 hline() 函数返回分别引用“plot”和“hline”类型实例的 ID。这些类型在图表上显示计算值和水平线,并且可以将其 ID 分配给变量,以便与内置的 fill() 函数一起使用。
例如,此脚本在图表上绘制两个 EMA,并使用 fill () 调用填充它们之间的空间:
//@version=5
indicator("plot fill demo", overlay = true)
//@variable A "series float" value representing a 10-bar EMA of `close`.
float emaFast = ta.ema(close, 10)
//@variable A "series float" value representing a 20-bar EMA of `close`.
float emaSlow = ta.ema(close, 20)
//@variable The plot of the `emaFast` value.
emaFastPlot = plot(emaFast, "Fast EMA", color.orange, 3)
//@variable The plot of the `emaSlow` value.
emaSlowPlot = plot(emaSlow, "Slow EMA", color.gray, 3)
// Fill the space between the `emaFastPlot` and `emaSlowPlot`.
fill(emaFastPlot, emaSlowPlot, color.new(color.purple, 50), "EMA Fill")
值得注意的是,与其他特殊类型不同,Pine 中没有
plot
orhline
关键字来明确声明变量的类型为“plot”或“hline”。
用户可以通过命名空间中的变量display.*
和plot*()
函数的参数来控制其脚本的绘图显示位置。此外,一个脚本可以通过
input.source()force_overlay
函数
将另一个脚本绘图中的值用作外部输入(请参阅我们的用户手册中有关源输入
的部分
)。
绘图类型
Pine Script™ 绘图类型允许脚本在图表上创建自定义绘图。它们包括: 线条、 线条填充、 框、 折线、 标签和 表格。
每种类型还具有一个命名空间,其中包含创建和管理绘图实例的所有内置函数。例如,以下*.new()
构造函数在脚本中创建这些类型的新对象:
line.new()、
linefill.new()、
box.new()、
polyline.new()、
label.new()和
table.new()。
这些函数中的每一个都会返回一个ID,该 ID 是唯一标识绘图对象的引用。ID 始终被限定为“系列”,这意味着它们的限定类型为“系列线”、“系列标签”等。绘图 ID 就像指针一样,因为每个 ID 都引用该绘图命名空间中所有函数中绘图的特定实例。例如, line.new()调用返回的线的 ID 稍后会在使用line.delete() 删除它时用于引用该特定对象 。
图表要点
图表点是代表图表上坐标的特殊类型。脚本使用chart.point对象中的信息 来确定线条、 框、 折线和标签 在图表上的位置 。
此类型的对象包含三个字段:time
、index
和
price
。绘图实例是否使用chart.point中的
time
或字段
作为 x 坐标取决于绘图的属性。price
xloc
我们可以使用以下任意函数在脚本中创建图表点:
- chart.point.new() -
使用指定的、和创建一个新的chart.point。
time
index
price
- chart.point.now() - 创建
具有指定y 坐标的新
chart.point 。和字段包含
函数执行的条形图的时间
和
bar_index 。
price
time
index
- chart.point_from_index() - 创建一个
具有x 坐标和y 坐标的新
chart.point 。
结果实例的字段为
na,这意味着它不适用于使用xloc.bar_time
值的
绘图对象。
index
price
time
xloc
- chart.point.from_time() - 创建一个
具有x 坐标和y 坐标的新
chart.point 。
结果实例的字段为
na,这意味着它不适用于使用xloc.bar_index
值的
绘图对象。
time
price
index
xloc
- chart.point.copy() - 创建一个新的
chart.point,其中包含与函数调用中的
相同的
time
、index
和price
信息 。id
此示例在每个图表条上绘制连接前一个条的
最高点
和当前条的
最低点的线。它还在每条线的两个点处显示标签。线和标签从和firstPoint
变量
获取信息,这些变量引用使用chart.point_from_index()
和
chart.point.now()secondPoint
创建的图表点
:
//@version=5
indicator("Chart points demo", overlay = true)
//@variable A new `chart.point` at the previous `bar_index` and `high`.
firstPoint = chart.point.from_index(bar_index - 1, high[1])
//@variable A new `chart.point` at the current bar's `low`.
secondPoint = chart.point.now(low)
// Draw a new line connecting coordinates from the `firstPoint` and `secondPoint`.
// This line uses the `index` fields from the points as x-coordinates.
line.new(firstPoint, secondPoint, color = color.purple, width = 3)
// Draw a label at the `firstPoint`. Uses the point's `index` field as its x-coordinate.
label.new(
firstPoint, str.tostring(firstPoint.price), color = color.green,
style = label.style_label_down, textcolor = color.white
)
// Draw a label at the `secondPoint`. Uses the point's `index` field as its x-coordinate.
label.new(
secondPoint, str.tostring(secondPoint.price), color = color.red,
style = label.style_label_up, textcolor = color.white
)
收藏
Pine Script™ 中的集合(数组、矩阵和映射)使用引用 ID,与其他特殊类型(例如标签)非常相似。ID 的类型定义了集合将包含的元素类型。在 Pine 中,我们通过将类型模板附加到 数组、矩阵或映射关键字来指定数组、 矩阵 和映射类型 :
array<int>
定义一个包含“int”元素的数组。array<label>
定义一个包含“标签”ID 的数组。array<UDT>
定义一个包含引用用户定义类型 (UDT)对象的 ID 的数组 。matrix<float>
定义一个包含“浮点”元素的矩阵。matrix<UDT>
定义一个矩阵,其中包含引用用户定义类型 (UDT)对象的 ID 。map<string, float>
定义一个包含“字符串”键和“浮点数”值的映射。map<int, UDT>
定义一个包含“int”键和 用户定义类型(UDT)实例的 ID 作为值的映射。
例如,可以通过以下任一等效方式声明一个单个元素值为 10 的“int”数组:
a1 = array.new<int>(1, 10)
array<int> a2 = array.new<int>(1, 10)
a3 = array.from(10)
array<int> a4 = array.from(10)
注意:
- 该
int[]
语法还可以指定“int”元素的数组,但不鼓励使用。没有等效的方法来以这种方式指定矩阵或映射的类型。 - 数组存在特定类型的内置函数,例如
array.new_int(),但更通用的array.new<type>
形式更受欢迎,它将
array.new<int>()
创建一个“int”元素的数组。
用户定义类型
type 关键字允许创建用户定义类型(UDT) ,脚本可以从中创建对象。UDT 是复合类型;它们包含任意数量的字段,这些字段可以是任何类型的字段,包括其他用户定义类型。
声明用户定义类型的语法是:
在哪里:
- export是库 脚本用来导出用户定义类型 的关键字 。要了解有关导出 UDT 的更多信息,请参阅我们的用户手册的库 页面。
<UDT_identifier>
是用户定义类型的名称。<field_type>
是字段的类型。<field_name>
是字段的名称。<value>
是字段的可选默认值,脚本将在创建该 UDT 的新对象时将其分配给该字段。如果没有提供值,则字段的默认值为 na 。与控制函数签名中参数默认值的规则相同的规则也适用于字段的默认值。例如,UDT 的默认值不能使用历史引用运算符[]或表达式的结果 。
此示例声明了一个pivotPoint
带有“int”pivotTime
字段和“float”priceLevel
字段的 UDT,它们分别保存有关计算枢轴的时间和价格信息:
//@type 包含枢轴信息的用户定义类型。 //@field pivotTime 包含有关枢轴的时间信息。 //@field priceLevel 包含有关枢轴的价格信息。 type pivotPoint int pivotTime float priceLevel
用户定义类型支持类型递归,即 UDT 的字段可以引用同一 UDT 的对象。在这里,我们nextPivot
在先前的pivotPoint
类型中添加了一个引用另一个
pivotPoint
实例的字段:
//@type 包含枢轴信息的用户定义类型。 //@field pivotTime 包含有关枢轴的时间信息。 //@field priceLevel 包含有关枢轴的价格信息。 //@field nextPivotpivotPoint
包含其他枢轴信息的实例。 type pivotPoint int pivotTime float priceLevel pivotPoint nextPivot
脚本可以使用两种内置方法来创建和复制 UDT:new()
和copy()
。请参阅我们的用户手册中的
对象页面,了解有关使用 UDT 的更多信息。
枚举类型
enum关键字允许创建枚举,也称为枚举、枚举类型或枚举类型。枚举是一种独特的类型构造,包含表示该类型成员(即可能的值)的不同命名字段。枚举允许程序员控制变量、条件表达式和集合接受的值,并且它们有助于使用input.enum()函数方便地创建下拉输入。
声明枚举的语法如下:
在哪里:
- export 是可选关键字,允许 库 导出枚举以供其他脚本使用。请参阅 本节以了解有关导出枚举类型的更多信息。
<enumName>
是枚举类型的名称。脚本可以在 变量声明和 类型模板中将枚举的名称用作类型关键字。<field_*>
是枚举字段的名称,表示类型的命名成员(值) 。每个字段必须具有唯一名称,且该名称不与枚举中任何其他字段的名称或标题匹配。要检索枚举成员,请使用点符号语法(即)enumName
引用其字段名称。enumName.fieldName
<title_*>
是分配给字段的“常量字符串”标题。如果没有指定标题,则字段的标题是其名称的“字符串”表示。input.enum () 函数在脚本的“设置/输入”选项卡中的下拉列表中显示字段标题。用户还可以使用 str.tostring() 函数检索字段的标题。与字段名称一样,每个字段的标题不得与枚举中任何其他字段的名称或标题匹配。
此示例声明了一个maChoice
枚举。此声明中的每个字段代表枚举类型的不同成员maChoice
:
//@enum An enumeration of named values for moving average selection.
//@field sma Selects a Simple Moving Average.
//@field ema Selects an Exponential Moving Average.
//@field wma Selects a Weighted Moving Average.
//@field hma Selects a Hull Moving Average.
enum maChoice
sma = "Simple Moving Average"
ema = "Exponential Moving Average"
wma = "Weighted Moving Average"
hma = "Hull Moving Average"
注意:
- 枚举的所有可能值在第一次执行脚本时可用 ,并且在后续执行中不会改变。因此,它们自动采用 简单限定符。
下面的脚本使用input.enum()maChoice
调用中的枚举
在“设置/输入”选项卡中
创建一个下拉输入,该输入显示所有字段标题。该值表示与用户选择的标题相对应的枚举成员。该脚本使用switch结构中的选定成员
来确定它计算的内置移动平均值:maInput
//@version=5
indicator("Enum types demo", overlay = true)
//@enum An enumeration of named values for moving average selection.
//@field sma Selects a Simple Moving Average.
//@field ema Selects an Exponential Moving Average.
//@field wma Selects a Weighted Moving Average.
//@field hma Selects a Hull Moving Average.
enum maChoice
sma = "Simple Moving Average"
ema = "Exponential Moving Average"
wma = "Weighted Moving Average"
hma = "Hull Moving Average"
//@variable The `maChoice` member representing a selected moving average name.
maChoice maInput = input.enum(maChoice.sma, "Moving average type")
//@variable The length of the moving average.
int lengthInput = input.int(20, "Length", 1, 4999)
//@variable The moving average selected by the `maInput`.
float selectedMA = switch maInput
maChoice.sma => ta.sma(close, lengthInput)
maChoice.ema => ta.ema(close, lengthInput)
maChoice.wma => ta.wma(close, lengthInput)
maChoice.hma => ta.hma(close, lengthInput)
// Plot the `selectedMA`.
plot(selectedMA, "Selected moving average", color.teal, 3)
请参阅枚举页面和 输入页面的枚举输入部分以了解有关使用枚举和枚举输入的更多信息。
空白
Pine Script™ 中有一个“void”类型。只有副作用且不返回可用结果的函数返回“void”类型。此类函数的一个示例是 alert();它执行某些操作(触发警报事件),但不返回可用值。
脚本不能在表达式中使用“void”结果或将其分配给变量。Pine void
Script™ 中不存在关键字,因为无法声明“void”类型的变量。
`na`值
Pine Script™ 中有一个特殊值,称为
na ,它是not available的首字母缩写。我们使用
na来表示变量或表达式中未定义的值。它与null
Java 和None
Python 中的类似。
脚本可以自动将 na值转换为几乎任何类型。但是,在某些情况下,编译器无法推断与na值 关联的类型, 因为可能适用多条类型转换规则。例如:
// Compilation error!
myVar = na
上面这行代码会导致编译错误,因为编译器无法确定myVar
变量的性质,即该变量是否引用用于绘图的数值、用于在标签中设置文本的字符串值,还是在脚本稍后执行时用于其他目的的其他值。
为了解决此类错误,我们必须明确声明与变量关联的类型。假设变量将在后续脚本迭代中引用“float”值。我们可以通过使用floatmyVar
关键字声明变量来解决错误
:
float myVar = na
或者通过float()函数明确将 na值转换为“float”类型 :
myVar = float(na)
要测试变量或表达式的值是否为
na,我们调用
na()true
函数,如果值未定义,则
返回该函数。例如:
//@variable Is 0 if the `myVar` is `na`, `close` otherwise.
float myClose = na(myVar) ? 0 : close
不要使用==
比较运算符来测试
na
值,因为脚本无法确定未定义值是否相等:
//@variable Returns the `close` value. The script cannot compare the equality of `na` values, as they're undefined.
float myClose = myVar == na ? 0 : close
最佳编码实践通常涉及处理 na 值以防止计算中出现未定义的值。
例如,这行代码检查 当前条的收盘 价是否大于前一条的收盘价:
//@variable Is `true` when the `close` exceeds the last bar's `close`, `false` otherwise.
bool risingClose = close > close[1]
在第一个图表条上,的值为risingClose
na
,因为没有过去的
收盘
值可供参考。
我们可以确保表达式在第一个柱上也返回可操作的值,方法是用当前柱的值替换未定义的过去值。 当值为 na时,此行代码使用nz()函数将过去柱的收盘价 替换 为当前柱的 开盘价:
//@variable Is `true` when the `close` exceeds the last bar's `close` (or the current `open` if the value is `na`).
bool risingClose = close > nz(close[1], open)
保护脚本免受
na
实例的影响有助于防止未定义的值在计算结果中传播。例如,此脚本
allTimeHigh
在第一个条形图上声明一个变量。然后,它使用
math.max()
在allTimeHigh
和条形图的
最高点之间
更新allTimeHigh
整个执行过程:
//@version=5
indicator("na protection demo", overlay = true)
//@variable The result of calculating the all-time high price with an initial value of `na`.
var float allTimeHigh = na
// Reassign the value of the `allTimeHigh`.
// Returns `na` on all bars because `math.max()` can't compare the `high` to an undefined value.
allTimeHigh := math.max(allTimeHigh, high)
plot(allTimeHigh) // Plots `na` on all bars.
此脚本在所有条形上绘制na值
,因为我们未在代码中包含任何
na
保护。为了修复此行为并绘制预期结果(即图表价格的历史最高点),我们可以使用
nz()替换
系列中的na
值allTimeHigh
:
//@version=5
indicator("na protection demo", overlay = true)
//@variable The result of calculating the all-time high price with an initial value of `na`.
var float allTimeHigh = na
// Reassign the value of the `allTimeHigh`.
// We've used `nz()` to prevent the initial `na` value from persisting throughout the calculation.
allTimeHigh := math.max(nz(allTimeHigh), high)
plot(allTimeHigh)
类型模板
类型模板指定集合(数组、 矩阵和 映射)可以包含的数据类型。
数组和
矩阵的模板由一个用尖括号括起来的类型标识符组成,例如<int>
,,
<label>
和<PivotPoint>
(其中PivotPoint
是
用户定义类型 (UDT))。
映射模板由两个用尖括号括起来的类型标识符组成,第一个标识符指定每个键值对中键的类型,第二个标识符指定值的类型。例如,是用于保存键和值的<string, float>
映射的类型模板。string
float
用户可以从以下位置构建类型模板:
- 基本类型: int、 float、 bool、 color和string
- 以下特殊类型: line、 linefill、 box、 polyline、 label、 table和 chart.point
- 用户定义类型 (UDT)
- 枚举类型
注意:
脚本使用类型模板来声明引用集合的变量,以及创建新集合实例时使用的类型模板。例如:
//@version=5
indicator("Type templates demo")
//@variable A variable initially assigned to `na` that accepts arrays of "int" values.
array<int> intArray = na
//@variable An empty matrix that holds "float" values.
floatMatrix = matrix.new<float>()
//@variable An empty map that holds "string" keys and "color" values.
stringColorMap = map.new<string, color>()
类型转换
Pine Script™ 包含自动类型转换机制,可在必要时将“int”值转换 (转换)为“float”。需要“float”值的变量或表达式也可以使用“int”值,因为任何整数都可以表示为小数部分等于 0 的浮点数。
为了向后兼容,Pine Script™ 还会在必要时自动将“int”和“float”值转换为“bool”。当将数值传递给需要“bool”类型的函数和操作的参数时,Pine 会自动将它们转换为“bool”。但是,我们不建议依赖此行为。大多数将数值自动转换为“bool”类型的脚本都会产生编译器警告。可以使用bool()函数避免编译器警告并提高代码的可读性 ,该函数明确将数值转换为“bool”类型。
将“int”或“float”转换为“bool”时,值 0 将转换为false
,而任何其他数值始终将转换为true
。
以下代码演示了 Pine 中已弃用的自动转换行为。它randomValue
在每个条形上创建一个具有“series float”值的变量,并将其传递给ifcondition
结构中的参数
和plotchar()函数调用中的参数
。由于两个参数都接受“bool”值,因此脚本在评估它们时会自动将其转换为“bool”:series
randomValue
//@version=5
indicator("Auto-casting demo", overlay = true)
//@variable A random rounded value between -1 and 1.
float randomValue = math.round(math.random(-1, 1))
//@variable The color of the chart background.
color bgColor = na
// This raises a compiler warning since `randomValue` is a "float", but `if` expects a "bool".
if randomValue
bgColor := color.new(color.blue, 60)
// This does not raise a warning, as the `bool()` function explicitly casts the `randomValue` to "bool".
if bool(randomValue)
bgColor := color.new(color.blue, 60)
// Display unicode characters on the chart based on the `randomValue`.
// Whenever `math.random()` returns 0, no character will appear on the chart because 0 converts to `false`.
plotchar(randomValue)
// We recommend explicitly casting the number with the `bool()` function to make the type transformation more obvious.
plotchar(bool(randomValue))
// Highlight the background with the `bgColor`.
bgcolor(bgColor)
当自动转换规则无法满足要求时,有时需要将一种类型转换为另一种类型。对于这种情况,可以使用以下类型转换函数: int()、 float()、 bool()、 color()、 string()、 line()、 linefill()、 label()、 box()和 table()。
下面的示例显示了一段代码,该代码尝试使用“const float”值作为ta.sma()length
函数调用中的参数
。该脚本将无法编译,因为它无法自动将“float”值转换为所需的“int”类型:
//@version=5
indicator("Explicit casting demo", overlay = true)
//@variable The length of the SMA calculation. Qualified as "const float".
float LENGTH = 10.0
float sma = ta.sma(close, LENGTH) // Compilation error. The `length` parameter requires an "int" value.
plot(sma)
代码引发以下错误:“无法使用参数‘length’=‘LENGTH’调用‘ta.sma’。使用了‘const float’类型的参数,但预期为‘series int’。”
编译器告诉我们,代码在需要“int”的地方使用了“float”值。没有自动转换规则将“float”转换为“int”,所以我们必须自己完成这项工作。在此版本的代码中,我们使用
int()函数在ta.sma()调用中将
“float”值显式转换LENGTH
为“int”类型
:
//@version=5
indicator("explicit casting demo")
//@variable The length of the SMA calculation. Qualified as "const float".
float LENGTH = 10.0
float sma = ta.sma(close, int(LENGTH)) // Compiles successfully since we've converted the `LENGTH` to "int".
plot(sma)
当声明分配给na 的变量时,显式类型转换也很方便 ,如上一节所述 。
例如,曾经可以通过以下任一等效方式明确地将值为 na的变量声明为“标签”类型:
// Explicitly specify that the variable references "label" objects:
label myLabel = na
// Explicitly cast the `na` value to the "label" type:
myLabel = label(na)
元组
元组是一组用逗号分隔的括号内的表达式。当函数、方法或其他本地块返回多个值时,脚本会以元组的形式返回这些值。
例如,以下 用户定义函数返回两个“浮点”值的和与乘积:
//@function Calculates the sum and product of two values.
calcSumAndProduct(float a, float b) =>
//@variable The sum of `a` and `b`.
float sum = a + b
//@variable The product of `a` and `b`.
float product = a * b
// Return a tuple containing the `sum` and `product`.
[sum, product]
当我们稍后在脚本中调用此函数时,我们使用元组声明来声明与函数调用返回的值相对应的多个变量:
// Declare a tuple containing the sum and product of the `high` and `low`, respectively.
[hlSum, hlProduct] = calcSumAndProduct(high, low)
请记住,与声明单个变量不同,我们无法明确定义元组的变量(在本例hlSum
中
hlProduct
)将包含的类型。编译器会自动推断与元组中的变量相关联的类型。
在上面的例子中,生成的元组包含相同类型(“float”)的值。但是,需要注意的是,元组可以包含多种类型的值。例如,chartInfo()
下面的函数返回一个包含“int”、“float”、“bool”、“color”和“string”值的元组:
//@function Returns information about the current chart.
chartInfo() =>
//@variable The first visible bar's UNIX time value.
int firstVisibleTime = chart.left_visible_bar_time
//@variable The `close` value at the `firstVisibleTime`.
float firstVisibleClose = ta.valuewhen(ta.cross(time, firstVisibleTime), close, 0)
//@variable Is `true` when using a standard chart type, `false` otherwise.
bool isStandard = chart.is_standard
//@variable The foreground color of the chart.
color fgColor = chart.fg_color
//@variable The ticker ID of the current chart.
string symbol = syminfo.tickerid
// Return a tuple containing the values.
[firstVisibleTime, firstVisibleClose, isStandard, fgColor, symbol]
元组对于在一次request.security()调用中请求多个值特别方便 。
例如,此roundedOHLC()
函数返回一个元组,其中包含四舍五入到最接近的价格的 OHLC 值,这些价格可被符号的最小刻度
值整除。我们将此函数作为request.security()expression
中的参数调用
,以请求包含每日 OHLC 值的元组:
//@function Returns a tuple of OHLC values, rounded to the nearest tick.
roundedOHLC() =>
[math.round_to_mintick(open), math.round_to_mintick(high), math.round_to_mintick(low), math.round_to_mintick(close)]
[op, hi, lo, cl] = request.security(syminfo.tickerid, "D", roundedOHLC())
我们还可以通过直接传递一个四舍五入值的元组来实现相同的结果,就像expression
在
request.security()
调用中一样:
[op, hi, lo, cl] = request.security(
syminfo.tickerid, "D",
[math.round_to_mintick(open), math.round_to_mintick(high), math.round_to_mintick(low), math.round_to_mintick(close)]
)
条件结构的局部块 (包括 if和 switch 语句)可以返回元组。例如:
[v1, v2] = if close > open
[high, close]
else
[close, low]
和:
[v1, v2] = switch
close > open => [high, close]
=> [close, low]
但是,三元语句不能包含元组,因为三元语句中的返回值不被视为本地块:
// Not allowed.
[v1, v2] = close > open ? [high, close] : [close, low]
请注意,从函数返回的元组中的所有项都限定为“简单”或“系列”,具体取决于其内容。如果元组包含“系列”值,则元组中的所有其他元素也将采用“系列”限定符。例如:
//@version=5
indicator("Qualified types in tuples demo")
makeTicker(simple string prefix, simple string ticker) =>
tId = prefix + ":" + ticker // simple string
source = close // series float
[tId, source]
// Both variables are series now.
[tId, source] = makeTicker("BATS", "AAPL")
// Error cannot call 'request.security' with 'series string' tId.
r = request.security(tId, "", source)
plot(r)