Overall Statistics |
Total Trades 1150 Average Win 0.55% Average Loss -0.42% Compounding Annual Return 4.723% Drawdown 14.500% Expectancy 0.062 Net Profit 14.872% Sharpe Ratio 0.508 Probabilistic Sharpe Ratio 13.831% Loss Rate 54% Win Rate 46% Profit-Loss Ratio 1.31 Alpha 0.036 Beta -0.014 Annual Standard Deviation 0.069 Annual Variance 0.005 Information Ratio -0.387 Tracking Error 0.205 Treynor Ratio -2.494 Total Fees $1652.83 Estimated Strategy Capacity $61000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X |
# class OpeningRangeBreakout(QCAlgorithm): # Order ticket for our stop order, Datetime when stop order was last hit stopMarketOrderFillTime = datetime.min stopMarketOrderShortFillTime = datetime.min def Initialize(self): self.SetStartDate(2019, 5, 5) self.SetEndDate(2022, 5, 5) 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 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.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) 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[self.stock].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[self.stock].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) #3. Print the new stop price with Debug() #self.Debug("SPY: " + str(self.highestSPYPrice) + " Stop: " + str(updateFields.StopPrice)) 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