How do I fix my positionscore in my code?

Hi all,

the code below does not take the highest ranked symbols in my backtest and I do not know how to fix this issue. Do you have any ideas or comments?

In my code I work on portfolio level with multiple buy signal on the same day. The same buy signal exists on multiple days for the same symbol. With positionscore the ten best ranked symbols based on ROC should be included. Here is an example with the Nasdaq100:

The first ten symbols that were entered on 2.1.20 are the highest ranked securities.
image
Trace results (in Excel):
image
On 3.3.20 was a new entry in KLAC:
image
The trace shows that eight symbols have a higher ranking:
image
Question: Why were the higher ranked symbols ignored? REGN should be opened.

I read that in portfolio mode SetBacktestMode( backtestRegularraw ) should be used. So I run the next test. The first ten positions are the same. The first entry was on 27.2. in GILD:
image
Again I have higher ranked symbols (without an open position) in the trace:
image
Again REGN has a higher positionscore.

I did a single backtest with GILD and REGN. REGN would open on 2.1. and GILD on 9.1.:
image
image
Is this a valid assumption: On 2.1.20 were the first ten open positions created. REGN was not opened because of the low ROC. But my code does not “reset” REGN and so it is ignored on 27.2.20. GILD did not have a buysignal on 2.1.20 and the signal on 9.1.20 was ignored because ten position were open. So how do I “reset” REGN in my code?
Code:

SetBacktestMode( backtestRegularraw ); // backtestRegularRaw
#include_once "Formulas\Norgate Data\Norgate Data Functions.afl";
/* Symbols: */
index = "$NDX";
indexFilter = NorgateIndexConstituentTimeSeries( index );
//======SETTINGS====================
SetOption( "PortfolioReportMode",0); // 0 - trade list 1 - detailed log 2 - summary 
SetOption("GenerateReport", 1 ); // 0 suppress generation of report  1 force generation of full report
OnSecondLastBarOfDelistedSecurity = !IsNull( GetFnData( "DelistingDate" ) ) AND( BarIndex() == ( LastValue( BarIndex() ) - 1 ) OR DateTime() >= GetFnData( "DelistingDate" ) ) ;
OnLastTwoBarsOfDelistedSecurity = !IsNull( GetFnData( "DelistingDate" ) ) AND( BarIndex() >= ( LastValue( BarIndex() ) - 1 ) OR DateTime() >= GetFnData( "DelistingDate" ) );
SetOption( "InitialEquity", 100000 ); RoundLotSize = 0; // SetTradeDelays( 0, 1, 1, 1 );
SetOption( "AccountMargin",0); 
maxopenpos = 10 ; 
SetOption( "MaxOpenPositions", maxopenpos );
SetPositionSize( 100 / (maxopenpos), spsPercentOfEquity );
SetOption( "CommissionMode" , 3 ); SetOption( "CommissionAmount" , 0.01 );
SetOption("holdminbars",10); SetOption("MinShares",1);//
//======ENTRY====================
longterm =  200 ;
shrtterm = 10 ;
medterm = 100 ;
symbol_Signal =  C  > ma( C, shrtterm ) AND C > ma( C, longterm ) ;
PositionScore = IIf(Ref(ROC( Close, medterm ),-1)>0  ,1000 + Ref(ROC( Close, medterm ),-1),0)         ;
buysignal =    symbol_Signal  ; 
Buy =   indexFilter AND       NOT OnLastTwoBarsOfDelistedSecurity   AND    Ref( buysignal, -1 ) ;
//======EXIT====================
Sell = DateTime() == GetFnData( "DelistingDate" ) /* sell if stock is de-listed */  OR !indexFilter        OR OnSecondLastBarOfDelistedSecurity ;
ApplyStop(stopTypeLoss,stopModePercent,20);
//======TRACE====================
  _TRACE("; "+Name() + ";;;; ;" + Date() + " ;" + "Positionscore =; "+PositionScore + " ;Buy: ;" + Buy);

Thanks,
Peter

Use 'Detailed log' to see full picture of what's happening.

SetOption( "PortfolioReportMode",0); Change this setting to 1.

SetOption( "AccountMargin",0); You sure you want this set to zero?

Thanks for the feedback!
The detailed log shows only GILD. But the trace shows that more symbols have a buy signal and a higher positionscore.
image

