Backtesting code of scalingout

Hi,

I have this back testing code. I am basically booking 50% of my position on 1st Target, and remaining if it hits second target or trail stop. So idea here is to initially buy 2 lots and book 1 lot for 1st target and the remining i.e., 1 lot for either 2nd target or trail stop. So I am using Scale Out feature of AFL. When I am back testing using "All Quote" as Range option I am getting results only until 26th Sep. On 27th and 28th Sep I had trades. Its not displaying in the tradelist window. Then I changed Range as From to Dates, but still the same problem. If I change the range as "From To Dates" and select individual date say for example start and end date as both 27 or 28 then it is displaying.
I don't know what I am doing wrong. But trades are clearly getting plotted on a chart for 27th and 28th. Problem i am facing is when I am doing a back testing. Need help on this..

Here are my questions..

First, Am I doing this right. This is the first time I have written back testing code which does scaleout / scalein?

Why it is not displaying last 2 days trades in the tradelist when I am doing a back testing ?

How to control the exit price when I am doing the scale out when it achieves the 1st target? Currently I don't have any control over this.. This is so important.

Below is my code..

_SECTION_BEGIN( "Index Based Strategy Ver 3.0" );

SetChartOptions( 0, chartShowDates );
SetOption("InitialEquity", 100000 ); 
SetOption("MaxOpenPositions", 2 );
SetOption("AccountMargin", 1);
SetOption("FuturesMode", 1);


_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

PER = Param( "Average Period", 5 );
TG2MULTIPLIER = Param("Target 2 Multiplier", 2, 1.5, 5, 0.5);
N = Param("No of trades allowed per symbol ?", 20, 1, 20, 1);
LOTSIZE = Param("Lot Size", 2, 2, 100, 2);


TimeFrameSet(inDaily);
AVERAGE_MINVALUEDIFF = MA(Min(abs(H - O), abs(O - L)), PER);
TimeFrameRestore();
AVERAGE_MINVALUEDIFF = TimeFrameExpand(AVERAGE_MINVALUEDIFF, inDaily);

TODAYS_OPENPRICE = TimeFrameGetPrice("O", inDaily);

UPPER_BAND = TODAYS_OPENPRICE + AVERAGE_MINVALUEDIFF;
LOWER_BAND = TODAYS_OPENPRICE - AVERAGE_MINVALUEDIFF;

R1 = UPPER_BAND + AVERAGE_MINVALUEDIFF;
R2 = R1 + (AVERAGE_MINVALUEDIFF * TG2MULTIPLIER);

S1 = LOWER_BAND - AVERAGE_MINVALUEDIFF;
S2 = S1 - (AVERAGE_MINVALUEDIFF * TG2MULTIPLIER);

Plot( UPPER_BAND, "UPPER BAD", colorGreen );
Plot( R1, "R1", colorGreen, styleDashed );
Plot( R2, "R2", colorGreen, styleDashed );

Plot( LOWER_BAND, "LOWER_BAND", colorRed );
Plot( S1, "S1", colorRed, styleDashed );
Plot( S2, "S2", colorRed, styleDashed );


tn = TimeNum();
NewDay = (Day()!= Ref(Day(), -1)) OR BarIndex() == 0;  

SignalStartTime = 94500;
SignalEndTime = 144500;  // in HHMMSS format
tradeEndTime = 150000;

timeOK = tn>= SignalStartTime AND tn <= SignalEndTime;


BUY0 = Cross(H, UPPER_BAND) AND timeOK;
SHORT0 = Cross(LOWER_BAND, L) AND timeOK;

Buy = Sell = Short = Cover = BuyPrice = ShortPrice = SellPrice = CoverPrice = Null;


Short_Trade_Entry = Long_Trade_Entry = 0;
Long_Trade_Stoploss = Short_Trade_Stoploss = 0;

bflag = sflag = 0;
signalGeneratedIndex = 0;
no_of_trades = 0;

TSL_LONG = Null;
TSL_SHORT = 999999;

