High before low again - how to with BarsSinceCompare?

There are several topics about detecting lows and highs backwards from the current bar, for instance:

However, I did not find the answer to my question from these.

The test data:
15 13 12 13 6 4 5 3 7 11 15 12 10 8 9 10 11

I would like to find out the first preceding bar that is less than 0.9 x of the current bar LOW_1, then the first bar larger than LOW_1 preceding LOW_1, let us call it HIGH_1 and so on. The first part is easy with the new good function:

_low_bar_1 = BarsSinceCompare(C, "<", C*0.9);

That is 2 for the last bar (11), meaning that the LOW_1 is 2 bars back, which is true (9). After that, I initially thought that the HIGH_1 could be found as following:

_high_bar_1 = BarsSinceCompare(Ref(C, -_low_bar_1), ">", Ref(C, -_low_bar_1));

As far as I understand, Ref(C, -_low_bar_1) should be the C array shifted to the right by 2 and therefore, the _high_bar_1 value for the last bar should be 2 as well, and the final answer 2+2=4 (the previous value larger than 9 is 10 in the test data, occupying the 4th position if we count backwards).

However, for some reason I do not comprehend, the value of high_bar_1 is 6!

_low_bar_1 = BarsSinceCompare(C, "<", C*0.9);	
_high_bar_1 = BarsSinceCompare(Ref(C, -_low_bar_1), ">", Ref(C, -_low_bar_1));
Plot(_low_bar_1, "low 1", colorRed);	
Plot(_high_bar_1, "high 1", colorGreen);

Could anybody please explain where am I mistaken. Why does high_bar_1 = 6? What should I do differently to achieve my goal?

The issue is that this statement:

_low_bar_1 = BarsSinceCompare(C, "<", C*0.9);

Returns an array, not a scalar. So yes, the value of that array is 2 for the last bar in your example data, but is not 2 for all other values in the array.

Now when you do this:

Ref(C, -_low_bar_1)

You are not, in fact, shifting the close array by a constant 2 bars, but rather by a variable number of bars as per the values in the _low_bar_1 array.

It will probably help you to understand what's going on if you add a simple exploration to output the value of Ref(C, -_low_bar_1) on each bar, i.e. do something like this:

Filter = True
shiftedClose = Ref(C, -_low_bar_1);
AddColumn(Close, "Close");
AddColumn(shiftedClose, "Shifted Close");

Depending on your goal, using SelectedValue(-_low_bar_1) or LastValue(-_low_bar_1) may solve your problem.

1 Like

@mradtke

So yes, the value of that array is 2 for the last bar in your example data, but is not 2 for all other values in the array.

Thanks, Matt, but I perfectly understand that. I was talking about the values for the last bar in the array in my original post:

That is 2 for the last bar (11), meaning that the LOW_1 is 2 bars back, which is true (9). After that, I initially thought that the HIGH_1 could be found as following

The fact that the high_1 is constantly changing as it should is well observable from the image I posted.

You are not, in fact, shifting the close array by a constant 2 bars, but rather by a variable number of bars as per the values in the _low_bar_1 array.

Agreed, but how come that

BarsSinceCompare(Ref(C, -_low_bar_1), ">", Ref(C, -_low_bar_1))

is 6 if the _low_bar_1 is 2 for the last value of the array (selected in the picture)? Where does the value 6 come from? How is it calculated?

Depending on your goal, using SelectedValue(-_low_bar_1) or LastValue(-_low_bar_1) may solve your problem.

The documentation says that the SelectedValue is always the last bar for Analysis:

In AA window 'selected element' means THE LAST BAR of currently selected
analysis range. It is the last available bar for "all quotes" and "last n quotes" range.
It is the the bar corresponding to "End Date" when using "From-To" range.

This seems to work:

	_low_bar_1 = BarsSinceCompare(C, "<", C*0.9);	
	_bars_since_higher = BarsSinceCompare(C, ">", C);
	_high_bar_1 = Ref(_bars_since_higher, -_low_bar_1);
	Plot(_low_bar_1, "low 1", colorRed);	
	Plot(_high_bar_1, "high 1", colorGreen);
	Plot(_low_bar_1 + _high_bar_1, "bars since peak before Low", colorYellow);