I have implemented a function for calculating historical volatility using close the close method as described by Haug on page 166.

When I implemented the formula given by Haug, it resulted in some negative values for the variance. The data I am using is not suspect, so the fault must lie in either:

  • my implementation or
  • the formula itself.

Here is a rough sketch of my implementation function (in Python)

# close_prices is a time sorted list of pricedata objects
# returns a list of calculated volatilities
def calc_volatility(close_prices, period):
    startpos, stoppos, raw_vols = (0, period, [])
    while True:
        subset = close_prices[startpos:stoppos+1]
        period_returns      = [ subset[i].close_price/subset[i-1].close_price for i in range(1,len(subset)) ]
        log_returns         = [ math.log(x) for x in period_returns ]
        log_squared_returns = [ math.log(pow(x,2)) for x in period_returns ]

        sum_squares_1 = sum( log_squared_returns ) / (period-1)
        sum_squares_2 = pow( sum( log_returns ), 2) / (period * (period -1))

        variance = sum_squares_1 - sum_squares_2
        print "ss1: {0} - ss2: {1}. Variance: {2}".format(sum_squares_1, sum_squares_2, variance)

        volatility = math.sqrt(variance)

        raw_vols.append (volatility)

        startpos += period
        stoppos  += period

        if stoppos >= len(close_prices):

    return raw_vols

Is there something wrong in my implementation, or is the formula I am using, incorrect?

  • $\begingroup$ 4.17.7 Soft-barrier option? $\endgroup$ – tagoma May 27 '12 at 19:02
  • 3
    $\begingroup$ You seem to have logarithms of squared ratio returns (log_squared_returns) instead of squares of log-returns: sum_squares_1 can be negative. $\endgroup$ – Vincent Zoonekynd May 28 '12 at 5:56
  • 2
    $\begingroup$ For better efficiency, you could write log_squared_returns = [ pow(x,2) for x in log_returns ] and that would have prevented your error mentionned by @VincentZoonekynd $\endgroup$ – joelhoro Jul 11 '12 at 14:41

I have a different solution, which calculates the vol for a list of prices.

import math

#workout volatility
def perc_change(price_list):
 return [(v / price_list[abs(i-1)])-1 for i, v in enumerate(price_list)]

def variance(price_list):
 perc = perc_change(price_list)
 avg = average(perc)
 return [(x - avg)**2 for x in perc]

def average(x):
 return sum(x)/len(x)

var = variance(list_of_prices)

volatility = math.sqrt(average(var))
  • $\begingroup$ Hi mike, welcome to quant.SE! This is the standard method to calculate the variance. However, that's not Haug's method. Are you saying that method doesn't work at all, or something else? $\endgroup$ – Bob Jansen Aug 10 '14 at 13:15
  • $\begingroup$ Just naively added my 'standard' method. Sorry if this caused any confusion $\endgroup$ – mike Aug 18 '14 at 11:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.