for( i = 4; i < BarCount; i++ )
{
	
	// reset trade counter on the new day
    if( newDay[ i ] ) no_of_trades = 0;
    
	// BUY CONDITION
	if( BUY0[i] AND bflag == 0 AND sflag == 0 AND no_of_trades < N)
    {
        Buy[i] = 1;
        bflag = 1;
        BuyPrice[i] = UPPER_BAND[i];
       
        Long_Trade_Entry = BuyPrice[i];
        Long_Trade_Stoploss = LOWER_BAND[i];
		signalGeneratedIndex = i;
		 no_of_trades++;
    }
    if( bflag )
    {
        // Trailing stoploss for buy trades
        if( Buy[i] ) TSL_LONG[i] = Max( TSL_LONG[i - 1], Long_Trade_Stoploss );
        else TSL_LONG[i] = Max( TSL_LONG[i - 1], Long_Trade_Stoploss + (H[i] - Long_Trade_Entry) );
        
         //SACLEOUT on acheive of first Target..
		if(H[i] >= R1[i]) {
			Buy[i] = sigScaleOut;
		}
        
    }
    if( ( SHORT0[i] OR tn[i-1] == tradeEndTime OR L[i] <= Long_Trade_Stoploss OR H[i] >= R2[i] OR L[i] <= TSL_LONG[i-1]) AND 
				signalGeneratedIndex != i AND bflag == 1 )
    {
        Sell[i] = 1;
        bflag = 0;
        SellPrice[i] = C[i];
		
		if(L[i] <= Long_Trade_Stoploss) {
			SellPrice[i] = Long_Trade_Stoploss;
		} else if(L[i] <= TSL_LONG[i-1]) {
			SellPrice[i] = TSL_LONG[i-1];
		} else if(H[i] >= R2[i]) {
			SellPrice[i] = R2[i];
		} else if(tn[i-1] == tradeEndTime) {
			SellPrice[i] = O[i];
		}
		
		if(SHORT0[i]) {
			i--;
			continue;
		}
		
    }
    
    //SHORT CONDITION
    if( SHORT0[i] AND sflag == 0 AND bflag == 0 AND no_of_trades < N)
    {
        Short[i] = 1;
        sflag = 1;
        ShortPrice[i] = LOWER_BAND[i];

        Short_Trade_Entry = ShortPrice[i];
        Short_Trade_Stoploss = UPPER_BAND[i];
		signalGeneratedIndex = i;
		 no_of_trades++;
    }
	if( sflag )
    {
        if( Short[i] ) TSL_SHORT[i] = Min( TSL_SHORT[i - 1], Short_Trade_Stoploss);
        else TSL_SHORT[i] = Min( TSL_SHORT[i - 1], Short_Trade_Stoploss - (Short_Trade_Entry - L[i]));
        
        //SACLEOUT on acheive of first Target..
		if(L[i] <= S1[i]) {
			Short[i] = sigScaleOut;
		}
		
    }
    if( ( Buy0[i] OR tn[i-1] == tradeEndTime  OR H[i] >= Short_Trade_Stoploss OR L[i] <= S2[i] OR H[i] >= TSL_SHORT[i-1] ) AND 
			signalGeneratedIndex != i AND sflag == 1 )
    {
        Cover[i] = 1;
        sflag = 0;
        CoverPrice[i] = C[i];
        
       if(H[i] >= Short_Trade_Stoploss) {
			CoverPrice[i] = Short_Trade_Stoploss;
		} else if (H[i] >= TSL_SHORT[i-1]) {
			CoverPrice[i] = TSL_SHORT[i-1];
		} else if(L[i] <= S2[i]) {
			CoverPrice[i] = S2[i];
		} else if(tn[i-1] == tradeEndTime) {
			CoverPrice[i] = O[i];
		}
		
		if(BUY0[i]) {
			i--;
			continue;
		}

    }
    
    
}
TSL_SHORT = IIf( TSL_SHORT == 999999, Null, TSL_SHORT );

