Backtesting - Exit ignored because signal predates already processed event

Hi

I'm attempting to work out why I'm receiving "Exit ignored because signal predates already processed event" during backtesting of a system that is occasionally simultaneously long and short on the same instrument. This message only seems occur when I need to exit a long and short trade on the same bar.

Have searched the forum and found the following posts ...

https://forum.amibroker.com/t/exit-ignored-because-signal-predates-already-processed-event/863

https://forum.amibroker.com/t/help-please-pyramiding-multiple-positions-of-the-same-symbol-and-allowsamebarexit/3834

https://forum.amibroker.com/t/partial-exit-with-sigscaleout-doesnt-work/12476

... which all have the same message as the topic subject but they haven't helped me work out what I'm doing wrong.

In my attempt to solve the problem, without asking the forum, I've created a very simple piece of AFL to create a basic system that can be long and short for the same instrument at the same time.

Version( 6.30 );

// Initialise all backtesting/optimisation options to a default value. It also
// serves as a reference check to make sure that all of the factors have been
// accounted for.
#include_once <Functions\BoilerPlate.afl>;

SetTradeDelays( 0, 0, 0, 0 ); // No trade delays for entry or exit

SetOption( "ReverseSignalForcesExit", False );
SetOption( "PortfolioReportMode", 1 ); // Detailed log in backtester results
SetOption( "SeparateLongShortRank", True );
SetOption( "AllowSameBarExit", True );
SetOption( "MaxOpenPositions", 2 );

SetPositionSize( 10, spsPercentOfEquity );

Buy = Sell = Short = Cover = 0;

BuyPrice = ShortPrice = Open;
SellPrice = CoverPrice = Close;

Short[ 0 ] = 1;
Buy[ 1 ] = 1;
Sell[ 2 ] = Cover[ 2 ] = 1;

if( Status( "action" ) == actionExplore )
{
	Filter = 1;
	AddColumn( O, "Open", 1.5 );
	AddColumn( H, "High", 1.5 );
	AddColumn( L, "Low", 1.5 );
	AddColumn( C, "Close", 1.5 );
	AddColumn( Buy, "Buy Signal", 1.0 );
	AddColumn( Sell, "Sell Signal", 1.0 );
	AddColumn( Short, "Short Signal", 1.0 );
	AddColumn( Cover, "Cover Signal", 1.0 );
}

SetBacktestMode( backtestRegularRawMulti ); // Required so can be long and short simultaneously for same instrument

The included BoilerPlate.afl I've used for some time to make sure I think about every setting I may need for my backtesting and alter in my main AFL code if I need to (I cannot remember where I downloaded it from buy thanks to BruceR for putting it together) ...

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//  BoilerPlate - Version 2
//              - BruceR 
//              - updated - 10/1/08 - cleanup and added more comments
//
//  The purpose of this include file is to initialize all backtesting/optimization "factors"
//  to a default value.  It also serves as a reference check to make sure that all of the
//  factors have been accounted for.
//
//  These factors fall into 3 categories -
//
//       1.  Factors that are in the AA Backtester Settings
//       2.  Factors that are NOT in Settings
//       3.  Factors that in Settings but can NOT be set programmatically
//
//  SO, the bottom line is that there is not a way to guarantee in one place that all 
//  factors are accounted for.  Theoretically, to cover all options, a Settings file AND
//  AFL settings should be used.
//
//  Experience has also shown that users are reluctant to utilize a distributed Settings file.  
//  The best trade-off seems to be to set as many as possible programmatically, and to check 
//  the ones that can only be set in settings.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//  Initialize the trading parameters

	//EnableRotationalTrading();

	BuyPrice = SellPrice = ShortPrice = CoverPrice = Open;

	SetTradeDelays( 1, 1, 1, 1 );

	SetOption(	 "InitialEquity",					10000	);
	SetOption(	 "MinShares", 						0.0001	);
	SetOption(	 "MinPosValue",						0		);
	SetOption(	 "FuturesMode", 					False	);
	SetOption(	 "AllowPositionShrinking", 			True	);
	SetOption(	 "ActivateStopsImmediately",		False	);
	SetOption(	 "ReverseSignalForcesExit", 		True	);
	SetOption(	 "AllowSameBarExit",				True	);
	SetOption(	 "CommissionMode", 					2		);
	SetOption(	 "CommissionAmount", 				0		);
	SetOption(	 "InterestRate", 					0		);
	SetOption(	 "AccountMargin",		 			100		);
	SetOption(	 "PortfolioReportMode",				0		);
	SetOption(	 "MaxOpenPositions", 				1		);
	SetOption(	 "WorstRankHeld", 					1		);						// Not in settings
	SetOption(	 "PriceBoundChecking",				False	);						// Not in settings
	SetOption(	 "UsePrevBarEquityForPosSizing",	True	);
	SetOption(	 "UseCustomBacktestProc",			False	);

	SetOption(	 "DisableRuinStop",					False	);						// Not in settings
	SetOption(	 "EveryBarNullCheck",				False	);						// Not in settings

	SetOption(	 "HoldMinBars",						0		);						// Not in settings
	SetOption(	 "HoldMinDays",						0		);						// Not in settings
	SetOption(	 "EarlyExitBars",					0		);						// Not in settings
	SetOption(	 "EarlyExitDays",					0		);						// Not in settings
	SetOption(	 "EarlyExitFee",					0		);						// Not in settings

	SetOption(	 "SeparateLongShortRank",			False	);						// Not in settings
	SetOption(	 "MaxOpenLong",						0		);						// Not in settings
	SetOption(	 "MaxOpenShort",					0		);						// Not in settings

	MaxPos				= 100 * 100 / GetOption( "MarginRequirement" );
	PositionSize		= -MaxPos / GetOption( "MaxOpenPositions" );

	RoundLotSize		= 0;  		// 0 for Funds, 100 for Stocks
	TickSize			= 0;  		// 0 for no min. size
	MarginDeposit		= 0;
	PointValue			= 1;		// For futures
	
	ExitAtTradePrice	= 0;
	ExitAtStop			= 1;
	ExitNextBar			= 2;

	ReEntryDelay		= 0;

	ApplyStop( stopTypeLoss, stopModeDisable, 0, ExitAtTradePrice, ReEntryDelay );
	ApplyStop( stopTypeProfit, stopModeDisable, 0, ExitAtTradePrice, ReEntryDelay );
	ApplyStop( stopTypeTrailing, stopModeDisable, 0, ExitAtTradePrice, ReEntryDelay );
	ApplyStop( stopTypeNBar, stopModeDisable, 0, ExitAtTradePrice, ReEntryDelay );

	//  THE FOLLOWING CANNOT BE SET PROGRAMMATICALLY AND SHOULD BE CHECKED

	//  Pad and align
	//  Reference symbol
	//  Risk-free rate Sharpe
	//  Risk-free rate UPI
	//  Add artificial future bar
	//  Limit trade size %
	//  Disable trade size limit
	//  Walk forward mode and data parameters
	//  Optimization target

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//  ALL CUSTOM SETTING SHOULD BE DONE AFTER THIS
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

