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():

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