Expressions, declarations and statements
Expressions
An expression is a sequence where operators or function calls are
applied to operands (variables or values) to define the calculations and
actions required by the script. Expressions in Pine almost always
produce a result (exceptions are the functions study
, fill
,
strategy.entry
, etc., which produce side effects and will be covered
later).
Here are some examples of simple expressions:
Variable declaration
Variables in Pine are declared with the special symbol =
and an
optional var
keyword in one of the following ways:
<identifier>
is the name of the declared variable, see
Identifiers
.
<type>
can be one of the predefined keywords: float
, int
, bool
,
color
, string
, line
or label
. However, in most cases, an
explicit type declaration is redundant because type is automatically
inferred from the <expression>
on the right of the =
at compile
time, so the decision to use them is often a matter of preference. For
example:
In the first line of the example, the compiler cannot determine the type
of the baseLine0
variable because na
is a generic value of no
particular type. The declaration of the baseLine1
variable is correct
because its float
type is declared explicitly. The declaration of the
baseLine2
variable is also correct because its type can be derived
from the expression float(na)
, which is an explicit cast of na
value
to float
type. The declarations of baseLine1
and baseLine2
are
equivalent.
The var
keyword is a special modifier that instructs the compiler to
create and initialize the variable only once. This behavior is very
useful in cases where a variable’s value must persist through the
iterations of a script across successive bars. For example, suppose
we’d like to count the number of green bars on the chart:
Without the var
modifier, variable count
would be reset to zero
(thus losing it’s value) every time a new bar update triggered a script
recalculation.
In Pine v3 the study “Green Bars Count” could be written without using
the var
keyword:
The v4 code is more readable and can be more efficient if, for example,
the count
variable is initialized with an expensive function call
instead of 0
.
Examples of simple variable declarations:
Examples with type modifiers and var keyword:
Example, illustrating the effect of var
keyword:
Variable assignment
A mutable variable is a variable which can be given a new value. The
operator :=
must be used to give a new value to a variable. A variable
must be declared before you can assign a value to it (see declaration of
variables above).
The type of a variable is identified at declaration time. From then on, a variable can be given a value of expression only if both the expression and the variable belong to the same type, otherwise a compilation error will occur.
Variable assignment example:
if statement
An if
statement defines a block of statements to be executed when the
if
’s conditional expression evaluates to true
, and optionally, an
alternative block to be executed when the expression is false
.
General code form:
where:
var_declarationX
- this variable is assigned the value of theif
statement as a whole.condition
- if thecondition
expression is true, the logic from the then block immediately following theif
first line (var_decl_then0
,var_decl_then1
, etc.) is used, if thecondition
is false, the logic from the else block (var_decl_else0
,var_decl_else1
, etc.) is used.return_expression_then
,return_expression_else
- the last expression from the then block or from the else block will determine the final value of the wholeif
statement.
The type of the returning value of the if
statement is determined by
the type of return_expression_then
and return_expression_else
. Their
types must match. It is not possible to return an integer value from the
then block if the else block returns a string value.
Example:
It is possible to omit the else block. In this case, if the
condition
is false, an empty value (na
, false
, or ""
) will be
assigned to the var_declarationX
variable.
Example:
It is possible to use either multiple else if blocks or none at all.
Example:
The then, else if and else blocks are shifted by four spaces1.
if
statements can be nested by adding four more spaces:
It is possible and quite frequent to ignore the resulting value of an
if
statement (var_declarationX =
can be omited). This form is used
when you need the side effect of the expression, for example in
`strategy trading:
for statement
The for
statement allows to execute a number of instructions
repeatedly:
where:
i
- a loop counter variable.from
- start value of the counter.to
- end value of the counter. When the counter becomes greater thanto
(or less thanto
in the case wherefrom > to
) the loop is stopped.step
- loop step. Optional. Default is 1. Iffrom
is greater thanto
, the loop step will automatically change direction; no need to use a negative step.var_decl0
, …var_declN
,return_expression
- body of the loop. It must be indented by 4 spaces.return_expression
- returning value. When a loop is finished or broken, the returning value is assigned tovar_declarationX
.continue
- a keyword. Can only be used in loops. It jumps to the loop’s next iteration.break
- a keyword. Can be used only in loops. It exits the loop.
for
loop example:
Variable sum
is a
mutable variable
so a new value can be given to it by the operator :=
in the loop’s
body. Note that we recommend using the built-in
sma()
function for simple moving averages, as it calculates faster.
Note that some built-in functions may behave unexpectedly in for loop. Let’s look at the following example:
While you may expect that sum
will contain
rma(close, 1) + rma(close, 2)
, this is not so. It will contain
rma(close, 1) + rma(close, 1)
because once rma
is initialized with
length 1, this length is stored until the script is removed from chart.
To avoid this you may use your own, stateless function implementation.
This is the list of built-in functions which have the same behavior:
rma(source, length)
:length
is stateful.ema(source, length)
:length
is stateful.valuewhen(condition, source, occurrence)
:occurrence
is stateful.rsi(x, y)
: wheny
is of type integer and behaves like a length,y
is stateful.
Footnotes
-
TradingView’s Pine Editor automatically replaces Tab with 4 spaces. ↩