Do I need to make a loop for self referencing code?

I'm trying to make a simple short selling code. The rules are as follows:

  • Below the 100MA, short after 2 up bars
  • Cover after any 3 down bars following the short

I have a counter to add up 3 down bars any time after the short, but each time it sees an additional short signal, it resets the counter to 0.

I think because it is self referencing that I have to use a loop but I'm not sure how I can do that. Would a competent coder be able to help me? I'd certainly be willing to offer some modest compensation.

This is my attempt to code it:

//short when you have two up burs and the price is below the 100 day moving average
//cover after any three down bars, following the short
entryDelay = 0;
exitDelay = 0;
SetTradeDelays( entryDelay, exitDelay, entryDelay, exitDelay );
BuyPrice = ShortPrice = IIf( entryDelay == 0, Close, Open );
SellPrice = CoverPrice = IIf( exitDelay == 0, Close, Open );

TrendMA = MA( Close, 100 );
DownTrend = Close < TrendMA;
DownBar = Close < Open;
UpBar = Close > Open;
UpTwoDays = BarsSince( DownBar ) > 2;
Short = DownTrend AND UpTwoDays;
DownBarCount = SumSince( Short, DownBar );
Cover = DownBarCount > 3;
Cover = ExRem( Cover, Short );
Short = ExRem( Short, Cover );
Buy = Sell = 0;

SetChartOptions( 0, chartShowArrows | chartShowDates );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
Plot( Close, "Close", ParamColor( "Color", colorDefault ), styleNoTitle | ParamStyle( "Style" ) | GetPriceStyle() );
Plot( TrendMA, "TrendMA", IIf( DownTrend, colorRed, colorGreen ) , Styleline | Stylethick );
Plot( DownBarCount, "DownBarCount", colorYellow, styleOwnScale );

Filter = 1;
AddColumn( Open, "Open", 1.2 );
AddColumn( High, "High", 1.2 );
AddColumn( Low, "Low", 1.2 );
AddColumn( Close, "Close", 1.2 );
AddColumn( DownBarCount, "DownBarCount", 1.0 );
AddColumn( IIF( Short, 'S', ' ' ), "Short", formatChar, colorDefault, IIf( Short, colorRed, colorDefault ) );
AddColumn( IIF( Cover, 'C', ' ' ), "Cover", formatChar, colorDefault, IIf( Cover, colorGreen, colorDefault ) );

I've also included a screen shot illustrating what I'm trying to do and the problem that I run into.Annotation%202020-03-12%20122157

/// Short when you have two up burs and the price is below the 100 day moving average
/// Cover after any three down bars, following the short
/// Original at 
/// @link https://forum.amibroker.com/t/do-i-need-to-make-a-loop-for-self-referencing-code/17705
/// modification at 
/// @link https://forum.amibroker.com/t/do-i-need-to-make-a-loop-for-self-referencing-code/17705/2
entryDelay = exitDelay = 0;
SetTradeDelays( entryDelay, exitDelay, entryDelay, exitDelay );

BuyPrice = ShortPrice = IIf( entryDelay == 0, Close, Open );
SellPrice = CoverPrice = IIf( exitDelay == 0, Close, Open );

TrendMA = MA( Close, 100 );
DownTrend = Close < TrendMA;
DownBar = Close < Open;
UpBar = Close > Open;

UpTwoDays = BarsSince( DownBar ) > 2;

ShortSignal = DownTrend AND UpTwoDays;

Short = Cover = 0;
cnt_array = Null;
s_entryprice = cnt = 0; 
for ( i = 0; i < BarCount; i++ ) {	
	if ( ShortSignal[ i ] && s_entryprice == 0 ) {
		Short[ i ] = 1;
		s_entryprice = ShortPrice[ i ];
	} 
	
	if ( s_entryprice > 0  ) {	
		if ( DownBar[i] ) 
			cnt++;
	
		// exit if count of downbar > n
		CoverSignal = cnt > 3;	
		if ( CoverSignal ) {
			Cover[ i ] = 1;    
			s_entryprice = cnt = 0;
		}		
		cnt_array[ i ] = cnt;	// store cnt to array
	} 	
}

//Cover = ExRem( Cover, Short );
//Short = ExRem( Short, Cover );

Buy = Sell = 0;

PlotShapes( Short * shapeDownArrow + Cover *shapeUpArrow ,
            IIf( Short, colorRed, colorGreen ), layer = 0, y = IIf( Short, H, L ) );

SetChartOptions( 0, chartShowArrows | chartShowDates );

