转至 Pine Script™ 版本5
介绍
本指南记录了Pine Script™ 从 v4 到 v5 的变更。它将指导您将现有 Pine 脚本适配到 Pine Script™ v5。请参阅我们的 发行说明,了解Pine Script™ v5 中的新功能列表。
将旧脚本转换为 v5 所需的最常见修改包括:
- 将study()更改 为 indicator() (函数的签名未改变)。
- 重命名内置函数调用以包含其新的命名空间(例如, v4 中的highest() 变为 v5 中的ta.highest() )。
- 重组输入以使用更专业的
input.*()
功能。 transp
通过使用 color.new() 同时定义与参数一起使用的颜色和透明度, 消除了对弃用参数的使用color
。- 如果您在 v4 的
study()
resolution
中使用了和参数,则需要在 v5 的 indicator()中更改为和。resolution_gaps
timeframe
timeframe_gaps
v4 到 v5转换器
Pine 编辑器包含一个实用程序,可自动将 v4 脚本转换为 v5。要访问它,请打开//@version=4
其中的脚本,然后在编辑器窗格右上角的“更多”菜单中选择“转换为 v5”选项(三个点标识):
并非所有脚本都可以自动从 v4 转换为 v5。如果您想手动转换脚本,或者您的指标在转换后返回编译错误,请使用以下部分来确定如何完成转换。您可以在本 指南的常见脚本转换错误部分找到自动转换过程中可能遇到的一些错误及其修复方法的列表。
重命名函数和变量
为了清晰和一致,许多内置函数和变量在 v5 中被重命名。在新的命名空间中包含 v4 函数名称是大多数更改的原因。例如,
v4 中的sma()
函数被移动到ta.
v5 中的命名空间:
ta.sma()。无需记住新的命名空间;如果您在编辑器中键入不带命名空间的函数的旧名称并按下“自动完成”热键(Ctrl
+
Space
,或Cmd
在 MacOS 上),则会出现一个显示匹配建议的弹出窗口:
不计算移动到新命名空间的函数,只有两个函数被重命名了:
study()
现在是 indicator()。tickerid()
现在是 ticker.new()。
重命名函数和变量的完整列表可在本指南的所有变量、函数和参数名称更改部分中找到 。
重命名函数参数
更改了一些内置函数的参数名称以改进命名法。这对大多数脚本没有影响,但如果您在调用函数时使用这些参数名称,则需要进行调整。例如,我们已经标准化了所有提及的内容:
// Valid in v4. Not valid in v5.
timev4 = time(resolution = "1D")
// Valid in v5.
timev5 = time(timeframe = "1D")
// Valid in v4 and v5.
timeBoth = time("1D")
重命名函数参数的完整列表可在本指南的所有变量、函数和参数名称更改部分中找到 。
删除了 `rsi()`过载
在 v4 中, rsi() 函数有两种不同的重载:
rsi(series float, simple int)
用于常规 RSI 计算,以及rsi(series float, series float)
对于 MFI 指标中使用的过载,它执行了相当于 的计算100.0 - (100.0 / (1.0 + arg1 / arg2))
。
这导致单个内置函数的行为方式截然不同,而且很难区分具体应用了哪种函数,因为这取决于第二个参数的类型。因此,许多指标误用了该函数并显示了错误的结果。为了避免这种情况,在 v5 中移除了第二个重载。
v5 中的ta.rsi()函数
仅接受“简单 int”参数作为其length
参数。如果您的 v4 代码使用了现已弃用的带有第二个参数的函数重载,则可以用以下公式float
替换整个
调用,该公式等效于:rsi()
100.0 - (100.0 / (1.0 + arg1 / arg2))
请注意,当您的 v4 代码使用“系列 int”值作为
rsi()的第二个参数时,它会自动转换为“系列浮点数”,并且使用该函数的第二个重载。虽然这在语法上是正确的,但它很可能没有产生您预期的结果。在 v5 中,
ta.rsi()
要求将“简单 int”用作参数length
,这排除了动态(或“系列”)长度。原因是 RSI 计算使用 ta.rma
()移动平均线,它与ta.ema()
类似,
因为它依赖于使用前一个条形图的值的长度相关的递归过程。这使得无法通过可能因条形图而异的“系列”长度获得正确的结果。
如果您的 v4 代码使用的长度是“const int”、“input int”或“simple int”,则无需进行任何更改。
保留关键字
一些字是保留字,不能用作变量或函数名。它们是:catch
,class
,do
,ellipse
,in
,is
,
polygon
,range
,return
,,。如果您的 v4 指标使用其中任何一个,请重命名您的变量或函数struct
,以便脚本在 v5 中运行。text
throw
try
删除了 `iff()` 和`offset()`
iff () 和 offset() 函数已被删除。使用 iff() 函数的代码可以使用三元运算符重写:
// iff(<condition>, <return_when_true>, <return_when_false>)
// Valid in v4, not valid in v5
barColorIff = iff(close >= open, color.green, color.red)
// <condition> ? <return_when_true> : <return_when_false>
// Valid in v4 and v5
barColorTernary = close >= open ? color.green : color.red
请注意,三元运算符是“惰性”求值的;仅计算所需值(取决于条件对true
或 的求值)。这与iff()false
不同
,后者始终求两个值,但仅返回相关值。
有些函数需要对每个条进行评估才能正确计算,因此您需要在三元运算之前对它们进行预先评估,从而为这些函数做出特殊准备:
// `iff()` in v4: `highest()` and `lowest()` are calculated on every bar
v1 = iff(close > open, highest(10), lowest(10))
plot(v1)
// In v5: forced evaluation on every bar prior to the ternary statement.
h1 = ta.highest(10)
l1 = ta.lowest(10)
v1 = close > open ? h1 : l1
plot(v1)
offset () 函数已被弃用,因为更易读的 [] 运算符等效于:
// Valid in v4. Not valid in v5.
prevClosev4 = offset(close, 1)
// Valid in v4 and v5.
prevClosev5 = close[1]
将“input()”拆分为几个函数
v4
input()
函数因过多的重载和参数而变得拥挤不堪。我们将其功能拆分为不同的函数以清理空间并提供更强大的结构来容纳计划的输入添加。每个新函数都使用
它所替换的input.*
v4 调用类型的名称input()
。例如,现在有一个专门的
input.float()
函数替换了 v4input(1.0, type = input.float)
调用。请注意,您仍然可以input(1.0)
在 v5 中使用它,但由于只有
input.float()
允许诸如minval
、maxval
等参数,因此它更强大。另请注意,
input.int()
是唯一不使用其等效 v4input.integer
名称的专门输入函数。input.*
常量已被删除,因为它们被用作参数的参数type
,而该参数已被弃用。
例如,要使用类型输入进行转换 v4 脚本
input.symbol
,
必须在 v5 中使用input.symbol()函数:
// Valid in v4. Not valid in v5.
aaplTicker = input("AAPL", type = input.symbol)
// Valid in v5
aaplTicker = input.symbol("AAPL")
input
()
函数在 v5 中仍然存在,但形式更简单,参数更少。它的优点是可以从使用的参数中自动检测输入类型“bool/color/int/float/string/source”
defval
:
// Valid in v4 and v5.
// While "AAPL" is a valid symbol, it is only a string here because `input.symbol()` is not used.
tickerString = input("AAPL", title = "Ticker string")
一些函数参数现在需要内置参数
在 v4 中,内置常量(例如plot.style_area
在调用 Pine Script™ 函数时用作参数的)对应于特定类型的预定义值。例如,的值为barmerge.lookahead_on
,因此在
security()true
函数调用中向参数提供参数时,可以使用true
而不是命名常量
。我们发现这是一个常见的混淆源,导致毫无戒心的程序员编写出产生意外结果的代码。lookahead
在 v5 中,必须使用正确的内置命名常量作为需要它们的函数参数的参数:
// Not valid in v5: `true` is used as an argument for `lookahead`.
request.security(syminfo.tickerid, "1D", close, lookahead = true)
// Valid in v5: uses a named constant instead of `true`.
request.security(syminfo.tickerid, "1D", close, lookahead = barmerge.lookahead_on)
// Would compile in v4 because `plot.style_columns` was equal to 5.
// Won't compile in v5.
a = 2 * plot.style_columns
plot(a)
要将脚本从 v4 转换为 v5,请确保使用正确命名的内置常量作为函数参数。
弃用“transp”参数
transp=
许多 v4 绘图函数签名中使用的参数已被弃用,因为它会干扰 RGB 功能。现在必须将透明度与颜色一起指定为诸如 、 等参数的参数。在color
这些textcolor
情况
下,需要使用color.new()
或
color.rgb()
函数来连接颜色及其透明度。
请注意,在 v4 中,
bgcolor()
和
fill()
函数有一个可选transp
参数,其使用默认值 90。这意味着下面的代码可以显示布林带,两个带之间使用半透明填充,带与价格交叉处使用半透明背景颜色,即使transp
在其
bgcolor()
和
fill()
调用中没有为参数使用任何参数:
//@version=4
study("Bollinger Bands", overlay = true)
[middle, upper, lower] = bb(close, 5, 4)
plot(middle, color=color.blue)
p1PlotID = plot(upper, color=color.green)
p2PlotID = plot(lower, color=color.green)
crossUp = crossover(high, upper)
crossDn = crossunder(low, lower)
// Both `fill()` and `bgcolor()` have a default `transp` of 90
fill(p1PlotID, p2PlotID, color = color.green)
bgcolor(crossUp ? color.green : crossDn ? color.red : na)
在 v5 中,我们需要明确提及颜色的 90 透明度,结果:
//@version=5
indicator("Bollinger Bands", overlay = true)
[middle, upper, lower] = ta.bb(close, 5, 4)
plot(middle, color=color.blue)
p1PlotID = plot(upper, color=color.green)
p2PlotID = plot(lower, color=color.green)
crossUp = ta.crossover(high, upper)
crossDn = ta.crossunder(low, lower)
var TRANSP = 90
// We use `color.new()` to explicitly pass transparency to both functions
fill(p1PlotID, p2PlotID, color = color.new(color.green, TRANSP))
bgcolor(crossUp ? color.new(color.green, TRANSP) : crossDn ? color.new(color.red, TRANSP) : na)
更改了 `time()` 和`time_close()`的默认会话天数
time()
和
time_close()session
函数中使用的字符串
的默认天数集,以及input.session()
返回的
天数集已从(星期一至星期五)更改为(星期日至星期六):"23456"
"1234567"
// On symbols that are traded during weekends, this will behave differently in v4 and v5.
t0 = time("1D", "1000-1200")
// v5 equivalent of the behavior of `t0` in v4.
t1 = time("1D", "1000-1200:23456")
// v5 equivalent of the behavior of `t0` in v5.
t2 = time("1D", "1000-1200:1234567")
这种行为变化不会对周末休市的传统市场运行的脚本产生太大影响。如果确保您的会话定义在 v5 代码中保留其 v4 行为对您来说很重要,请将其添加":23456"
到您的会话字符串中。有关更多信息,请参阅本手册的“会话”页面。
`strategy.exit()` 现在必须做一些事情
允许
strategy.exit()函数闲置的日子已经一去不复返了。现在它必须通过使用以下至少一个参数对策略产生实际影响:、、、,或以下一对参数:与或结合使用。当使用不满足这些标准的strategy.exit()在将
策略profit
转换为
v5时触发
错误limit
时
,您可以安全地删除这些行,因为它们在您的代码中没有任何作用。loss
stop
trail_offset
trail_price
trail_points
常见的脚本转换错误
‘plot’/‘hline’调用中的参数‘style’/‘linestyle’无效
为了使其正常工作,您需要将
plot()
和
hline()中
使用的“int”style
参数更改
为内置常量:linestyle
// Will cause an error during conversion
plotStyle = input(1)
hlineStyle = input(1)
plot(close, style = plotStyle)
hline(100, linestyle = hlineStyle)
// Will work in v5
//@version=5
indicator("")
plotStyleInput = input.string("Line", options = ["Line", "Stepline", "Histogram", "Cross", "Area", "Columns", "Circles"])
hlineStyleInput = input.string("Solid", options = ["Solid", "Dashed", "Dotted"])
plotStyle = plotStyleInput == "Line" ? plot.style_line :
plotStyleInput == "Stepline" ? plot.style_stepline :
plotStyleInput == "Histogram" ? plot.style_histogram :
plotStyleInput == "Cross" ? plot.style_cross :
plotStyleInput == "Area" ? plot.style_area :
plotStyleInput == "Columns" ? plot.style_columns :
plot.style_circles
hlineStyle = hlineStyleInput == "Solid" ? hline.style_solid :
hlineStyleInput == "Dashed" ? hline.style_dashed :
hline.style_dotted
plot(close, style = plotStyle)
hline(100, linestyle = hlineStyle)
有关更多信息,请参阅 本指南的某些函数参数现在需要内置参数部分。
未声明的标识符‘input.%input_name%’
要解决此问题,请input.*
从代码中删除常量:
// Will cause an error during conversion
_integer = input.integer
_bool = input.bool
i1 = input(1, "Integer", _integer)
i2 = input(true, "Boolean", _bool)
// Will work in v5
i1 = input.int(1, "Integer")
i2 = input.bool(true, "Boolean")
有关更多信息,请参阅用户手册的输入页面和 本指南的某些函数参数现在需要内置参数部分。
‘strategy.close’调用中的参数‘when’无效
这是由于strategy.entry() 和 strategy.close()之间的混淆造成的 。
strategies.close()的第二个参数
是when
,它需要一个“bool”参数。在 v4 中,允许使用strategy.long
参数,因为它是一个“bool”。但是,在 v5 中,必须使用命名内置常量作为参数,因此
strategy.long
不再允许将其作为参数的参数when
。
此代码中的调用strategy.close("Short", strategy.long)
相当于strategy.close("Short")
,这是在 v5 中必须使用的:
// Will cause an error during conversion
if (longCondition)
strategy.close("Short", strategy.long)
strategy.entry("Long", strategy.long)
// Will work in v5:
if (longCondition)
strategy.close("Short")
strategy.entry("Long", strategy.long)
有关更多信息,请参阅 本指南的某些函数参数现在需要内置参数部分。
无法使用参数“minval”=“%value%”调用“input.int”。使用了“literal float”类型的参数,但预期为“const int”
minval
在 v4 中,当输入“int”值时,可以传递“float”参数。这在 v5 中不再可能;“int”输入需要“int”值:
// Works in v4, will break on conversion because minval is a 'float' value
int_input = input(1, "Integer", input.integer, minval = 1.0)
// Works in v5
int_input = input.int(1, "Integer", minval = 1)
有关更多信息,请参阅用户手册的输入页面和 本指南的某些函数参数现在需要内置参数部分。
所有变量、函数和参数名称均发生更改
删除了函数和变量
v4 | v5 |
---|---|
input.bool 输入 | 取而代之input.bool() |
input.color 输入 | 取而代之input.color() |
input.float 输入 | 取而代之input.float() |
input.integer 输入 | 取而代之input.int() |
input.resolution 输入 | 取而代之input.timeframe() |
input.session 输入 | 取而代之input.session() |
input.source 输入 | 取而代之input.source() |
input.string 输入 | 取而代之input.string() |
input.symbol 输入 | 取而代之input.symbol() |
input.time 输入 | 取而代之input.time() |
iff() | 改用?: 运算符 |
offset() | 改用[] 运算符 |
重命名函数和参数
无命名空间更改
v4 | v5 |
---|---|
study(<...>, resolution, resolution_gaps, <...>) | indicator(<...>, timeframe, timeframe_gaps, <...>) |
strategy.entry(long) | strategy.entry(direction) |
strategy.order(long) | strategy.order(direction) |
time(resolution) | time(timeframe) |
time_close(resolution) | time_close(timeframe) |
nz(x, y) | nz(source, replacement) |
技术分析函数和变量的“ta”命名空间
指标函数和变量
v4 | v5 |
---|---|
accdist | ta.accdist |
alma() | ta.alma() |
atr() | ta.atr() |
bb() | ta.bb() |
bbw() | ta.bbw() |
cci() | ta.cci() |
cmo() | ta.cmo() |
cog() | ta.cog() |
dmi() | ta.dmi() |
ema() | ta.ema() |
hma() | ta.hma() |
iii | ta.iii |
kc() | ta.kc() |
kcw() | ta.kcw() |
linreg() | ta.linreg() |
macd() | ta.macd() |
mfi() | ta.mfi() |
mom() | ta.mom() |
nvi | ta.nvi |
obv | ta.obv |
pvi | ta.pvi |
pvt | ta.pvt |
rma() | ta.rma() |
roc() | ta.roc() |
rsi(x, y) | ta.rsi(source, length) |
sar() | ta.sar() |
sma() | ta.sma() |
stoch() | ta.stoch() |
supertrend() | ta.supertrend() |
swma(x) | ta.swma(source) |
tr | ta.tr |
tr() | ta.tr() |
tsi() | ta.tsi() |
vwap | ta.vwap |
vwap(x) | ta.vwap(source) |
vwma() | ta.vwma() |
wad | ta.wad |
wma() | ta.wma() |
wpr() | ta.wpr() |
wvad | ta.wvad |
支持功能
v4 | v5 |
---|---|
barsince() | ta.barsince() |
change() | ta.change() |
correlation(source_a, source_b, length) | ta.correlation(source1, source2, length) |
cross(x, y) | ta.cross(source1, source2) |
crossover(x, y) | ta.crossover(source1, source2) |
crossunder(x, y) | ta.crossunder(source1, source2) |
cum(x) | ta.cum(source) |
dev() | ta.dev() |
falling() | ta.falling() |
highest() | ta.highest() |
highestbars() | ta.highestbars() |
lowest() | ta.lowest() |
lowestbars() | ta.lowestbars() |
median() | ta.median() |
mode() | ta.mode() |
percentile_linear_interpolation() | ta.percentile_linear_interpolation() |
percentile_nearest_rank() | ta.percentile_nearest_rank() |
percentrank() | ta.percentrank() |
pivothigh() | ta.pivothigh() |
pivotlow() | ta.pivotlow() |
range() | ta.range() |
rising() | ta.rising() |
stdev() | ta.stdev() |
valuewhen() | ta.valuewhen() |
variance() | ta.variance() |
与数学相关的函数和变量的“math”命名空间
v4 | v5 |
---|---|
abs(x) | math.abs(number) |
acos(x) | math.acos(number) |
asin(x) | math.asin(number) |
atan(x) | math.atan(number) |
avg() | math.avg() |
ceil(x) | math.ceil(number) |
cos(x) | math.cos(angle) |
exp(x) | math.exp(number) |
floor(x) | math.floor(number) |
log(x) | math.log(number) |
log10(x) | math.log10(number) |
max() | math.max() |
min() | math.min() |
pow() | math.pow() |
random() | math.random() |
round(x, precision) | math.round(number, precision) |
round_to_mintick(x) | math.round_to_mintick(number) |
sign(x) | math.sign(number) |
sin(x) | math.sin(angle) |
sqrt(x) | math.sqrt(number) |
sum() | math.sum() |
tan(x) | math.tan(angle) |
todegrees() | math.todegrees() |
toradians() | math.toradians() |
请求外部数据的函数的“request”命名空间
v4 | v5 |
---|---|
financial() | request.financial() |
quandl() | request.quandl() |
security(<...>, resolution, <...>) | request.security(<...>, timeframe, <...>) |
splits() | request.splits() |
dividends() | request.dividends() |
earnings() | request.earnings() |
”ticker” 命名空间,用于帮助创建代码的函数
v4 | v5 |
---|---|
heikinashi() | ticker.heikinashi() |
kagi() | ticker.kagi() |
linebreak() | ticker.linebreak() |
pointfigure() | ticker.pointfigure() |
renko() | ticker.renko() |
tickerid() | ticker.new() |
操作字符串的函数的命名空间“str”
v4 | v5 |
---|---|
tostring(x, y) | str.tostring(value, format) |
tonumber(x) | str.tonumber(string) |