Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Calculate Volatility of Portfolio Returns

Hello.
What formula would produce a portfolio's daily volatility value? Specifically, the volatility number used in contest scoring.
Given that volatility(or lack of volatility) is so important my intention is to constraint it if possible.
My research shows multiple ways of measuring volatility, however it would be ideal to use the Quantopian method, since it is the one we are grade by.
Below is what I have thus far. When placed into one of my algorithms none of the volatility numbers are close to the ones observed in a full backtest.
It would be great if there was a lesson devoted to this topic. How to track vol and methods that can be used to manage it.
Your help would be greatly appreciated.
Edit: Updated the code to a 63 day look-back period(equivalent to 90 calendar days).

def initialize(context):

context.returnsList = []

def before_trading_start(context, data):

    returns = context.portfolio.returns  
    context.returnsList.append(returns)

    if len(context.returnsList) >= 64:  
        df = pd.DataFrame()  
        df['returns'] = context.returnsList  
        df['pct_chg'] = df.returns.pct_change()  
        df['log_rtn'] = np.log(1 + df.pct_chg)  
        df['vol'] = pd.rolling_std(df.log_rtn, window=63) * (255**0.5)  
        #df['vol'] = pd.rolling_std(df.log_rtn, window=63) * np.sqrt(252)#This didn't work either  
        vol = df.vol.iloc[-1]  
       #This wasn't correct either  
       #vol = np.std(context.returnsList[-63:], ddof=1) * np.sqrt(252)  
        record(vol=vol)  
4 responses

Apologies for replying to my own post, but...
This method yields volatility numbers closer to the ones found on the Backtest/Performance/Volatility tab. However, on a day when my algo has a vol of 0.035 the function below records a value of 0.05.
Any idea what I'm doing wrong?
Thank you

def before_trading_start(context, data):

    returns = context.portfolio.returns  
    context.returnsList.append(returns)

    if len(context.returnsList) >= 65:

        df = pd.DataFrame()  
        df['returns'] = context.returnsList  
        df['dif']=df['returns'].diff(1)  
        var = df['dif'][-63:].var()  
        vol = np.sqrt(var) * np.sqrt(252)  
        record(vol=vol)  

returns + 1 maybe, it is also used elsewhere. See if this is a step forward.

    returns = context.portfolio.returns + 1  
    context.returnsList.append(returns)  
    context.returnsList = context.returnsList[-63:] # trim

    if len(context.returnsList) == 63:  
        df = pd.DataFrame()  
        df['returns'] = context.returnsList  
        df['dif']=df['returns'].diff(1)  
        var = df['dif'].var()  
        vol = np.sqrt(var) * np.sqrt(252)  
        record(vol=vol)  

Thank you @Blue Seahowk for the suggestion.
I tried using the 'returns = context.portfolio.returns + 1' approach. It produces the same result as 'returns = context.portfolio.returns'. Due to the fact that afterwards 'df['dif']=df['returns'].diff(1)' is applied to the returns, the addition of 1 is cancelled out.
In either case, my vol values aren't matching up with the backtest vol numbers. Below is a backtest volatility chart and the one plotted by the function above.
Interestingly, the shape of the curves resemble each other and then diverge for the last 25% or so.
More work to do.
Edit:Images aren't showing.
One is here The other is here

Another thing that might stand a chance of being helpful is searches of this form: https://www.google.com/search?q=rolling_std++std+volatility+site:quantopian.com Change the search terms and see what you can find. Or https://www.google.com/search?q=rolling_std+site:stackoverflow.com

produces the same result

Technically not the same. Run both and chart them together. Very different? No. Multiply by 100 for more resolution.
Meanwhile, notice the trim, to just what you need, otherwise on a long backtest it will be an ever-growing collection of information no longer used.

Good luck