_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
Plot( Close, "Close", ParamColor( "Color", colorDefault ), styleNoTitle | ParamStyle( "Style" ) | GetPriceStyle() );
Plot( TrendMA, "TrendMA", IIf( DownTrend, colorRed, colorGreen ) , Styleline | Stylethick );
Plot( cnt_array, "DownBarCount", colorYellow, styleOwnScale );

Filter = 1;

AddColumn( Open, "Open", 1.2 );
AddColumn( High, "High", 1.2 );
AddColumn( Low, "Low", 1.2 );
AddColumn( Close, "Close", 1.2 );
AddColumn( cnt_array, "DownBarCount", 1.0 );
AddColumn( IIF( Short, 'S', ' ' ), "Short", formatChar, colorDefault, IIf( Short, colorRed, colorDefault ) );
AddColumn( IIF( Cover, 'C', ' ' ), "Cover", formatChar, colorDefault, IIf( Cover, colorGreen, colorDefault ) );

9

8 Likes

@fxshrat I love seeing any of your work with Amibroker. It's always so accurate, competent and concise! I sent a small donation for your special cause. Thank you so much!

7 Likes

Here is another solution - more or less without a loop.
Therefore it's faster and a bit shorter.

If the conditions are more difficult/dynamic, it's probably much harder to find such a solution?!

Buy = Sell = Short = Cover = 0;
delay = 0;
SetTradeDelays(delay, delay, delay, delay);
ShortPrice = CoverPrice = IIf(delay == 0, Close, Open);  

upBar = C > O;
downBar = C < O;
below_MA = C < MA(C,100);
nbr_upBars = 2; //Param("Number of consec upBars", 2, 1, 100, 1);
nbr_downBars = 3; //Param("Number of downBars", 3, 1, 100, 1);

// Short
Consec_up = BarsSince( !upBar );
UpTwoDays = Cross(Consec_up, nbr_upBars-1); 
Short = Ref(UpTwoDays AND below_MA, -1); 

// Cover
for(i=1; i<=2; i++) {
	add = ValueWhen(Short, downBar);
	Count_down = SumSince(Short, downBar) + add;
	Cover = Ref(Cross(Count_down, nbr_downBars-1), -1); 
	
	if(i==1) {
	Cover = ExRem( Cover, Short );
	Short = ExRem( Short, Cover );
	}

	if(i==2) { //
	InTrade = Flip(Short, Cover);
	Count_down = IIf(InTrade, Count_down, Null);
	Cover = Ref(Cross(Count_down, nbr_downBars-1), -1);
	}	
}


// Plot
PlotShapes( Short*shapeDownArrow + Cover*shapeUpArrow, IIf(Short, colorRed, colorGreen), layer = 0, y = IIf(Short, H, L) );

SetChartOptions( 0, chartShowArrows | chartShowDates );

_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
Plot( Close, "Close", ParamColor( "Color", colorDefault ), styleNoTitle | ParamStyle( "Style" ) | GetPriceStyle() );
Plot( MA(C,100), "MA", IIf(below_MA, colorRed, colorGreen) , Styleline | Stylethick );
Plot( Count_down, "Count_down", colorYellow, styleOwnScale );

To the experienced users:
Is it possible to code everything in such a style?
Sure, it would be much harder sometimes, but also faster (and the code more or less shorter).

I found e.g. this thread:

Can someone provide another example, where one must loop?
I'm sometimes not sure if I should/must use loops or not.
So respectively I need a rule when to use loops. This would be nice :slight_smile:
Obviously, self-referencing isn't (always) the right rule...

On the other hand, I found this post, especially the last two sentences:

I'm not sure. Do you have a rough rule when to use loops (because it would be too much work or the code would be too difficult/unfriendly) ?

1 Like

Your code is not correct (not the same) as it does not work with any signal.

E.g. just use only

TrendMA = MA( Close, 100 );
DownTrend = Close < TrendMA;
Short = DownTrend;

in both codes and you will see that your code does not enter properly according to the rules .

13

But also if using your entry rules in both codes then your code misses signals according to rules (BTW to compare you should use nbr_downBars = 4; and remove signal delay in your code).

14

I don't see array solution since Cover is dependent on Short (number of down bars since short). So it is kind of an n-bar stop.

1 Like

@fxshrat Thank you for the clarification!

Originally I've thought, that it's only working with Cross and Buy @ next Bar Open for now.
(I should have mentioned that in my first post.)
But even that's not true. (altough it often seems like that)

Self-Referencing --> Loop. Thanks!
E.g. one exception would be if there is always only one short-signal until one cover-signal occurs (original signals).

In majority of cases you do NOT need loops. This includes self-referencing code. It can be written without loops as shown: Doubt when using self referencing

2 Likes