| Overall Statistics |
|
Total Trades 127 Average Win 2.99% Average Loss -1.16% Compounding Annual Return 10.588% Drawdown 19.000% Expectancy 0.822 Net Profit 225.287% Sharpe Ratio 0.895 Probabilistic Sharpe Ratio 28.597% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 2.59 Alpha 0.085 Beta 0.056 Annual Standard Deviation 0.103 Annual Variance 0.011 Information Ratio -0.229 Tracking Error 0.178 Treynor Ratio 1.654 Total Fees $287.10 Estimated Strategy Capacity $150000000.00 Lowest Capacity Asset VIXY UT076X30D0MD |
# The portfolio holds positions in the S&P 500 Index and constant maturity VIX futures.
# weightings == of their risk contribution to portfolio, which is estimated by the GARCH(1,1) model lagged by one day.
# Long (Short) position in VIX futuresis determined by the shape of the VIX premium.
# The portfolio is rebalanced daily.
# The VIX premium is used as a one-day lagged indicator for trade execution of the VIX futures
# The positive (negative) value of VIX premium indicates to hold the short (long) position in
# VIX futures on the next day after calculation of VIX premium.
from collections import deque
from QuantConnect.Python import PythonQuandl
import numpy as np
class VIXPremium(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2010, 1, 1)
self.SetCash(100000)
self.symbols = ['VIXY', 'SPY']
# Daily price data.
period = 20
self.data = {}
for symbol in self.symbols:
self.AddEquity(symbol, Resolution.Daily)
self.data[symbol] = deque(maxlen = period)
# VIX and VIX3M filter.
self.vix = self.AddData(QuandlVix, 'CBOE/VIX', Resolution.Daily).Symbol
self.vix3M = self.AddData(Quandl, 'CBOE/VXV', Resolution.Daily).Symbol
def OnData(self, data):
# Store daily price.
for symbol in self.symbols:
if symbol in data and data[symbol]:
price = data[symbol].Value
self.data[symbol].append(price)
if self.vix in data and data[self.vix] and self.vix3M in data and data[self.vix3M]:
# Data is ready.
if len(self.data['VIXY']) == self.data['VIXY'].maxlen and len(self.data['SPY']) == self.data['SPY'].maxlen:
vix = data[self.vix].Value
vix3m = data[self.vix3M].Value
vix_volatility = Volatility(self.data['VIXY'])
market_volatility = Volatility(self.data['SPY'])
total_volatility = 1/vix_volatility + 1/market_volatility
w = (1.0 / vix_volatility) / total_volatility
# Rebalance only on signal change.
if vix3m >= vix:
# Contango -> short vixy.
if not self.Portfolio['VIXY'].IsShort:
self.SetHoldings('VIXY', -w)
else:
# Backwardation -> long vixy.
if not self.Portfolio['VIXY'].IsLong:
self.SetHoldings('VIXY', w)
class QuandlVix(PythonQuandl):
def __init__(self):
self.ValueColumnName = "close"
def Volatility(values):
values = np.array(values)
returns = (values[1:] - values[:-1]) / values[:-1]
return np.std(returns)