Loops

Structuring Loops in Pine Script™

Introduction

Programmers often resort to loops when performing calculations or operations repetitively. However, in many scenarios within Pine Script™, loops can be circumvented using built-in functions which not only make the code more concise but also enhance performance.

When to Avoid Loops

Let's consider a simple example. Suppose a novice Pine Script™ programmer aims to calculate the average of the last 10 close values. They might write code such as:

//@version=5
indicator("Inefficient MA", "", true)
MA_LENGTH = 10
sumOfCloses = 0.0
for offset = 0 to MA_LENGTH - 1
    sumOfCloses := sumOfCloses + close[offset]
inefficientMA = sumOfCloses / MA_LENGTH

This approach, though functional, is not efficient for Pine Script™. Instead, one can utilize the built-in function ta.sma() to achieve the same result more efficiently:

//@version=5
indicator("Efficient MA", "", true)
thePineMA = ta.sma(close, 10)

Similarly, to count the number of up bars in the last 10 bars, one can avoid loops by using the math.sum() built-in function:

//@version=5
indicator("Efficient sum")
upBars = math.sum(close > open ? 1 : 0, 10)

In this code:

  1. We use the ?: ternary operator to build an expression that yields 1 on up bars and 0 on other bars.

  2. We use the math.sum() built-in function to keep a running sum of that value for the last 10 bars.

When to Use Loops

While built-in functions can replace loops in many situations, there are scenarios where loops become necessary. These typically include:

  1. Manipulating arrays.

  2. Analyzing historical bars using a reference value only known on the current bar.

  3. Performing calculations on past bars that cannot be accomplished using Pine Script™’s built-in functions, like the Pearson correlation coefficient.

Using for Loop

The for structure allows repetitive execution of statements with a counter. Here's a case where we need to look back a user-defined number of bars to determine how many bars have a high that is higher or lower than the high of the last bar. A for loop is necessary here since the script only has access to the reference value on the chart’s last bar.

//@version=5
indicator("`for` loop")
lookbackInput = input.int(50, "Lookback in bars", minval = 1, maxval = 4999)
higherBars = 0
lowerBars = 0
if barstate.islast
    var label lbl = label.new(na, na, "", style = label.style_label_left)
    for i = 1 to lookbackInput
        if high[i] > high
            higherBars += 1
        else if high[i] < high
            lowerBars += 1

Using while Loop

The while structure allows repetitive execution of statements until a condition becomes false. Here's the previous example rewritten using a while loop instead of a for one :

//@version=5
indicator("`while loop")
lookbackInput = input.int(50, "Lookback in bars", minval = 1, maxval = 4999)
higherBars = 0
lowerBars = 0
if barstate.islast
    var label lbl = label.new(na, na, "", style = label.style_label_left)
    i = 1
    while i <= lookbackInput
        if high[i] > high
            higherBars += 1
        else if high[i] < high
            lowerBars += 1
        i += 1

Both for and while structures can achieve the same tasks, and the choice often depends on the programmer's preferences and the specifics of the task at hand.

Conclusion

The rule of thumb in Pine Script™ is to avoid loops when possible and resort to built-in functions for tasks such as moving averages, cumulative sums, etc. However, when built-in functions are not an option, understanding how to utilize for and while loops becomes a vital tool for advanced calculations and data manipulation. Always ensure your loops do not exceed the maximum loop iterations limit in Pine Script™, which at the time of writing, is set at 5000 iterations.

Remember, clear and efficient coding is not just about achieving the desired output; it's about doing so in a way that optimizes the performance and readability of your script.

Last updated