'Get the bar_index of the first bar that has a lower low than the low of the current bar

To find divergences I'm trying to get the bar_index of the first bar that has a lower low than the low of the current bar.

enter image description here

I wish I could inject current bar values into the condition field of ta.valuewhen() but this is not possible.

I could use a for loop, but this is slow as hell and iterating over ALL candles, which is not necessary because I want to check the first lower pivot and not all candles are pivots.

Using ta.valuewhen(condition, source, occurrence) inside a for loop and iterate with the occurrence field is discouraged by the script itself.

Eg:

prevPivLL  = na
prevPivLLI = na

// Looking back 5 pivot lows for a lower low than current low
for i = 0 to 5  
    prevPivotLo = ta.valuewhen(na(pivotLo), pivotLo, i)
    prevPivLL  := pivotLo > prevPivotLo ? pivotLo : na
    prevPivLLI := bar_index - ta.valuewhen(na(pivotLo), bar_index, i)

So, what else then? Is there a better approach to this?

I have seen probably all other scripts that look for divergence, look if the current low is higher than the previous one. The thing is that the current low can be a lower one with the previous pivot, but still a higher one with a earlier pivot. I want to check against the first lower pivot, even if there are higher ones in between. After that, i stop looking (because it becomes irrelevant then).

Same goes for close btw.

This is kinda backwards from what most scripts do, but probably way more accurate.



Solution 1:[1]

You can use arrays to store the pivots and their corresponding bar indices as they occur. Then you only need to iterate through a small array of pivot values to do the evaluation.

You'll need to limit the historical search though, by the number of pivots and/or by a bar lookback limit.

//@version=5
indicator("Last pivot low index", overlay = true)

lb_limit = input.int(100, title = "bar lookback limit")

piv_limit = input.int(5, title = "number of pivots limit")

var float[] piv_l_price = array.new_float()
var int[] piv_l_index = array.new_int()

bool pivl = low > low[1] and low[1] < low[2]

if pivl
    array.unshift(piv_l_price, low[1])
    array.unshift(piv_l_index, bar_index[1])

if array.size(piv_l_price) > piv_limit
    array.pop(piv_l_price)
    array.pop(piv_l_index)

size = array.size(piv_l_price)

bool found_piv_l = false
float last_piv_l_price = na
int last_piv_l_index = na

if size > 0
    for i = 0 to size - 1
        temp_piv_l_price = array.get(piv_l_price, i)
        temp_piv_l_index = array.get(piv_l_index, i)
        if temp_piv_l_price < low and temp_piv_l_index > bar_index - lb_limit
            found_piv_l := true
            last_piv_l_price := temp_piv_l_price
            last_piv_l_index := temp_piv_l_index
            break

var line piv_l_line = line.new(x1 = na, y1 = na, x2 = na, y2 = na, color = color.teal)

if found_piv_l
    line.set_xy1(piv_l_line, x = last_piv_l_index, y = last_piv_l_price)
    line.set_xy2(piv_l_line, x = bar_index, y = low)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rumpypumpydumpy