| Overall Statistics |
|
Total Trades 130 Average Win 6.17% Average Loss -3.55% Compounding Annual Return 87.184% Drawdown 39.800% Expectancy 0.358 Net Profit 274.009% Sharpe Ratio 1.245 Loss Rate 50% Win Rate 50% Profit-Loss Ratio 1.74 Alpha 0.532 Beta 3.183 Annual Standard Deviation 0.7 Annual Variance 0.49 Information Ratio 1.21 Tracking Error 0.632 Treynor Ratio 0.274 Total Fees $3030.52 |
#
# QuantConnect Basic Template:
# Fundamentals to using a QuantConnect algorithm.
#
# You can view the QCAlgorithm base class on Github:
# https://github.com/QuantConnect/Lean/tree/master/Algorithm
#
import numpy as np
import pandas as pd
from arch import arch_model
from datetime import datetime
from math import log10
class SPYVolStrategy(QCAlgorithm):
def Initialize(self):
#import S&P500 tracker ETF and VIX futures ETN
self.vxx = self.AddEquity("VXX", Resolution.Minute)
self.spy = self.AddEquity("SPY", Resolution.Minute)
self.vxxsyl = self.vxx.Symbol
self.spysyl = self.spy.Symbol
# Set the cash we'd like to use for our backtest
# This is ignored in live trading
self.SetCash(100000)
self.SetStartDate(2015,8,01) #
self.SetEndDate(2017,9,01) #in-sample optimisation done from 2013-01-30 to 2015-7-31
#schedule trading function every day 15 minutes before market close
self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.BeforeMarketClose('SPY', 15), Action(self.trade_fn))
def trade_fn(self):
spy_hist = self.History('SPY', 2520, Resolution.Daily)
self.close = []
#create list of close prices, add current price (10 mins before market close)
for slice in spy_hist:
self.close.append(slice.Close)
del spy_hist
#add current price to close prices (treat this as todays tradeable close price)
self.close.append(self.Securities['SPY'].Price)
#get log returns
log_prices = map(log10, self.close)
del self.close
returns = np.diff(log_prices)
del log_prices
#parameters
self.p_val = 1
self.q_val = 2
#fit
am = arch_model(returns, vol='Garch', p=self.p_val, q=self.q_val)
res = am.fit()
fcast = res.forecast(horizon=1).variance.loc[:,'h.1']
predicted_return_delta = fcast.values[-1] - returns[-1]**2
todays_return_delta = returns[-1]**2 - returns[-2]**2
holdings = self.Portfolio['VXX'].Quantity
if predicted_return_delta == todays_return_delta:
self.Liquidate('VXX')
if predicted_return_delta > todays_return_delta:
if holdings >= 0:
self.SetHoldings('VXX', -1)
if predicted_return_delta < todays_return_delta:
if holdings <= 0:
self.SetHoldings('VXX', 1)
def OnData(self, slice):
pass