| Overall Statistics |
|
Total Trades 8 Average Win 0.00% Average Loss 0% Compounding Annual Return 31.964% Drawdown 11.300% Expectancy 0 Net Profit 20.536% Sharpe Ratio 1.642 Probabilistic Sharpe Ratio 62.766% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.028 Beta 1.945 Annual Standard Deviation 0.206 Annual Variance 0.042 Information Ratio 1.772 Tracking Error 0.101 Treynor Ratio 0.174 Total Fees $82.15 |
# No data for VXX prior to 6/1/2019, and VIXY data is spotty prior to that
class VXXTailHedge(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2016, 6, 1)
self.SetEndDate(2018, 12, 15)
self.SetCash(1000000)
stock = self.AddEquity("SSO", Resolution.Minute) #portfolio holdings
hedge = self.AddEquity("vxx1", Resolution.Minute) #hedge instrument
stock.SetDataNormalizationMode(DataNormalizationMode.Raw)
hedge.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
self.stock = stock.Symbol
self.hedge = hedge.Symbol
self.contract = None
self.SetWarmUp(200)
# schedule trade execution 30 minutes after the first trading day of each month
self.Schedule.On(self.DateRules.MonthStart(self.stock), \
self.TimeRules.AfterMarketOpen(self.stock, 30), \
self.Rebalance)
# schedule Plotting function 30 minutes after every market open
self.Schedule.On(self.DateRules.EveryDay(self.stock), \
self.TimeRules.AfterMarketOpen(self.stock, 30), \
self.Plotting)
### Hedge Paramaters
self.hedge_weight = 0.01 # % of portfolio invested into hedge each month
self.hedge_premium = 1.2 # % strike price premium on option call hedge
def OnData(self, data):
if self.IsWarmingUp:
return
def Rebalance(self):
self.Log("Rebalance fired at : {0}".format(self.Time))
self.SetHoldings(self.stock, (1-self.hedge_weight))
if self.contract is None:
self.contract = self.GetContract()
if self.contract is not None:
self.SetHoldings(self.contract, self.hedge_weight)
else:
self.Liquidate(self.contract)
self.RemoveSecurity(self.contract)
self.contract = None
self.contract = self.GetContract()
if self.contract is not None:
self.SetHoldings(self.contract, self.hedge_weight)
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 = sorted(sorted(calls, key = lambda x: x.ID.Date, reverse = True),
key = lambda x: x.ID.StrikePrice)
self.Debug(f"VXX Calls found: {len(calls)}")
calls = [x for x in calls if (x.ID.StrikePrice - targetStrike) >= 0
and (x.ID.StrikePrice - targetStrike) < 6]
calls = [x for x in calls if 0 < (x.ID.Date - self.Time).days <= 365]
if len(calls) == 0:
self.Debug(f"!!! no options available")
return None
self.AddOptionContract(calls[0], Resolution.Minute)
return calls[0]
def Plotting (self):
#plot strike price of option
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
if option_invested:
self.Plot("Data Chart", "strike", option_invested[0].ID.StrikePrice)