HHV and Barssince issue

I would appreciate if somebody can advise me what I am doing wrong in this code. I find the HHV going back 28-bars. Then I do a BarsSince() on that price but it returns the number 41 when it should be 1. If I hardcode the price from HHV() in BarsSince() then I get the right answer. EndValue() on HHV() gives the right answer but that causes other problems in the code. My code is as follows. Thanks.

Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() );

x=HHV( H, 28);
Plot(x,"",colorWhite); // In this case the value in question is 2887.25

hs = BarsSince( H == x );
Plot(hS,"",colorRed,styleLeftAxisScale); // This says 41 but it should be 1

hs = BarsSince( H == x );


Would HHVBars work better?

hs = HHVBars( High, 28 );

Thanks for the reply BoNeZ. Ideally HHVBars() is what I would like to use instead of HHV() but the problem with HHVBars() is that if within the range, 28 in this case, there are two highs with the same price, then it will return the number of periods that have passed since the first occurrence instead of the last occurrence.

In the above example HHVBars(High,28) will return 10, the high at 10:22, instead of 1 which is the high at 10:30.

As in sports, the person who scores exactly the same time as world record holder does NOT become new world record holder. The one who was first is a winner. Same with HHVBars, but you can get "last occurence" HHVBars behavior if you wish by adding constantly growing value to array:

HHVBars( High + 0.00001 * BarIndex(), 28 ); // trick to get "last" as a winner

Also it is not clear what "other problems in your code" you mean with BarsSince use. BarsSince( H == HHV( H, 28 ) ); should work as well.


Thanks Tomasz. I agree " BarsSince( H == HHV( H, 28 ) ); should work as well." This should work but for some reason it doesn't and I can't figure out why.

HHVBars( High + 0.0001 * BarIndex(), 28 ) works but if I go to another decimal place as per above, i.e. "HHVBars( High + 0.00001 * BarIndex(), 28 )" it doesn't. Here is the screenshot from the latter case just a few mins ago. Notice how the 07:21 bar gives a different count. The entire code is:

Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() );

x=HHV( H, 28);
hs = BarsSince( H == x );

Plot(HHVBars( High + 0.00001 * BarIndex(), 28 ),"",colorYellow,styleLeftAxisScale);


Maybe it is a case of floating point precision but there is a workaround. How about adding an option to HHVBars() which tells it to give the first or last occurrence?

Yes, there is a limited floating point resolution in PC hardware http://www.amibroker.com/kb/2010/07/20/about-floating-point-arithmetic/

Your HHV value (white line) is showing 2887.25, but are you sure that's really the full value and not being rounded for display purposes? The bars at 10:04 and 10:22 (I think) look like possible HHV candidates. You should verify that one of them doesn't actually have a high price that's slightly greater than 2887.25.

The ES futures trade in 0.25 increment so it is not possible for one price to be "slightly greater". Yes 10:04 and 10:22 bars have identical high. Maybe it has something to do with floating point representation of the values. It is very odd that the code doesn't show the right results. When I place the cursor on those two bars it shows the exact same high, 2887.25.

But even if one of 10:04 or 10:22 bar was "slightly greater" it shouldn't go back 41-bars to find the high. At most it should go back 28 bars because the code says "x=HHV( H, 28);"

I don't think this line is doing what you think it is:

hs = BarsSince( H == x );

You believe that at 10:31, the function is looking back to find the first bar where the High is equal to the current value of X (2887.25). However, what the function is really doing is looking back to find the first bar where the High is equal to X on that bar. In other words, your logic is finding the last occurrence of a 28-bar highest high.That happened around 9:50, or 41 bars before 10:31.

1 Like

mradtke, I initially coded this as follows:

hs = BarsSince( H == HHV( H, 28) );

That gave the same erroneous result. How should this line be code so it finds that last occurrence of the highest high going back 28 bars? Thanks in advance.

I'm not aware of any way for you to accomplish your goal without using a loop to assign each element of your hs array.

@spoostrader1 I had to read this thread more than once to understand what was going on. This bit of exploration helped to clarify the behavior. As you can see, HhvBars(x,N) returns values in the range 0..N-1. BarsSince() can look back any distance.

x = HHV(H, 28);
idx = Lastvalue(ValueWhen(Status("LastBarInRange"), BarIndex())) - BarIndex();
AddColumn(idx, "idx", 1.0);
AddColumn(H, "H");
AddColumn(HHV(H, 28), "x = HHV(H, 28)");
AddColumn(BarsSince(H == x), "BarsSince(H == x)", 1.0);
AddColumn(HHVBars(H, 28), "HHVBars(H, 28)", 1.0);
equal = BarsSince(H == HHV(H, 28)) == HHVBars(H, 28);
AddColumn(equal, "Equal", 1.0);
Filter = 1;
1 Like

This my trial to estimate how far is the latest highest high but the code need to be tested

P    =  30;
HH  = HHV(H,P);
HB  = HHVBars(H,p);
BH  = BarsSince(ROC(HH,1) != 0);

C1 = BH < p AND HH == H;

BS  = BarsSince(C1)+1;

R1 = IIf(Hold(C1,p),BS,p);

NH = HHVBars(High,R1);
function geqHHVBars( array, period)
{  // >= HHV
	rev_hhvb = Reverse( HHVBars( Reverse( array), period));
	a = period - 1;
	return a - Ref( rev_hhvb, -a);