Can this be coded with no loop?

Need a little help with coding the below concept, if possible, then without loop

  1. Signal is price crossing ema
  2. Count max signals from beginning of session.
  3. There should be a gap of 30 bars for a signal to be called a valid signal
  4. Valid signal count should be a max of three.

I have tried a few times but can't make it work. So, perhaps looping would be required, which I am not able to as I am not a programmer. Below is the final iteration after which I came to seek help.

Help and guidance is highly appreciated.

//it's a new day <-- don't use signals from previous session
t=TimeNum();
tStarts = 091500;
tEnds = 153000;
nd = Day() != Ref(Day(),-1) AND t >= tStarts AND t <= tEnds;

//get first cross signal
ema200 = EMA(C,200);
upX = nd AND Cross(C,ema200);
dnX = nd AND Cross(ema200,C);

//avoid all signals for next 30 bars
upXsum = Ref(Sum(upx,30)==0,-1);
dnXsum = Ref(Sum(dnx,30)==0,-1);

//do this till you have max 3 signals or day ends
totalBuys = SumSince(nd,upx) <=3 ;
totalShorts = SumSince(nd,dnx)<=3 ;

if ( nd )
{
	for ( i = 1; i <= 3; i++ )
	

"Can this be coded with no loop" is not a good title for possible search requests.
Anything can be coded.
"How to sum signals after certain point of time" would be better subject.

//it's a new day <-- don't use signals from previous session
t=TimeNum();
tStarts = 091500;
tEnds = 153000;

nd = Day() != Ref(Day(),-1) AND t >= tStarts AND t <= tEnds;

//get cross signals
ema200 = EMA(C,200);
upX = Cross(C,ema200);
dnX = Cross(ema200,C);

// https://forum.amibroker.com/t/can-this-be-coded-with-no-loop/30829/2
thirty_bars = BarsSince(nd)+1 == 30;
min_t = t >= ValueWhen(thirty_bars, t);

cs_buy = SumSince(thirty_bars,upx);
cs_short = SumSince(thirty_bars,dnx);

//do this till you have max 3 signals or day ends
totalBuys = IIf(min_t, cs_buy > 0 AND cs_buy <= 3, 0);
totalShorts = IIf(min_t, cs_short > 0 AND cs_short <= 3, 0);
3 Likes

Hey, you're right. My apologies for that. Will remember to create better subjects from next time. Don't think I can edit it now.

About the problem.

I am not waiting for first 30 minutes from session start. A signal can come even at the very start of the session.

However, the next signal will be called valid only after 30 minutes from the first (if it comes). So, there's no first 30 minutes wait-time from session start time. But there is after getting the first signal and so on. Till we have a total of 3 or session ends.

This may not be the most efficient solution, and crosses 2-N could be implemented in a loop if needed. However, I think it accomplishes your stated goal. Note that your New Day (nd) logic was flawed, so I fixed that as well.

//it's a new day <-- don't use signals from previous session
t=TimeNum();
tStarts = 091500;
//tEnds = 153000;
nd = (Day() != Ref(Day(),-1) OR Ref(t,-1) < tStarts) AND t >= tStarts;	// AND t <= tEnds;
barsSinceND = BarsSince(nd);

// Find all crosses
ema200 = EMA(C,200);
upX = Cross(C,ema200);
dnX = Cross(ema200,C);

// First cross of the day
upX1 = upX AND SumSince(nd, upX) == 1;
dnX1 = dnX AND SumSince(nd, dnX) == 1;

// Second cross must be at least 30 bars after the first
upX2 = upX AND BarsSince(upX1) >= 30 AND BarsSince(upX1) < barsSinceND;
upX2 = upX2 AND SumSince(nd, upX2) == 1;

dnX2 = dnX AND BarsSince(dnX1) >= 30 AND BarsSince(dnX1) < barsSinceND;
dnX2 = dnX2 AND SumSince(nd, dnX2) == 1;

// Third cross must be at least 30 bars after the second
upX3 = upX AND BarsSince(upX2) >= 30 AND BarsSince(upX2) < barsSinceND;
upX3 = upX2 AND SumSince(nd, upX3) == 1;

dnX3 = dnX AND BarsSince(dnX2) >= 30 AND BarsSince(dnX2) < barsSinceND;
dnX3 = dnX3 AND SumSince(nd, dnX3) == 1;

isBuySig = upX1 OR upX2 OR upX3;
isShortSig = dnX1 OR dnX2 OR dnX3;

PlotShapes(shapeUpArrow * isBuySig, colorBrightGreen, 0, L);
PlotShapes(shapeDownArrow * isShortSig, colorRed, 0, H);
2 Likes

Thanks, @mradtke .

Is the purpose of the below code is to ensure that previous session's signals are not counted?

1 Like

It's to make sure that upX2 today occurs after upX1 today, not after upX1 from a previous day.

2 Likes

Good, I asked.

You corrected the newday code. Could you please tell why this is not required? Or, why is it making the code wrong?

t <= tEnds;

Really appreciate all the guidance @mradtke

1 Like

It's just not necessary. NewDay is an impulse signal which should be true on the first in-hours bar after an out-of-hours bar or after a bar from the previous day. I suppose you could get a false NewDay signal if you only have out-of-hours data for a particular day, for example, the first timestamp today is at 15:35. However, that seems unlikely.

Normally you would use logic like:

isInHours = t >= tStarts AND t <= tEnds;

For a state variable that remains true for the entire regular hours trading session. But that's not what we want here.

Or maybe you DO want something like isInHours, because right now there is no guarantee that the three crosses occurred during regular trading hours, only that they occurred sometime after today's first bar after the open.

3 Likes

Your code does not work properly and is flawed itself.
Also there is no looping required

It is much simpler as it is just ApplyStop required.
Here is code that works for any number of signals set and without any need of looping.

function sig(dir, bars, numsig) {
	global Buy, Sell, Short, Cover, eq, nd;	
	ApplyStop(stopTypeNBar, stopModeBars, bars, 1, 0);
	eq = Equity(1,0);
	if ( dir == 0 )	result = Buy AND 
					SumSince(nd, Buy) > 0 AND 
					SumSince(nd, Buy) <= numsig;
	else			result = Short AND 
					SumSince(nd, Short) > 0 AND 
					SumSince(nd, Short) <= numsig;
	return result;
}

/// @link https://forum.amibroker.com/t/can-this-be-coded-with-no-loop/30829/9

t=TimeNum();
tStarts = 091500;
tEnds = 235959;
session = t >= tStarts AND t <= tEnds;
nd = session AND Ref(session,-1) == 0;
ema200 = EMA(C,200);

num_sig = 3;// number of signals allowed per day
distance = 30;// minimum distance between signals of same direction

Buy = Cross(C,ema200) AND session;
Sell = Ref(nd,1);
BuySig = sig(0, distance, num_sig);

Short = Cross(ema200,C) AND session;
Cover = Ref(nd,1);
ShortSig = sig(1, distance, num_sig);

Buy = BuySig /*AND...*/;
Short = ShortSig /*AND...*/;

Plot( C, "Price", colorDefault, styleBar );
PlotShapes(shapeUpArrow * Buy, colorBrightGreen, 0, L);
PlotShapes(shapeDownArrow * Short, colorRed, 0, H);
Plot(nd, "", colorRed, styleHistogram | styleOwnScale, 0, 1 );

SetBarsRequired(1500);

You did not say so.

Added reset after function call.

function sig(dir, bars, numsig) {
	global Buy, Sell, Short, Cover, eq, nd;	
	ApplyStop(stopTypeNBar, stopModeBars, bars, 1, 0);
	eq = Equity(1,0);
	if ( dir == 0 )	result = Buy AND 
					//SumSince(nd, Buy) > 0 AND 
					SumSince(nd, Buy) <= numsig;
	else			result = Short AND 
					//SumSince(nd, Short) > 0 AND 
					SumSince(nd, Short) <= numsig;
	return result;
}

/// @link https://forum.amibroker.com/t/can-this-be-coded-with-no-loop/30829/10
SetOption("ReverseSignalForcesExit", 0);

t=TimeNum();
tStarts = 091500;
tEnds = 235959;
session = t >= tStarts AND t <= tEnds;
nd = session AND Ref(session,-1) == 0;
ema200 = EMA(C,200);

num_sig = 3;// number of signals allowed per day
distance = 30;// minimum distance between signals of same direction

Buy = Cross(C,ema200) AND session;
Sell = Ref(nd,1);
BuySig = sig(0, distance, num_sig);
Buy = Sell = 0;// Reset

Short = Cross(ema200,C) AND session;
Cover = Ref(nd,1);
ShortSig = sig(1, distance, num_sig);
Short = Cover = 0;// Reset

Buy = BuySig /*AND...*/;
Short = ShortSig /*AND...*/;

Plot( C, "Price", colorDefault, styleBar );
PlotShapes(shapeUpArrow * Buy, colorBrightGreen, 0, L);
PlotShapes(shapeDownArrow * Short, colorRed, 0, H);
Plot(nd, "", colorRed, styleHistogram | styleOwnScale, 0, 1 );

SetBarsRequired(1500);

Sorry, I missed it. Will come back after market hours to understand your code. Thanks, again. :slight_smile: :+1:

Here is update:

  1. fixed if a signal occurs at session start (then it could happen that number of signals was n+1 because SumSince is zero based).
  2. fixed if session start is equal to new day start.
function sum_since(cond,array) {
	return SumSince(cond,array) + ValueWhen(cond,array);
}
function sig(dir, bars, numsig) {
	global Buy, Sell, Short, Cover, eq, nd;	
	ApplyStop(stopTypeNBar, stopModeBars, bars, 1, 0);
	eq = Equity(1,0);
	if ( dir == 0 )	result = Buy AND 
					//sum_since(nd, Buy) > 0 AND 
					sum_since(nd, Buy) <= numsig;
	else			result = Short AND 
					//sum_since(nd, Short) > 0 AND 
					sum_since(nd, Short) <= numsig;
	return result;
}

/// @link https://forum.amibroker.com/t/can-this-be-coded-with-no-loop/30829/12
SetOption("ReverseSignalForcesExit", 0);

t=TimeNum();
tStarts = 091500;
tEnds = 235959;
session = t >= tStarts AND t <= tEnds;
nd = session AND Ref(session,-1) == 0;
nd = IIf(session == Ref(session,-1), Day()!=Ref(Day(),-1), nd);
ema200 = EMA(C,200);

num_sig = 3;// number of signals allowed per day
distance = 30;// minimum distance between signals of same direction

Buy = Cross(C,ema200) AND session;
Sell = Ref(nd,1);
BuySig = sig(0, distance, num_sig);
Buy = Sell = 0;// Reset

Short = Cross(ema200,C) AND session;
Cover = Ref(nd,1);
ShortSig = sig(1, distance, num_sig);
Short = Cover = 0;// Reset

Buy = BuySig /*AND...*/;
Short = ShortSig /*AND...*/;

Plot( C, "Price", colorDefault, styleBar );
PlotShapes(shapeUpArrow * Buy, colorBrightGreen, 0, L);
PlotShapes(shapeDownArrow * Short, colorRed, 0, H);
Plot(nd, "", colorRed, styleHistogram | styleOwnScale, 0, 1 );

SetBarsRequired(1500);
1 Like

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.