Exit ignored because signal predates already processed event

Hi,
I have a trading strategy on a Portfolio of S&P100 index constituents. I allow same bar Exit and have a Positionscore to select the stocks to trade whenever there are more signals than max open positions of 10.

When there was an entry Signal in a stock yesterday and this stock was ignored because of Positionscore and today the entry Signal on the same stock is taken, the first Exit Signal is ignored. In the detailed log, it says ‘Exit ignored because Signal predates already processed Event’.

I tried to Exit with the custom backtester with the following code:

SetCustomBacktestProc( "" );

if( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();
    bo.PreProcess();

    for( i = 0; i < BarCount; i++ )
    {

        for( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() );

        for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
        {
            if( sig.IsExit() )
                bo.ExitTrade( i, sig.Symbol, sig.Price );
        }

        bo.ProcessTradeSignals( i );
    }

    bo.PostProcess();
}

However, it does not work. I am new to custom backtester and trying to learn.

Does anybody know how to avoid that the backtester ignores the Exit Signal, when from the individual ticker’s perspective that SELL belongs to the previous BUY Signal?

Your help is very much appreciated.

Roland

The message is correct and you do NOT need to “avoid” it.

It merely says: YOU CAN NOT TURN BACK TIME.

And it is there to clearly say that signal won’t be acted upon because it physically can’t (again no time travel possible).

Backtester internally remembers the ORDER in which signals occur within bar and if you already processed say 3rd signal in sequence you can not turn back time and process 2nd (earlier).

Also you do NOT need custom backtester. In 99% of cases there is no need for CBT and
if you are not experienced programmer, don’t use it. Signal matching is automatic and does not need CBT.

How do I know? I can see that from the code. I can detect skill of every person after looking at few lines of code.

Basic problem with your coding is not really the code itself, but pretty obvious mistake.
You are mixing midlevel with highlevel and you are attempting to process same signal twice.

Hi Tomasz,

Yes, I am not an experienced programmer but eager to learn.

I am live trading my System an have exited a trade in live trading according to my rules but this has not happened in backtesting.

I enter my trades at the opening and Exit at the Close if there is an Exit Signal and I allow same bar Exit. If there was a buy Signal yesterday but because of Portfolio constraints, I could not take this trade but can take it today and then I get an Exit Signal on same entry day, in backtesting the System does not Exit. I would like to Change that in order to get more precise backtesting results.

How can it be done? Amibroker Support told me to use CBT and that is what I tried to do.

Thank you for any help.

Roland

Hello,

I was puzzling over the same message in the detailed log. I’m hoping my train of thought is correct, but I’m still left with some questions that probably require mid-level CBT.

E.g. simple counter-trend system trading S&P100 constituents. Buy signal generated on close and position entered next day on open. Sell signal generated and “executed” on close. Allow same bar exit. Maximum open positions = 10, PositionScore to select top 10 positions.

// Counter-Trend System w/ PositionScore

SetOption("UsePrevBarEquityForPosSizing",True);
SetOption("MinShares",1); 
SetOption("AllowSameBarExit",True);
SetOption("HoldMinBars",0);
SetTradeDelays(1,0,0,0); 

InitialEquity = 100000;
SetOption("InitialEquity",InitialEquity);
MaxPos = 10;
SetOption("MaxOpenPositions",MaxPos);
SetPositionSize(100/MaxPos,spsPercentOfEquity);

// 

Oversold = C < MA(C,10);

Trend = C > MA(C,100);

// 

BuySignal = Oversold AND Trend;

BuyPrice = O;
Buy = BuySignal;

SellSignal = C > Ref(C,-1);

SellPrice = C;
Sell = SellSignal;

PositionScore = 1000 + ROC(C,100); 

1/3/2017 CHTR generates buy signal - rank #20 - position not entered b/c not in top 10

1/4/2017 CHTR generates buy signal - rank #10 - position entered on open at 286.98

1/4/2017 CHTR generates sell signal, but “Exit ignored because signal predates already processed event”

1/5/2017 CHTR generates sell signal, position exited on close at 296.17

1 - exit ignored

According to UserGuide the default backtestRegular mode:

“If trade is NOT entered on first entry signal due to weak rank, not enough cash or reaching the maximum open position count, subsequent entry signals are ignored until matching exit signal.”

In other words, the first sell signal (1/4/2017) is ignored because it refers to first buy signal (1/3/2017) and “physically can’t” execute because the position was never taken. Hence, we need to wait for next sell signal (1/5/2017) to exit position entered on second buy signal (1/4/2017).