So my very simple AFL should enter a short trade on the very first bar, enter a long trade on the second bar and exit both the long and the short trade on the third bar (well that's what I think should happen).

When I run a backtest I get the following detailed log ...

image

The short trade is entered on first bar, long trade is entered on the second bar but on the third bar only the short trade is exited. The sell exit signal is ignored because signal predates already processed event. I've run an exploration to make sure the entry/exit signals are being generated as I believe they should be ...

image

If I change my AFL code so that the long trade is entered first and the short trade is entered second ...

Short[ 1 ] = 1;
Buy[ 0 ] = 1;
Sell[ 2 ] = Cover[ 2 ] = 1;

... and re-run the backtest I get the following detailed log ...

image

... with the associated exploration to show the signals ...

image

This time the long trade is entered on first bar, the short trade is entered on the second bar and both the long and the short are exited on the third bar.

For my system I'd like both positions to exit on the same bar regardless of whether I've entered a long or short position first.

Is there a way of doing this?

Would appreciated a nudge in the right direction as I cannot seem to work it out.

Thanks

Craig

I might rephrase my question from the original post.

How would I write some AFL that will enter a short trade for a specific instrument, then enter a long trade for that same instrument on a subsequent bar and finally exit both the short and the long trades on the same bar further down the track?

Reason I ask is that I have a system that enters a short trade on one bar, enters a long trade on a subsequent bar and uses an n-bar exit strategy where n is a different value for long and short. So occasionally I exit both positions on the same bar.

With the bare basics code I submitted in my first post I'm unable to exit both positions on the same bar which I don't understand. Is there a SetOption settings that I'm missing or would I need to use the mid/low-level custom backtester to achieve the outcome I'm after.

Would really appreciated someone steering me in the right direction.

Thanks

Craig

You could definitely get the behavior you want with a low-level CBT. I'm not sure whether you can achieve your goal using the built-in backtester. The problem is you're trying to model something that, to the best of my knowledge, can't actually be done in live trading: being long and short the same instrument simultaneously in a single account.

Read the manual please http://www.amibroker.com/guide/h_portfolio.html

Scroll down to RESOLVING SAME BAR, SAME SYMBOL SIGNAL CONFLICTS and read carefully.

ONLY scenarios described in the manual are supported by built-in backtester.

Your scenario is not mentioned there, however as @mradtke wrote, you can write custom backtester procedure to do so.

1 Like

Thank you @mradtke and @Tomasz. Much appreciated.

I had read the RESOLVING SAME BAR, SAME SYMBOL SIGNAL CONFLICTS a number of times but obviously didn't understand it. Now I do. Live and learn. I'll work on a low-level CBT procedure to achieve what I need to achieve.

Thanks again

Cheers

Craig

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