Counting the number of bars back to a price

Hi all,

I have recently purchased Amibroker as i was impressed with the trial and am trying to port over a mechanical strategy i use.

I have successfully created my buy and sell signals. However for a filter i use the low of the bar that created the buy (for example) but i need to know how many hours (bars) was the (low) price at that level

image

I have identified the high(or low) of the trigger candle but i cant work out how to identify that price level backwards (I have tried code with BarIndex, LastValue) and tried to search the forum but to no avail

Any suggestions ?

Regards

You can have a look at this thread here.

Basically you need a combination of two functions, HighestSince() or HHV() (LowestSince() or LLV()) etc and pass it to ValueWhen()

ValueWhen() will correspond to the values when Buy / Sell or another condition was True.

Do note that ValueWhen() will return an array with recent most True, see the 3rd argument in Manual.
so if you have multiple Buy as in the image, you need to take that into account as to which one is being referred.

Hi Travick

Thanks for that - i read the above thread but it uses a timebased approach (intraday) however my time series is 4 hour (trading FX).

image

In the pic above - i want to calculate the number of bars the price has reached the low (in a buy) which is represented by A (12 candles).
However when i use the valuewhen and llv i get the lowest low in the range which is the last lower low (represented by B).

I am protyping with this code.

// Long only for Bull Engulfing 
Bull_Engulfing =  Ref(C,-1) < Ref(O,-1) AND C > O AND O <=Ref(C,-1) AND C > Ref(O,-1);
Buy = C > EMA(C,30) AND Bull_Engulfing;

// Buy at todays close  
BuyPrice = Close;
Sell = 0;

// Low value and Barindex number at 'Buy' Signal 
Hx = Valuewhen(Buy, Low);
bi =BarIndex();

vw = LowestSince(L,bi);

PlotShapes(Buy*shapeUpArrow, colorYellow, 0, Low);

Filter = Buy ;	
AddColumn (BuyPrice,"BuyPrice",1.5);
AddColumn (L,"L",1.5);
AddColumn (Hx,"HX",1.5);
AddColumn (bi,"vw",1);
AddColumn (vw,"vw",1.5);

(hopefully i have formated it correctly)

I can identify the low of the signal bar and the barindex - now i just want to pick up the number of candles back when that price was low (i.e. identifying the support)

Thanks

To count the number of bars since an event has occurred, just use the BarsSince() function. One of these or something similar should work:

// These will do the same thing in your example.
bsHx = BarsSince(L == Hx);
bsBuy = BarsSince(Buy);

