MarketCap Rank Filter

backtest
howto
Tags: #<Tag:0x00007f2d79d3d440> #<Tag:0x00007f2d79d3d238>

#1

Hello people

Trying to add a MarketCap Rank Filter to a rotational system that has another rank in positionscore.
Here´s the code so far. Only the McapRank is missing. Can you please help?

MaxPos = 5;
SetOption("InitialEquity", 100000 ); 
SetOption("AllowPositionShrinking", True ); 
SetOption("MaxOpenPositions", MaxPos ); 
SetOption("AccountMargin", 100 ); 
SetPositionSize( 100/MaxPos, spsPercentOfEquity ); 
SetTradeDelays( 1, 1, 0, 0 );
BuyPrice = O;
SellPrice = O;


MarketCap = Close * GetFnData( "SharesOut" );


/////

// McapRank ??

/////


TopMcapRank = 10; 
McapRankFilter = McapRank <= TopMcapRank;

SetBacktestMode( backtestRotational );

ROCLenght = 250;
ROCValue = ROC( C , ROCLenght );

Score = ROCValue;

PositionScore = IIf(McapRankFilter, Score, 0); 



// Exploration
Filter=1;
AddColumn(C,"Close",1.2);
AddColumn(MarketCap,"MarketCap",1);
AddColumn(McapRank,"McapRank",1);

#2

@nick I have not tested your code but following the User Guide for generating a ranking I have put this together and you may try and see if it is of help.
https://www.amibroker.com/guide/h_ranking.html

// as per fxshrat's standard formatting of code
///@link http://forum.amibroker.com/t/marketcap-rank-filter/4423
// Based upon User guide Ranking Example

wlnum = GetOption( "FilterIncludeWatchlist" ); 
List = CategoryGetSymbols( categoryWatchlist, wlnum ) ; 

if ( Status("stocknum") == 0 ) 
{ 
    StaticVarRemove( "values*" ); 

    for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    ) 
    { 
        SetForeign ( symbol ); 
        values = Close * GetFnData( "SharesOut" );
        RestorePriceArrays(); 
        StaticVarSet (  "values"  +  symbol, values ); 
        _TRACE( symbol ); 
    } 

    StaticVarGenerateRanks( "rank", "values", 0, 1224 ); 
} 

symbol = Name(); 

MarketCap = StaticVarGet ( "values" +  symbol ); 
rank = StaticVarGet ( "rankvalues" +  symbol ); 

Filter = 1; 
AddColumn ( MarketCap, "MarketCap", 1.0 ); 
AddColumn ( rank, "rank", 1.0); 
SetSortColumns( 4 );

And you get this type of output (on the DJIA),
image


#3

Hello Larry and Nick.
Larry Thanks for the Ranking code brilliant. As I explain to Nick I didn’t need any Runking before, but should be easy for someone to code this.
Today as an a practice I just look the manual and I saw at the very-very top lines says

Second kind of ranking is simply assigning a number (rank) to the line of exploration output. The rank column is added to the exploration output just by calling AddRankColumn function after performing a sort using SetSortColumns function. You can call SetSortColumns multiple times and you can call AddRankColumn multiple times to achieve many different ranks based on multiple-columns.

So That is cool,
for a NEW user or (lazy user like me) that he like to do rank with a quick way is this

// Sort a column and then rank this particular column

MarketCap = Close * GetFnData( "SharesOut" );
// code for exploration mode
Filter = 1; 
AddColumn ( MarketCap, "MarketCap", 1.0 );
SetSortColumns( -3 ); // sort by 3rd column in descending order 
AddRankColumn(); // rank according to 3rd column (ascending) 

rankMarketCap

Larry thanks again


#4

Hi Portfoliobuilder

Sorry for the delay. I´ve tested the exact code on sp100 list and it doesn´t seem to work:

mcap%20filter%201

Any ideas on what could be wrong? The EOD data is on place and also the shares outstanding.
I´m after running backtests only in the top 10 symbols by mcap at any given time. Still haven´t been able to do so.


#5

@Nick it works just fine for me. I use Version 6.25 and have great data. I tried it against several different Indexes and it worked every time.

To check if it is your data I've added a couple of lines in the Explore to see that your data is there.

wlnum = GetOption( "FilterIncludeWatchlist" ); 
List = CategoryGetSymbols( categoryWatchlist, wlnum ) ; 

if ( Status("stocknum") == 0 ) 
{ 
    StaticVarRemove( "values*" ); 

    for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    ) 
    { 
        SetForeign ( symbol ); 
        values = Close * GetFnData( "SharesOut" );
        RestorePriceArrays(); 
        StaticVarSet (  "values"  +  symbol, values ); 
        _TRACE( symbol ); 
    } 

    StaticVarGenerateRanks( "rank", "values", 0, 1224 ); 
} 

symbol = Name(); 

MarketCap = StaticVarGet ( "values" +  symbol ); 
rank = StaticVarGet ( "rankvalues" +  symbol ); 

