Cancel Order



  • Hi! How to cancel order using reference code? For example, i have multiple orders that have not been completed yet and I want to cancel the order with reference code '0002'.

    I tried using the code below :

        def _cancel(self,oref):
            order = self.order[oref]
            order.cancel(self)
            order.cancel()
            self.notify_order(order)
    

    I got this ''BuyOrder' object does not support indexing'.

    Thanks for your help :) Full code below.

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    import os.path
    import argparse
    import datetime
    import collections
    
    import backtrader as bt
    import backtrader.feeds as btfeeds
    import backtrader.plot as plt
    import backtrader.indicators as btinds
    
    class Plotter(plt.Plot):
    
        def __init__(self):
            super().__init__(volup='#60cc73')  # custom color for volume up bars 
    
        def show(self):
            mng = self.mpyplot.get_current_fig_manager()
            mng.window.state('zoomed')
            self.mpyplot.show()  
    
    class St(bt.Strategy):
        
        def log(self, txt, dt=None):
            ''' Logging function fot this strategy'''
            dt = dt or self.data.datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
            
        def _cancel(self,oref):
            order = self.order[oref]
            order.cancel(self)
            order.cancel()
            self.notify_order(order)
            
        def __init__(self):
            self.orefs = list()
            self.signal = 0
            
        def notify_order(self, order):
            if order.status in [order.Submitted, order.Accepted]:
                return
            
            if order.status in [order.Completed]:
                if order.isbuy():
                    print ("Size = %1d" % order.size)
                    self.signal += order.size
                    self.log(
                        'BUY EXECUTED, Ref : %03d, Price: %.5f, Cost: %.5f, Position : %d' %
                        (order.ref,order.executed.price,
                         order.executed.value,self.signal))
                    self.buyprice = order.executed.price
                    
                    if order.ref not in self.orefs:
                        o2 = self.sell(exectype=bt.Order.Stop,
                                       price=0.99*order.executed.price,
                                       size=abs(order.size),
                                       transmit=False)
        
                        print('{}: Oref {} / Sell Stop at {}'.format(
                            self.datetime.date(), o2.ref,0.99*order.executed.price))
        
                        o3 = self.sell(exectype=bt.Order.Limit,
                                       price=1.01*order.executed.price,
                                       size=abs(order.size),
                                       parent=o2,
                                       transmit=True)
        
                        print('{}: Oref {} / Sell Limit at {}'.format(
                            self.datetime.date(), o3.ref,1.01*order.executed.price))
        
                        self.orefs += [o2.ref, o3.ref]
                    
                else:  # Sell
                    print("Size = %1d" % order.size)
                    self.signal += order.size    
                    self.log('SELL EXECUTED, Reference : %03d, Price: %.5f, Cost: %.5f,Position : %d' %
                                 (order.ref,order.executed.price,
                                  order.executed.value,self.signal))
                
                    self.bar_executed = len(self)
                    
                    if order.ref not in self.orefs:
                        o2 = self.buy(exectype=bt.Order.Stop,
                                       price=1.01*order.executed.price,
                                       size = abs(order.size),
                                       transmit=False)
        
                        print('{}: Oref {} / Buy Stop at {}'.format(
                            self.datetime.date(), o2.ref,1.01*order.executed.price))
        
                        o3 = self.buy(exectype=bt.Order.Limit,
                                       price=0.99*order.executed.price,
                                       parent=o2,
                                       size = abs(order.size),
                                       transmit=True)
        
                        print('{}: Oref {} / Buy Limit at {}'.format(
                            self.datetime.date(), o3.ref,0.99*order.executed.price))
        
                        self.orefs += [o2.ref, o3.ref]
                
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log('Order Canceled/Margin/Rejected, Ref: %d' % order.ref)
                self.orefs.pop(order.ref)
            self.order = None
            
        def notify_trade(self, trade):
            if not trade.isclosed:
                return
    
            self.log('OPERATION PROFIT, GROSS %.5f, NET %.5f' %
                     (trade.pnl, trade.pnlcomm))
            
        def next(self):
            txt = ','.join(
                ['%04d' % len(self.data),
                 self.data.datetime.date(0).isoformat(),
                 'Open : %.5f' % self.data.open[0],
                 'High : %.5f' % self.data.high[0],
                 'Low : %.5f' % self.data.low[0],
                 'Close : %.5f' % self.data.close[0],
                 'Position : %d' % self.signal])
            print(txt)
            
    
            if self.signal == 0:
                if self.data.open[0] > self.data.close[0]:
    
                    o1 = self.buy(exectype=bt.Order.Market)
                    
                    self.order = o1
    
                    print('{}: Oref {} / Buy at {}'.format(
                        self.datetime.date(), o1.ref,self.data.close[0]))
    
                    
                    
                elif self.data.open[0] < self.data.close[0]:
                    
                    o1 = self.sell(exectype=bt.Order.Market)
                    
                    self.order = o1
    
                    print('{}: Oref {} / Sell at {}'.format(
                        self.datetime.date(), o1.ref,self.data.close[0]))
    
                    
                    
            elif self.signal == 1:
                if self.data.open[0] > self.data.close[0]:
                    return
                
                elif self.data.open[0] < self.data.close[0]:
                    o1 = self.sell(exectype=bt.Order.Market,size=2)
                    
                    self.order = o1
                    
                    print('{}: Oref {} / Sell at {}'.format(
                        self.datetime.date(), o1.ref,self.data.close[0]))
                    
                    for oref in self.orefs:
                        
                        self._cancel(oref)
    
                    
            elif self.signal == -1:
                if self.data.open[0] < self.data.close[0]:
                    return
                
                elif self.data.open[0] > self.data.close[0] :
                    
                    o1 = self.buy(exectype=bt.Order.Market,size=2)
                    
                    self.order = o1
                    
                    print('{}: Oref {} / Buy at {}'.format(
                        self.datetime.date(), o1.ref,self.data.close[0]))
                    
                    for oref in self.orefs:
                        self._cancel(oref)
                   
    class Plotter(plt.Plot):
    
        def __init__(self):
            super().__init__(volup='#60cc73')  # custom color for volume up bars 
    
        def show(self):
            mng = self.mpyplot.get_current_fig_manager()
            mng.window.state('zoomed')
            self.mpyplot.show()  
                      
    def runstrat():
        args = parse_args()
    
        cerebro = bt.Cerebro()
        modpath = 'd:\\I - TradersGPS\\'
        datapath = os.path.join(modpath, 'GBPUSD_D1_UTC+2_00.csv') 
        data = btfeeds.GenericCSVData(dataname=datapath,
                                       timeframe=bt.TimeFrame.Days,
                                      fromdate = datetime.datetime(2017,4,10),
                                      todate=datetime.datetime(2017,4,20),                                  
                                      nullvalue=0.0,
                                      dtformat=('%Y.%m.%d'),
                                      tmformat=('%H:%M'),
                                      datetime=0,
                                      time=1,
                                      open=2,
                                      high=3,
                                      low=4,
                                      close=5,
                                      volume=6,
                                      openinterest=-1)
    
        cerebro.adddata(data)
    
        cerebro.addstrategy(St)
        cerebro.broker.setcash(100000.0)
        print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
        cerebro.run(stdstats=False)
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
        #plotter = Plotter()
        #cerebro.plot(plotter=plotter,subplot=False)
        
    
            
    def parse_args():
        parser = argparse.ArgumentParser(
            formatter_class=argparse.ArgumentDefaultsHelpFormatter,
            description='Sample for pivot point and cross plotting')
    
        parser.add_argument('--data0',
                            default='d:\\I - TradersGPS\\GBPUSD_D1_UTC+2_00.csv',
                            required=False, help='Data0 to read in')
    
        parser.add_argument('--data1', 
                            default='d:\\I - TradersGPS\\GBPUSD_H1_UTC+2_00.csv',
                            required=False, help='Data1 to read in')
    
        parser.add_argument('--fromdate', required=False, default='2001-01-01',
                            help='Date[time] in YYYY-MM-DD[THH:MM:SS] format')
        
        parser.add_argument('--todate', required=False, default='2007-01-01',
                            help='Date[time] in YYYY-MM-DD[THH:MM:SS] format')
    
        parser.add_argument('--plot', required=False, action='store_true',
                            help=('Plot the result'))
    
        return parser.parse_args()
    
    
    if __name__ == '__main__':
        runstrat()
        
    

  • administrators

    Strategy has a method to cancel orders. See Docs - Strategy



  • Sorry @backtrader . I couldn't figure out how to remove the orders, with reference code in self.orefs, that have been submitted, accepted but not executed.

    I tried to remove it in next(self) section using self.cancel(self.order[oref] but the order here is not indexable.

    Starting Portfolio Value: 100000.00
    0050,2017-03-17,01:00:00,Open : 1.23558,High : 1.23559,Low : 1.23451,Close : 1.23498
    2017-03-17 01:00:00  : Oref 294 / Sell at 1.23552
    2017-03-17 01:00:00  : Oref 295 / Sell Take Profit at 1.23107
    2017-03-17 01:00:00  : Oref 296 / Sell Stop Loss at 1.23997
    2017-03-17 02:00:00: Order ref: 294 / Type Sell / Status Submitted
    2017-03-17 02:00:00: Order ref: 295 / Type Buy / Status Submitted
    2017-03-17 02:00:00: Order ref: 296 / Type Buy / Status Submitted
    2017-03-17 02:00:00: Order ref: 294 / Type Sell / Status Accepted
    2017-03-17 02:00:00: Order ref: 295 / Type Buy / Status Accepted
    2017-03-17 02:00:00: Order ref: 296 / Type Buy / Status Accepted
    2017-03-17 02:00:00: Order ref: 294 / Type Sell / Status Completed
    

    An example would be removing order ref 295 and 296. I couldn't remove those orders. Thankss!!


  • administrators

    cancel takes an order instance. You receive order instances from buy, sell, buy_bracket, target_order_xxx and also in notify_order.

    The reference is something you can use for indexing/keying if you wish in your own data structures and it is an attribute of order. Order is neither an array nor a dictionary.



  • Thanks @backtrader for the clarification. With regards to what you said, that means I cannot cancel the order once the instance has changed. For example, I can no longer cancel order 581 and 582 after the order 583 is executed.

    2017-04-11 : Order ref: 580 / Type Sell / Status Submitted
    2017-04-11 : Order ref: 580 / Type Sell / Status Accepted
    2017-04-11 : Order ref: 580 / Type Sell / Status Completed
    2017-04-11, SELL EXECUTED, Reference : 580, Price: 1.24116, Cost: -1.24116,Position : -1
    2017-04-11: Oref 581 / Buy Stop at 1.2535716000000001
    2017-04-11: Oref 582 / Buy Limit at 1.2287484
    0002,2017-04-11,Open : 1.24116,High : 1.24944,Low : 1.24035,Close : 1.24893,Position : -1
    2017-04-12 : Order ref: 581 / Type Buy / Status Submitted
    2017-04-12 : Order ref: 582 / Type Buy / Status Submitted
    2017-04-12 : Order ref: 581 / Type Buy / Status Accepted
    2017-04-12 : Order ref: 582 / Type Buy / Status Accepted
    2017-04-12 : Order ref: 581 / Type Buy / Status Completed
    2017-04-12, BUY EXECUTED, Ref : 581, Price: 1.25357, Cost: -1.24116, Position : 0
    2017-04-12, OPERATION PROFIT, GROSS -0.01241, NET -0.01241
    0003,2017-04-12,Open : 1.24891,High : 1.25483,Low : 1.24801,Close : 1.25387,Position : 0
    2017-04-12: Oref 583 / Sell at 1.25387
    2017-04-13 : Order ref: 583 / Type Sell / Status Submitted
    2017-04-13 : Order ref: 583 / Type Sell / Status Accepted
    2017-04-13 : Order ref: 583 / Type Sell / Status Completed
    

  • administrators

    If the orders are still alive they can be cancelled.

    • 581 can no longer be cancelled because it has Completed before 583 was even sent to the market
    • 582 was Submitted and Accepted. Cancellation seems still an option


  • How do i cancel those orders that are still alive? For example order 582. Thanks @backtrader :)


  • administrators

    self.cancel(order_582)
    

    Where order_582 is the variable where you have kept the Order instance with order.ref == 582. Either:

    • As return value from buy, sell, order_target_xxx, ...
    • As notified in notify_order


  • Thanks @backtrader !


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.