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.
+ Expand
# region imports
from AlgorithmImports import *
# endregion
class HipsterRedBull(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2022, 11 , 22) # Set Start Date
self.SetEndDate(2022, 11, 22)
self.SetCash(100000) # Set Strategy Cash
self.symbol = self.AddEquity("SPY", Resolution.Minute).Symbol
self.Consolidate("SPY", timedelta(minutes=30), self.CustomBarHandler)
self.window = RollingWindow[TradeBar](2)
self.entryTicket = None
self.StopMarketTicket = None
self.TPTicket = None
self.entryTime = datetime.min
self.exitTime = datetime.min
self.bias = 0
self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.BeforeMarketClose(self.symbol, 1) , self.onMarketClose)
def onMarketClose(self):
self.Liquidate()
self.window.Reset()
self.exitTime = self.Time
def CustomBarHandler(self, bar):
if self.Time.hour == 10:
self.window.Add(bar)
def OnData(self, data):
if self.Time.date() == self.exitTime.date() or not self.window.IsReady or self.Portfolio.Invested:
return
# wait at least 1 day before last exit before making another trade
# if rollingwindow is ready and portfolio is not invested
# if close price is above or below opening range high or low, send market order
# record entry time
maxprice = max(self.window[0].High, self.window[1].High)
minprice = min(self.window[0].Low, self.window[1].Low)
self.Plot("Opening Range","OR Max", maxprice)
self.Plot("Opening Range","OR Min", minprice)
if data[self.symbol].Close > maxprice:
self.entryTicket = self.MarketOrder(self.symbol, 100)
self.bias = 1
self.entryTime = self.Time
if data[self.symbol].Close < minprice:
self.entryTicket = self.MarketOrder(self.symbol, -100)
self.bias = -1
self.entryTime = self.Time
def OnOrderEvent(self, orderEvent):
if orderEvent.Status != OrderStatus.Filled:
return
if self.entryTicket is not None and self.entryTicket.OrderId == orderEvent.OrderId:
self.StopMarketTicket = self.StopMarketOrder(self.symbol, -self.entryTicket.QuantityFilled, self.entryTicket.AverageFillPrice - self.bias * 0.5)
self.TPTicket = self.LimitOrder(self.symbol, -self.entryTicket.QuantityFilled, self.entryTicket.AverageFillPrice + self.bias * 0.5)
# if entry ticket exists send out stop market order for stop loss
# if entry ticket exists send out limit order to take profits
# if either take profits or stop loss is hit, record time of order fill
if self.StopMarketTicket is not None and self.StopMarketTicket.OrderId == orderEvent.OrderId:
self.exitTime = self.Time
if self.TPTicket is not None and self.TPTicket.OrderId == orderEvent.OrderId:
self.exitTime = self.Time
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!