PositionSize backtesting with no result

I am trying to manage position sizing and after searching this forum and Amibroker guide https://www.amibroker.com/guide/h_pyramid.html tried to create the following.

  1. Exit 50% position in Target 1
  2. Exit 50% position if hits SL 1
  3. Exit rest 50% position either if the Exit criteria satisfy or if SL 2 hit.
    When I am trying to backtest, its not giving me any resul, however trace is giving me result.
    Attaching the AFL code as reference, any help would be appreciated specially from
type or paste cFirstProfitTarget = 50; // profit
pct = 50;
FirstSL = 20;
FinalSL = 40;

//Array Initialization
Buy = Sell = Short = Cover = TSL = Null;
priceatbuy = 0;
highsincebuy = 0;
exit = 0;
text = "";
EOD_Sell = 0;
//Using Loop to generate signals


for( i = 0; i < BarCount; i++ )
{
    //Long Positions
    if( _Buy[ i ] AND priceatbuy == 0 AND tn[ i ] < 143100 )
    {
        Buy[ i ] = 1;
        BuyPrice[ i ] = _BuyPrice[ i ];
        priceatbuy = BuyPrice[ i ];
        Qty = _Qty;
        _TRACE( "Inside Buy Block " + ", Buy Price: " + priceatbuy + ", BuyBB_Price: " + Lower_BB_H + ", Buy_SAR: " + Buy_SAR +  ", Buy_BB: " + ( O > Upper_BB_H ) + ", Qty: " + Qty );
    }

    if( priceatbuy > 0 )
    {

        if( Buy[i] != 1 AND exit == 0 AND High[ i ] >= ( 1 + FirstProfitTarget * 0.01 ) * priceatbuy )
        {
            // first profit target hit - scale-out exit at closed price
            exit = 1;
            Buy[ i ] = sigScaleOut;
            Qty = _Qty / 2;
            _TRACE( "First Target block" +  ", Target Price: " + ( 1 + FirstProfitTarget * 0.01 ) * priceatbuy + ", Qty: " + Qty );
        }


        if( Buy[i] != 1 AND  exit == 0 AND Low[ i ] <= ( 1 - FirstSL * 0.01 ) * priceatbuy )
        {
            // First SL point hit - scale-out exit at closed price
            exit = 1;
            Sell[ i ] = sigScaleOut;
            Qty = _Qty / 2;
            _TRACE( "First Stop Loss Hit: " + ", SL Price: " + ( 1 - FirstSL * 0.01 ) * priceatbuy + ", Qty: " + Qty );
        }


        if( ( _Sell[ i ] OR tn[ i ] >= 151400 OR Low[ i ] <= ( 1 - FinalSL * 0.01 ) * priceatbuy ) )
        {

            Sell[ i ] = 1; //Selling-off the Long position

            if( exit = 1 ) Qty = _Qty / 2;
            else
                if( exit = 0 ) Qty = _Qty;


            if( EOD_Sell == 0 AND _sell[ i ] )
            {
                SellPrice[ i ] = _SellPrice[ i ];
                _TRACE( "Final Exit block" + ", Exit True :" + Short_BB[ i ] + ", Sell Price: " + _SellPrice[ i ] + ", Qty: " + Qty );
                EOD_Sell = 1;
            }
            else
                if( EOD_Sell == 0 AND tn[ i ] >= 151400 )
                {
                    SellPrice[ i ] = O[ i ];
                    _TRACE( "Final Exit block" + ", Exit :" + tn[ i ] + ", Qty: " + Qty );
                    EOD_Sell = 1;
                }
                else
                    if( EOD_Sell == 0 AND Low[ i ] <= ( 1 - FinalSL * 0.01 ) * priceatbuy )
                    {
                        SellPrice[ i ] = ( 1 - FinalSL * 0.01 ) * priceatbuy ;
                        _TRACE( "Final Exit block" + ", Exit Time :" + ( 1 - FinalSL * 0.01 ) * priceatbuy + ", Qty: " + Qty );
                        EOD_Sell = 1;
                    }

            exit = 2;
        }


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

    if( Buy[i] )
        PlotText( "Buy@\n" + Prec( ValueWhen( Buy, Buyprice[ i ] ), 1 ), i, L[ i ], colorBrightGreen, colorBlack, -65 );

    if( Sell[i] )
        PlotText( "Sell@\n" + Prec( ValueWhen( Sell, SellPrice[ i ] ), 1 ), i, L[ i ] , colorgold, colorBlack, -65 );
}

SetPositionSize( QTY, spsShares );
`SetPositionSize( 1, IIf( Buy == sigScaleOut OR Sell == sigScaleOut, spsShares, spsNoChange ) );`


in the above code I am more interested to know why this is not giving me any result i backtest. Specially I am not sure if the last statement in my code is correctly coded.

type oSetPositionSize( 1, IIf( Buy == sigScaleOut OR Sell == sigScaleOut, spsShares, spsNoChange ) );

Where I want to scaleout in either target 1 achieve or SL 1 hit.
Any help would be appreciated.

As you guessed... it is incorrect.

 Sell[ i ] = sigScaleOut;

That's incorrect too.

The manual says that scaling constants should be assigned to entry variables only (Buy, Short). Same applies to equality checks (e.g. Buy == sigScaleOut)
There is zero mention to use them with Sell/Cover.

Two special constants: sigScaleIn / sigScaleOut added to provide means to tell the backtester when you want to scale-in/out

All you have to do to implement pyraminding is to:

  • Assign sigScaleIn to BUY/SHORT variable if you want to scale-in (increase size of) LONG/SHORT position
  • Assign sigScaleOut to BUY/SHORT variable if you want to scale-out (decrease size of) LONG/SHORT position

You have even added the link to that quote in first post.

@Tomasz responded here already in addition to manual

So not sure why you do things differently than as explained in manual and forum.
And there are several scaling examples too.


??

Besides QTY is not array.


This one is incorrect also

if( Buy[i] )
        PlotText( "Buy@\n" + Prec( ValueWhen( Buy, Buyprice[ i ] ), 1 ), i, L[ i ], colorBrightGreen, colorBlack, -65 );

if( Sell[i] )
       PlotText( "Sell@\n" + Prec( ValueWhen( Sell, SellPrice[ i ] ), 1 ), i, L[ i ] , colorgold, colorBlack, -65 );

No one (of AmiBroker.com and forum contributors) has ever shown anything as incorrectly as that one in forum.
(And I know you have copied it from those but added incorrect code to it)
-> ValueWhen and Buy are arrays.
You should not use Valuewhen in Barcount loop at all.

Better, e.g.:

if( Buy[i] )
        PlotText( StrFormat("Buy@\n%1.1f", Buyprice[ i ] ), i, L[ i ], colorBrightGreen, colorBlack, -65 );

if( Sell[i] )
       PlotText( StrFormat("Sell@\n%1.1f", SellPrice[ i ] ), i, L[ i ] , colorgold, colorBlack, -65 );

There are other flaws but stopping for now...


Besides if you copy code then you should add reference to original one in the code you modify

E.g.

/// Derived from:
/// @link https://www.amibroker.com/guide/h_pyramid.html
/// modified at:
/// @link https://forum.amibroker.com/t/positionsize-backtesting-with-no-result/19419
/// copied/modified code below

I do not think it takes much time to add at least single link.

Thanks @fxshrat for your response, let me work on this and will update this thread with my final version.

@fxshrat I want to consider a fixed quantity to be traded every day. Do not want to trade on the cumulative quantity due to increased profit.
Trying to use below code, where daily starting quantity is fixed to 40.
This is now working in my backtest.
SetPositionSize( 40, spsShares ); SetPositionSize( pct, IIf( Buy == sigScaleIn, spsPercentOfPosition, spsNoChange ) ); ;

I shall share the final code once I am satisfied with the backtest..
Thanks..

I made few changes post @fxshrat your suggestion, now its backtestable. But not sure if this can be optimized, specially I tried to optimize the Target and Stop Loss percent, but no suggestion found and return was also not changed. Hence I believe the below code still has some bug in it.

Any comment to fix the bug would be appreciated.

FirstTarget = Optimize("FirstTarget",50,10,100,5);

pct = 50;
//FirstTarget = 50; // profit
FirstSL = 20;
FinalSL = 40;

//Array Initialization
Buy = Sell = Short = Cover = TSL = Null;
priceatbuy = 0;
highsincebuy = 0;
exit = 0;
text = "";
EOD_Sell = 0;
//Using Loop to generate signals


for( i = 0; i < BarCount; i++ )
{
    //Long Positions
    if( _Buy[ i ] AND priceatbuy == 0 AND tn[ i ] < 143100 )
    {
        Buy[ i ] = 1;
        BuyPrice[ i ] = _BuyPrice[ i ];
        priceatbuy = BuyPrice[ i ];
        Qty = _Qty;
        _TRACE( "Inside Buy Block " + ", Buy Price: " + _BuyPrice[i] +  ", Qty: " + Qty );
    }

    if( priceatbuy > 0 )
    {

        if( Buy[i] != 1 AND exit == 0 AND High[ i ] >= ( 1 + FirstTarget * 0.01 ) * priceatbuy )
        {
            // first profit target hit - scale-out exit at closed price
            exit = 1;
            Buy[ i ] = sigScaleOut;
            Qty = _Qty / 2;
            _TRACE( "First Target block" +  ", Target Price: " + ( 1 + FirstTarget * 0.01 ) * priceatbuy + ", Qty: " + Qty );
        }


        if( Buy[i] != 1 AND  exit == 0 AND Low[ i ] <= ( 1 - FirstSL * 0.01 ) * priceatbuy )
        {
            // First SL point hit - scale-out exit at closed price
            exit = 1;
            Buy[ i ] = sigScaleOut;
            Qty = _Qty / 2;
            _TRACE( "First Stop Loss block: " + ", SL Price: " + ( 1 - FirstSL * 0.01 ) * priceatbuy + ", Qty: " + Qty );
        }


        if( ( _Sell[ i ] OR tn[ i ] >= 151400 OR Low[ i ] <= ( 1 - FinalSL * 0.01 ) * priceatbuy ) )
        {

            Sell[ i ] = 1; //Selling-off the Long position

            if( exit = 1 ) Qty = _Qty / 2;
            else
                if( exit = 0 ) Qty = _Qty;


            if( EOD_Sell == 0 AND _sell[ i ] )
            {
                SellPrice[ i ] = _SellPrice[ i ];
                _TRACE( "Final Exit block" + ", Exit True :" + Short_BB[ i ] + ", Sell Price: " + _SellPrice[ i ] + ", Qty: " + Qty );
                EOD_Sell = 1;
            }
            else
                if( EOD_Sell == 0 AND tn[ i ] >= 151400 )
                {
                    SellPrice[ i ] = O[ i ];
                    _TRACE( "Final Exit block" + ", Exit :" + tn[ i ] + ", Qty: " + Qty );
                    EOD_Sell = 1;
                }
                else
                    if( EOD_Sell == 0 AND Low[ i ] <= ( 1 - FinalSL * 0.01 ) * priceatbuy )
                    {
                        SellPrice[ i ] = ( 1 - FinalSL * 0.01 ) * priceatbuy ;
                        _TRACE( "Final Exit block" + ", Exit Time :" + ( 1 - FinalSL * 0.01 ) * priceatbuy + ", Qty: " + Qty );
                        EOD_Sell = 1;
                    }

            exit = 2;
        }


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

if( Buy[i] )
        PlotText( StrFormat("Buy@\n%1.1f", Buyprice[ i ] ), i, L[ i ], colorBrightGreen, colorBlack, -65 );

if( Sell[i] )
       PlotText( StrFormat("Sell@\n%1.1f", SellPrice[ i ] ), i, L[ i ] , colorgold, colorBlack, -65 );

}



//FixedDollarAmount = 25000; 
//PositionSize = FixedDollarAmount;
//SetPositionSize( pct, spsPercentOfEquity );


SetPositionSize( 40, spsShares );
SetPositionSize( pct, IIf( Buy == sigScaleIn, spsPercentOfPosition, spsNoChange ) ); 


Attaching the Optimization snapshot, as a reference.
image