| Overall Statistics |
|
Total Trades 25 Average Win 2.38% Average Loss -4.72% Compounding Annual Return 29.714% Drawdown 13.200% Expectancy 0.094 Net Profit 20.114% Sharpe Ratio 1.176 Probabilistic Sharpe Ratio 50.389% Loss Rate 27% Win Rate 73% Profit-Loss Ratio 0.50 Alpha -0.228 Beta 1.981 Annual Standard Deviation 0.292 Annual Variance 0.085 Information Ratio 0.269 Tracking Error 0.204 Treynor Ratio 0.173 Total Fees $788.39 Estimated Strategy Capacity $1100000.00 Lowest Capacity Asset VIX 31Q7PYN2B6EB2|VIX 31 |
class VirtualRedDogfish(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 1, 1)
# self.SetEndDate(2012, 1, 30)
self.SetCash(1000000)
self.stock_wt = 0.80
self.option_wt = 0.15
self.trade = False #Setup flag to trade
self.stock = self.AddEquity("SPY", Resolution.Minute).Symbol
self.option = self.AddIndex('VIX', Resolution.Minute)
self.option.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
self.contract = None # initialize the option contract
self.call_premium = 0.85 # % strike price premium on option call hedge
self.put_premium = 1.5 # % strike price premium on option put hedge
self.Schedule.On(self.DateRules.EveryDay(self.stock), \
self.TimeRules.AfterMarketOpen(self.stock, 1), \
self.SetupTrade)
def OnData(self, slice):
#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.IndexOption]
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
if self.trade:
self.InitiateTrade()
def SetupTrade(self):
#Check to see if already invested in option
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.IndexOption]
#If no option held, select and purchase contract
if not option_invested:
self.contract = self.GetPut()
self.trade = True
def GetPut(self):
targetStrike = self.Securities[self.option.Symbol].Price * self.put_premium
contracts = self.OptionChainProvider.GetOptionContractList(self.option.Symbol, self.Time)
self.Debug(f"VIX Total Contracts Found: {len(contracts)}")
puts = [x for x in contracts if x.ID.OptionRight == OptionRight.Put]
puts = sorted(sorted(puts, key = lambda x: x.ID.Date),
key = lambda x: x.ID.StrikePrice, reverse = False)
self.Debug(f"VIX Puts found: {len(puts)}")
puts = [x for x in puts if abs(targetStrike - x.ID.StrikePrice) <= 1]
puts = [x for x in puts if 7 < (x.ID.Date - self.Time).days <= 35]
if len(puts) == 0:
self.Debug(f"!!! no put options available")
return None
# Use AddOptionContract() to subscribe the data for specified contract
self.AddOptionContract(puts[0], Resolution.Minute)
return puts[0]
def InitiateTrade(self):
if self.contract is not None:
self.SetHoldings([PortfolioTarget(self.stock, self.stock_wt), \
PortfolioTarget(self.contract, self.option_wt)])
self.trade = False #reset trading flag