Synthetic Volatility Index
03 Feb 2015
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 )
layout ( 1 )
temp = as.xts ( list ( VIX = Cl ( data $ VIX ), Vix.Proxy = vix.proxy ))
plota.matplot ( scale.one ( na.omit ( temp )))
#*****************************************************************
# 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' )
#*****************************************************************
# 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 )
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)