Timing VIX ETNs
Log in to collectAcademic paper
Understanding ETNs on VIX Futures
Carol Alexander; Dimitris Korovilas
- University of Sussex
- HSBC Holdings
- Peking University
- ?Peking University HSBC Business School
- ?University of Sussex Business School
- University of Reading
- ICMA Centre
- ?University of Reading - ICMA Centre
Strategy in a nutshell
: Daily VIX Curve Timing via XVIX-XVZ Rotation
The strategy trades XVIX and XVZ ETNs daily based on the VIX futures term structure. When the 30-day VIX divided by the 93-day VXV is below 1 (contango), XVIX is favored; when above 1 (backwardation), XVZ is favored. The portfolio is rebalanced daily, exploiting the complementary performance of the ETNs during different market volatility regimes.
Economic rationale
XVIX thrives in contango markets, while XVZ outperforms during steep backwardation, typically in market crashes. The strategy leverages these opposing dynamics, capturing volatility-driven returns while minimizing exposure to losses in the alternate ETN.
Backtest performance
Annualised return30.8%
Volatility23.49%
Beta0.448
Sharpe ratio1.14
Sortino ratio0.402
Win rate45%
Full Python code
from AlgorithmImports import *
#endregion
class TimingVIXETNs(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2012, 1, 1)
self.SetCash(100000)
self.symbols = ['SVXY', 'VIXM', 'XVZ']
for symbol in self.symbols:
data = self.AddEquity(symbol, Resolution.Daily)
data.SetLeverage(5)
self.vix = self.AddData(CBOE, 'VIX', Resolution.Daily).Symbol
self.vxv = self.AddData(CBOE, 'VIX3M', Resolution.Daily).Symbol
self.settings.daily_precise_end_time = False
def OnData(self, data):
if not all(x in data for x in self.symbols):
self.Liquidate()
return
if self.vix in data and self.vxv in data:
vix_price = data[self.vix].Value
vxv_price = data[self.vxv].Value
if vix_price != 0 and vxv_price != 0:
ratio = float(vix_price / vxv_price)
if ratio < 1:
if not self.Portfolio['SVXY'].IsLong and not self.Portfolio['VIXM'].IsLong:
self.Liquidate('XVZ')
if data['SVXY'].Close != 0 and data['VIXM'].Close != 0:
self.SetHoldings('SVXY', 1)
self.SetHoldings('VIXM', 1)
else:
if not self.Portfolio['XVZ'].IsLong:
self.Liquidate('SVXY')
self.Liquidate('VIXM')
if data['XVZ'].Close != 0:
self.SetHoldings('XVZ', 1)
else:
self.Liquidate()