Control Structures
All control structures in Pine Script are expressions — they produce a value. The last expression evaluated in the executed branch or iteration is the returned value. This means if, for, while, and switch can all appear on the right-hand side of an assignment.
if / else if / else
if close > open
label.new(bar_index, high, "Bullish")
else if close < open
label.new(bar_index, low, "Bearish")
else
label.new(bar_index, close, "Doji")Returning a value from if
The last expression in each branch is the result. All branches must return the same type:
x = if close > open
close
else
open
plot(x)With else if:
x = if open > close
5
else if high > low
close
else
openWhen the else block is omitted, the result is na (or false / "" for bool/string) when the condition is false:
x = if close > open
close
// x is na when close <= openReturning tuples from if
Each branch must return a tuple of the same structure:
[v1, v2] = if close > open
[high, close]
else
[close, low]for Loop
Counting Form
sum = 0.0
for i = 0 to 9
sum += close[i]
averageClose = sum / 10With a step:
for i = 0 to 20 by 2
// i = 0, 2, 4, 6, ..., 20Reverse loop with negative step:
for i = 10 to 0 by -1
array.push(arr, i)
// i = 10, 9, 8, ..., 0Collection Iteration (for...in)
Iterate over arrays with value only, or with both index and value:
var prices = array.from(100.0, 200.0, 300.0)
// Value only
for value in prices
log.info(str.tostring(value))
// Index and value (destructured)
for [index, value] in prices
log.info(str.tostring(index) + ": " + str.tostring(value))Returning a value from for
A for loop returns the last expression evaluated in its final iteration. If no iterations execute, it returns na:
// Count how many OHLC values are greater than the SMA
array<float> ohlcValues = array.from(open, high, low, close)
qtyGreaterThan(value, array) =>
int result = 0
for currentElement in array
if currentElement > value
result += 1
result
plot(qtyGreaterThan(ta.sma(close, 20), ohlcValues))while Loop
i = 0
sum = 0.0
while i < 10
sum += close[i]
i += 1Returning a value from while
Like for, a while loop returns the last expression evaluated in its final iteration:
int i = 0
int result = while i < 10
i += 1
i * 2
// result is 20 (last iteration: i = 10, 10 * 2 = 20)break and continue
breakexits the loop immediately. The loop returns the value of the last expression evaluated beforebreak.continueskips the rest of the current iteration and proceeds to the next one.
for i = 0 to 99
if close[i] < 0
break // Exit the loop
if na(close[i])
continue // Skip this iteration
// process close[i]Using break and continue with loop return values:
string tempString = ""
string finalText = for number in randomArray
if number == 8
break // exit loop; returns last evaluated expression
else if number % 2 == 0
continue // skip even numbers
tempString := tempString + str.tostring(number) + ", "
// finalText holds the returned value after loop terminationswitch
With Value
Match against a specific value:
dayName = switch dayofweek
dayofweek.monday => "Mon"
dayofweek.tuesday => "Tue"
dayofweek.wednesday => "Wed"
dayofweek.thursday => "Thu"
dayofweek.friday => "Fri"
=> "Weekend"string i_maType = input.string("EMA", "MA type", options = ["EMA", "SMA", "RMA", "WMA"])
float ma = switch i_maType
"EMA" => ta.ema(close, 10)
"SMA" => ta.sma(close, 10)
"RMA" => ta.rma(close, 10)
=> ta.wma(close, 10)
plot(ma)Without Value (condition-based)
When no key expression is provided, each arm uses a boolean condition. The first matching arm executes:
direction = switch
close > open => "up"
close < open => "down"
=> "flat" // DefaultReturning tuples from switch
[v1, v2] = switch
close > open => [high, close]
=> [close, low]switch arms use => to separate the condition from the body. The default arm has no condition before =>.
Next Steps
- Functions & Methods — defining custom functions
- Custom Types & Enums — user-defined types