Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Error comparing stock returns to SPY returns in pipeline

Hi, I'm new to Quantopian and currently working on my first algorithm. I would like to calculate of the % price change in a stock over 20 days to the % price change in the SPY ETF over the same period of days. I currently have the following pipeline code:

def make_pipeline():    

    universe = QTradableStocksUS()

    stock_returns = Returns(window_length=20) * 100 + 100  
    spy_returns = stock_returns[symbols('SPY')]  
    stock_returns_to_spy_returns = stock_returns / spy_returns * 100

    return Pipeline(columns={'stock returns': stock_returns, 'stock returns to SPY': stock_returns_to_spy_returns, 'spy returns': spy_returns},  
                   screen=universe  
                   )  

The problem is that this gives me an error for the spy returns column:

Cannot add column 'spy returns' with term NumExprFactor(...)[Equity(8554 [SPY])]. Adding slices or single-column-output terms as pipeline columns is not currently supported.

Does anyone know how to fix this? Ideally I would like to divide the values by each other indexed to 100. For example, if stock XYZ returns over a 20 day period are 10% and SPY returns over the same 20 day period are 5%, the stock returns to spy column should return 110/105*100=104.76~. Any different ways to achieve this would also be appreciated!

3 responses

Update on the above, I managed to get the result that I was looking for by creating a custom factor, called it RelativeStrength:

class RelativeStrength(CustomFactor):  
    inputs = [USEquityPricing.close]  
    window_length = 20  
    def compute(self, today, assets, out, close):  
        out[:] = (close[-1] / close[0] *100) / (close[1][np.where(assets==8554)] / close[0][np.where(assets==8554)] *100) *100  
def make_pipeline():    

    close = [USEquityPricing.close.latest]  
    rs = RelativeStrength()  
    return Pipeline()  

Unfortunately I am now getting stuck on the next step, which is to look at the % increase of this custom factor over the past 10 days, which I will call RSMomentum:

class RSMomentum(CustomFactor):  
     window_length = 10  
    def compute(self, today, assets, out, rs):  
        out[:] = rs[-1] / rs[0] * 100  
def make_pipeline():    

    close = [USEquityPricing.close.latest]  
    rs = RelativeStrength()  
    mom = RSMomentum(rs)

    return Pipeline()  

This doesn't seem to work though, is there a way to use custom factors as inputs of other custom factors?

I have it comparing today's position to its performance 1m ago. You can change that adjust the larger denominator to fit your need.

class RelativeStrength(CustomFactor):  
    inputs = [USEquityPricing.close]  
    window_length = 60  
    def compute(self, today, assets, out, close):  
        out[:] = ((close[-1] / close[-21]) / (close[-1][np.where(assets==8554)] / close[-21][np.where(assets==8554)])) /((close[-21] / close[-42]) / (close[-21][np.where(assets==8554)] / close[-41][np.where(assets==8554)]))-1 

I personally like this way better which shows rate-of-change of alpha.

class RelativeStrength20(CustomFactor):  
    inputs = [USEquityPricing.close]  
    window_length = 21  
    def compute(self, today, assets, out, close):  
        out[:] = (close[-1]/close[-1][np.where(assets==8554)]) / (close[-21] / close[-21][np.where(assets==8554)]) -1