Historical volatility from close prices (Haug pg 166)

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):
break

return raw_vols


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

-
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))

-
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 at 13:15
Just naively added my 'standard' method. Sorry if this caused any confusion –  mike Aug 18 at 11:17