SetPositionSize(LOTSIZE, spsShares);
// scale out 50% of position when first trget is acheived...
SetPositionSize( 50, spsPercentOfPosition * ( Short == sigScaleOut OR Buy == sigScaleOut ) ); 

Plot( TSL_LONG, "TSL Buy", colorBlue, styleDashed );
Plot( TSL_SHORT, "TSL Short", colorBlue, styleDashed );

PlotShapes( IIf( Buy==1, shapeSquare, shapeNone ), colorGreen, 0, L, Offset = -40 );
PlotShapes( IIf( Buy==1, shapeSquare, shapeNone ), colorLime, 0, L, Offset = -50 );
PlotShapes( IIf( Buy==1, shapeUpArrow, shapeNone ), colorWhite, 0, L, Offset = -45 );
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorRed, 0, H, Offset = -70 );
PlotShapes( IIf( Short==1, shapeSquare, shapeNone ), colorRed, 0, H, Offset = 40 );
PlotShapes( IIf( Short==1, shapeSquare, shapeNone ), colorOrange, 0, H, Offset = 50 );
PlotShapes( IIf( Short==1, shapeDownArrow, shapeNone ), colorWhite, 0, H, Offset = -45 );
PlotShapes( IIf( Cover, shapeUpArrow, shapeNone ), colorBlue, 0, L, Offset = -70  );



_SECTION_END();

Here are the list of trades displayed when Range selected as 1st Sep to 29 Sep. Notice that there are no trades for 27th and 28th.
image

But notice when from to date selected as 27 then it displays 27th trade
image

Also notice when from to date selected as 28 then it displays 28th trade
image

I am totally struck in this issue.. Any help on this would be much appreciated..

Thanks and Regards,
Vinay V

@vinaykumar, as a first step, I suggest you to use the Detailed log report to see if there is any reason that explains the skipped trades.

immagine

2 Likes

I did see the detailed log. I am not able to see any differences.

Trades are getting plotted on the chart, but not displaying in backtesting.. See the below trade of 28th Sep. First red dotted line is the first target, second red dotted line is the second target. Solid red line is the entry.. Blue dotted above is the trail stop.

image

I did notice one peculiar thing which I can't understand when I saw a detailed log. Its saying not entered because of insufficient fund or wrong position size/value.. I am sure I am doing something wrong here, but unable to crack it.. This log is when I am closing my position when it hit 2nd Target. Why is it trying to enter new position ?

image

Problem resolved. I was not properly scaling out. I was not setting properly exit code for Short or Buy array. Thanks.. Seeing the detailed log closely did help @beppe

But one my question is still outstanding, I will create a new topic for that.

Also going through below KB helped.

http://www.amibroker.com/kb/2006/03/06/re-balancing-open-positions/

1 Like

Here is the complete solution. It may benefit other users if they are facing similar problems. Its a complete strategy with trail stop and scaleout.

_SECTION_BEGIN( "Index Based Strategy Ver 3.0" );

SetChartOptions( 0, chartShowDates );
SetOption("InitialEquity", 100000 ); 
SetOption("MaxOpenPositions", 2 );
SetOption("AccountMargin", 10);
SetOption("FuturesMode", 1);


_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 


AVGPER = Param( "Average Period", 5 );
TG2MULTIPLIER = Param("Target 2 Multiplier", 2, 1.5, 5, 0.5);
N = Param("No of trades allowed per symbol ?", 20, 1, 20, 1);
LOTSIZE = Param("Lot Size", 2, 2, 100, 2);

tn = TimeNum();
NewDay = (Day()!= Ref(Day(), -1)) OR BarIndex() == 0;  

FirstCandleTime = 91500;
SignalStartTime = 94500;
SignalEndTime = 144500;  // in HHMMSS format
tradeEndTime = 150000;

timeOK = tn>= SignalStartTime AND tn <= SignalEndTime;

StartBar = tn == FirstCandleTime;

FIRST_BAR_OPEN = ValueWhen( StartBar, O );

