A script in Pine Script™ follows this general structure:
<version>
<declaration_statement>
<code>
Double slashes (//
) define comments in Pine Script™. Comments can begin anywhere on the line.
They can also follow Pine Script™ code on the same line:
//@version=5
indicator("")
// This line is a comment
a = close // This is also a comment
plot(a)
The Pine Script™ Editor has a keyboard shortcut to comment/uncomment lines: ctrl + /. You can use it on multiple lines by highlighting them first.
A compiler directive in the following form tells the compiler which of the versions of Pine Script™ the script is written in:
//@version=5
Notable changes to the current version of Pine Script™ are documented in the Release notes.
All Pine scripts must contain a declaration statement, which is a call to one of these functions:
The declaration statement:
Each type of script has distinct requirements:
strategy.*()
call, e.g.,
strategy.entry().Lines in a script that are not comments or compiler directives are statements, which implement the script’s algorithm. A statement can be one of these:
Statements can be arranged in multiple ways:
,
) as a separator.A simple valid Pine Script™ v5 indicator can be generated in the Pine Script™ Editor by using the “Open” button and choosing “New blank indicator”:
//@version=5
indicator("My Script")
plot(close)
This indicator includes three local blocks, one in the f()
function declaration,
and two in the variable declaration using an if structure:
//@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)
You can bring up a simple Pine Script™ v5 strategy by selecting “New blank strategy” instead:
//@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)
Long lines can be split on multiple lines, or “wrapped”. Wrapped lines must be indented with any number of spaces, provided it’s not a multiple of four (those boundaries are used to indent local blocks):
a = open + high + low + close
may be wrapped as:
a = open +
high +
low +
close
A long plot() call may be wrapped as:
plot(ta.correlation(src, ovr, length),
color = color.new(color.purple, 40),
style = plot.style_area,
trackprice = true)
Statements inside user-defined function declarations can also be wrapped. However, since a local block must syntactically begin with an indentation (4 spaces or 1 tab), when splitting it onto the following line, the continuation of the statement must start with more than one indentation (not equal to a multiple of four spaces). For example:
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)
You can use comments in wrapped lines:
//@version=5
indicator("")
c = open > close ? color.red :
high > high[1] ? color.lime : // A comment
low < low[1] ? color.blue : color.black
bgcolor(c)