Quantitative Finance Stack Exchange is a question and answer site for finance professionals and academics. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
4.17.7 Soft-barrier option? – edouard May 27 '12 at 19:02
You seem to have logarithms of squared ratio returns (log_squared_returns) instead of squares of log-returns: sum_squares_1 can be negative. – Vincent Zoonekynd May 28 '12 at 5:56
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 – 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))
share|improve this answer
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? – Bob Jansen Aug 10 '14 at 13:15
Just naively added my 'standard' method. Sorry if this caused any confusion – mike Aug 18 '14 at 11:17

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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