Back testing Scaling-Out

Hi,

I am trying to understand how scaling out function works.

I have implemented the sample scaling out code, "Example of code that exits 50% on first profit target, 50% on next profit target and everything at trailing stop" quoted here: (AFL Function Reference - SETPOSITIONSIZE) over my base back code.

I am unit testing the trades generated by the base code (let's call it a HHV/ LLV break out strategy) vs the implemented scaling out strategy.

One particular trade in the base code has generated a large profit even with a wide exit point so I have set the scaling out rules tight so that 2 x profit exit and 1 x trailing exit is generated.

I am expecting all three trades to be generated on the same day and same price, where as the system is generating them in series. Why?

My code is here:

/*/*
        Version 20231226-01
*/

// Set backtest settings
SetBacktestMode(backtestRegular);
SetTradeDelays(0, 0, 0, 0); // Trade happens on the same day

PortEquity = Foreign("~~~EQUITY", "C");  // Setting previous day's portfolio equity (closing prices of ~~EQUITY)

// Customizable lookback period
LookbackPeriod = 20; // Default is 20 days, change this to modify the period

// Define the long entry and exit signals
HHVLookback = HHV(High, LookbackPeriod); // Highest high value of the last 'LookbackPeriod' days
LLVLookback = LLV(Low, LookbackPeriod); // Lowest low value of the last 'LookbackPeriod' days

Buy = Close > Ref(HHVLookback, -1); // Today's close is higher than the high of the lookback period
Sell = Close < Ref(LLVLookback, -1); // Today's close is lower than the low of the lookback period

// Defining Buy and Sell prices
BuyPrice = C; // Buying at today's close
SellPrice = C; // Selling at today's close

// Position Sizing and Risk Management
PercentRisk = 1;
RiskPerShare = BuyPrice - Ref(LLVLookback, -1); // Risk per share is the difference between buy price and stop loss
PositionSize = (PortEquity * PercentRisk * 0.01) / RiskPerShare; // Position size based on current equity

// the system will exit 
// 50% of position if FIRST PROFIT TARGET stop ishit 
// 50% of position is SECOND PROFIT TARGET stopis hit 
// 100% of position if TRAILING STOP is hit 

 FirstProfitTarget = 10; // profit  
 SecondProfitTarget = 20; // in percent 
 TrailingStop = 20; // also in percent 

 priceatbuy=0; 
 highsincebuy = 0; 

 exit = 0; 

for( i = 0; i < BarCount; i++ ) 
 { 
    if( priceatbuy == 0 AND Buy[ i ] ) 
     { 
        priceatbuy = BuyPrice[ i ]; 
     } 

    if( priceatbuy > 0 ) 
     { 
        highsincebuy = Max( High[ i ], highsincebuy ); 

       if( exit == 0 AND 
           High[ i ] >= ( 1 + FirstProfitTarget * 0.01 ) * priceatbuy ) 
        { 
          // first profit target hit - scale-out 
          exit = 1; 
          Buy[ i ] = sigScaleOut; 
        } 

       if( exit == 1 AND 
           High[ i ] >= ( 1 + SecondProfitTarget * 0.01 ) * priceatbuy ) 
        { 
          // second profit target hit - exit 
          exit = 2; 
          SellPrice[ i ] = Max( Open[ i ], ( 1 + SecondProfitTarget * 0.01 ) * priceatbuy ); 
        } 

       if( Low[ i ] <= ( 1 - TrailingStop * 0.01 ) * highsincebuy ) 
        { 
          // trailing stop hit - exit 
          exit = 3;    
          SellPrice[ i ] = Min( Open[ i ], ( 1 - TrailingStop * 0.01 ) * highsincebuy ); 
        } 

       if( exit >= 2 ) 
        { 
          Buy[ i ] = 0; 
          Sell[ i ] = exit + 1; // mark appropriate exit code 
          exit = 0; 
          priceatbuy = 0; // reset price 
          highsincebuy = 0; 
        } 
     } 
 } 


// Set position size as number of shares
SetPositionSize(PositionSize, spsShares);
SetPositionSize( 50, spsPercentOfPosition * ( Buy == sigScaleOut ) ); // scale out 50% of position

// show all bars
Filter = 1; 
Cond1 = Buy;
Cond2 = Sell;
//
AddColumn(Cond1, "BuyTrigger", 1.0);
AddColumn(Ref(HHVLookback,-1), "LongTrigger", 1.4);
AddColumn(BuyPrice, "BuyPrice", 1.4);
AddColumn(LLVLookback, "InitialStop",1.6);
AddColumn(BuyPrice - Ref(LLVLookback, -1), "RiskPershare",1.6);
AddColumn((PortEquity * PercentRisk * 0.01 / RiskPerShare), "PositionSize");
AddColumn(PortEquity,"EquityAtBuy");
AddColumn(Cond2, "SellTrigger",1.0);
AddColumn(ValueWhen(Cond2,Equity()), "EquityAtSell");


Thanks,
Arpad

Same day meaning that you are using End-of-day data and you want to get three exits from single trade at the same bar?

Unfortunately your question isn't clear enough and does not provide all necessary details to give you an answer. Please follow this advice: How to ask a good question

Hi Tomasz,

I am using end of day data and expecting the three trades to enter the same day, same bar and exit on three different days: at first profit (50% of shares), at second profit (50% of remaining shares) and at third trailing stop (whatever is left open, which is 25% of original number of shares).

I am testing it over a period where the original SELL only rule, (without the profit targets and trailing stop) generated a large profit. So now with the implementation of 2x profit targets and trailing stop I am expecting 3 trades entering on the same bar and exiting on a profit targets and trailing stop.

This is because the SELL rule was wide and the profit targets and trailing stop were much tighter, meaning I would exit at trail much earlier than with the SELL rule alone.

For example:

A. original logic, where SELL rule alone was used to exit:

  • Trade entry at $10, Qty 100
  • Trade's HHV at $30
  • Trade exit (qty 100) at SELL at $20

B. with the implementation of 2x profit and trailing stops. I am expecting 3 trades over the same period:

  1. trade entry at $10, Qty 50 (same bar as in logic A)
  • trade 1 exit at 10% = $11
  1. trade entry at $10, Qty 25 (same bar as in logic A)
  • trade 2 exit at 20% = $12
  1. trade entry at $10, Qty 25 (same bar as in logic A)
  • trade 3 exit at 20% trailing (from HHV of $30 as per logic A) = $24

Please let me know if this is clearer.

Thanks,
Arpad

You can't have 3 exits at single bar on single symbol under regular backtest mode. You should code the formula to generate one exit at the bar that combines all three.

If you really want to generate three exits at the very same bar at very same symbol, you have to use low-level CBT.

Hi Tomasz,

I do not want three exits on a single bar. I am expecting three entries on the same bar.

Maybe my question is not clear, please allow me to rephrase:
In a multiple scaling out and trailing stop situation, what should I expect to see in the list of trades? My simple logic dictates 3 trades entered on the same bar and existed on three different occasions at 10% profit, 20% profit and 20% trialing stop.
What am I missing?

Thanks,
Arpad

Hi Tomasz,

Following up on this issue please. Did you have time to consider?

Appreciate the support.

Thanks,
Arpad

The regular backtester only takes one trade per bar. If you want multiple trades in a bar, you would have to code that using the custom backtester. This sounds like a bad idea to me.

You should seriously consider intraday data instead of daily bars. This way you would have better insights into what the prices are doing inside of the daily bar.

Make sure you read Dr. Bandy's books: Books > Blue Owl Press

Hi PeterD,

Thank you for the feedback and for the book links. I had a look, they all look like great read.

OK so about my original question on scaling in/scaling out: let's look at this from trading perspective, without considering Amibroker functionality or coding for now. I am new to Amibroker, but I have several decades of active trading and investing experience.

For simplicity's sake, let's consider the broker report (say IBKR or any reputable broker) on scaling in / out.

For scaling in (say every 10% gain up to 3 times, same qty of shares):

  • there would be three trades on separate days 3 different prices (of course).
  • there would be a summary roll up where the volumetric average entry price is shown without an entry date (because you cannot really average an entry date without confusing the report)
  • then there is a drop-down option to show the 3 trades with details

For scaling out (say half the share qty at 20% and the rest at 30% loss):

  • there would be a rolled up summary (volumetric average exit price) with no dates
  • then a drop down would show the 2 exit dates and prices

Let's discuss if this (or something similar) is what we all expect from the broker report.
Then if we agree, let's discuss how is this reported on Amibroker back test report.
Without this it would be very difficult to unit test the code.

Thanks,
Arpad

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