Incoporating Looping trailing stop AND Closing trades in delisted symbols

Hi AB Community,

My goal is to be able to use a looping trailing stop (say, the Chandelier stop loss) and NOT the ApplyStop() function, whilst back testing with delisted data from Norgate.

My example is one where I set the 1-bar trade delays in my backtesting settings.

The problem without having some code in the SELL criteria of the looping stop loss is that the results present a number of stocks that are held until the end of the back test - with a trade category of "Open Long". This is clearly not right as it impacts the amount of equity available for trading throughout the test period and given the stock delisted it doesn't release these funds as intended.

To keep it simple, I have copied the two pieces of code I think should be somehow combined , with particular emphasis on the second code set Closing trades in delisted symbols and where the SELL criteria goes within the looping stop loss How to plot a trailing stop in the Price chart.

So where does the Sell = /* your regular sell rules */ OR exitLastBar go?

Much appreciate for any assistance.

How to plot a trailing stop in the Price chart

StopLevel = 1 - Param("trailing stop %", 3, 0.1, 10, 0.1)/100;

Buy = Cross( MACD(), Signal() );
Sell = 0;
trailARRAY = Null;
trailstop = 0;

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

   if( trailstop == 0 AND Buy[ i ] ) 
   { 
      trailstop = High[ i ] * stoplevel;
   }
   else Buy[ i ] = 0; // remove excess buy signals

   if( trailstop > 0 AND Low[ i ] < trailstop )
   {
      Sell[ i ] = 1;
      SellPrice[ i ] = trailstop;
      trailstop = 0;
   }

   if( trailstop > 0 )
   {
      trailstop = Max( High[ i ] * stoplevel, trailstop );
      trailARRAY[ i ] = trailstop;
   }

}

Closing trades in delisted symbols

SetTradeDelays(1,1,1,1);
bi = BarIndex();
exitLastBar = bi == LastValue( bi - 1 );
Sell = /*your regular sell rules*/ OR exitLastBar

If you copy code from elsewhere then please add link to the code.


E.g.

/// Original code by amibroker.com at:
/// @link https://www.amibroker.com/kb/2007/03/24/how-to-plot-a-trailing-stop-in-the-price-chart/
/// modified at:
/// @link https://forum.amibroker.com/t/incoporating-looping-trailing-stop-and-closing-trades-in-delisted-symbols/25518/2
StopLevel = 1 - Param("trailing stop %", 3, 0.1, 10, 0.1)/100;

SetTradeDelays(0,0,0,0);

bi = BarIndex();
second_to_lastBar = LastValue(bi)-1;
exitLastBar = bi == second_to_lastBar;

BuyPrice = Open;
Buy = Cross( MACD(), Signal() );
Buy = Ref(Buy, -1);

Sell = 0;

SellSignal = /*your regular sell rules OR*/ exitLastBar;
SellSignal = Ref(SellSignal, -1);

trailARRAY = Null;
trailstop = 0;
for( i = 1; i < BarCount; i++ )
{
	if( trailstop == 0 AND Buy[ i ] ) 
	{ 
		trailstop = High[ i ] * stoplevel;
	}
	else Buy[ i ] = 0; // remove excess buy signals

	if( trailstop > 0 AND (Low[ i ] < trailstop OR SellSignal[ i ]))
	{
		Sell[ i ] = 1;

		if ( SellSignal[ i ] ) 
			SellPrice[ i ] = Open[ i ];
		else
			SellPrice[ i ] = trailstop;
			
		trailstop = 0;
	}

	if( trailstop > 0 )
	{
		trailstop = Max( High[ i ] * stoplevel, trailstop );
		trailARRAY[ i ] = trailstop;
	}
}

Other than that...

Instead of looping you could just use ApplyStop function and instead of Sell = 0; using

/// Incomplete Snippet
/// see here for more
/// @link https://www.amibroker.com/kb/2007/03/24/how-to-plot-a-trailing-stop-in-the-price-chart/

Sell = /*your regular sell rules*/ OR exitLastBar;
ApplyStop( stopTypeTrailing, stopModePercent, StopLevel, True );

Thanks fxshrat. Soon after my original post, I found this on the Norgate site:
How do I exit a position in a backtest prior to a stock being delisted?

Assuming a trade delay of 1 bar, you need to have an "exit" signal on the second last bar to simulate exiting a delisted stock. This will cause AmiBroker to exit the position on the final day of trading. You also want to avoid entering any new positions during the final 2 days.

OnSecondLastBarOfDelistedSecurity = !IsNull(GetFnData("DelistingDate")) AND (BarIndex() == (LastValue(BarIndex()) -1) OR DateTime() >= GetFnData("DelistingDate") ) ;
OnLastTwoBarsOfDelistedSecurity = !IsNull(GetFnData("DelistingDate")) AND (BarIndex() >= (LastValue(BarIndex()) -1) OR DateTime() >= GetFnData("DelistingDate") );

Buy = Buy AND NOT OnLastTwoBarsOfDelistedSecurity;
Sell = Sell OR OnSecondLastBarOfDelistedSecurity;

// If you have a short selling system you will also need to include the following:
Short = Short AND NOT OnLastTwoBarsOfDelistedSecurity;
Cover = Cover OR OnSecondLastBarOfDelistedSecurity;
  

I inserted it and appears to work.

Your main question was about incorporating regular sell condition into loop. What is part of (regular, non-trailstop) Sell condition is of secondary importance since it is up to you what sell exit you look for there.

There already is trade delay added to loop version!
Also you should not use SetTradeDelays (delay greater zero) with that loop version but Ref() function as I did.

Adding

Sell = Sell OR OnSecondLastBarOfDelistedSecurity;

after loop is incorrect (e.g. it would use trail stop sell price for delisting sell condition and not Open, also trail would not reset).

Thanks fx, I'll take another look at the code, cheers.

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