To Pine Script™ version 5
Introduction
This guide documents the changes made to Pine Script™ from v4 to v5. It will guide you in the adaptation of existing Pine scripts to Pine Script™ v5. See our Release notes for a list of the new features in Pine Script™ v5.
The most frequent adaptations required to convert older scripts to v5 are:
- Changing study() for indicator() (the function’s signature has not changed).
- Renaming built-in function calls to include their new namespace (e.g., highest() in v4 becomes ta.highest() in v5).
- Restructuring inputs to use the more specialized
input.*()
functions. - Eliminating uses of the deprecated
transp
parameter by using color.new() to simultaneously define color and transparency for use with thecolor
parameter. - If you used the
resolution
andresolution_gaps
parameters in v4’s study(), they will require changing totimeframe
andtimeframe_gaps
in v5’s indicator().
v4 to v5 converter
The Pine Editor includes a utility to automatically convert v4 scripts
to v5. To access it, open a script with //@version=4
in it and select
the “Convert to v5” option in the “More” menu identified by three
dots at the top-right of the Editor’s pane:
Not all scripts can be automatically converted from v4 to v5. If you want to convert the script manually or if your indicator returns a compilation error after conversion, use the following sections to determine how to complete the conversion. A list of some errors you can encounter during the automatic conversion and how to fix them can be found in the Common script conversion errors section of this guide.
Renamed functions and variables
For clarity and consistency, many built-in functions and variables were
renamed in v5. The inclusion of v4 function names in a new namespace is
the cause of most changes. For example, the
sma()
function in v4 is moved to the ta.
namespace in v5:
ta.sma().
Remembering the new namespaces is not necessary; if you type the older
name of a function without its namespace in the Editor and press the
‘Auto-complete’ hotkey (Ctrl
+
Space
, or Cmd
on MacOS), a popup
showing matching suggestions appears:
Not counting functions moved to new namespaces, only two functions have been renamed:
study()
is now indicator().tickerid()
is now ticker.new().
The full list of renamed functions and variables can be found in the All variable, function, and parameter name changes section of this guide.
Renamed function parameters
The parameter names of some built-in functions were changed to improve the nomenclature. This has no bearing on most scripts, but if you used these parameter names when calling functions, they will require adaptation. For example, we have standardized all mentions:
The full list of renamed function parameters can be found in the All variable, function, and parameter name changes section of this guide.
Removed an `rsi()` overload
In v4, the rsi() function had two different overloads:
rsi(series float, simple int)
for the normal RSI calculation, andrsi(series float, series float)
for an overload used in the MFI indicator, which did a calculation equivalent to100.0 - (100.0 / (1.0 + arg1 / arg2))
.
This caused a single built-in function to behave in two very different ways, and it was difficult to distinguish which one applied because it depended on the type of the second argument. As a result, a number of indicators misused the function and were displaying incorrect results. To avoid this, the second overload was removed in v5.
The
ta.rsi()
function in v5 only accepts a “simple int” argument for its length
parameter. If your v4 code used the now deprecated overload of the
function with a float
second argument, you can replace the whole
rsi()
call with the following formula, which is equivalent:
Note that when your v4 code used a “series int” value as the second
argument to
rsi(),
it was automatically cast to “series float” and the second overload of
the function was used. While this was syntactically correct, it most
probably did not yield the result you expected. In v5,
ta.rsi()
requires a “simple int” for the argument to length
, which precludes
dynamic (or “series”) lengths. The reason for this is that RSI
calculations use the
ta.rma()
moving average, which is similar to
ta.ema()
in that it relies on a length-dependent recursive process using the
values of previous bars. This makes it impossible to achieve correct
results with a “series” length that could vary bar to bar.
If your v4 code used a length that was “const int”, “input int” or “simple int”, no changes are required.
Reserved keywords
A number of words are reserved and cannot be used for variable or
function names. They are: catch
, class
, do
, ellipse
, in
, is
,
polygon
, range
, return
, struct
, text
, throw
, try
. If your
v4 indicator uses any of these, rename your variable or function for the
script to work in v5.
Removed `iff()` and `offset()`
The iff() and offset() functions have been removed. Code using the iff() function can be rewritten using the ternary operator:
Note that the ternary operator is evaluated “lazily”; only the
required value is calculated (depending on the condition’s evaluation
to true
or false
). This is different from
iff(),
which always evaluated both values but returned only the relevant one.
Some functions require evaluation on every bar to correctly calculate, so you will need to make special provisions for these by pre-evaluating them before the ternary:
The offset() function was deprecated because the more readable [] operator is equivalent:
Split of `input()` into several functions
The v4
input()
function was becoming crowded with a plethora of overloads and
parameters. We split its functionality into different functions to clear
that space and provide a more robust structure to accommodate the
additions planned for inputs. Each new function uses the name of the
input.*
type of the v4 input()
call it replaces. E.g., there is now
a specialized
input.float()
function replacing the v4 input(1.0, type = input.float)
call. Note
that you can still use input(1.0)
in v5, but because only
input.float()
allows for parameters such as minval
, maxval
, etc., it is more
powerful. Also note that
input.int()
is the only specialized input function that does not use its equivalent
v4 input.integer
name. The input.*
constants have been removed
because they were used as arguments for the type
parameter, which was
deprecated.
To convert, for example, a v4 script using an input of type
input.symbol
, the
input.symbol()
function must be used in v5:
The
input()
function persists in v5, but in a simpler form, with less parameters. It
has the advantage of automatically detecting input types
“bool/color/int/float/string/source” from the argument used for
defval
:
Some function parameters now require built-in arguments
In v4, built-in constants such as plot.style_area
used as arguments
when calling Pine Script™ functions corresponded to pre-defined values
of a specific type. For example, the value of barmerge.lookahead_on
was true
, so you could use true
instead of the named constant when
supplying an argument to the lookahead
parameter in a
security()
function call. We found this to be a common source of confusion, which
caused unsuspecting programmers to produce code yielding unintended
results.
In v5, the use of correct built-in named constants as arguments to function parameters requiring them is mandatory:
To convert your script from v4 to v5, make sure you use the correct named built-in constants as function arguments.
Deprecated the `transp` parameter
The transp=
parameter used in the signature of many v4 plotting
functions was deprecated because it interfered with RGB functionality.
Transparency must now be specified along with the color as an argument
to parameters such as color
, textcolor
, etc. The
color.new()
or
color.rgb()
functions will be needed in those cases to join a color and its
transparency.
Note that in v4, the
bgcolor()
and
fill()
functions had an optional transp
parameter that used a default value
of 90. This meant that the code below could display Bollinger Bands with
a semi-transparent fill between two bands and a semi-transparent
backround color where bands cross price, even though no argument is used
for the transp
parameter in its
bgcolor()
and
fill()
calls:
In v5 we need to explictly mention the 90 transparency with the color, yielding:
Changed the default session days for `time()` and `time_close()`
The default set of days for session
strings used in the
time()
and
time_close()
functions, and returned by
input.session(),
has changed from "23456"
(Monday to Friday) to "1234567"
(Sunday to
Saturday):
This change in behavior should not have much impact on scripts running
on conventional markets that are closed during weekends. If it is
important for you to ensure your session definitions preserve their v4
behavior in v5 code, add ":23456"
to your session strings. See this
manual’s page on Sessions for more information.
`strategy.exit()` now must do something
Gone are the days when the
strategy.exit()
function was allowed to loiter. Now it must actually have an effect on
the strategy by using at least one of the following parameters:
profit
, limit
, loss
, stop
, or one of the following pairs:
trail_offset
combined with either trail_price
or trail_points
.
When uses of
strategy.exit()
not meeting these criteria trigger an error while converting a strategy
to v5, you can safely eliminate these lines, as they didn’t do anything
in your code anyway.
Common script conversion errors
Invalid argument ‘style’/‘linestyle’ in ‘plot’/‘hline’ call
To make this work, you need to change the “int” arguments used for the
style
and linestyle
arguments in
plot()
and
hline()
for built-in constants:
See the Some function parameters now require built-in arguments section of this guide for more information.
Undeclared identifier ‘input.%input_name%’
To fix this issue, remove the input.*
constants from your code:
See the User Manual’s page on Inputs, and the Some function parameters now require built-in arguments section of this guide for more information.
Invalid argument ‘when’ in ‘strategy.close’ call
This is caused by a confusion between strategy.entry() and strategy.close().
The second parameter of
strategy.close()
is when
, which expects a “bool” argument. In v4, it was allowed to
use strategy.long
an argument because it was a “bool”. With v5,
however, named built-in constants must be used as arguments, so
strategy.long
is no longer allowed as an argument to the when
parameter.
The strategy.close("Short", strategy.long)
call in this code is
equivalent to strategy.close("Short")
, which is what must be used in
v5:
See the Some function parameters now require built-in arguments section of this guide for more information.
Cannot call ‘input.int’ with argument ‘minval’=‘%value%‘. An argument of ‘literal float’ type was used but a ‘const int’ is expected
In v4, it was possible to pass a “float” argument to minval
when an
“int” value was being input. This is no longer possible in v5; “int”
values are required for “int” inputs:
See the User Manual’s page on Inputs, and the Some function parameters now require built-in arguments section of this guide for more information.
All variable, function, and parameter name changes
Removed functions and variables
v4 | v5 |
---|---|
input.bool input | Replaced by input.bool() |
input.color input | Replaced by input.color() |
input.float input | Replaced by input.float() |
input.integer input | Replaced by input.int() |
input.resolution input | Replaced by input.timeframe() |
input.session input | Replaced by input.session() |
input.source input | Replaced by input.source() |
input.string input | Replaced by input.string() |
input.symbol input | Replaced by input.symbol() |
input.time input | Replaced by input.time() |
iff() | Use the ?: operator instead |
offset() | Use the [] operator instead |
Renamed functions and parameters
No namespace change
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” namespace for technical analysis functions and variables
Indicator functions and variables
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 |
Supporting functions
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” namespace for math-related functions and variables
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” namespace for functions that request external data
v4 | v5 |
---|---|
financial() | request.financial() |
quandl() | request.quandl() |
security(<...>, resolution, <...>) | request.security(<...>, timeframe, <...>) |
splits() | request.splits() |
dividends() | request.dividends() |
earnings() | request.earnings() |
”ticker” namespace for functions that help create tickers
v4 | v5 |
---|---|
heikinashi() | ticker.heikinashi() |
kagi() | ticker.kagi() |
linebreak() | ticker.linebreak() |
pointfigure() | ticker.pointfigure() |
renko() | ticker.renko() |
tickerid() | ticker.new() |
”str” namespace for functions that manipulate strings
v4 | v5 |
---|---|
tostring(x, y) | str.tostring(value, format) |
tonumber(x) | str.tonumber(string) |