Search code examples
loopswhile-looppine-scriptpine-script-v5pine-script-v4

How can I start a while loop in PineScript when the price has fallen below a certain level and stop it when it has risen above a higher level?


I would like to define the following with a while loop. After falling below a certain price level a loop is started. It ends only when a higher price level is exceeded again. When the loop ends, it should output a value that I can then continue to work with.

For example

a = 0

If the SPX falls below 4000, the loop starts. Only when the SPX then rises again above 4200, the loop stops and changes a := 1

Then I know when a = 1, the scenario has occurred and can take further action based on that.

Can someone give me an example, that shows how to define that?


Solution

  • Revised Answer:

    The solution is simply to iterate through each previous bar to check for the fallenBelow condition being withing a certain range of the risenAbove condition using a while loop that looks like this:

    // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
    // © lysergik
    
    //@version=5
    indicator("backAboveDectector")
    
    bool belowThenAboveInRange = false // this becomes true when your condition is met
    
    // Inputs
    float priceLevel = input.float(23700)
    int lookback = input.int(10, 'lookback')
    
    // Logic
    
    bool fallenBelow = close[1] >= priceLevel and close < priceLevel
    bool risenAbove = close[1] <= priceLevel and close > priceLevel
    
    i = 1
    while belowThenAboveInRange == false and i <= lookback
        if risenAbove[0] and fallenBelow[i]
            belowThenAboveInRange := true
        else
            i += 1
    
    // front-end
    
    plotshape(belowThenAboveInRange ? 0 : na, style=shape.diamond, location=location.absolute)
    

    The trick to get a boolean of risenAbove but only when fallenBelow was true within a specified range prior is to use a while loop to look through the previous bars.

    The loop checks for the current candle being analyzed by the script for the risenAbove condition and then checks the previous bar for the fallenBelow condition. If it did not fall below on that prior candle, it will add 1 to i and repeat the check until either both conditions are met or the iteration limit is hit.

    Notes:

    • There must be a limit (although it can be quite large) because the script is run on every single bar in visible range and therefore Pinescript limits the script to take maximum 500ms to compute.
    • If you only want your condition to be true when the level is risen-above the very next bar after falling-below, then you can omit the while loop altogether and just run the check once; replacing i with '1'

    example of solution working

    Additional Example

    You can define two different levels for fallenBelow and risenAbove like this, where float1 is the threshold for falling below ('starting the loop') and float2 is the threshold it must rise above afterwards:

    Uncorrelated; unrelated and individually mutable

    bool fallenBelow = close[1] >= [float1] and close < [float1]
    bool risenAbove = close[1] <= [float2] and close > [float2]
    

    Correlated; float2 is in this example always 5% higher than float1

    bool fallenBelow = close[1] >= [float1] and close < [float1]
    bool risenAbove = close[1] <= [float1*1.05] and close > [float1*1.05]