Filter = 1; 
AddColumn ( MarketCap, "MarketCap", 1.0 ); 
AddColumn ( rank, "rank", 1.0, colorWhite, colorLightBlue); 
SetSortColumns( 4 );
AddColumn(Close, "Close");
AddColumn(GetFnData( "SharesOut" ), "Shares Outstanding", 1.0);

image


#6

@Nick, I tested @portfoliobuilder code with my data (that is not so great.... Yahoo source), and it works perfectly; the numbers do not agree, but this is due to different values for the shares out values.
Just to double check, even if I doubt that this could solve your issue, set the date filter to the 1 recent bar only and since you are using the SetForeign function also be sure to check the Pad And Align option in the Analysis settings (in the past other users reported issues in ranking due to some missing/spurious data)


#7

Very strange. Even with beppe suggestion doesn´t work:

mcap%20filter%202

I´ll check if an upgrade is needed. Will report back.


#8

@beppe and @portfoliobuilder: had version 6.20. I´ve installed version 6.25 BETA. Same results:

mcap%20filter%203

I´ve checked Pad and align => AAPL

Pad%20and%20align

Not sure what else to try to get it working.

From Tomasz:

One has to realize obvious fact that ANY kind of ranking REQUIRES data to be aligned (i.e. without holes)

Could this be it? How can we solve it?
Couldn´t it rank the rest of the symbols (that doesn´t have holes)?


#9

The code works for me using Norgate data and AB v6.20.1. However, I see in your results that the Market Cap column is empty, which tells me that your values array was not populated with data as you expected. I'm not sure who your data provider is, but perhaps they don't support GetFnData() inside the SetForeign() - RestorePriceArrays() block. I would try replacing GetFnData() with GetFnDataForeign() to see if you get different results.


#10

For performance reasons it is hugely beneficial to use GetFnDataForeign alone instead of SetForeign/GetFnData/RestorePricearrays.


#11

Thanks @mradtke and @Tomasz.
I´ve tested it (not sure if this is correct) but still doesn´t work:

mcap%20filter%204

Beppe said is working for him with Yahoo as source.
I´m using Yahoo data for EOD too. The shares outstanding were imported from a TOS csv.
I´ve also tested pad and align to different symbols with the same results.

Any ideas?


#12

You have two errors in your code:

  1. The GetFnDataForeign() function takes two arguments, not one. Please look it up in the Help.
  2. You are using Close without any SetForeign, so you would always get the closing price for the current symbol (stocknum 0). You should replace Close with Foreign(symbol,"C").

If that still doesn't work, you will need to do some debugging to figure out why MarketCap is still being calculated as an empty/null value in your loop.


#13

What does GetFnDataForeign got to do with the fact that the two columns for marketcap and rank are empty with existing code? It should work with the original code! SharesOut column in his picture does output values. Don't you see it?

If marketcap and rank don't output values then it is some setting causing it.

@Nick, why don't you simply debug the code?
For example check wlnum variable. What does it return? What does List variable return? Those are first two variables that make bells ring but not whether it is GetFnData or GetFnDataForeign.

wlnum = GetOption( "FilterIncludeWatchlist" ); 
List = CategoryGetSymbols( categoryWatchlist, wlnum ) ; 

if ( Status("stocknum") == 0 ) 
{ 
    _TRACEF( "WL: %g, List: %s", wlnum, List );
}

The most obvious setting that might cause empty columns is Watchlist drop down menu of Filter Include being empty. Have you checked that, @Nick? Yes/No?

(Also check Exclude tab. Is there anything excluded?)

180255


#14

Ah finally!

Check this out, I was using by a watchlist on a different category slot.
This is because I was running some strategies in 2 watchlists simultaneously a couple of times. So as a result I ended up with a filter like this:

mcap%20filter%205%20-%20bug%202

As you can see, it doesn´t work.

Moderator comment: it does not work because it CAN NOT work with the formula you have used. The filter settings you used was wrong. In your formula you have used FilterIncludeWatchlist which SPECIFICALLY and ALWAYS refers to the VERY FIRST item of given category in the Filter settings window (by default watch list is in 5th position) - this is what FilterIncludeWatchlist refers to, not to watch list, that is why it could not work. If you re-define meaning of filter from ICB to Watch list so there is MORE than ONE watch list category, FilterIncludeWatchList would give you FIRST one, NOT last one. FilterIncludeWatchlist ALWAYS refers to FIRST setting, which by default is 5th slot. Apparently another protection against people shooting themselves in the foot - next version will issue error/warning if same category is selected multiple times and GetOption("Filter*... ) is used, as this is simply incorrect usage scenario.

Then, just to test it exactly as @fxshrat suggested, I used the watchlist in the "correct" category slot. See what happens:

mcap%20filter%205%20-%20bug%203

You can test it yourselves.

Thank you all very much. I really appreciate all the support.


#15

@Nick, it would be useful if you marked this thread as resolved by selecting the @fxshrat response. :slight_smile:


#16

The system should allow more than one solution.
@portfoliobuilder answered with the correct code and @fxshrat fixed the problem.
You both have my gratitude, and everyone else that contributed too :slight_smile: