Edgoro
Indicator · Language features

Pine Script for and while loops: examples and limits

for and while loops in Pine Script v6: a lookback search with break, a while loop, counting down, the time limit, and when a built-in or var does it better.

Short answer

for i = 1 to n repeats a block with i going from 1 to n inclusive, for x in myArray walks through an array, and while condition repeats while the condition is true; break leaves the loop and continue skips to the next pass. Use a loop only when no ta.* built-in or var accumulator does the job, because the loop runs again on every bar.

The script

A search back through history that a built-in can't do (how many bars since a higher high), a while loop, and the same count kept by a var counter. Paste it into a new indicator in the Pine Editor, then save and add it to the chart.

Pine Script v6
//@version=6
indicator("How many bars since a higher high", overlay = false)

maxBack = input.int(300, "Search at most N bars back", minval = 10, maxval = 2000)

// for + break: walk back until a bar's high exceeds this bar's high
int barsBack = na
for i = 1 to maxBack
    if high[i] > high
        barsBack := i
        break
// The loop reads high up to 2000 bars back: keep that much history from the start
max_bars_back(high, 2000)

// while: count the closes in a row that were higher than the one before
int streak = 0
while streak < maxBack and close[streak] > close[streak + 1]
    streak += 1

// The same streak without a loop: a var counter updated once per bar
var int streakVar = 0
streakVar := close > close[1] ? streakVar + 1 : 0

plot(nz(barsBack, maxBack), "Bars since a higher high", na(barsBack) ? color.orange : color.gray, style = plot.style_columns)
plot(streak, "Higher closes in a row (while)", color.teal)
plot(streakVar, "Higher closes in a row (var)", color.blue, display = display.data_window)

How it works

  • for i = 1 to maxBack runs with i = 1, 2, … maxBack: both ends are included. Inside, high[i] is the high i bars ago.
  • break stops at the first older bar with a higher high, so on most bars the loop only runs a few passes. When no higher high exists within maxBack bars, barsBack stays na and the column is orange: this bar's high is the highest of the whole window.
  • Why a loop here. ta.highestbars() needs a fixed window; "how far back until something higher" has no fixed window, so a search loop is the natural tool.
  • max_bars_back(high, 2000) tells Pine to keep 2,000 bars of high history from the start, because the offset i changes at run time. The max_bars_back example covers this in detail.
  • while checks its condition before each pass: here it stops at the first close that isn't higher than the one before it, or at maxBack. The cap makes sure the loop ends.
  • streakVar gets the same number with one line per bar and no loop: the counter adds 1 on a higher close and drops to 0 otherwise. Prefer this form whenever the answer for this bar can be built from the previous bar's answer.

Pitfalls

  • Loops that take too long. A loop runs again on every bar, so nested loops over hundreds of past bars add up quickly and the script stops with Loop is too long (> 500 ms). Cap the number of passes, break early, or replace the loop with a built-in or a var counter.
  • Counting down by accident. When the end is below the start, Pine counts down: for i = 0 to n - 1 with n = 0 runs for i = 0 and i = -1. On an empty array that's an Index is out of bounds error. Check n > 0 first, or loop with for x in array.
  • ta. calls inside the loop.* ta.sma(close, i) inside a loop is called a different number of times and with different lengths from bar to bar, so its history is wrong, and TradingView warns should be called on each calculation. Calculate built-ins before the loop, or do the arithmetic yourself inside it.
  • Offsets beyond the history buffer. close[i] with an i that only gets large after the script has loaded can fail on live bars with historical offset beyond the buffer limit. Size the buffer with max_bars_back().
  • Variables declared inside the loop. A variable declared inside the loop body doesn't exist after it (Undeclared identifier). Declare it before the loop and update it with := inside.

Variations

A weighted average written as a loop. The loop below reproduces ta.wma(), so the two lines overlap; change the weight formula (w) to build an average that has no built-in:

//@version=6
indicator("Custom weighted average (loop)", overlay = true)
len = input.int(20, "Length", minval = 2, maxval = 200)
// Weights len, len - 1, ..., 1: the newest bar weighs most, as in ta.wma()
float num = 0.0
float den = 0.0
for i = 0 to len - 1
    float w = len - i
    num += close[i] * w
    den += w
plot(num / den, "Loop average", color.orange, 2)
plot(ta.wma(close, len), "ta.wma()", color.blue)

Steps and skipping. for i = 0 to 20 by 5 takes i = 0, 5, 10, 15, 20. Inside any loop, continue jumps to the next pass, for example to skip bars with no volume: if volume[i] == 0 then continue. Walking through an array with for x in a is shown in the arrays example.

Questions

Does a Pine Script for loop include the last number?

Yes. for i = 1 to 5 runs five times, with i = 1, 2, 3, 4 and 5. That's why loops over an array run to size() - 1, and why they need a size check first.

How do I loop backwards in Pine Script?

Write the larger number first: for i = 10 to 0 counts down from 10 to 0, because Pine counts down whenever the end is below the start. Looping backwards is also the safe way to remove array elements during the loop.

Why does my loop make the script slow or stop?

The whole loop runs on every bar of the chart, and on every live update. A loop of 1,000 passes on 20,000 bars is 20 million passes. Use built-ins, break early, cap the passes, or carry results from bar to bar with var.

Every script on this page was checked with Edgoro Pine Check (Pine Script v6 rules). Pine Check is a static checker, not TradingView's compiler: TradingView compiles the script when you save it in the Pine Editor. The scripts are examples to learn from, not trading systems. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.

Need a different version of this script?

Describe the change in plain English and Edgoro writes the Pine Script v6 for you, checked with Pine Check. For example:

“For each bar, count how many bars back you have to go to find a higher high, and highlight bars where none exists in the last 500 bars.”