Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Sector exposure help

Hello Quants,
I was wondering if someone could give me a little help on line 50 of this algo so that I can bring sector exposure down.

The algo filters out stocks below $1, market cap below $100m and requires a dollar volume traded per day proportional to the portfolio value. After this, in "Before trading start" it ranks the average of 2 different fundamental parameters for value and cuts this to the best 1000 stocks available. From these 1000 stocks it sorts them by highest 252 day momentum.

It is at this point I need help, to cycle through the list of stocks with momentum and pick the stock with the highest momentum, then the next highest from a different sector, then the next highest from a different sector. Once 1 stock is picked from each of the 11 sectors, I'd like it to cycle to the 2nd best momentum form 1 sector, the next best momentum from a different sector and so on. Is this even possible? I tried adding the optimize, but I can't get that to work with the sorting features I have in the before_trading_start. Any suggestions for code that could accomplish this would be much appreciated.

6 responses

Hello Darth.
This might work.

topByMomentum = results.groupby('sector')['momentum'].nlargest(2)  

When placed inside 'before_trading_start', this will create a dataframe from your pipeline output containing the symbols that have the largest 2 momentums for each sector. nsmallest(2) would get you the 2 smallest momentums.
Hope that helps.

Hello Bryan,
Thank you for your input. I tried you suggestion but get an error "Expected assets argument to be of type or iterable of type Asset". I also tried this:

ranktop = results.sort_values(by='combo_rank', ascending=True).iloc[:1000]
topbymomentum = ranktop.sort_values(by='momentum', ascending=True)
topbysector = topbymomentum.groupby('sector')
topofall = topbysector.iloc[:context.num_long]
context.longs = topofall

This brings up the error "Cannot access callable attribute 'iloc' of 'DataFrameGroupBy' objects, try using the 'apply' method". Ultimately I'd like to take the 1000 stocks after ranking them on value, then be able to sort by momentum, whereby if my final long count goal was 20 stocks for example I'd have at most 3 stocks from any sector.

Do you have any other ideas?

Darth,
Sorry, but it's getting late and I'm leaving in the morning to take my boys to the gulf coast for a couple of weeks.
This will give you the top three momentums by sector. Maybe ditch the iloc 1000 idea?
Best of luck.

Bryan,
Had a look at your suggestion and this is what I came up with. I'm getting a new error. Any suggestions?

Hey Darth,

That error is being thrown from your for loop code block beginning at line 178. If you 'print(security)' from within that block you'll notice that 'security' contains (101, Equity(1595 [CLF])). I'm guessing 101 is the sector.
By inserting 'security = security[1]' as a new line at 179 the symbol will be stripped out and work as expected.
Like this:

for security in context.longs.index:  
        security = security[1]  
        if get_open_orders(security):  
            continue  
        #print(security, weight)  
        if data.can_trade(security):  
            if (security in context.portfolio.positions) or (can_buy):  
                order_target_percent(security, weight)  
                equity_weight += weight  

Your other ordering sections don't seem to be affected by this, but you might want to check to make sure.
When looping through lists of lists remember that they are zero based indices. security[0] is the first element, security[1] is the 2nd and so on.
You might already know that, but thought I'd throw it in just in case.
Hope that helps.
Bryan

Bryan,
I want to thank you for your help, the suggestions you have made have fixed the problem. Everything is working well thanks to you!