Search code examples
arraysfilterpine-scriptohlc

Filter out Down-candles to only include Up-candles in calculations in Pine Script


So, here's what I'm aiming to do: I want to write a script that uses OHLC-data exclusively from UP-candles [close > open] to calculate % change from Open to High, Close to High, and Open to Low, then take a (moving) average of those values to determine dynamic take profit-, trailing deviation- and stop loss-levels. I figured that this should do the trick.

// Variables
upCandle = (close > open) and barstate.isconfirmed

MP = if upCandle
    ((high - open) / open) * 100

TD = if upCandle
    ((high - close) / close) * 100

ML = if upCandle
    ((low - open) / open) * 100

It gets the values of the Up-candles correctly (so that part works), but then it interpolates between the empty values it gets from Down-candles. I want to ONLY take the OHLC-data from Up-candles, not have N/A- or ZERO-values inserted if no data is available. I think I might be able to solve this using arrays, something along the lines of "if the Up-candle is confirmed, stick the appropriate value into a corresponding FIFO-array, if not then don't". Then, I could calculate the average from that array with a specified lookback period (f.x. include only the last 9 Up-candles) which I could then plot as a moving average for the array-data and a histogram for the raw Up-candle data. In other words, I think I can accomplish what I want to do by filtering out Down-candles from an array.

But how do I do that? Anyone have any ideas? :)


Solution

  • You can indeed use the arrays to accomplish the goal. Add an array element only if the current candle is the one you are looking for - upCandle, using the input you can control the number of elements in the array and take its average using the array.avg() built-in. I have also introduced the upCandleCount counter for the plot() functions to start plotting on the chart only after 9 upCandles are found.

    //@version=5
    indicator("My script")
    
    // Variables
    upCandle = (close > open) and barstate.isconfirmed
    
    MP = if upCandle
        ((high - open) / open) * 100
    
    TD = if upCandle
        ((high - close) / close) * 100
    
    ML = if upCandle
        ((low - open) / open) * 100
    
    // Average of the given values for the latest 9 upCandles
    avgPeriod = input.int(9, 'Average Period')
    
    var float[] upCandleMPs = array.new<float>(avgPeriod)
    var float[] upCandleTDs = array.new<float>(avgPeriod)
    var float[] upCandleMLs = array.new<float>(avgPeriod)
    
    var int upCandleCount = 0
    
    if upCandle
        array.unshift(upCandleMPs, MP)
        array.unshift(upCandleTDs, TD)
        array.unshift(upCandleMLs, ML)
        upCandleCount += 1
    
    plot(upCandleCount >= avgPeriod ? array.avg(upCandleMPs) : na)
    plot(upCandleCount >= avgPeriod ? array.avg(upCandleTDs) : na)
    plot(upCandleCount >= avgPeriod ? array.avg(upCandleMLs) : na)