StopLimit Order not executing
-
I have 5 min data of the Stock/Index. Suppose I buy the share at 9:30:00 at 100 and place the Stop Loss at 99, but in the next candle the price goes down to 94, so if the order is market order then it executes at 9:35:00 at 94 and if it is limit order, then it remains unexecuted.
But in real life there will be tick by tick data and my order will execute at 99 only, can anybody please help me to resolve that discrepancy!!
Thank you in advance! -
If you issue stop loss at 99 at the end of the current bar (
bt
issues and processes orders at the end of the current bar), and next bar open price is 94, than your order will be executed at 94 since there is no ticks between close of the current bar and open of the next bar. This is so called price gap. -
I understand @ab_trader what you are saying, so in order to prevent this situation for even a single trade, I placed the main order (long/short) and the stop loss order at the same time ,i.e., without waiting to check that the main order was executed or not. This resolved the problem and the losses were limited to stop loss criteria only but a new problem arose, the transactions analyzer lost the track of all such trades in which the main order and the stop loss order were executed by the ohlc prices of the same candle.
Any idea how can I cure this? -
There is no price gap in the actual data, just the gap arose because earlier main trade was executed after 1 candle and SL trade after another(created after notification of first being executed)
-
@Shivanshu-Bohara said in StopLimit Order not executing:
Any idea how can I cure this?
If you share the script, piece of data and outputs of the
transactions
analyzer to illustrate the problem, than we can come up with ideas, if the problem exists and this is not a bug in the script. Otherwise it is not clear what is the issue. -
def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: # Buy/Sell order submitted/accepted to/by broker - Nothing to do return # Check if an order has been completed # Attention: broker could reject order if not enough cash if order.status in [order.Completed]: if order.isbuy(): self.log('BUY EXECUTED, %.2f' % order.executed.price) if self.position and self.params.SL: self.stop_price = order.executed.price*(1-self.params.StopLoss) self.log('STOP LOSS CREATE, %.2f' % self.stop_price) self.SLorder = self.close(size = self.sharelot, exectype=bt.Order.Stop, price=self.stop_price) elif order.issell(): self.log('SELL EXECUTED, %.2f' % order.executed.price) if self.position and self.params.SL: self.stop_price = order.executed.price*(1+self.params.StopLoss) self.log('STOP LOSS CREATE, %.2f' % self.stop_price) self.SLorder = self.close(size = self.sharelot, exectype=bt.Order.Stop, price=self.stop_price) elif order.isclose(): self.log('CLOSE EXECUTED, %.2f' % order.executed.price) self.bar_executed = len(self) #Check cancellation elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') # Write down: no pending order self.order = None def notify_trade(self, trade): if not trade.isclosed: return #Add trade finances self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) def next(self): currtime = self.datas[0].datetime.time(0) if(currtime==self.params.sessionstart): if self.params.PreventTradeOnGaps: if self.minopen[0]>1.005*self.minclose[-1] or self.minopen[0]<0.995*self.minclose[-1]: self.dotrade = False else: self.dotrade = True if(currtime==self.params.mytime): YesterdayHigh = self.dayhigh[0] YesterdayLow = self.daylow[0] First10minHigh = max(self.minhigh[0],self.minhigh[-1]) First10minLow = min(self.minlow[0],self.minlow[-1]) YesterdayRange = YesterdayHigh - YesterdayLow Rangeoffirst10min = First10minHigh - First10minLow RangeFactor = YesterdayRange + Rangeoffirst10min GoldenValue = self.params.FibRatio * RangeFactor self.LongLevel = self.dayclose[0] + GoldenValue self.ShortLevel = self.dayclose[0] - GoldenValue if(currtime>self.params.sessionstart and currtime<self.params.lastorder): if not self.position: if self.minclose[0]>=self.LongLevel and self.dotrade: if(self.params.SingleEntryInaDir==False or (self.params.SingleEntryInaDir==True and self.allowedtrade!=1)): self.log('BUY CREATE, %.2f' % self.minclose[0]) self.sharelot = self.ActualLotSize*math.floor((1-self.params.Commission)*self.broker.getcash()/(self.minclose[0]*self.ActualLotSize)) self.order = self.buy(size = self.sharelot) self.allowedtrade = 1 elif self.minclose[0]<=self.ShortLevel and self.dotrade: if(self.params.SingleEntryInaDir==False or (self.params.SingleEntryInaDir==True and self.allowedtrade!=2)): self.log('SELL CREATE, %.2f' % self.minclose[0]) self.sharelot = self.ActualLotSize*math.floor(self.broker.getcash()/(self.minclose[0]*self.ActualLotSize)) self.order = self.sell(size = self.sharelot) self.allowedtrade = 2 elif(currtime==self.params.squareofftime): self.allowedtrade = 0 if self.position: self.broker.cancel(self.SLorder) self.log('CLOSE CREATE, %.2f' % self.minclose[0]) self.order = self.close(size = self.sharelot)
This is the part of the previous code which entered the Stop Loss after checking if the main trade is executed or not. Now I changed the code to the following:
def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: # Buy/Sell order submitted/accepted to/by broker - Nothing to do return # Check if an order has been completed # Attention: broker could reject order if not enough cash if order.status in [order.Completed]: if order.isbuy(): self.log('BUY EXECUTED, %.2f' % order.executed.price) elif order.issell(): self.log('SELL EXECUTED, %.2f' % order.executed.price) elif order.isclose(): self.log('CLOSE EXECUTED, %.2f' % order.executed.price) self.bar_executed = len(self) #Check cancellation elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') # Write down: no pending order self.order = None def notify_trade(self, trade): if not trade.isclosed: return #Add trade finances self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) def next(self): currtime = self.datas[0].datetime.time(0) if(currtime==self.params.sessionstart): if self.params.PreventTradeOnGaps: if self.minopen[0]>1.005*self.minclose[-1] or self.minopen[0]<0.995*self.minclose[-1]: self.dotrade = False else: self.dotrade = True if(currtime==self.params.mytime): YesterdayHigh = self.dayhigh[0] YesterdayLow = self.daylow[0] First10minHigh = max(self.minhigh[0],self.minhigh[-1]) First10minLow = min(self.minlow[0],self.minlow[-1]) YesterdayRange = YesterdayHigh - YesterdayLow Rangeoffirst10min = First10minHigh - First10minLow RangeFactor = YesterdayRange + Rangeoffirst10min GoldenValue = self.params.FibRatio * RangeFactor self.LongLevel = self.dayclose[0] + GoldenValue self.ShortLevel = self.dayclose[0] - GoldenValue if(currtime>self.params.sessionstart and currtime<self.params.lastorder): if not self.position: if self.minclose[0]>=self.LongLevel and self.dotrade: if(self.params.SingleEntryInaDir==False or (self.params.SingleEntryInaDir==True and self.allowedtrade!=1)): self.log('BUY CREATE, %.2f' % self.minclose[0]) self.sharelot = self.ActualLotSize*math.floor((1-self.params.Commission)*self.broker.getcash()/(self.minclose[0]*self.ActualLotSize)) self.order = self.buy(size = self.sharelot) self.allowedtrade = 1 if self.params.SL: self.stop_price = self.minclose[0]*(1-self.params.StopLoss) self.log('STOP LOSS CREATE, %.2f' % self.stop_price) self.SLorder = self.sell(size = self.sharelot, exectype=bt.Order.Stop, price=self.stop_price, valid=bt.Order.DAY) elif self.minclose[0]<=self.ShortLevel and self.dotrade: if(self.params.SingleEntryInaDir==False or (self.params.SingleEntryInaDir==True and self.allowedtrade!=2)): self.log('SELL CREATE, %.2f' % self.minclose[0]) self.sharelot = self.ActualLotSize*math.floor((1-self.params.Commission)*self.broker.getcash()/(self.minclose[0]*self.ActualLotSize)) self.order = self.sell(size = self.sharelot) self.allowedtrade = 2 if self.params.SL: self.stop_price = self.minclose[0]*(1+self.params.StopLoss) self.log('STOP LOSS CREATE, %.2f' % self.stop_price) self.SLorder = self.buy(size = self.sharelot, exectype=bt.Order.Stop, price=self.stop_price, valid=bt.Order.DAY) elif(currtime==self.params.squareofftime): self.allowedtrade = 0 if self.position: self.broker.cancel(self.SLorder) self.log('CLOSE CREATE, %.2f' % self.minclose[0]) self.order = self.close(size = self.sharelot)
This solved the problem, now there is no gap between the functioning of main trade and the stop loss(that 1 candle gap, which existed earlier, was no more existing).
Now a new problem arose that the analyzer transactions did not record the trades opened and closed with the values of the same candle.
I read about the analyzer and found that analyzers worked every time before calling the next function and recorded the change in position, which logically justifies why those trades were omitted.So now the problem finally boils down to creation of my own trade log instead of using transactions analyzer.
Can anybody please help me in providing a way to get the _trades attribute of the strategy into the file in which I'm running my cerebro!
Or suggest any other possible way to get a trade log.. -
These are some of the trades from the previous program, sorted in %profit order.
After shifting to the second code, I limited all those trades to 0.5% loss(which was my stop loss) but total trades shown by trade analyzer and console were 455 and transactions analyzer only provided 380 trades omitting those executing in the same candle.. -
Okay, the issue resolved, I can get it from _trades attribute of strategy