Custom Backtester Interface converts sig.PosScore to positive numbers

I'm working on a script that @mradtke has been very helpful with (thank you). It can be run as an exploration or backtest. The exploration is just to verify the signals and order of the signals. When running a back test, the script outputs the ticker symbols that meet the buy signal criteria in order as determined by PositionScore. The issue I'm having is that for some reason the output in the Custom Backtester from sig.PosScore CONVERTS negative values of positionscore to positive values. This causes the ranking/positionscore of the final output signals to be in the incorrect order for the negative values. Any idea why this is happening and how to work around it so that the exploration (which is correct) matches the ordered file output??

Thank you,

DaveDM
image

maxpos = Param( "Max Number of Positions", 1500, 1, 1000, 1 ); // maximum number of open positions
SetOption( "InitialEquity", 100000 ); // set initial equity = 100K
SetOption( "MaxOpenPositions", maxpos );
SetPositionSize( 100 / maxpos, spsPercentOfEquity );

SetOption( "usecustombacktestproc", True );


buysignal = Cross( MACD(), Signal() );
Buy = buysignal ;

PositionScore = ROC( C, 126 );

sellsignal = Cross( Signal(),  MACD() );
Sell = sellsignal ;

BuyPrice = Close;
SellPrice = Close;

Filter = buy ;

AddSummaryRows( 16 ) ;
AddColumn( PositionScore, "PositionScore" );
AddColumn( buysignal, "MACD Status", format = 1, colorDefault, IIf( Buy, bkcolor = coloryellow, bkcolor = colordefault ) ) ;


SetSortColumns( -3 );



SetCustomBacktestProc( "" );

// CBT mid-level
if( Status( "action" ) == actionPortfolio )
{
    dt = DateTime();
    bo = GetBacktesterObject();
    bo.PreProcess();
    

    // Delete old file
    filepath = "C:\\Users\\Dave\\Alera\\TestAccount1\\1001\\CBT Frame Test - BUYS.sig";
    fdelete( filepath );

    for( bar = 0; bar < BarCount; bar++ )
    {
        Cnt = 0;
        // open file in "share-aware" append mode
        fh = fopen( filepath, "a", True );

        if( fh )
        {


            for( sig = bo.getfirstsignal( bar ); fh AND sig; sig = bo.GetNextSignal( bar ) )
            {

              
                if( sig.isentry() AND Cnt < maxpos )
                {
                
					// write to file
                    
                    
                    fputs( sig.symbol + "," + sig.posscore + "\n", fh );
					
                    Cnt++;

                }

            } // end For all signals

            // close file handle
            fclose( fh );

        }
        else
        {
            _TRACE( "Failed to open the file" );
        }

        bo.ProcessTradeSignals( bar );
    }

    bo.PostProcess();

}




Read about PositionScore here: https://www.amibroker.com/guide/h_ranking.html

AmiBroker uses the absolute value of your PositionScore , i.e. it ignores the sign. One easy way to get around this is to add a large number (i.e. considerably greater than your expected range) to the PositionScore value.

1 Like

Thanks. I wonder why it would do that :-/ I'll fool around with it, but adding a large number would (conceivably) still rank the negative values in the same (and wrong) position, unless the calculation takes place prior to converting to an abs number. I'll try that and see how it goes!

you can set exactly for that reason

SetOption("SeparateLongShortRank", True/False );

setoption

thank you @Dionysos. I'll give that a try but from reading the documentation it appears that is more for maintaining two ranking lists, one for longs and one for shorts. I don't have any short trades.

Ok, I understand you want to skip short trades.
Try this then:
PositionScore = IIF(ROC(C,126)>0,ROC(C,126),0);

1 Like

Alternatively you could use ROC,126, pass it as a staticvariable to your CBT, read it out at sig.EntryDateTime and then re-assign it to PositionScore, see what it does. ( I haven't tried to assign a negative PosScore in CBT)

Lastly, I don't understand why you don't want to try what mradke suggested:

AmiBroker uses the absolute value of your PositionScore , i.e. it ignores the sign. **One easy way to get around this is to add a large number** (i.e. considerably greater than your expected range) to the PositionScore value.
1 Like

Doooht! thanks @dionysos and @mradtke the positionscore work around seems to work fine and super easy to implement. I was aware of this from previous systems that I've worked on but I think my mind goes to mush when I work on these things too long :wink: much obliged!