I'm not sure what you were trying to do with vw', but theLowestSince()` function expects an array of booleans as the first argument, not a price array.

1 Like

@Pervaz If you're scanning for candlestick patterns, you might want to use built-in functions.
some common ones are available.

@mradtke I think one would have to loop through this one.

@Pervaz try this

sHSUP = shapeHollowSmallUpTriangle;
bi    = BarIndex();

fv  = Status("firstvisiblebar"); lv = Status("lastvisiblebar");

CBE = CdBullishEngulfing( 0.01, 0.05);

for( i = fv; i < lv; i++ )
{
  if(CBE[i])
  {
     BS = BarsSince( L < L[i]);
     PlotText( NumToStr( Nz(BS[i]) , 1, 0), bi[i], H[i], colorAqua, colorDefault, 15);		
  }
}

Plot(C, "Close", colorDefault, styleNoTitle | ParamStyle("Style") | GetPriceStyle() );
PlotShapes( CBE * sHSUP, colorLightOrange, 0, L, -15 );

image

2 Likes

He does not want to count forward from signal.
He wants to count backward from signal.
It is pretty clearly mentioned in thread subject and 1st post ("bars back", and in pictures).

Here is (a) solution function.
(Do not copy it to other forums. It is available from AmiBroker forum here only. Also not for commercial use.) If you use it then hit thanks. If you don't use it then don't but I am tired of copycats and people just grabbing what they can with their two hands.

function fxMxBackwardCross(sig, cross_array) {
	/// @link https://forum.amibroker.com/t/counting-the-number-of-bars-back-to-a-price/10897/7
	/// by fxshrat@gmail.com
	Version(6.0);
	bir = Status("barvisible" );// chart area array	
	cums = Cum(IIf(bir, sig, 0));
	lastcum = LastVisibleValue(cums);//LastValue(cums);
	stop_mat = Matrix(3, Max(1,lastcum), 0);
	colnum = MxGetSize(stop_mat, 1);
	for ( i = 0, n = 0; i < BarCount; i++ ) {
		if ( bir[i] ) {
			if ( sig[i] ) {				
				if ( n < colnum ) {
					stop_mat[0][n] = i; // start bar
					stop_mat[1][n] = 0; // end bar
					stop_mat[2][n] = cross_array[i]; // level	
					for ( j = i; j >= 0; j-- ) {
						if ( L[j] < stop_mat[2][n] ) {
							stop_mat[1][n] = j; // end bar
							break;
						}
					}
				}
				n++;
			}
		}
	}		
	printf( "#lines: %g, BarCount: %g", colnum, BarCount );	
	for ( n = 0; n < colnum; n++ ) {
		GfxMoveTo(x1 = stop_mat[0][n], y = stop_mat[2][n] );
		GfxLineTo(x2 = stop_mat[1][n], y ); 
		GfxTextOut(StrFormat("-%g bars", x1-x2), x2, y ); 
	}
	return stop_mat;
}

Function used in his example code:

// Do NOT forget to insert upper function to this example!!

// Long only for Bull Engulfing 
Bull_Engulfing = Ref(C < O, -1) AND C > O AND O <= Ref(C,-1) AND C > Ref(O,-1);
Buy = C > EMA(C,30) AND Bull_Engulfing;

// Buy at todays close  
BuyPrice = Close;
Sell = 0;

// Low value and Barindex number at 'Buy' Signal 
Hx = Valuewhen(Buy, Low);

RequestTimedRefresh( 1 );
SetChartOptions( 0, chartShowDates | chartShowArrows | chartWrapTitle );

Plot( C, "Price", colorDefault, styleBar );
PlotShapes( Buy * shapeUpArrow, colorGreen, 0, L, -15 );
//Plot( Hx, "Hx", Colorblack, styleStaircase | styleThick ); 

GfxSetZOrder( 1 );
GfxSetCoordsMode( 1 );
GfxSetBkMode(2);
GfxSetTextAlign(2|0);
GfxSetTextColor( colorLightYellow );
GfxSelectFont("Arial", 8, 500 );
GfxSetBkColor( colorRed);
GfxSelectPen( colorRed, 1, 0 );	
	
mat = fxMxBackwardCross(Buy, cross_array = L);
printf( "\n%s", MxToString(mat));

37


You should not use array functions inside Barcount loop.
It's called hundreds/thousands of times. Your code will slow down everything.
Besides using status("lastvisiblebar") will result in error because of exceeding barcount range.
13
You should read here Understanding how AFL works

There aren't no inbuilt candlestick pattern functions.
What you use there is a 32-bit 3rd party DLL.

11 Likes

Hi

travick Thank you it was as a loop that was required - you code worked perfectly !

mradtke - Thank you for your suggestion also for using the candle pattern in AB - i was just testing out a protype and just automatically coded a specific pattern that i knew at the top of my head :slight_smile:

Regards

1 Like

Hi fxshrat

I must have been replying while you were posting

Thank you for a professional reply and your time. It worked perfectly. I will not use this commercial or distribute your code to any forum.

Thanks to you all guys - ive learnt a lot today - now if any of you are in the UK (or London) i would definately buy you a beer/coffee (and carrot cake!)

Regards

2 Likes

Five posts were split to a new topic: Private exchange between fxshrat and travick

Moderator comment: the forum does not need "big ego" exchange like this. If you need to continue it, use private channel. The forum needs co-operation, not animosity. Make sure to address other people with respect.

On this ocasion I would like to share some general thoughts.

We are only humans and nobody is perfect here, but there are currently 3390 users on this forum and according to the forum's statistics only about 440 of them (13%) have received at least one like! That means that the overwhelming majority with 0 (zero) likes - about 2950 users (87%)! are just passive onlookers enjoying other users' effort put to create the content of this site (not to mention the number of people who read this forum without registration - which is unknown). For this reason we should rather support those belonging to this valuable minority.

I thank everyone (without any exception) who spends his/her free time helping unknown users or providing any kind of positive input. If not such users, nine out of ten posts would regularly start and end with "I want this... I need that..." because even Tomasz himself or the best and the most proficient single user on the forum wouldn't be able to deal with hundreds or thousands of new posts and requests...

11 Likes

@fxshrat
Thanks for code .
(rough) try to replicate same result without using matrix.... hope it’s correct.

/// taken from @fxshrat above code
Bull_Engulfing = Ref(C < O, -1) AND C > O AND O <= Ref(C,-1) AND C > Ref(O,-1);
Buy = C > EMA(C,30) AND Bull_Engulfing;

SetChartOptions( 0, chartShowDates | chartShowArrows | chartWrapTitle );

Plot( C, "Price", colorDefault, styleBar );
PlotShapes( Buy * shapeUpArrow, colorGreen, 0, L, -15 );

bir = Status("barvisible" );

BuyLow = 0;
BuySwitch = 0;

GfxSetCoordsMode( 1 ); 
GfxSetOverlayMode( 0 );
GfxSelectPen( ColorRed, 1 );

for ( i = BarCount-1; i > 0; i-- )
	{
	if ( bir[i] ) 
		{
		if ( Buy[i] )
			{
			BuyLow = L[i];
			BuySwitch = 1;
			GfxMoveTo(i, BuyLow );
			}
		if ((BuySwitch == 1) AND (Low[i]<BuyLow))
			{
			BuySwitch = 0;
			GfxLineTo( i, BuyLow );
			}
		}
	}
1 Like

@Fossil,

thanks for your code idea, too.

But it misses cases where lines "overlap".
See example below showing what I mean by missing "overlapping" lines...

As you can see the yellow marked signal that had a cross 17 bars before is "overlapping" the backward run (line) of the signal before which had a backward cross after just one bar.

Such cases will be missed by your single loop version.

Here is picture showing the current differences (your version is in lower pane)
47

Here is another example of missings
36

1 Like

@fxshrat
Thank you again for your time to examine my code & pointing out my coding error :tulip:.

@fxshrat is it correct....

///@fxshrat above code......@Fossil style
Bull_Engulfing = Ref(C < O, -1) AND C > O AND O <= Ref(C,-1) AND C > Ref(O,-1);
Buy = C > EMA(C,30) AND Bull_Engulfing;

SetChartOptions( 0, chartShowDates | chartShowArrows | chartWrapTitle );

Plot( C, "Price", colorDefault, styleBar );
PlotShapes( Buy * shapeUpArrow, colorGreen, 0, L, -15 );

bir = Status("barvisible" );

BuySwitch = 0;

GfxSetCoordsMode( 1 ); 
GfxSetOverlayMode( 0 );
GfxSelectPen( ColorRed, 1 );

for ( i = BarCount-1; i > 0; i-- )
	{
	if ( bir[i] ) 
		{
		if ( Buy[i] )
			{
			BuySwitch += 1;
			BuyX[BuySwitch] = i;
			BuyY[BuySwitch] = L[i];
			}
		
		if (BuySwitch > 0)
			{
			SwitchHolder = BuySwitch;
			for ( n = 1; n <= SwitchHolder; n++ )
				{
				GfxMoveTo(BuyX[n], BuyY[n] );
				
				if(Low[i] < BuyY[n])
					{
					GfxLineTo(i, BuyY[n] );
					BuySwitch -= 1;
					
					m = n;
					k = n + 1;
					
					for ( z = k; z <= SwitchHolder; z++ )
						{
						BuyX[m] = BuyX[z];
						BuyY[m] = BuyY[z];
						m += 1;
						}
					}
				}
			}
		}
	}

5 Likes

@Fossil,

I see you do not give up. I like that. :+1:

That being said... on quick look the output looks OK now (have not checked closely, same for looking for possible code flaws). The differences between our two versions is that you use triple nested loop and me using double nested loop. Execution timing of my version is a bit better.

Thank your for sharing!

3 Likes