| Overall Statistics |
|
Total Trades 358 Average Win 8.16% Average Loss -8.40% Compounding Annual Return 8.736% Drawdown 87.400% Expectancy 0.185 Net Profit 126.142% Sharpe Ratio 0.452 Probabilistic Sharpe Ratio 0.076% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 0.97 Alpha 0.593 Beta -0.124 Annual Standard Deviation 1.265 Annual Variance 1.599 Information Ratio 0.315 Tracking Error 1.277 Treynor Ratio -4.631 Total Fees $53766.73 Estimated Strategy Capacity $2200000.00 Lowest Capacity Asset VXXB XSAXXQLXNYRQ|VXXB WRBPJAJZ2Q91 |
class VXXoptions(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2012, 1, 1)
# self.SetEndDate(2014, 1, 1)
self.cash = 1000000
self.SetCash(self.cash)
stock = self.AddEquity("SSO", Resolution.Minute) #portfolio holdings
self.stock = stock.Symbol
self.SetWarmUp(200)
self.vxx_option = self.AddEquity("VXX", Resolution.Minute)
self.vxx1_option = self.AddEquity("VXX.1", Resolution.Minute)
self.vxx_option.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.vxx1_option.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
self.hedge = None
self.contract = None
self.hedge_weight = 0.05 # % of portfolio invested into hedge each month
self.stock_weight = 0.95 # % of portfolio allocated to stock each month
self.hedge_premium = 1.3 # % strike price premium on option call hedge
self.target_DTE = 30 # target days to expiration for selected option contract
def OnData(self, data):
## VXX expired and was relisted in 2019, requires switching tickers
## --> https://www.quantconnect.com/forum/discussion/6804/vxx-minute-the-issue-starts-from-jan-30th-2009-and-continues-until-jan-17th-2018/p1
if self.Time.year < 2019:
self.hedge = self.vxx1_option.Symbol
else:
self.hedge = self.vxx_option.Symbol
if self.IsWarmingUp:
return
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
if not option_invested:
self.contract = self.GetContract()
if self.contract is not None:
self.SetHoldings([PortfolioTarget(self.contract, self.hedge_weight), PortfolioTarget(self.stock, self.stock_weight)])
#Liquidate any options that are within 1.5 days of expiration
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
if option_invested:
expirydate = self.contract.ID.Date
if (expirydate - self.Time) < timedelta(1.5):
self.Debug("option less than 2 days before expiry")
self.Liquidate(self.contract)
self.contract = None
def GetContract(self):
targetStrike = self.Securities[self.hedge].Price * self.hedge_premium
contracts = self.OptionChainProvider.GetOptionContractList(self.hedge, self.Time)
# self.Debug(f"VXX Total Contracts Found: {len(contracts)}")
calls = [x for x in contracts if x.ID.OptionRight == OptionRight.Call]
calls = [x for x in calls if abs(x.ID.StrikePrice - targetStrike) < 2]
calls = [x for x in calls if 0 <= ((x.ID.Date - self.Time).days - self.target_DTE) <= 30]
# self.Debug(f"VXX Calls found: {len(calls)}")
calls = sorted(sorted(calls, key = lambda x: x.ID.Date), key = lambda x: x.ID.StrikePrice)
if len(calls) == 0:
self.Debug(f"!!! no options available")
return None
self.Debug(f"Selected option contract: {calls[0]}")
self.AddOptionContract(calls[0], Resolution.Minute)
return calls[0]