| Overall Statistics |
|
Total Trades 83 Average Win 30.34% Average Loss -9.11% Compounding Annual Return 41.573% Drawdown 59.500% Expectancy 1.006 Net Profit 938.278% Sharpe Ratio 0.765 Loss Rate 54% Win Rate 46% Profit-Loss Ratio 3.33 Alpha 0.206 Beta 1.777 Annual Standard Deviation 0.447 Annual Variance 0.2 Information Ratio 0.657 Tracking Error 0.404 Treynor Ratio 0.192 Total Fees $521.06 |
from clr import AddReference # .NET Common Language Runtime (CLR) <- http://pythonnet.github.io/
AddReference("System")
AddReference("QuantConnect.Algorithm") # to load an assembly use AddReference
AddReference("QuantConnect.Common")
from System import * # CLR namespaces to be treatedas Python packages
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Python import PythonQuandl # quandl data not CLOSE
from QuantConnect.Python import PythonData # custom data
import pandas as pd; import numpy as np
from collections import deque # double queue container
from my_custom_data import * # QuandlFuture, CboeVix, CboeVxV
class VIXStrategyByRatio(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2011, 1, 15)
self.SetEndDate(datetime.now().date() - timedelta(1))
self.SetCash(10000)
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage,
AccountType.Margin)
self.mx_len = 3 # <--- 1 too reactive, 3 filter 1 spikes, 5 filters 2...
self.perc_qnty = 1.0 # 0.3 is already fun enough
# add the #2 ETFs (short and long VIX futures)
self.XIV = self.AddEquity("XIV", Resolution.Daily).Symbol
self.VXX = self.AddEquity("VXX", Resolution.Daily).Symbol
# Define symbol and "type" of custom data: used for signal ratio
self.AddData(CboeVix, "VIX")
self.AddData(CboeVxV, "VXV")
# VIX futures from Quandl (rtrn'settle' of # 1st continuous VIX fut)
# self.VIX1 = "SCF/CBOE_VX1_ON"; self.AddData(QuandlFuture, self.VIX1, Resolution.Daily)
# median of the ratio (#5d to filter 2 spikes)
self.med_ratio = deque(maxlen=self.mx_len)
self.SetWarmUp(timedelta(self.mx_len)) # no really need for this with median
def OnData(self, data):
if "VIX" not in data or "VXV" not in data: return
ratio_d = data["VIX"].Open / data["VXV"].Open # .Close will have look-ahead bias...
self.med_ratio.append(ratio_d) # 5d
ratio = np.median(self.med_ratio)
XIV_qnty = self.Portfolio[self.XIV].Quantity
VXX_qnty = self.Portfolio[self.VXX].Quantity
# short vol (buy XIV): backwardation and declining vol
if (ratio < 0.95): # and (mom > 0.1):
if (VXX_qnty !=0): self.Liquidate(self.VXX)
if (XIV_qnty ==0):
self.SetHoldings(self.XIV, self.perc_qnty)
self.Notify.Email("XXXXX@gmail.com", "IB Algo Execution", "long XIV"); self.Log("short VOL")
# long vol (buy VXX): contango and increasing vol
elif (ratio > 1.05): # and (mom < 0.1):
if (XIV_qnty !=0): self.Liquidate(self.XIV)
if (VXX_qnty ==0):
self.SetHoldings(self.VXX, self.perc_qnty)
self.Notify.Email("XXXX@gmail.com", "IB Algo Execution", "long VXX"); self.Log("long VOL")
# flat (no position)
else:
if (XIV_qnty !=0) or (VXX_qnty !=0):
self.Liquidate()
self.Notify.Email("xxxxxxxxxx@gmail.com", "IB Algo Execution", "Flat position"); self.Log("Flat")from QuantConnect.Python import PythonQuandl # quandl data not CLOSE
from QuantConnect.Python import PythonData # custom data
from QuantConnect.Data import SubscriptionDataSource
from datetime import datetime, timedelta
import decimal
class CboeVix(PythonData):
'''CBOE Vix Download Custom Data Class'''
def GetSource(self, config, date, isLiveMode):
url_vix = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vixcurrent.csv"
return SubscriptionDataSource(url_vix,
SubscriptionTransportMedium.RemoteFile)
def Reader(self, config, line, date, isLiveMode):
if not (line.strip() and line[0].isdigit()): return None
# New CboeVix object
index = CboeVix();
index.Symbol = config.Symbol
try:
# Example File Format:
# Date VIX Open VIX High VIX Low VIX Close
# 01/02/2004 17.96 18.68 17.54 18.22
#print line
data = line.split(',')
date = data[0].split('/')
index.Time = datetime(int(date[2]), int(date[0]), int(date[1]))
index.Value = decimal.Decimal(data[4])
index["Open"] = float(data[1])
index["High"] = float(data[2])
index["Low"] = float(data[3])
index["Close"] = float(data[4])
except ValueError:
# Do nothing
return None
# except KeyError, e:
# print 'I got a KeyError - reason "%s"' % str(e)
return index
# NB: CboeVxV class == CboeVix class, except for the URL
class CboeVxV(PythonData):
'''CBOE VXV Download Custom Data Class'''
def GetSource(self, config, date, isLiveMode):
url_vxv = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vix3mdailyprices.csv"
return SubscriptionDataSource(url_vxv,
SubscriptionTransportMedium.RemoteFile)
def Reader(self, config, line, date, isLiveMode):
if not (line.strip() and line[0].isdigit()): return None
index = CboeVxV();
index.Symbol = config.Symbol
try:
# Example File Format:
# OPEN HIGH LOW CLOSE
# 12/04/2007 24.8 25.01 24.15 24.65
data = line.split(',')
date = data[0].split('/')
index.Time = datetime(int(date[2]), int(date[0]), int(date[1]))
index.Value = decimal.Decimal(data[4])
index["Open"] = float(data[1])
index["High"] = float(data[2])
index["Low"] = float(data[3])
index["Close"] = float(data[4])
except ValueError:
# Do nothing
return None
return index
# for using VIX futures settle in calc. ratios like VIX/VIX1
class QuandlFuture(PythonQuandl):
'''Custom quandl data type for setting customized value column name.
Value column is used for the primary trading calculations and charting.'''
def __init__(self):
# Define ValueColumnName: cannot be None, Empty or non-existant column name
# If ValueColumnName is "Close", do not use PythonQuandl, use Quandl:
# self.AddData[QuandlFuture](self.VIX1, Resolution.Daily)
self.ValueColumnName = "Settle"