Back to Community
limit QTU to specfic industry sector and market cap?

Looking for guidance on how to limit QTradableStocksUS() (QTU) to a specific industry sector and market cap? Also is there a way to compute the market cap weights of the industry sectors (e.g. point-in-time, Industrials represents what percentage by market cap of the sectors in the QTU))?

12 responses

Here's one way:

from quantopian.pipeline.classifiers.morningstar import Sector

factor = factor.zscore(groupby=Sector())

That's going to be very useful! Thanks @Joakim

Hi Grant,

Is that what you're looking for?

Loading notebook preview...
Notebook previews are currently unavailable.

Thanks all -

Getting there. Here's what I came up with so far, which I think should get me 0-50 percentile market cap of the financial sector (103) within the QTU, right?

def factor_pipeline():  
    market_cap = factset.Fundamentals.mkt_val.latest  
    universe = market_cap.percentile_between(0,50, mask = Sector().eq(103) & QTradableStocksUS())  
    factors = make_factors()  
    pipeline_columns = {}  
    for k,f in enumerate(factors):  
        pipeline_columns['alpha_'+str(k)] = f(mask=universe)  
    pipe = Pipeline(columns = pipeline_columns,  
    screen = universe)  
    return pipe  

Wondering if it would also work just to use the market cap values of the sector ETFs (see https://www.quantopian.com/papers/risk)?

Here's an update. This seems to work pretty well:

def factor_pipeline():  
    factors = make_factors()  
    sectors = [101,102,103,104,205,206,207,308,309,310,311]  
    market_cap = factset.Fundamentals.mkt_val.latest  
    pipeline_columns = {}  
    for k,f in enumerate(factors):  
        for s in sectors:  
            universe = market_cap.percentile_between(0,33, mask = QTradableStocksUS() & Sector().eq(s))  
            pipeline_columns['alpha_sc_'+str(k)+'_'+str(s)] = f(mask=universe)  
            universe = market_cap.percentile_between(33,66, mask = QTradableStocksUS() & Sector().eq(s))  
            pipeline_columns['alpha_mc_'+str(k)+'_'+str(s)] = f(mask=universe)  
            universe = market_cap.percentile_between(66,100, mask = QTradableStocksUS() & Sector().eq(s))  
            pipeline_columns['alpha_lc_'+str(k)+'_'+str(s)] = f(mask=universe)

    pipe = Pipeline(columns = pipeline_columns,  
    screen = QTradableStocksUS())  
    return pipe  

There's a nice, detailed factor construction recipe here, by the way:

Step-by-step guide to Vanguard’s factor construction
https://advisors.vanguard.com/iwe/pdf/FASFMTH.pdf

No complex "optimangler" required.

@ Grant, thanks for the Vanguard read. It's probably the clearest example I've seen in a while, so I appreciate it. I'm wondering if something similar can be done with the style risk factors as you've done so with Market Cap and Sectors. Essentially silo each risk factor and mask over factors to later on be combined as the weight? Perhaps something for me to test out over the weekend (There's only so much groupby=sector() one can take lol... need change it up lol)

@ Daniel -

Yes, it should be possible (e.g. run factor on momentum-ish stocks and non-momentum-ish stocks separately, and then combine).

It's basically putting in some knobs to diversify at the factor level; smear it out across the market, in effect. I'm not sure this is the best thing for the Q fund, since ideally one might just want to accept the tilts that will come with running a given factor across the QTU, and then average lots of factors together with different tilts, and have the "pure alpha" magically appear.

Agreed, for me I always hit a crossroad where I have make a decision to submit something with more tilt but pure vs less tilt and slightly pure. The thought of averages at the Q Fund level kind of helps in the decision since it wont be run as a standalone.

Hi Grant,

Thanks for posting your solution. Encountered this problem and your solution was really helpful!

In your most recent solution, is it important to apply screen = QTradableStocksUS()) if the this mask has already been applied to each column? Removing the additional screen doesn't seem to affect my pipeline result, but wanted to check if you know of any issues that require the mask to be applied again?

Thanks.

@ Joseph -

The screen may not be necessary, but I don't think it should do any harm either. It's probably good practice to leave it, since if the code is modified it'll catch any non-QTU names that would end up corrupting the algo.

@ Grant,

True, thanks for your help.

Joseph