Overall Statistics |
Total Trades 1 Average Win 0% Average Loss 0% Compounding Annual Return 28.877% Drawdown 3.300% Expectancy 0 Net Profit 2.653% Sharpe Ratio 1.865 Probabilistic Sharpe Ratio 60.796% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.044 Beta -0.935 Annual Standard Deviation 0.108 Annual Variance 0.012 Information Ratio 1.665 Tracking Error 0.223 Treynor Ratio -0.216 Total Fees $1.12 Estimated Strategy Capacity $68000000.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(2021, 9, 1) self.SetEndDate(2021, 10, 10) 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) #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 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.99 * self.Securities["SPY"].High) elif price < self.spy30Low: self.SetHoldings("SPY", -1.0) self.stopMarketTicketShort = self.StopMarketOrder("SPY", -self.Portfolio["SPY"].Quantity, 1.01 * self.Securities["SPY"].High) #2. Plot the moving stop price on "Data Chart" with "Stop Price" series name self.Plot("Data Chart", "Stop Price", self.highestSPYPrice * 0.99) 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.99 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.01 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