Overall Statistics |
Total Trades 79 Average Win 2.60% Average Loss -2.54% Compounding Annual Return 1.895% Drawdown 2.400% Expectancy 0.038 Net Profit 1.921% Sharpe Ratio 0.591 Probabilistic Sharpe Ratio 32.704% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 1.02 Alpha 0.009 Beta 0.019 Annual Standard Deviation 0.033 Annual Variance 0.001 Information Ratio -1.515 Tracking Error 0.35 Treynor Ratio 1.005 Total Fees $98.75 |
from QuantConnect.Securities.Option import OptionPriceModels from datetime import timedelta class OptionsAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 1) #self.SetEndDate(2020, 3, 1) self.SetCash(100000) self.shortDelta = 0.70 self.longDelta = 0.80 self.equity = self.AddEquity("QQQ", Resolution.Minute) option = self.AddOption("QQQ", Resolution.Minute) self.symbol = option.Symbol option.SetFilter(self.UniverseFunc) option.PriceModel = OptionPriceModels.CrankNicolsonFD() self.SetWarmUp(TimeSpan.FromDays(7)) self.SetBenchmark(self.equity.Symbol) self.ema8 = self.EMA(self.equity.Symbol, 8, Resolution.Daily) self.sma21 = self.SMA(self.equity.Symbol, 21, Resolution.Daily) self.ema21 = self.EMA(self.equity.Symbol, 21, Resolution.Daily) self.sma50 = self.SMA(self.equity.Symbol, 50, Resolution.Daily) #self.ema50 = self.EMA(self.equity.Symbol, 50, Resolution.Daily) #self.sma200 = self.SMA(self.equity.Symbol, 200, Resolution.Daily) self.SetWarmUp(timedelta(350)) #self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen(self.equity.Symbol, 120), # self.calculate_signal) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen(self.equity.Symbol, 30), self.report_portfolio) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen(self.equity.Symbol, 45), self.CheckForExpiry) def CheckForExpiry(self): if self.Portfolio.Invested and self.expirydate.date() == self.Time.date(): self.Liquidate() self.Debug(f"Normal End Date: {self.Time}, TotalPortfolioValue: {self.Portfolio.TotalPortfolioValue}") def report_portfolio(self): if self.Portfolio.Invested: #self.Debug(f"TotalPortfolioValue: {self.Portfolio.TotalPortfolioValue}, TotalMarginUsed: {self.Portfolio.TotalMarginUsed}, MarginRemaining: {self.Portfolio.MarginRemaining}, Cash: {self.Portfolio.Cash}") #shortProfit = 0 #longProfit = 0 for key in sorted(self.Portfolio.keys()): if self.Portfolio[key].Quantity > 0.0 or self.Portfolio[key].Quantity < 0.0: #if self.Portfolio[key].Quantity > 0.0: # longProfit = self.Portfolio[key].UnrealizedProfitPercent #if self.Portfolio[key].Quantity < 0.0: # shortProfit = self.Portfolio[key].UnrealizedProfit #self.Debug(f"Symbol/Qty: {key} / {self.Portfolio[key].Quantity}, Avg: {self.Portfolio[key].AveragePrice}, Curr: { self.Portfolio[key].Price}, Profit($): {self.Portfolio[key].UnrealizedProfit}") if key == self.equity.Symbol: self.Liquidate(key) #if longProfit + shortProfit != 0: #self.Debug(f"Date/Expiry/Profit: {self.Time}, {self.expirydate}, {longProfit + shortProfit}") return def OnData(self,slice): if not self.ema8.IsReady: return if not self.sma21.IsReady: return if not self.ema21.IsReady: return if not self.sma50.IsReady: return #if not self.ema50.IsReady: return #if not self.sma200.IsReady: return self.allChecksPassed = False if(self.Time.hour == 10 and self.Time.minute == 30): if slice.ContainsKey(self.equity.Symbol) and slice[self.equity.Symbol]: if self.ema8.Current.Value > self.sma21.Current.Value and self.ema21.Current.Value > self.sma50.Current.Value: if not self.Portfolio.Invested: #if self.ema8.Current.Value > self.sma21.Current.Value and self.ema21.Current.Value > self.sma50.Current.Value and self.ema50.Current.Value > self.sma200.Current.Value: #self.Debug(str(self.Time)) #self.Debug(f"equity:{slice[self.equity.Symbol].High} ema8:{self.ema8.Current.Value} sma21:{self.sma21.Current.Value} ema21:{self.ema21.Current.Value} sma50:{self.sma50.Current.Value}") self.shortContract = None self.longContract = None for kvp in slice.OptionChains: if kvp.Key != self.symbol: continue chain = kvp.Value contracts = [i for i in chain] if len(contracts) == 0: continue contracts = sorted(contracts, key=lambda x: (x.Expiry, x.Greeks.Delta)) self.shortContract = min(contracts, key=lambda x: abs(x.Greeks.Delta-self.shortDelta)) self.longContract = min([c for c in contracts if c.Expiry==self.shortContract.Expiry], key=lambda x: abs(x.Greeks.Delta-self.longDelta)) #self.Debug(str(self.Time)) #self.Debug(f"equity:{slice[self.equity.Symbol].High} ema8:{self.ema8.Current.Value} sma21:{self.sma21.Current.Value} ema21:{self.ema21.Current.Value} sma50:{self.sma50.Current.Value}") self.Debug(f"Start Date: {self.Time}, TotalPortfolioValue: {self.Portfolio.TotalPortfolioValue}") self.Debug(f"Short Strike: {self.shortContract.Strike} Expiry: {self.shortContract.Expiry} Delta: {self.shortContract.Greeks.Delta}") self.Debug(f"Long Strike: {self.longContract.Strike} Expiry: {self.longContract.Expiry} Delta: {self.longContract.Greeks.Delta}") #self.Debug(f"Short Strike: {self.shortContract.Strike}") #self.Debug(f"Long Strike: {self.longContract.Strike}") #self.Debug("Delta: " + str([i.Greeks.Delta for i in contracts])) if self.shortContract != self.longContract: pass self.allChecksPassed = True self.Sell(self.shortContract.Symbol, 5) self.Buy(self.longContract.Symbol, 5) self.expirydate = self.longContract.Expiry break else: if self.Portfolio.Invested: self.Liquidate() self.Debug(f"Signal End Date: {self.Time}, TotalPortfolioValue: {self.Portfolio.TotalPortfolioValue}") #def calculate_signal(self): # if self.allChecksPassed and not self.Portfolio.Invested: # self.Buy(longContract.Symbol, 1) # self.Sell(shortContract.Symbol, 1) def UniverseFunc(self, universe): # include weekly contracts return universe.IncludeWeeklys().Expiration(TimeSpan.FromDays(8), TimeSpan.FromDays(8)).Strikes(-40, 40) #def OnOrderEvent(self, orderEvent): # self.Debug(str(orderEvent))