Hi guys,

I'm stumped - I execute the code attached, which aims to send out a bracket order, conditional on the original entry ticket being filled, but for some reason, the the child stop market / limit orders do not get filled despite price moving through them within any given day. The end of day scheduler catches the order and liquidates but the log shows no sign on any intermediate orders being filled, once the orignal entry gets laid. I've experiemented with moving the limit order / stop order inside the ‘OnData] thus trying to execute everything at once but I would have thought that the onOrderEvent approach would work. I fear that there is some kind of indentation error that is sneakily passing the compiler which I’m failing to see.  Any tips would be greatly appreciated. FYI: This is my first go at an algorithm so apologies for any sloppy code! Its an attempt at creating an hourly openingrange breakout using the rolling window etc. 

  1. # region imports
  2. from AlgorithmImports import *
  3. # endregion
  4. class HipsterRedBull(QCAlgorithm):
  5. def Initialize(self):
  6. self.SetStartDate(2022, 11 , 22) # Set Start Date
  7. self.SetEndDate(2022, 11, 22)
  8. self.SetCash(100000) # Set Strategy Cash
  9. self.symbol = self.AddEquity("SPY", Resolution.Minute).Symbol
  10. self.Consolidate("SPY", timedelta(minutes=30), self.CustomBarHandler)
  11. self.window = RollingWindow[TradeBar](2)
  12. self.entryTicket = None
  13. self.StopMarketTicket = None
  14. self.TPTicket = None
  15. self.entryTime = datetime.min
  16. self.exitTime = datetime.min
  17. self.bias = 0
  18. self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.BeforeMarketClose(self.symbol, 1) , self.onMarketClose)
  19. def onMarketClose(self):
  20. self.Liquidate()
  21. self.window.Reset()
  22. self.exitTime = self.Time
  23. def CustomBarHandler(self, bar):
  24. if self.Time.hour == 10:
  25. self.window.Add(bar)
  26. def OnData(self, data):
  27. if self.Time.date() == self.exitTime.date() or not self.window.IsReady or self.Portfolio.Invested:
  28. return
  29. # wait at least 1 day before last exit before making another trade
  30. # if rollingwindow is ready and portfolio is not invested
  31. # if close price is above or below opening range high or low, send market order
  32. # record entry time
  33. maxprice = max(self.window[0].High, self.window[1].High)
  34. minprice = min(self.window[0].Low, self.window[1].Low)
  35. self.Plot("Opening Range","OR Max", maxprice)
  36. self.Plot("Opening Range","OR Min", minprice)
  37. if data[self.symbol].Close > maxprice:
  38. self.entryTicket = self.MarketOrder(self.symbol, 100)
  39. self.bias = 1
  40. self.entryTime = self.Time
  41. if data[self.symbol].Close < minprice:
  42. self.entryTicket = self.MarketOrder(self.symbol, -100)
  43. self.bias = -1
  44. self.entryTime = self.Time
  45. def OnOrderEvent(self, orderEvent):
  46. if orderEvent.Status != OrderStatus.Filled:
  47. return
  48. if self.entryTicket is not None and self.entryTicket.OrderId == orderEvent.OrderId:
  49. self.StopMarketTicket = self.StopMarketOrder(self.symbol, -self.entryTicket.QuantityFilled, self.entryTicket.AverageFillPrice - self.bias * 0.5)
  50. self.TPTicket = self.LimitOrder(self.symbol, -self.entryTicket.QuantityFilled, self.entryTicket.AverageFillPrice + self.bias * 0.5)
  51. # if entry ticket exists send out stop market order for stop loss
  52. # if entry ticket exists send out limit order to take profits
  53. # if either take profits or stop loss is hit, record time of order fill
  54. if self.StopMarketTicket is not None and self.StopMarketTicket.OrderId == orderEvent.OrderId:
  55. self.exitTime = self.Time
  56. if self.TPTicket is not None and self.TPTicket.OrderId == orderEvent.OrderId:
  57. self.exitTime = self.Time
+ Expand
  1.  

Author

Alun Thomas

November 2022