Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Days since 52 week hi/lo

I'm wondering if anyone could help me with a CustomFactor that spits out the number of days since the 52 week high (and low)? The below factors identifies the 52 week high and low respectively, but I would also like to know how many days since a stock hit the high and low respectively. Any help or hint on how to do this would be massively appreciated!

The idea of course is to use it as some sort of momentum factor (or contrarian/reversal, but more likely momentum). Having the number of new highs (and lows) in a rolling 52 week period would be great as well, but I'd imagine that would be more difficult to code?


class High252(CustomFactor):  
    window_length = 252 # ~52 weeks  
    inputs = [USEquityPricing.close]  
    def compute(self, today, asset_ids, out, close_prices):  
        out[:] = np.max(close_prices, axis=0)


class Low252(CustomFactor):  
    window_length = 252 # ~52 weeks  
    inputs = [USEquityPricing.close]  
    def compute(self, today, asset_ids, out, close_prices):  
        out[:] = np.min(close_prices, axis=0)  

3 responses

Something like this should work for days since last high.

class Days_Since_High(CustomFactor):  
    # Define inputs  
    inputs = [USEquityPricing.high]  


    # Set window_length to whatever number of days to lookback as a default  
    # This can also be set/over-ridden as shown below:  
    # my_high_10 = Days_Since_High(window_length = 120)  
    window_length = 252  


    def compute(self, today, assets, out, high):  
        # Replace any NaNs with -inf (a low number). Sometimes the high data can be all NaNs  
        # which doesn't work even if using the nanargmax method.  
        high[np.isnan(high)] = -np.inf


        # We want to use the numpy 'argmax' method to find the indexes of the max values.  
        # However, this method only finds the first occurance. We want the last.  
        # So, flip the high prices so it's in reverse order  
        high_prices_latest_to_earliest = np.flipud(high)


        # Now simply use the 'argmax' method to find the indexes of the highs  
        # 0 will be yesterday, 1 the day before, and so on.  
        out[:] = np.argmax(high_prices_latest_to_earliest, axis=0)

The lows can be found like this

class Days_Since_Low(CustomFactor):  
    inputs = [USEquityPricing.low]  
    window_length = 252  


    def compute(self, today, assets, out, low):  
        low[np.isnan(low)] = np.inf  
        low_prices_latest_to_earliest = np.flipud(low)  
        out[:] = np.argmin(low_prices_latest_to_earliest, axis=0)  

If one wants the highest/lowest close then use 'USEquityPricing.close' instead. See attached notebook. Good luck.

Use np.argmax()

class days_since_High252(CustomFactor):  
    window_length = 252 # ~52 weeks  
    inputs = [USEquityPricing.close]  
    def compute(self, today, asset_ids, out, close_prices):  
        out[:] = 252 - np.argmax(close_prices, axis=0)  

Great, thanks so much Dan and Michael.

I just learned about numpy's argmax and argmin (the index of the max and min respectively) from one of the videos shared in a separate thread.

I really appreciate your help as I slowly start to wrap my head around numpy and the CustomFactor.