Skip to content

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

pine
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:

pine
x = if close > open
    close
else
    open

plot(x)

With else if:

pine
x = if open > close
    5
else if high > low
    close
else
    open

When the else block is omitted, the result is na (or false / "" for bool/string) when the condition is false:

pine
x = if close > open
    close
// x is na when close <= open

Returning tuples from if

Each branch must return a tuple of the same structure:

pine
[v1, v2] = if close > open
    [high, close]
else
    [close, low]

for Loop

Counting Form

pine
sum = 0.0
for i = 0 to 9
    sum += close[i]
averageClose = sum / 10

With a step:

pine
for i = 0 to 20 by 2
    // i = 0, 2, 4, 6, ..., 20

Reverse loop with negative step:

pine
for i = 10 to 0 by -1
    array.push(arr, i)
    // i = 10, 9, 8, ..., 0

Collection Iteration (for...in)

Iterate over arrays with value only, or with both index and value:

pine
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:

pine
// 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

pine
i = 0
sum = 0.0
while i < 10
    sum += close[i]
    i += 1

Returning a value from while

Like for, a while loop returns the last expression evaluated in its final iteration:

pine
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

  • break exits the loop immediately. The loop returns the value of the last expression evaluated before break.
  • continue skips the rest of the current iteration and proceeds to the next one.
pine
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:

pine
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 termination

switch

With Value

Match against a specific value:

pine
dayName = switch dayofweek
    dayofweek.monday    => "Mon"
    dayofweek.tuesday   => "Tue"
    dayofweek.wednesday => "Wed"
    dayofweek.thursday  => "Thu"
    dayofweek.friday    => "Fri"
    => "Weekend"
pine
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:

pine
direction = switch
    close > open => "up"
    close < open => "down"
    => "flat"  // Default

Returning tuples from switch

pine
[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

Released under the MIT License.