ScaleIn/ScaleOut if forecast position is 10% higher/lower than current pos

I am testing a long only EOD continuous trading system that provides a score indicating the number of shares I should hold, daily.

Rather than trade daily, which is too expensive, I need to scale in/scale out only when today´s forecast position size (no. of shares) is 10%+ above/below my existing (previous) position size.

I have read the pyramiding guide https://www.amibroker.com/guide/h_pyramid.html, plus reviewed numerous examples in the forum but can’t figure out a solution. I hint that going the CBT route might be an option but I am afraid I don’t have the required coding skills for that.
Any guidance would be much appreciated.

There's a detailed knowledge base article on the Amibroker site covering how to achieve this.

Note the comment in the code where it uses a 0.5% (0.005) threshold. There you can set it to use your 10% (0.1) threshold instead.

Thank you very much MacAllan for your help. Since my position size is based on number of shares instead of percent of equity, I have tweaked the code in the example, but I am not very confident with my changes tbh. Also, I get the following error and can't execute it as it currently is:

"Condition in IF, WHILE, FOR statements
has to be Numeric or Boolean type.
You can not use array here,
please use [] (array subscript operator)
to access array elements"

Here is the tweaked code:

Score = 1130; // This is just an example, in reality I'll use a formula to calculate the //desired number of shares 

Setpositionsize(Score, spsShares);

SetOption("UseCustomBacktestProc", True ); 

if( Status("action") == actionPortfolio )
{
  bo = GetBacktesterObject();

  bo.PreProcess(); // Initialize backtester

  for(bar=0; bar < BarCount; bar++)
  {
   bo.ProcessTradeSignals( bar );
  
   //CurEquity = bo.Equity; // I don't think I need this as I use number of shares
  
   for( pos = bo.GetFirstOpenPos(); pos; pos = bo.GetNextOpenPos() )
   {
    posval = pos.GetPositionValue();
   
    price = pos.GetPrice( bar, "C" );
    shares = posval/price; // Calculate the number of shares held currently
    
    diff = Score / shares; // Desired shared divided by current shares
   
    // rebalance only if difference between desired and
    // current number of shares is greater than 10% ->ScaleIn
    // or number of shares is lower than -10% ->ScaleOut
    if( diff != 0 AND
        abs( diff ) > 1.1 OR abs( diff ) < 0.9)

    {
     bo.ScaleTrade( bar, pos.Symbol, diff < 0, price, abs( diff ) ); // I don't understand this so can´t say if I need to change anything
    }
   }
  }
  bo.PostProcess(); // Finalize backtester

Thank you so much for taking a look at it.

You are missing } at the bottom of your code.

Tip: Use Edit> Prettify Selection.

1 Like

Thank you TrendSurfer, yes I have now corrected a couple errors and added the full code using some simplified rules for this example. The CBT part is the one where I am having trouble as it does neither scale in nor scale out, it just sells the whole position.

// I want to scalein/scaleout if desired number of shares projected is 10%+ above/below my current share holding

InitialEquity= 100000;

NumPosic= 20;

SetOption("MaxOpenLong",NumPosic);
SetOption("MaxOpenPositions",NumPosic);
SetOption("ExtraColumnsLocation",1);
SetOption("CommissionMode",1); // 
SetOption("CommissionAmount", 0.0); // No commisions for this example
SetOption("InitialEquity", InitialEquity);
SetOption( "AllowSameBarExit", False );
SetOption( "ReverseSignalForcesExit", False );
SetOption( "HoldMinBars", 1 );
SetOption( "AccountMargin", 100 );

SetTradeDelays(0,0,0,0); // No delays
BuyPrice=ShortPrice=SellPrice=CoverPrice= C;

//Number of Shares desired (example)

score = MA(C, 20)-MA(C, 40);

PositionScore = score;

SharesDesired = 0.001 * InitialEquity / ATR(20); // I leave InitialEquity rather than Equity in order to simply things for this example

SetPositionSize(SharesDesired, spsShares);

// BUY AND SELL EXECUTION

Buy = Score > 0; 
Sell = Score < 0; 

//SCALEIN SCALEOUT BASED ON FORUM GUIDANCE

SetOption( "UseCustomBacktestProc", True );

if( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();

    bo.PreProcess(); // Initialize backtester

    for( bar = 0; bar < BarCount; bar++ )
    {
        bo.ProcessTradeSignals( bar );

        //CurEquity = bo.Equity;

        for( pos = bo.GetFirstOpenPos(); pos; pos = bo.GetNextOpenPos() )
        {
            posval = pos.GetPositionValue();

            //diff = posval - 0.01 * EachPosPercent * CurEquity;
            price = pos.GetPrice( bar, "C" );
            shares = posval / price; // Calculate the number of shares held currently

            diff = SharesDesired[ bar ] / shares; 

            // scale in if difference between number of shares desired and number of current shares held is > 10%
            // scale out if difference between number of shares desired and number of current shares held is < 10%
            if( diff != 0 AND
                    abs( diff ) > 1.1 OR
                    abs( diff ) < 0.9 ) // 
                //abs( diff ) > price )
            {
                bo.ScaleTrade( bar, pos.Symbol, diff < 0, price, abs( diff ) ); // I don´t know what this does or if it makes any sense
            }
        }
    }

    bo.PostProcess(); // Finalize backtester
}		

Thank you for your help.