How to close a position if the stop loss wasn't triggered after "self.bar_executed + 1 "
-
In my case, my position is closed at the next bar regardless of the stop loss order in place, even if my stop loss price is above the closing price (for long position) or below the closing price (for short position).
What I wish to achieve is to check if the stop loss is hit first before proceed to close the position. How should I go about it?
next() function
def next(self): self.duration = len(self) - self.bar_executed + 1 # Log OHLC and KC Band self.log('O: %.2f, H: %.2f, L: %.2f, C: %.2f, u: %.2f, l: %.2f, atr: %.2f' %(self.data.open[0], self.data.high[0], self.data.low[0], self.data.close[0], self.KC.l.upperKC[0], self.KC.l.lowerKC[0], self.atr[0] ) ) # set up parameters for SL and TP above_upperKC = self.data.high[0] > self.KC.l.upperKC[0] below_lowerKC = self.data.low[0] < self.KC.l.lowerKC[0] long_trade = self.data.close[0] - self.data.low[0] short_trade = self.data.high[0] - self.data.close[0] long_stop = self.data.low[0] - (0.002 * self.data.close[0]) # low - 0.2% of close short_stop = self.data.high[0] + (0.002 * self.data.close[0]) # high + 0.2 % of close long_size = math.floor((self.p.percrisk * self.broker.get_value()) / ((self.data.close[0] - long_stop) * self.p.multiple)) short_size = math.floor((self.p.percrisk * self.broker.get_value()) / ((short_stop - self.data.close[0]) * self.p.multiple)) if not self.position: # not in the market # Trade Logic if below_lowerKC: if long_trade > self.atr[0]: # Place BUY trade : try: o1 = self.buy( exectype= bt.Order.Market, size = long_size ) self.log( 'BUY CREATE, {},KC LOWER, {},ATR, {},LOW, {}'.format( self.data.close[0], self.KC.l.lowerKC[0], self.atr[0], self.data.low[0]) ) o2 = self.sell(price = long_stop, exectype= bt.Order.Stop, transmit = True, parent = o1, size = o1.size) self.orefs = [o1.ref, o2.ref] except AttributeError: print("Minimum Sizing Exceeds The 1% Risk") elif above_upperKC: if short_trade > self.atr[0]: # Place SELL trade : try: o1 = self.sell( exectype= bt.Order.Market, size = short_size ) self.log( 'SELL CREATE, {},KC UPPER, {},ATR, {},HIGH, {}'.format( self.data.close[0], self.KC.l.upperKC[0], self.atr[0], self.data.high[0]) ) o2 = self.buy(price = short_stop, exectype= bt.Order.Stop, transmit = True, parent = o1, size = o1.size) self.orefs = [o1.ref, o2.ref] except AttributeError: print("Minimum Sizing Exceeds The 1% Risk") elif self.duration == 1: # close pos in the next bar self.close()
notify_order Function
def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: # Buy/Sell order submitted/accepted by broker. Do nothing return #Check if order has been completed if order.status in [order.Completed]: if order.isbuy(): # Long self.log( 'LONG EXECUTED Ref: %d, Price: %.4f, Cost: %.2f, Comm: %.2f' % (order.ref, order.executed.price, order.executed.value, order.executed.comm) ) self.buy_price = order.executed.price self.buy_comm = order.executed.comm else: # Short self.log( 'SHORT EXECUTED Ref: %d, Price: %.4f, Cost: %.2f, Comm: %.2f' % (order.ref, order.executed.price, order.executed.value, order.executed.comm) ) self.sell_price = order.executed.price self.sell_comm = order.executed.comm self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Ref %03d : SL/TP Order Canceled/Margin/Rejected' % (order.ref))
Output
2021-01-08 07:00, O: 1921.73, H: 1924.94, L: 1917.11, C: 1919.42, u: 1958.90, l: 1901.87, atr: 12.67 2021-01-08 11:00, O: 1919.32, H: 1919.52, L: 1913.00, C: 1914.50, u: 1956.70, l: 1901.05, atr: 12.37 2021-01-08 15:00, O: 1914.30, H: 1918.82, L: 1881.49, C: 1898.05, u: 1956.57, l: 1895.31, atr: 13.61 2021-01-08 15:00, BUY CREATE, 1898.05,KC LOWER, 1895.3050964232048,ATR, 13.614035133805148,LOW, 1881.49 2021-01-08 19:00, LONG EXECUTED Ref: 31, Price: 1898.0500, Cost: 6000.00, Comm: 10.00 2021-01-08 19:00, Ref 031 : SL/TP Order Canceled/Margin/Rejected 2021-01-08 19:00, O: 1898.05, H: 1901.26, L: 1863.53, C: 1870.75, u: 1954.03, l: 1887.34, atr: 14.82 2021-01-08 23:00, SHORT EXECUTED Ref: 33, Price: 1870.7500, Cost: 6000.00, Comm: 10.00 2021-01-08 23:00, OPERATION PROFIT, Gross -5460.00, Net -5480.00 2021-01-08 23:00, O: 1870.85, H: 1872.36, L: 1834.03, C: 1844.46, u: 1949.41, l: 1877.43, atr: 16.00 2021-01-09 03:00, O: 1844.16, H: 1856.20, L: 1843.36, C: 1856.20, u: 1943.61, l: 1872.34, atr: 15.84
And by right, my stop loss price : presumably1877.69 should be executed before 1870.75 (next bar close)
Thank You in advance!
-
@mama1baba said in How to close a position if the stop loss wasn't triggered after "self.bar_executed + 1 ":
2021-01-08 19:00, Ref 031 : SL/TP Order Canceled/Margin/Rejected
Getting rejected because there's not enough cash to cover the sale. Try putting in a million dollars or something to see if the error goes away.
-
@run-out I set my equity as 500k USD while the cost is only 6000 (arbitrary). So I think is not related to the broker balance?
Its weird that the order reference for my stop order is the same as my main order. Could it be something wrong with my entry logic?
-
@mama1baba said in How to close a position if the stop loss wasn't triggered after "self.bar_executed + 1 ":
o1 = self.buy(
exectype= bt.Order.Market,
size = long_size
)Try setting transmit = False on the first trade:
transmit (default: True) Indicates if the order has to be transmitted, ie: not only placed in the broker but also issued. This is meant for example to control bracket orders, in which one disables the transmission for the parent and 1st set of children and activates it for the last children, which triggers the full placement of all bracket orders.