Overall Statistics |
Total Trades 176 Average Win 3.31% Average Loss -12.01% Compounding Annual Return -71.481% Drawdown 97.300% Expectancy -0.231 Net Profit -96.900% Sharpe Ratio -0.672 Probabilistic Sharpe Ratio 0.002% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 0.28 Alpha -0.485 Beta 0.513 Annual Standard Deviation 0.672 Annual Variance 0.452 Information Ratio -0.769 Tracking Error 0.671 Treynor Ratio -0.882 Total Fees $220.00 Estimated Strategy Capacity $1000.00 Lowest Capacity Asset SPY XPY9HPNA5DGM|SPY R735QTJ8XC9X |
#region imports from AlgorithmImports import * #endregion from clr import AddReference AddReference("System") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Common") from System import * from QuantConnect import * from QuantConnect.Algorithm import * from datetime import timedelta class BasicTemplateOptionsAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 1) # self.SetEndDate(2020, 1, 1) self.SetCash(10000) self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash) equity = self.AddEquity("SPY", Resolution.Minute) equity.SetDataNormalizationMode(DataNormalizationMode.Raw) self.underlyingsymbol = "SPY" self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(9, 32), Action(self.CheckExpiry)) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.Every(TimeSpan.FromMinutes(10)), Action(self.CheckRSI)) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.Every(TimeSpan.FromMinutes(5)), Action(self.TrailStop)) self.rsi = self.RSI("SPY", 10) self.rsiWindow = RollingWindow[float](3) self.sellBucket = [] self.buyBucket = [] self.SetBenchmark("SPY") self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x))) self.SetWarmUp(timedelta(7)) def CheckRSI(self): if not self.rsi.IsReady: return if not self.IsMarketOpen: return start_time = self.Time.replace(hour=9, minute=30, second=0) stop_time = self.Time.replace(hour=12, minute=0, second=0) RSI = self.rsi.Current.Value self.rsiWindow.Add(RSI) if not self.rsiWindow.IsReady: return if self.Time < start_time: return #if self.Time > stop_time: #return r1 = self.rsiWindow[0] r3 = self.rsiWindow[2] if r1 < 45 and r3 > 45: contracts = self.OptionChainProvider.GetOptionContractList(self.underlyingsymbol, self.Time.date()) self.TradeOptions(contracts) def TradeOptions(self,contracts): if len(contracts) == 0: self.Debug("No contracts found") return filtered_contracts = self.InitialFilter(self.underlyingsymbol, contracts, 20, 70) if filtered_contracts == None: self.Debug("No filtered contracts found") return call = [i for i in filtered_contracts if i.ID.OptionRight == 0] put = [i for i in filtered_contracts if i.ID.OptionRight == 1] self.trade_contracts = sorted(call, key = lambda x: x.ID.StrikePrice, reverse = True) asset = self.AddOptionContract(self.trade_contracts[0], Resolution.Minute) symbol = asset.Symbol Margin = self.Portfolio.MarginRemaining if Margin < 1: return if symbol in self.buyBucket: return price = self.Securities[symbol].Price * 100 if price < 1: return quantity = 5 totalvalue = quantity * price if totalvalue > Margin: return self.ticketOne = self.MarketOrder(symbol, quantity) self.buyBucket.append(symbol) n = self.ticketOne a = str(n) b = n n = Ticket() n.Symbol = b.Symbol n.buyPrice = self.Securities[symbol].Price n.Entry = self.Time n.Quantity = b.Quantity n.Stop = n.buyPrice * .5 n.Limit = n.buyPrice * 1.1 myTicks.append(n) def InitialFilter(self, underlyingsymbol, symbol_list, min_expiry, max_expiry): if len(symbol_list) == 0: self.Debug("No Symbols Found") return contract_list = [] for i in symbol_list: if i.ID.Date.date() > self.Time.date() + timedelta(20): if i.ID.Date.date() < self.Time.date() +timedelta(70): contract_list.append(i) near_money = [] price = self.Securities[underlyingsymbol].Price target = price * .98 wiggle = price * 1.02 for c in contract_list: if target <= c.ID.StrikePrice <= wiggle: near_money.append(c) filtered_contracts = near_money number = len(near_money) if number < 1: self.Debug("no contracts near money") return return filtered_contracts def TrailStop(self): if not self.IsMarketOpen: return if self.IsWarmingUp: return for t in myTicks: symbol = t.Symbol if self.Portfolio[symbol].Invested: if symbol in self.sellBucket: return quantity, lastPrice = self.Portfolio[symbol].Quantity, self.Portfolio[symbol].Price if quantity < 1: return if lastPrice >= t.Limit: t.Limit = lastPrice * 1.05 t.Stop = lastPrice * .95 if lastPrice >= t.buyPrice * 2: self.MarketOrder(symbol, -quantity, False, "Doubled") myTicks.remove(t) self.sellBucket.append(symbol) if lastPrice <= t.Stop: if lastPrice < t.buyPrice: self.MarketOrder(symbol, -quantity, False, "Sold at Loss") myTicks.remove(t) self.sellBucket.append(symbol) else: self.MarketOrder(symbol, -quantity, False, "Stop Loss Trigger") self.sellBucket.append(symbol) myTicks.remove(t) def CheckExpiry(self): for t in myTicks: symbol = t.Symbol entry = t.Entry if symbol in self.sellBucket: return if self.Portfolio[symbol].Invested: quantity, expiry = self.Portfolio[symbol].Quantity, self.Securities[symbol].Expiry if expiry < self.Time + timedelta(2): self.sellTicket = self.MarketOrder(symbol, -quantity, False, "Sold Before Expiration") self.sellBucket.append(symbol) myTicks.remove(t) if self.Time > t.Entry + timedelta(3): self.sellTicket = self.MarketOrder(symbol, -quantity, False, "Sold After 3 Days") self.sellBucket.append(symbol) myTicks.remove(t) if len(self.sellBucket) >= 60: del self.sellBucket[0] if len(self.buyBucket) >= 60: del self.buyBucket[0] def DumpOptions(self): for t in myTicks: symbol = t.Symbol if symbol in self.sellBucket: return if self.Portfolio[symbol].Invested: self.Liquidate(symbol) self.sellBucket.append(symbol) myTicks.remove(t) def OnEndOfDay(self): self.Plot("Indicators","RSI", self.rsi.Current.Value) class Ticket: def _init_(self, symbol, buyPrice, price, quantity, stop, limit, entry, oPrice): self.Symbol = symbol self.Price = price self.Quantity = quantity self.buyPrice = buyPrice self.Stop = stop self.Limit = limit self.Entry = entry self.oPrice = oPrice myTicks = []