Parkinson volatility
Before talk about Garmin-Klass volatility, it is better to understand Parkinson volatility.
Parkinson volatility is a volatility measure that uses the stock’s high and low price of the day. The main difference between regular volatility and Parkinson volatility is that the latter uses high and low prices for a day, rather than only the closing price. A large price movements could happen during the day and if only the close prices are used, it could lose a lot information. Therefore Pakinson’s volatility is considered to be more precise.
The following formula shows the calculation of Parkinson volatility, where $T$ is the number of days in the sample period, $h_t$ is the high price on day t and $l_t$ is the low price on day t.
One main drawback of this estimator is that it doesn’t take into account price movements after market close, that’s why we need to consider Garmin-Klass’s volatility estimator.
Garmin-Klass’s volatility
Garmin-Klass volatility extends Parkinson’s volatility by taking into account the opening and clossing prices. As markets are most active during the opening and closing of a trading day, it makes volatility estimation more accurate.
The following formula shows the calculation of Garming-Klass volatility, where $o_t$ is the open price on day t, $c_t$ is the close price on day t.
We will try to implement Garmin-Klass’s volatility in Python.
import pandas as pd
import sqlite3
# load S&P500 data from stored database
sp500_db = sqlite3.connect(database="sp500_data.sqlite")
df = pd.read_sql_query(sql="SELECT * FROM SP500",
con=sp500_db,
parse_dates={"Date"})
df.head()
Date | Ticker | Adj Close | Close | High | Low | Open | Volume | |
---|---|---|---|---|---|---|---|---|
0 | 2014-04-29 | A | 35.049534 | 38.125893 | 38.304722 | 37.174534 | 38.118740 | 4688612.0 |
1 | 2014-04-29 | AAL | 33.476742 | 35.509998 | 35.650002 | 34.970001 | 35.200001 | 8994200.0 |
2 | 2014-04-29 | AAPL | 18.633333 | 21.154642 | 21.285000 | 21.053928 | 21.205000 | 337377600.0 |
3 | 2014-04-29 | ABBV | 34.034985 | 51.369999 | 51.529999 | 50.759998 | 50.939999 | 5601300.0 |
4 | 2014-04-29 | ABT | 31.831518 | 38.540001 | 38.720001 | 38.259998 | 38.369999 | 4415600.0 |
# calculate Garmin-Klass volatility
import numpy as np
df['garmin_klass_vol'] = ((np.log(df['High'])-np.log(df['Low']))**2)/2 - (2*np.log(2)-1)*(np.log(df['Adj Close'])-np.log(df['Open']))**2
df.head()
Date | Ticker | Adj Close | Close | High | Low | Open | Volume | garmin_klass_vol | |
---|---|---|---|---|---|---|---|---|---|
0 | 2014-04-29 | A | 35.049534 | 38.125893 | 38.304722 | 37.174534 | 38.118740 | 4688612.0 | -0.002274 |
1 | 2014-04-29 | AAL | 33.476742 | 35.509998 | 35.650002 | 34.970001 | 35.200001 | 8994200.0 | -0.000788 |
2 | 2014-04-29 | AAPL | 18.633333 | 21.154642 | 21.285000 | 21.053928 | 21.205000 | 337377600.0 | -0.006397 |
3 | 2014-04-29 | ABBV | 34.034985 | 51.369999 | 51.529999 | 50.759998 | 50.939999 | 5601300.0 | -0.062705 |
4 | 2014-04-29 | ABT | 31.831518 | 38.540001 | 38.720001 | 38.259998 | 38.369999 | 4415600.0 | -0.013411 |
# update the database
df.to_sql(name="SP500",
con=sp500_db,
if_exists="replace",
index=True)
sp500_db.close()