But this raises another puzzle: why was the position entered on 1/4/2017 in the first place when the first “trade” had not yet completed? After all “If trade is NOT entered on first entry signal … subsequent entry signals are ignored until matching exit signal.”

It seems this is because the combination of AllowSameBarExit and the default HoldMinBars (zero) means that in this instance the sell signal is processed before the buy signal. There is a buy signal and a sell signal on the same bar. According to scenario 2 (cf. http://www.amibroker.com/guide/h_portfolio.html):

“If we are flat on given symbol, then entry is taken … but we do not move to next bar immediately.”

“If we are long on given symbol, then sell signal is taken. … Only after processing all signals we move to the next bar.”

On 1/4/2017 we are “long” ghost trade from 1/3/2017 buy signal which means the sell signal takes precedence (but signal ignored because it refers to a ghost trade). But, before moving to the next bar, the backtester checks whether there is also a buy signal on the bar - which there is - and enters the position on 1/4/2017 without the possibility of exiting this position on the same bar.

One could remove “ghost trades” by ranking the PositionScores and restricting buy signals to the top 10 issues (cf. https://www.amibroker.com/kb/2014/11/26/handling-limit-orders-in-the-backtester/).

// Counter-Trend System w/ Ranking

SetOption("UsePrevBarEquityForPosSizing",True);
SetOption("MinShares",1); 
SetOption("AllowSameBarExit",True);
SetOption("HoldMinBars",0);
SetTradeDelays(1,0,0,0); 

InitialEquity = 100000;
SetOption("InitialEquity",InitialEquity);
MaxPos = 10;
SetOption("MaxOpenPositions",MaxPos);
SetPositionSize(100/MaxPos,spsPercentOfEquity);

// 

List = CategoryGetSymbols(categoryWatchlist,12); // #12 = S&P 100 

if(Status("stocknum")==0)
{
	StaticVarRemove("values*");
	
	for( n = 0; (Symbol = StrExtract(List,n)) !=""; n++)
	{
		SetForeign(symbol); 
		
		values = 1000 + ROC(C,100); 
		
		RestorePriceArrays();
		StaticVarSet("values"+symbol,values);
		_TRACE(symbol);
	}
	
	StaticVarGenerateRanks("rank","values",0,1224);
}

symbol = Name();
values = StaticVarGet("values" + symbol);
rank = StaticVarGet("rankvalues" + symbol);

PositionScore = values;

// 

Oversold = C < MA(C,10);

Trend = C > MA(C,100);

Top = rank <= 10; 

// 

BuySignal = Oversold AND Trend AND Top;

BuyPrice = O;
Buy = BuySignal;

SellSignal = C > Ref(C,-1);

SellPrice = C;
Sell = SellSignal;

This seems to solve the “Exit ignored because signal predates already processed event” issue. But it does not completely address the problem.

If we are actually long on a given symbol, then the sell signal will still take precedence. If the bar has both buy and sell signal, then according to the backtester we would exit the long on close but also enter a new long on open!? At least this is my interpretation of the detailed log:

1/3/2017 NVDA generates buy signal - rank #1 - position entered on open at 104.4

1/4/2017 NVDA generates sell signal, position exited on close at 104.39

1/4/2017 NVDA generates buy signal - rank #1 - position entered on open at 103.4

2 - same bar conflict

(As an aside, I’m not clear why CHTR is not listed as a buy as above?)

In any case, if I understand “Scenario 2” properly, then we have a same bar, same symbol signal conflict. On 1/4/2017 we are long NVDA therefore sell signal takes precedence, subsequent to which buy signal is processed.

Changing HoldMinBars to one (“Scenario 3”) yields same result in this case because entering NVDA on 1/4/2017 does not violate HoldMinBars = 1 as sell signal preceded it, thereby guaranteeing that we hold NVDA minimum 1 bar.

3 - same bar conflict

If I understand the issue correctly, then it seems best to either change BuyPrice=SellPrice and set AllowSameBarExit to False avoiding this problem altogether, or delving into mid-level CBT to process signals manually (e.g., entry signal takes precedence over exit signal, if flat then execute entry before exit as per scenario 2, however if long then ignore entry signal and only execute exit signal)?

Is this correct? Any pointers would be much appreciated.

1 Like

Did you ever get this solution figured out. I find this issue very confusing.

See response marked as Solution. Signals are ordered in TIME. Example:

  1. Signal A ( Sell)
  2. Signal B (Buy)

Once Signal B (Buy) was already acted upon, signal A won't be acted upon because it is already in the PAST and time does not go backwards.

1 Like

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