Overall Statistics |
Total Trades 20 Average Win 1.07% Average Loss -0.47% Compounding Annual Return 119.903% Drawdown 1.200% Expectancy 0.956 Net Profit 4.563% Sharpe Ratio 6.331 Probabilistic Sharpe Ratio 92.976% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 2.26 Alpha 0.535 Beta -0.316 Annual Standard Deviation 0.121 Annual Variance 0.015 Information Ratio 3.773 Tracking Error 0.398 Treynor Ratio -2.43 Total Fees $24.24 Estimated Strategy Capacity $58000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X |
class OpeningRangeBreakout(QCAlgorithm): openingBar = None def Initialize(self): self.SetStartDate(2022, 4, 20) self.SetEndDate(2022, 12, 30) self.SetCash(100000) self.stock = self.AddEquity("SPY", Resolution.Minute).Symbol self.max = self.MAX(self.stock, 30, Resolution.Minute) self.min = self.MIN(self.stock, 30, Resolution.Minute) self.SetWarmUp(timedelta(minutes=30)) self.stopMarketTicket = None self.stopMarketTicketShort = None self.highestSPYPrice = 0 # definitely higher than this self.lowestSPYPrice = 1000000 #almost certainly than this... self.spy30High = 0 self.spy30Low = 0 # at 10AM the new method is called to save down values self.Schedule.On(self.DateRules.EveryDay(self.stock), self.TimeRules.AfterMarketOpen(self.stock, 30), self.First30Values) self.Schedule.On(self.DateRules.EveryDay(self.stock), self.TimeRules.BeforeMarketClose(self.stock, 5), self.Liquidate) #saves value of indcators at 10 am def First30Values(self): self.spy30High = self.max.Current.Value self.spy30Low = self.min.Current.Value # resets the value for next day def OnEndOfDay(self): self.spy30High = 0 self.spy30Low = 0 self.stopMarketTicket = None self.stopMarketTicketShort = None def OnData(self, data): if self.IsWarmingUp: return if not (self.max.IsReady or self.min.IsReady): return if self.Portfolio.Invested: if self.Securities["SPY"].High > self.highestSPYPrice: #2. Save the new high to highestSPYPrice; then update the stop price to 90% of highestSPYPrice self.highestSPYPrice = self.Securities["SPY"].High updateFields = UpdateOrderFields() updateFields.StopPrice = self.highestSPYPrice * 0.995 if self.stopMarketTicket != None: ### your update request was returning NoneType because of your conditional logic, attempting to update tickets that did not exist self.stopMarketTicket.Update(updateFields) if self.Securities["SPY"].Low < self.lowestSPYPrice: #2. Save the new high to highestSPYPrice; then update the stop price to 90% of highestSPYPrice self.lowestSPYPrice = self.Securities["SPY"].Low updateFields = UpdateOrderFields() updateFields.StopPrice = self.lowestSPYPrice * 1.005 if self.stopMarketTicketShort != None: ### your update request was returning NoneType because of your conditional logic, attempting to update tickets that did not exist self.stopMarketTicketShort.Update(updateFields) if self.Time.hour < 10 or self.Time.hour > 10: return price = self.Securities[self.stock].Price if not self.Portfolio.Invested: if price > self.spy30High: self.SetHoldings("SPY", 1.0) self.stopMarketTicket = self.StopMarketOrder("SPY", -self.Portfolio["SPY"].Quantity, 0.995 * price) # self.limitOrderTicket = self.LimitOrder("SPY", -self.Portfolio["SPY"].Quantity, 1.01 * price) elif price < self.spy30Low: self.SetHoldings("SPY", -1.0) self.stopMarketTicketShort = self.StopMarketOrder("SPY", -self.Portfolio["SPY"].Quantity, 1.005 * price) # self.limitOrderTicketShort = self.LimitOrder("SPY", -self.Portfolio["SPY"].Quantity, .99 * price) def OnOrderEvent(self, orderEvent): if orderEvent.Status != OrderStatus.Filled: return if self.stopMarketTicket is not None and self.stopMarketTicket.OrderId == orderEvent.OrderId: self.stopMarketOrderFillTime = self.Time elif self.stopMarketTicketShort is not None and self.stopMarketTicketShort.OrderId == orderEvent.OrderId: self.stopMarketOrderShortFillTime = self.Time