TimeFrameSet(inDaily);
AVERAGE_MINVALUEDIFF = MA(Min(abs(H - O), abs(O - L)), AVGPER);
TimeFrameRestore();
AVERAGE_MINVALUEDIFF = TimeFrameExpand(AVERAGE_MINVALUEDIFF, inDaily);

TODAYS_OPENPRICE = TimeFrameGetPrice("O", inDaily);

UPPER_BAND = FIRST_BAR_OPEN + AVERAGE_MINVALUEDIFF;
LOWER_BAND = FIRST_BAR_OPEN - AVERAGE_MINVALUEDIFF;

R1 = UPPER_BAND + AVERAGE_MINVALUEDIFF;
R2 = R1 + (AVERAGE_MINVALUEDIFF * TG2MULTIPLIER);

S1 = LOWER_BAND - AVERAGE_MINVALUEDIFF;
S2 = S1 - (AVERAGE_MINVALUEDIFF * TG2MULTIPLIER);

BAND_DIFF = UPPER_BAND - LOWER_BAND;

Plot( UPPER_BAND, "UPPER BAD", colorGreen );
Plot( R1, "R1", colorGreen, styleDashed );
Plot( R2, "R2", colorGreen, styleDashed );

Plot( LOWER_BAND, "LOWER_BAND", colorRed );
Plot( S1, "S1", colorRed, styleDashed );
Plot( S2, "S2", colorRed, styleDashed );


BUY0 = (Cross(H, UPPER_BAND) OR (Ref(C, -1) < UPPER_BAND AND H > UPPER_BAND)) AND timeOK;
SHORT0 = (Cross(LOWER_BAND, L) OR (Ref(C, -1) > LOWER_BAND AND L < LOWER_BAND)) AND timeOK;

Buy = Sell = Short = Cover = BuyPrice = ShortPrice = SellPrice = CoverPrice = Null;


Short_Trade_Entry = Long_Trade_Entry = 0;
Long_Trade_Stoploss = Short_Trade_Stoploss = 0;

bflag = sflag = 0;
signalGeneratedIndex = 0;
no_of_trades = 0;

TSL_LONG = Null;
TSL_SHORT = 999999;

longexit = shortexit = 0;