The Detailed Log shows Buys to enter into on that Bar. Your Trace report is not lining up because it is showing your Buy Signal Bar (which is ref(-1) to your Trade Execution Bar).

So my ref-1 causes the GILD entry? I removed the ref-1 entries and the entry is moved from 27.2. to 26.2... but REGN is still the highest ranked symbol:
image
image
Code:

SetBacktestMode( backtestRegularraw  ); // backtestRegularRaw
#include_once "Formulas\Norgate Data\Norgate Data Functions.afl";
/* Symbols: */
index = "$NDX";
indexFilter = NorgateIndexConstituentTimeSeries( index );
//======SETTINGS====================
SetOption( "PortfolioReportMode",1); // 0 - trade list 1 - detailed log 2 - summary 
SetOption("GenerateReport", 1 ); // 0 suppress generation of report  1 force generation of full report
OnSecondLastBarOfDelistedSecurity = !IsNull( GetFnData( "DelistingDate" ) ) AND( BarIndex() == ( LastValue( BarIndex() ) - 1 ) OR DateTime() >= GetFnData( "DelistingDate" ) ) ;
OnLastTwoBarsOfDelistedSecurity = !IsNull( GetFnData( "DelistingDate" ) ) AND( BarIndex() >= ( LastValue( BarIndex() ) - 1 ) OR DateTime() >= GetFnData( "DelistingDate" ) );
SetOption( "InitialEquity", 100000 ); RoundLotSize = 0; // SetTradeDelays( 0, 1, 1, 1 );
SetOption( "AccountMargin",0); 
maxopenpos = 10 ; 
SetOption( "MaxOpenPositions", maxopenpos );
SetPositionSize( 100 / (maxopenpos), spsPercentOfEquity );
SetOption( "CommissionMode" , 3 ); SetOption( "CommissionAmount" , 0.01 );
SetOption("holdminbars",10); SetOption("MinShares",1);//
//======ENTRY====================
longterm =  200 ;
shrtterm = 10 ;
medterm = 100 ;
symbol_Signal =  C  > ma( C, shrtterm ) AND C > ma( C, longterm ) ;
PositionScore = IIf(ROC( Close, medterm )>0  ,1000 + ROC( Close, medterm ),0)         ;
buysignal =    symbol_Signal  ; 
Buy =   indexFilter AND       NOT OnLastTwoBarsOfDelistedSecurity   AND  buysignal;//  Ref( buysignal, -1 ) ;
//======EXIT====================
Sell = DateTime() == GetFnData( "DelistingDate" ) /* sell if stock is de-listed */  OR !indexFilter        OR OnSecondLastBarOfDelistedSecurity ;
ApplyStop(stopTypeLoss,stopModePercent,20);
// bars = sumSince(Buy,buy);
//======TRACE====================
  _TRACE("; "+Name() + ";;;; ;" + Date() + " ;" + "Positionscore =; "+PositionScore + " ;Buy: ;" + Buy//+ " ;Bars: ;" + Bars
  );

What you want to look at is between using 'Ref(Buy, -1)' and your 'Trade Delay Settings', as it stands for your Trade Execution Bar, the only Buy signal AmiBroker is to act on is GILD.

I activated SetTradeDelays( 0, 0, 0, 0 ) and nothing changes. In the chart I can easily see that REGN matches the buy condition:
Close: 457 > MA10: 413 and MA200: 327
So I do not understand why the detailed log does not invest in REGN and the trace have different results.

The reason is that line.
It affects sequence of signals and as such even though Trace would show Buy signal and (higher) PositionScore backtester would ignore signal(s) at those days because of holdminbars setting.

Examples:
Apply to: Current and symbol being REGN and just one open trade in result list.

If setting holdminbars to 1 (bar) then sequence of entry signals looks like follows

If holdminbars is set to 10 bars then sequence of entry signals looks like follows

Which means that also PositionScore would be considered at those entry dates only.

Perhaps @Tomasz is willing to give more info on inner workings of holdminbars setting.

4 Likes

Thanks for the solution and the detailed explanation! I would not find this solution on my own! One thing I take from this feedback is that I need to test more and also deactivate functionality that in my view is not obiously connected to the problem...
I already learned a lot on your comments in other forum entries! Your deep know how is really amazing.

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