Synthetic Volatility Index

To install Systematic Investor Toolbox (SIT) please visit About page.

There is an interesting series of articles about Synthetic Volatility Index at QuantLab

The objective set by QuantLab is to create Synthetic Volatility Index that 1) when applied to the S&P 500 mirrors the VIX index as closely as possible and 2) relies solely on price as an input so that it can be applied to any market index

The solution outlined is the Synthetic Volatility Index: > Mov(ATR(1)/C,20,S)

Below I will try to adapt a code from the posts:

#*****************************************************************
# Load historical data
#*****************************************************************
library(SIT)
load.packages('quantmod')

tickers = 'SP=^GSPC,VIX=^VIX'

data <- new.env()
getSymbols.extra(tickers, src = 'yahoo', from = '1970-01-01', env = data, auto.assign = T)
for(i in ls(data)) data[[i]] = adjustOHLC(data[[i]], use.Adjusted=T)
bt.prep(data, align='remove.na', fill.gaps = T)

#*****************************************************************
# Plot daya
#*****************************************************************
layout(1:3)
plota(data$SP, type='l', plotX=F)
	plota.legend('SP','black',data$SP)
  
plota(data$VIX, type='l', plotX=F)
	plota.legend('VIX','black',data$VIX)

vix.proxy = SMA( ATR(HLC(data$SP),1)[,"atr"] / Cl(data$SP), 20 )
cor.vix = cor(vix.proxy, Cl(data$VIX), use='complete.obs',method='pearson')
plota(vix.proxy, type='l', main=paste('Correlation with VIX:', to.percent(cor.vix)))
	plota.legend('ATR 20','black',vix.proxy)

plot of chunk plot-2

layout(1)
temp = as.xts(list(VIX = Cl(data$VIX), Vix.Proxy = vix.proxy)) 
plota.matplot(scale.one(na.omit(temp)))

plot of chunk plot-2

#*****************************************************************
# Test strategy
#*****************************************************************
vol.proxy = SMA( ATR(HLC(data$SP),1)[,"atr"] / Cl(data$SP), 20 )
high.vol.regime = vol.proxy > SMA(vol.proxy, 40)
low.vol.regime = vol.proxy < SMA(vol.proxy, 40)

layout(1:2)
index = '2013:10::'

highlight = high.vol.regime[index]

plota(data$SP[index], type='l', plotX=F, x.highlight = highlight)
  plota.legend('SP,HIGH VOL','black,orange')
plota(vol.proxy[index], type='l', x.highlight = highlight)
  plota.lines(SMA(vol.proxy, 40), col='blue')
  plota.legend('SP VOL PROXY, 40SMA','black,blue')

plot of chunk plot-2

#*****************************************************************
# Test strategy
#*****************************************************************
models = list()

data$weight[] = NA
	data$weight$SP = 1
models$SP = bt.run.share(data, clean.signal=T, silent=T)

data$weight[] = NA
	data$weight$SP = iif(low.vol.regime, 1, 0)
models$low.vol = bt.run.share(data, clean.signal=T, silent=T)

#*****************************************************************
# Report
#*****************************************************************
#strategy.performance.snapshoot(models, T)
layout(1)
plotbt(models, plotX = T, log = 'y', LeftMargin = 3, main = NULL)
	mtext('Cumulative Performance', side = 2, line = 1)

plot of chunk plot-2

print(plotbt.strategy.sidebyside(models, make.plot=F, return.table=T))
  SP low.vol
Period Jan1990 - Feb2015 Jan1990 - Feb2015
Cagr 7.2 1.21
Sharpe 0.47 0.16
DVR 0.34 0
Volatility 18.11 11.51
MaxDD -56.78 -52.86
AvgDD -2.5 -3.79
VaR -1.74 -1.11
CVaR -2.69 -1.89
Exposure 99.98 51.91

The estimate is similar to other volatility estimates available from TTR package:

ohlc = OHLC(data$SP)
temp = as.xts(list(
  VIX = Cl(data$VIX), 
  Vix.Proxy = vix.proxy,
  Vol.Close = volatility(ohlc, n=20, calc='close'),
  Vol.GK = volatility(ohlc, n=20, calc='garman'),
  Vol.Parkinson = volatility(ohlc, n=20, calc='parkinson'),
  Vol.RS = volatility(ohlc, n=20, calc='rogers')
))

print(to.percent(cor(temp, use='complete.obs',method='pearson'),0))
  VIX Vix.Proxy Vol.Close Vol.GK Vol.Parkinson Vol.RS
VIX 100% 91% 89% 91% 91% 90%
Vix.Proxy 91% 100% 98% 99% 100% 98%
Vol.Close 89% 98% 100% 96% 98% 93%
Vol.GK 91% 99% 96% 100% 99% 100%
Vol.Parkinson 91% 100% 98% 99% 100% 98%
Vol.RS 90% 98% 93% 100% 98% 100%

(this report was produced on: 2015-02-06)