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/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 ...
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 ...
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 ...
... with the associated exploration to show the signals ...
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