Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Computing Excess Returns (relative to SPY) in Pipeline

I would like to use excess returns (relative to the market) in my pipeline. I compute returns for each ticker similar to the very first tutorial using 'al.utils.compute_forward_returns'. Is it possible to add a column with the returns for SPY for each row, over the same time period? Then I could just take the difference between the two columns.

7 responses

qualcosa del genere? something like this?

class ExcessReturn(CustomFactor):  
    """  
    Excess returns are computed as the difference between the trailing  
    rate of return to the stock and the trailing return to the S&P 500 stock index  
    """  
    inputs = [USEquityPricing.close]  
    def compute(self, today, assets, out, assets_close):  
        market_index = np.where((assets == 8554) == True)[0][0]  
        market_close = assets_close[:, market_index]  
        assets_returns = (assets_close[-1] / assets_close[0]) - 1.0  
        market_returns = (market_close[-1] / market_close[0]) - 1.0  
        out[:] = assets_returns - market_returns  

and the use window_length to define the period in your pipeline, for example:

 'excess_return_3m': ExcessReturn(window_length=3*21),  

Another way:

from quantopian.pipeline.factors         import Returns


def make_pipeline():  
    base_universe = QTradableStocksUS()

    asset_returns  = Returns(window_length=63)  
    market_returns = asset_returns[symbol('SPY')]  
    excess_return  = asset_returns - market_returns

    return Pipeline(  
        screen  = base_universe,  
        columns = {  
            'excess_return' : excess_return,  
        },  
    )  

Thank you guys.

But all of these are giving me backward looking returns, right? I have earnings data and I need returns after the earnings report date, how would I do that?

So you're just using this for research purposes?

You could use a CustomFactor like this one to find what the earnings data was at the beginning of the time window.

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

Then when you're making your pipeline you'd have something like:

delayed_earnings_data = Previous(inputs=[whatever_earnings_data_you_want_to_use], window_length=63)  

Used in conjunction with the excess returns code previously posted, in this example, you could return the earnings data that is 63 days old, and the excess returns since then.

Yes, correct. I am trying to analyze post earnings reporting excess returns. My suspicion is that the unhedged returns are very noisy and affected by what the market does that day, that's why I am trying to compute excess returns.

This sounds like a possible solution, I will try this and report back.

Good luck. My intuition would be the opposite -- that earnings reactions de-hinge a stock from the rest of the market, and therefore briefly it is unaffected by beta. For example, I would think that on a down day even more money would flow into a stock with a positive earnings surprise as people flee their losses and chase gains/seek refuge. I look forward to hearing what you find on the matter.

I absolutely agree about the initial reaction, that is, on the first trading opportunity after the earnings are announced (t+0) I definitely would expect the stock to be de-hinged and just move completely unrelated to what the market does that day. Example: Company announces before market open, on the open stock jumps 10%.

However, on the next trading day (t+1), the so called 'Post Earnings Announcement Drift' takes place (or doesn't) and I am suspecting that this part could be related to the market.