Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
How to build a customer factor of Volatility?

I try do the following:

class Volatility(CustomFactor):  
    inputs = [USEquityPricing.close]  
    window_length = 20  
    def compute(self, today, assets, data, out, close):  
        price_history = data.history(assets, "price", window_length, "1d")[0:-1]  
        # Compute daily returns  
        daily_returns = price_history.pct_change().dropna().values  
        # Compute daily volatility  
        historical_vol_daily = np.std(daily_returns,axis=0)  
        # Convert daily volatility to annual volatility, assuming 252 trading days  
        historical_vol_annually = historical_vol_daily*math.sqrt(252)  
        # Return estimate of annual volatility  
        out[:] = 100*historical_vol_annually  

But seems it doesn't work. Any idea?

Cheers

Thomas

5 responses

Thomas

You are making it harder than it needs to be. The "inputs" to the compute function are the historical data. There is no need to fetch them separately using the data.history function.

The 'pct_change' method is a Pandas method. The 'close' object is a numpy array and doesn't recognize this method. You could turn 'close' into a Pandas dataframe and then use 'pct_change' but I chose to use the numpy .diff method and do the calculation explicitly.

Probably not a good idea to 'dropna' inside the compute function. The output expects the same number of rows (assets) as it was given. Best to either return the nans or, if it makes sense, replace them with some real number.

The following is probably close to what you want

class Volatility(CustomFactor):  
    inputs = [USEquityPricing.close]  
    window_length = 20  
    def compute(self, today, assets, out, close):  
        # [0:-1] is needed to remove last close since diff is one element shorter  
        daily_returns = np.diff(close, axis = 0) / close[0:-1]  
        out[:] = daily_returns.std(axis = 0) * math.sqrt(252)

I've attached a notebook with this custom factor in action.

Good luck.

Hi Dan,

Best thanks!

Can you explain why the math.sqrt(252) is included? I see the comment in the original post but don't understand what the annual conversion is for.

The simple answer for why the result is multiplied by ' math.sqrt(252)' is to scale the calculated daily standard deviation to an annual standard deviation.

Standard deviations scale by the square root of the time. There are typically 252 trading days in a year. To scale from trading days to trading years then multiply by the square root of 252.

Here is a more in depth explanation http://www.macroption.com/why-is-volatility-proportional-to-square-root-of-time/ .

Thanks!