for( i = 4; i < BarCount; i++ )
{
	
	// reset trade counter on the new day
    if( newDay[ i ] ) no_of_trades = 0;
    
	// BUY CONDITION
	if( BUY0[i] AND bflag == 0 AND sflag == 0 AND no_of_trades < N)
    {
        Buy[i] = 1;
        bflag = 1;
        BuyPrice[i] = UPPER_BAND[i];
       
        Long_Trade_Entry = BuyPrice[i];
        Long_Trade_Stoploss = LOWER_BAND[i]; //+ BAND_DIFF[i]/4;
		signalGeneratedIndex = i;
		no_of_trades++;
    }
    if( bflag )
    {
        // Trailing stoploss for buy trades
        if( Buy[i] ) TSL_LONG[i] = Long_Trade_Stoploss; //Max( TSL_LONG[i - 1], Long_Trade_Stoploss );
        else TSL_LONG[i] = Max( TSL_LONG[i - 1], Long_Trade_Stoploss + (H[i] - Long_Trade_Entry) );
        
         //SACLEOUT on acheive of first Target..
		if(longexit == 0 AND H[i] >= R1[i]) {
			longexit = 1;
			Buy[i] = sigScaleOut;
			BuyPrice[i] = R1[i];
		}
        
    }
    if( ( SHORT0[i] OR tn[i-1] == tradeEndTime OR L[i] <= Long_Trade_Stoploss OR H[i] >= R2[i] OR L[i] <= TSL_LONG[i-1]) AND 
				signalGeneratedIndex != i AND bflag == 1 )
    {
        
		longexit = 3;
		bflag = 0;
		SellPrice[i] = C[i];
		 
		if(L[i] <= Long_Trade_Stoploss) {
			SellPrice[i] = Long_Trade_Stoploss;
		} else if(L[i] <= TSL_LONG[i-1]) {
			SellPrice[i] = TSL_LONG[i-1];
		} else if(H[i] >= R2[i]) {
			longexit = 2;
			SellPrice[i] = R2[i];
		} else if(tn[i-1] == tradeEndTime) {
			SellPrice[i] = O[i];
		}
		
		Sell[i] = longexit + 1;
        
        longexit = 0;
        
		if(SHORT0[i]) {
			i--;
			continue;
		}
		
    }
    
    //SHORT CONDITION
    if( SHORT0[i] AND sflag == 0 AND bflag == 0 AND no_of_trades < N)
    {
        Short[i] = 1;
        sflag = 1;
        ShortPrice[i] = LOWER_BAND[i];

        Short_Trade_Entry = ShortPrice[i];
        Short_Trade_Stoploss = UPPER_BAND[i]; //- BAND_DIFF[i]/4;
		signalGeneratedIndex = i;
		 no_of_trades++;
    }
	if( sflag )
    {
        if( Short[i] ) TSL_SHORT[i] = Short_Trade_Stoploss; //Min( TSL_SHORT[i - 1], Short_Trade_Stoploss);
        else TSL_SHORT[i] = Min( TSL_SHORT[i - 1], Short_Trade_Stoploss - (Short_Trade_Entry - L[i]));
        
        //SACLEOUT on acheive of first Target..
		if(shortexit == 0 AND L[i] <= S1[i]) {
			shortexit = 1;
			Short[i] = sigScaleOut;
			ShortPrice[i] = S1[i];
		}
		
    }
    if( ( Buy0[i] OR tn[i-1] == tradeEndTime  OR H[i] >= Short_Trade_Stoploss OR L[i] <= S2[i] OR H[i] >= TSL_SHORT[i-1] ) AND 
			signalGeneratedIndex != i AND sflag == 1 )
    {
		shortexit = 3;
        sflag = 0;
        CoverPrice[i] = C[i];
        
       if(H[i] >= Short_Trade_Stoploss) {
			CoverPrice[i] = Short_Trade_Stoploss;
		} else if (H[i] >= TSL_SHORT[i-1]) {
			CoverPrice[i] = TSL_SHORT[i-1];
		} else if(L[i] <= S2[i]) {
			CoverPrice[i] = S2[i];
			shortexit = 2;
		} else if(tn[i-1] == tradeEndTime) {
			CoverPrice[i] = O[i];
		}
		
		Cover[i] = shortexit + 1;
		shortexit = 0;
		
		if(BUY0[i]) {
			i--;
			continue;
		}

    }
    
    
}
TSL_SHORT = IIf( TSL_SHORT == 999999, Null, TSL_SHORT );



SetPositionSize(LOTSIZE, spsShares);
// scale out 50% of position when first trget is acheived...
SetPositionSize( 50, spsPercentOfPosition * ( Short == sigScaleOut OR Buy == sigScaleOut ) ); 

Plot( TSL_LONG, "TSL Buy", colorBlue, styleDashed );
Plot( TSL_SHORT, "TSL Short", colorBlue, styleDashed );

PlotShapes( IIf( Buy==1, shapeSquare, shapeNone ), colorGreen, 0, L, Offset = -40 );
PlotShapes( IIf( Buy==1, shapeSquare, shapeNone ), colorLime, 0, L, Offset = -50 );
PlotShapes( IIf( Buy==1, shapeUpArrow, shapeNone ), colorWhite, 0, L, Offset = -45 );
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorRed, 0, H, Offset = -70 );
PlotShapes( IIf( Short==1, shapeSquare, shapeNone ), colorRed, 0, H, Offset = 40 );
PlotShapes( IIf( Short==1, shapeSquare, shapeNone ), colorOrange, 0, H, Offset = 50 );
PlotShapes( IIf( Short==1, shapeDownArrow, shapeNone ), colorWhite, 0, H, Offset = -45 );
PlotShapes( IIf( Cover, shapeUpArrow, shapeNone ), colorBlue, 0, L, Offset = -70  );

_SECTION_END();
8 Likes

Thank you for sharing the trailing scaleout code. One thing i want to ask how to debug, such a long conditions in for loop.