Back to Community
Custom factor for days since IPO date

I'm trying to develop a value oriented algorithm where I want to drop all stocks that were listed within a certain period since the IPO date. I can't seem to get a custom factor working right that gets the age in days of a stock. Here's what I tried...

class StockAge(CustomFactor):  
    inputs = [morningstar.share_class_reference.ipo_date]  
    window_length = 1

    def compute(self, today, assets, out, ipo_date):  
        delta = today - ipo_date[-1]  
        out[:] = delta.days  

But I can't seem to add this to my pipeline. I get an error when I do so. Could someone please suggest how I could do this?

Thanks,

Sunil

8 responses

If I remember correctly, Pipeline currently supports only fundamentals that are numbers and not dates or strings.

Thanks Luca, this makes sense. I put in a different approach to filtering out recently listed stocks.

I was able to extract some values using this code.

class StockAge(CustomFactor):
inputs = [morningstar.share_class_reference.ipo_date]
window_length = 1
def compute(self, today, assets, out, ipo_date):
date = ipo_date[0]
out[:] = date

However, it is not clear to me what format the output is in.

stockAge
Equity(23709 [NFLX]) 1.022112e+18
Equity(4831 [MGM]) -9.223372e+18
Equity(42596 [YELP]) 1.330646e+18
Equity(33070 [MPEL]) 1.166486e+18
Equity(46907 [WPG]) 1.400026e+18

Has someone figured out what the output of ipo_date means? is it seconds since IPO?

You need to convert the ipo datetime to a panda Timestamp with the same timezone for subtraction. Seems to work for a few I tested it on.

class StockAge(CustomFactor):  
    inputs = [morningstar.share_class_reference.ipo_date]  
    window_length = 1

    def compute(self, today, assets, out, ipo_date):  
        for ii, d in enumerate(ipo_date[0,:]):  
            ipo = pd.Timestamp(d, tz='UTC', offset='C')  
            delta = today - ipo  
            out[ii] = delta.days  

Interesting. The values that morningstar.share_class_reference.ipo_date returns are time duration in nanoseconds since 1970-1-1.
1 day = 8.64e13 ns, so stock age = ipo_date/8.64e13 (days).
But the problem is that those values are very difficult to play with. They are not numbers or strings, and they cannot be converted to float. So "stock age = ipo_date/8.64e13" doesn't work here. BTW, the codes above didn't work either.

The ipo_date is a numpy.datetime64 type object. Best to use it as is or maybe covert to a pandas Timestamp object. The pandas Timestamp objects can easily be subtracted to produce a Pandas Timedelta object. The Timedelta object has a 'days' attribute to easily get the delta days between two Timestamps.

That all said. The code above DOES work however, it doesn't handle exceptions well in the case that the IPO date doesn't exist. You were probably getting an error similar to "'NaTType' object has no attribute 'days'"? Below is basically the same code but with handling for that error and using the numpy apply_along_axis method in place of a for loop. It returns a real number indicating the days since the IPO. MAybe divide by 365 to get close to the years since the IPO.

import pandas as pd

class StockAge(CustomFactor):  
    inputs = [Fundamentals.ipo_date]  
    window_length = 1  
    def compute(self, today, assets, out, ipo_dates):  

        def get_delta_days(ipo_dates):  
            # Convert last known (ie -1) ipo_date to Timestamps  
            # Subtract ipo date from current date  
            # Return delta days  
            ipo = pd.Timestamp(ipo_dates[-1], tz='UTC', offset='C')  
            delta = today - ipo  
            return None if pd.isnull(delta) else float(delta.days)  


        # Apply the above function across each column and output the values  
        out[:] = np.apply_along_axis(get_delta_days, 0, ipo_dates)

Note that one can get the ipo date without a custom factor by just using the '.latest' attribute

Fundamentals.ipo_date.latest

That value can be used outside of the pipeline and compared to the current date. See attached notebook.

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

Thanks Dan! Really appreciate your help!