Pine Script for Loop: Syntax, Lookbacks, and Array Iteration
March 17, 2026
Pine Script's for loop is the primary tool for performing lookback calculations, iterating over arrays, and implementing custom indicators that built-in functions can't express. The syntax is different from Bash or Python, there are a few gotchas (the end value is inclusive, you can't break out early), and performance limits apply. This guide covers everything you need to write effective for loops in Pine Script.
1. Basic For Loop Syntax
//@version=5
indicator("For Loop Demo", overlay=false)
// Basic: for i = start to end (end value is INCLUSIVE)
// This loops i = 0, 1, 2, 3, 4 (5 iterations)
sumVal = 0.0
for i = 0 to 4
sumVal += close[i] // close[0]=current, close[1]=1 bar ago, etc.
plot(sumVal / 5, "5-bar sum / 5")
// With step parameter: by step (default step is 1)
evenSum = 0.0
for i = 0 to 10 by 2 // i = 0, 2, 4, 6, 8, 10
evenSum += i
// evenSum = 30
// Countdown
for i = 9 to 0 by -1 // i = 9, 8, 7, ..., 0
// process i
2. The Inclusive End Gotcha
In most languages, for i = 0 to N runs N iterations (0 through N-1). In Pine Script, the end is inclusive — for i = 0 to 9 runs 10 iterations (0 through 9). This is the most common source of off-by-one errors:
length = 14
// WRONG: loops 15 times (0 to 14 inclusive)
for i = 0 to length
// processes bar_index 0..14 — one too many
// CORRECT: loops 14 times (0 to 13 inclusive)
for i = 0 to length - 1
// processes bar_index 0..13
// Manual moving average example (correct)
total = 0.0
for i = 0 to length - 1
total += close[i]
myMA = total / length
plot(myMA)
3. Lookback Calculations (Most Common Use Case)
//@version=5
indicator("Custom Lookback", overlay=false)
length = input.int(20, "Length", minval=1)
// Find highest high over last N bars (equivalent to ta.highest)
highestHigh = high
for i = 1 to length - 1
if high[i] > highestHigh
highestHigh := high[i]
// Find how many bars ago price was above a threshold
barsAbove = 0
threshold = ta.sma(close, 50)
for i = 0 to length - 1
if close[i] > threshold
barsAbove += 1
// Calculate a weighted average (more weight to recent bars)
weightedSum = 0.0
weightTotal = 0.0
for i = 0 to length - 1
weight = length - i // recent bars get higher weight
weightedSum += close[i] * weight
weightTotal += weight
wma = weightedSum / weightTotal
plot(wma, "WMA")
4. Iterating Arrays
//@version=5
indicator("Array Iteration")
// Build an array of the last 5 closing prices
prices = array.new_float(5)
for i = 0 to 4
array.set(prices, i, close[i])
// Traditional index-based iteration
total = 0.0
for i = 0 to array.size(prices) - 1
total += array.get(prices, i)
avgPrice = total / array.size(prices)
// Pine Script v5: for-in syntax (cleaner)
levels = array.from(support1, support2, resistance1, resistance2)
for level in levels
hline(level, color=color.gray, linestyle=hline.style_dashed)
// for-in with index
for [idx, val] in levels
label.new(bar_index, val, str.tostring(idx), style=label.style_label_left)
5. The "Loop Too Long" Error and How to Avoid It
Pine Script limits loop execution time. Loops that process too many bars or iterations produce: "Script could not be translated from: Loop is too long (~500ms)".
Three fixes:
// Fix 1: Use built-in functions instead of manual loops
// SLOW: manual loop for highest high
highestHigh = high
for i = 1 to 499
if high[i] > highestHigh
highestHigh := high[i]
// FAST: built-in — Pine computes this natively
highestHigh = ta.highest(high, 500)
// Fix 2: Limit the range dynamically
maxLookback = math.min(bar_index, 100) // don't look back further than bars available
for i = 0 to maxLookback - 1
// process
// Fix 3: Restructure — accumulate instead of looking back
// BAD: O(N²) — scans history on every bar
// GOOD: running sum — O(N) total
runningSum = 0.0
if bar_index >= length - 1
for i = 0 to length - 1
runningSum += close[i] // same result but limit to when data is available
6. for vs while in Pine Script
- Use
for i = 0 to Nwhen you know the exact number of iterations in advance — lookbacks, array processing. - Use
while conditionwhen the number of iterations depends on data — searching for a level, converging to a value. - Pine Script does NOT support
breakto exit aforloop early. Workaround: use a flag variable andif not doneguards inside the loop.
// No break — use a found flag instead
found = false
foundIndex = -1
for i = 0 to 49
if not found and close[i] < ta.sma(close, 20)[i]
found := true
foundIndex := i
For plot visualization after your loop calculations, see the Pine Script plot() guide. For strategies that use loop-based entries, see the strategy.entry guide.
Summary
Pine Script for loops run from start to end (inclusive) — always use to length - 1 when you want N iterations. Use by step to skip values or count down. Prefer built-in functions (ta.highest, ta.sma) over manual loops when available — they're significantly faster. For early exit, use a boolean flag instead of break since Pine Script's for loop doesn't support it.