PositionScoring with stocks in different watchlists?

Hi,

I have a list of stocks in watchlist 0, a different list in WL 1 and another list in WL2.

I am testing the buying and selling of 10 stocks in each watchlist at the year start and end - using RSI values as a positionscore.

SetBacktestMode( backtestRegular );
SetTradeDelays(0,0,0,0);
SetOption( "InitialEquity", 10000);
SetOption("CommissionMode",2);
SetOption("CommissionAmount",10);
SetOption("FuturesMode" ,False);
SetOption("MinShares",1);

SetOption("MaxOpenPositions", 10);
PositionSize = -10;

Buy=Month()==1 AND Ref(Month(), -1)==12;
Sell = Ref(Buy, 1);

xx = 14;
PositionScore = 100-RSI(xx);

This works if I use Apply to > Filter > Watchlist 0 and a date range of 2018-2019.

But if I want to optimize the formula for different RSI values for all the dates:

2012 - 2015 --- using WL#2
2016 - 2018 --- WL#1
2018 - 2019 --- WL#0

I tried Apply to > All Stocks and Optimising, with these changes:

xx = Optimize("RSI",14,2,20,1);
PositionScore = 100-RSI(xx);

PositionScore = IIf(Year()>=2012 AND Year()<2016 AND !InWatchList(2), -999999, PositionScore);
PositionScore = IIf(Year()>=2016 AND Year()<2018 AND !InWatchList(1), -999999, PositionScore);
PositionScore = IIf(Year()>=2018 AND !InWatchList(0), -999999, PositionScore);

-999999 was to exclude the current stock from positionscore ranking if it wasn't in the required WL.

But this didn't work. And I'm not sure what to do next.

Suggestions welcome.....

Thanks

AmiBroker uses the absolute value of PositionScore to rank your entry signals. Therefore, -999999 will always be ranked higher than any of your 100-RSI values in the range 0-100.

1 Like

You do not need code.

Just use

xx = Optimize("RSI",14,2,20,1);
PositionScore = 100-RSI(xx);

and remove your IIfs

Then do

  1. Create three analysis project files (.apx extension).
  2. Save each project file with different Filter and different From-To Range (of analysis tool bar)
  3. Create batch process witch would look similar to this one and click run
    000

Since each project runs on different separate toolbar range (but not on Range: All quotes) each project's optimization should run faster than all WLs using entire range (as in your case -> All quotes). Also it would be used less code.

1 Like

fxshrat - thanks, however I plan to use more watchlists and optimizations at once, so would prefer it all in one AFL if possible.

I used posscore of zero just on one of the iif's:

PositionScore = IIf(Year()>=2012 AND Year()<2016 AND !InWatchList(2), 0, PositionScore);

This worked for a few trades, but then other symbols from outside the WL started coming in.

Is there a way - maybe even using custom BT - to eliminate symbols from portfolio backtesting if they don't meet the WL criteria?

Apperently you don't understand but the projects refer all to the very same AFL.
If you still want to do per Watchlist stuff you can do so via if statement

if ( InWatchlist(x) ) 
{
   // do something
}

But IMO it is not greatest idea to handle date range like that. If you want some symbols to be analyzed for certain date range only then you should rather use Range selector of analysis tool bar.
And if you want to access recently used project files quickly you can do so from File - Recent Files.
Recent Files menu can be moved even to AmiBroker menu bar via Tools - Customize - Commands.

But if you still want to exclude symbols from certain date range via code I would rather do like so (defining it via trade signals)

/// @link https://forum.amibroker.com/t/positionscoring-with-stocks-in-different-watchlists/11041/5
dn = DateNum();
dncond = exitcond = 0; 
if ( InWatchList(0) ) { dncond = dn >= 1120101 AND dn <= 1151231; exitcond = dn >= 1151231; }
if ( InWatchList(1) ) { dncond = dn >= 1160101 AND dn <= 1171231; exitcond = dn >= 1171231; }
if ( InWatchList(2) ) { dncond = dn >= 1180101 AND dn <= 1201231; exitcond = dn >= 1201231; }

SetPositionSize(1, spsShares);

Buy = Cross(C, MA(C,50));
Sell = Cross(MA(C,50), C);

Buy = Buy AND dncond;
Sell = Sell AND dncond OR exitcond;

xx = Optimize("RSI",14,2,20,1);
PositionScore = 100-RSI(xx);
2 Likes

@traderuk99, take a look at the following modified version of your code.

I changed years ranges and some other values only to make simpler to visually verify my exploration/backtest results - applied to All symbols (or including all the tested watchlists) over a range From-To-dates that includes all the years defined in the code.

This seems to work, but since I did not test it thoughtfully, it is entirely up to you to verify it.
As usual, I've added some exploration code that will help to inspect the values โ€‹โ€‹of the used arrays, to check if the logic is correct or if there is still some debug work to be done.

SetBacktestMode( backtestRegular );
SetTradeDelays( 0, 0, 0, 0 );
SetOption( "InitialEquity", 100000 );
SetOption( "CommissionMode", 2 );
SetOption( "CommissionAmount", 10 );
SetOption( "FuturesMode" , False );
SetOption( "MinShares", 1 );

SetOption( "AllowPositionShrinking", False); 
RoundLotSize = 1;
maxpos = 10;
SetPositionSize( 100 / maxpos, spsPercentOfEquity );

xx = 14;
xx = Optimize( "RSI period", xx, 2, 20, 1 );
RSIv = RSI( xx );
PositionScore = 100 - RsiV;
PositionScore = IIf( IsTrue( RsiV ), PositionScore, 0 ); // discard when RSIv is null or 0

y = Year();
inValidWL = InWatchList( 0 ) OR InWatchList( 1 ) OR InWatchList( 2 );

PositionScore = IIf( ( Y <  2016 OR Y >= 2019 ) OR( inValidWL == False ), 0, PositionScore );
PositionScore = IIf( ( Y >= 2016 AND Y < 2017 ) AND !InWatchList( 2 ), 0, PositionScore );
PositionScore = IIf( ( Y >= 2017 AND Y < 2018 ) AND !InWatchList( 1 ), 0, PositionScore );
PositionScore = IIf( ( Y >= 2018 AND Y < 2019 ) AND !InWatchList( 0 ), 0, PositionScore );

Buy = Month() == 1 AND Ref( Month(), -1 ) == 12;
Sell = Ref( Buy, 1 );
Buy = Buy AND ( PositionScore > 0 );

// Exploration
function nil( a )
{
    return ( IIf( a, a, Null ) );
}
Filter =  PositionScore > 0; //  AND (Buy OR Sell);
AddColumn( PositionScore, "Score" );
AddColumn( RsiV, "RSI" );
AddColumn( Year(), "Year", 1 );
AddColumn( Nil( InWatchList( 0 ) ), "In WL 0", 1 );
AddColumn( Nil( InWatchList( 1 ) ), "In WL 1", 1 );
AddColumn( Nil( InWatchList( 2 ) ), "In WL 2", 1 );

// AddColumn( Nil(Buy), "Buy", 1);
// AddColumn( Nil(Sell), "Sell", 1);
if( Status( "action" ) == actionExplore )
    SetSortColumns( -2 );

Anyway, I agree with @fxshrat. His approach that applies exclusions directly to trade signals is a better one.

1 Like

Much appreciated all the answers - I went with fxshrat's solution in the end and it is working nicely :slight_smile: