Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Pipeline - filter equal amounts of stocks from sectors by market cap - How???

Hi Quantopian Community,

I want this algorithm to choose the top 10 stocks by market cap of each sector listed. How can I do that?

Somehow 'attach' didn't work, so my algorithm is copied down below.

Thanks for helping me in advance.

from quantopian.algorithm import attach_pipeline, pipeline_output, order_optimal_portfolio
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage, AverageDollarVolume, RollingLinearRegressionOfReturns
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters.morningstar import IsPrimaryShare
from quantopian.pipeline.classifiers.morningstar import Sector
from quantopian.pipeline.filters import StaticAssets

import numpy as np
import pandas as pd

from quantopian.pipeline.filters import Q500US
import quantopian.experimental.optimize as opt

class Previous(CustomFactor):
def compute(self, today, assets, out, inputs):
out[:] = inputs[0]

def initialize(context):
sector = Sector()
base_universe = Q500US()
set_commission(commission.PerShare(cost=0.003, min_trade_cost=0))
set_slippage(slippage.VolumeShareSlippage(volume_limit=1, price_impact=0))

schedule_function(func=rebalance,  
                  date_rule=date_rules.month_start(),  
                  time_rule=time_rules.market_open(hours=0, minutes=30),  
                  half_days=True)  

schedule_function(func=recording_statements,  
                  date_rule=date_rules.every_day(),  
                  time_rule=time_rules.market_close(),  
                  half_days=True)  
pipe = Pipeline()  
attach_pipeline(pipe,'my_pipe')  

#context.102 =  
#context.205 =  
#context.206 =  
#context.309 =  
#context.310 =  

MC = morningstar.valuation.market_cap.latest  
pipe.add(MC, 'MC')  

pipe.set_screen(base_universe & sector.element_of([102,205,206,309,310]))  

def before_trading_start(context, data):
context.pipeline_data = pipeline_output('my_pipe')
my_pipe = context.pipeline_data.fillna(0)

context.top6 = my_pipe.sort_values(by='MC',ascending=True).head(10)  

def recording_statements(context, data):
record(num_positions=len(context.portfolio.positions))

record(leverage=context.account.leverage)  

def rebalance(context, data):
if float(len(context.top6)) == 0:
weight = 0
else:
weight = 1 / float(len(context.top6))

for stock in context.top6.index:  
    order_target_percent(stock, weight)  


for stock in context.portfolio.positions:  
    if stock not in context.top6.index:  
        order_target_percent(stock, 0)  
2 responses

First off . Please attach your algorithm. Don't simply paste the code into a post. There are a lot of members here on the forums which offer their time to help but it makes their job little easier (and you get better results) if you provide a head start and include the algorithm.

So, after copying the code to a new algorithm and piecing the pieces together and then fixing the indentation issues, here is the solution...

Use the '.top' method with the 'groupby' parameter set to ' sector'. See the documentation https://www.quantopian.com/help#quantopian_pipeline_factors_Factor ) Place the following code in your pipeline definition...

  mkt_cap_top_10 = mc.top(10, mask=base_universe, groupby=sector)  
  pipe.add(mkt_cap_top_10, 'mkt_cap_top_10')  

Then create a list from the dataframe. Select only those stocks which pass this filter (ie the value is True)

    context.top10_each_sector = my_pipe.query('mkt_cap_top_10 == True').index.tolist()

Finally, order those stocks

See attached backtest.

I modified the code to experiment with other metrics besides market cap, this result was the best so far but it's mostly driven by beta. Added data.can_trade(stock) in the rebalancing section because the platform suggested it when backtests crashed with different algorithms. Replaced the hard-coded limit of 10 stocks with stock_count to experiment with that, although it doesn't seem like that variable gets transferred from initialize to before_trading_start so I had to define it twice to get the backtest to work. Didn't add the PvR code here but that's something to consider as well. Seems like several libraries are imported but aren't used in the algorithm as well.