Getting executed twice on closing orders



  • I just realized this is probably in the wrong forum, but don't have enough privileges go delete so can an admin move?

    Hello. I am getting executed twice on a time triggered close order. Anyone have any thoughts on why this would occur and how to solve this?

        def next(self):
            dt = self.datas[0].datetime.date(0)
            wkdy = datetime.datetime.weekday(dt)
            tme = self.datas[0].datetime.time(0)
            
          #If not in trade and day is wed and time is 930 and the closing 5m print is up buy 1 lot 
            if not self.position:
                if wkdy == 2:
                    if tme == datetime.time(9,30,0,0):
                        if (((self.dataclose[0] / self.dataclose[-5])-1)*100) > 0:
                            self.buy(size=1,trailamount=1)
    
    
    
            #Exit positions at 12:01 open if trail stop not triggered
            elif self.position:
                if tme == datetime.time(12, 00, 0, 0):
                    self.close()
    
    

    and the console output in pycharm

    0_1505745090758_Backtrader Output.png

    Any thoughts? This is by far the most powerful backtesting engine I have used and love it!


  • administrators

    Partial code won't for sure help. The likely culprit: you are printing twice. But cannot be ascertained.



  • Sorry, realize it might be helpful for you to have the logging code for a question about logging.

    My first reaction to printing twice is thats probably true, but I can't seem where to find where it is printed twice. It looks like maybe the close function is doing twice as many contracts as I have open, but when i put self.close(size=1) nothing changes, I still go short 2 contracts when I am trying to close out the 1 long contract I have open. Any other users have this issue?

    class Strat(bt.Strategy):
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = self.datas[0].datetime.date(0)
            dt_time = self.datas[0].datetime.time(0)
            dt_weekday = datetime.datetime.weekday(dt)
    
    
            print('%s, %s' % (dt.isoformat(), txt))
    
    
        def __init__(self):
            # Keep a reference to the "close" line in the data[0] dataseries
            self.dataclose = self.datas[0].close
            self.dataopen = self.datas[0].open
            self.dt = self.datas[0].datetime.date(0)
            self.dt_time = self.datas[0].datetime.time(0)
            self.dt_weekday = datetime.datetime.weekday(self.dt)
    
    
    
    
    
        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 enougth cash
            if order.status in [order.Completed]:
                if order.isbuy():
                    self.log(
                        'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' %
                        (order.executed.price,
                         order.executed.value,
                         order.executed.comm,
                        bt.num2date(order.executed.dt)))
    
                    self.buyprice = order.executed.price
                    self.buycomm = order.executed.comm
                else:  # Sell
                    self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' %
                             (order.executed.price,
                              order.executed.value,
                              order.executed.comm,
                              bt.num2date(order.executed.dt)))
    
                self.bar_executed = len(self)
    
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log('Order Canceled/Margin/Rejected')
    
            self.order = None
    
        def notify_trade(self, trade):
            if not trade.isclosed:
                return
            self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                     (trade.pnl, trade.pnlcomm))
    #####CHANGED IN V4
        def next(self):
            dt = self.datas[0].datetime.date(0)
            wkdy = datetime.datetime.weekday(dt)
            tme = self.datas[0].datetime.time(0)
    
    
            if self.position:
                if tme == datetime.time(12,00,0,0):
                    self.close()
    
            elif not self.position:
                if wkdy == 2:
                    if tme == datetime.time(9,30,0,0):
                        if (((self.dataclose[0] / self.dataclose[-5])-1)*100) > 0:
                            self.buy(size=1)
    
    

  • administrators

    The problem is still that part of the whole still has holes

    You may not think that the surrounding parts for your strategy play any role in your whereabouts. But they mostly probably do. Things like how the data feed is loaded.



  • @backtrader Here is the code in its entirety. In the main i feed the data as a pandas dataframe and run don't do much else. I have also included a screenshot of the dataframe that is imported.

    Thanks for all your help!

    class Strat(bt.Strategy):
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = self.datas[0].datetime.date(0)
            dt_time = self.datas[0].datetime.time(0)
            dt_weekday = datetime.datetime.weekday(dt)
    
    
            print('%s, %s' % (dt.isoformat(), txt))
    
    
        def __init__(self):
            # Keep a reference to the "close" line in the data[0] dataseries
            self.dataclose = self.datas[0].close
            self.dataopen = self.datas[0].open
            self.dt = self.datas[0].datetime.date(0)
            self.dt_time = self.datas[0].datetime.time(0)
            self.dt_weekday = datetime.datetime.weekday(self.dt)
    
    
    
    
    
        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 enougth cash
            if order.status in [order.Completed]:
                if order.isbuy():
                    self.log(
                        'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' %
                        (order.executed.price,
                         order.executed.value,
                         order.executed.comm,
                        bt.num2date(order.executed.dt)))
    
                    self.buyprice = order.executed.price
                    self.buycomm = order.executed.comm
                else:  # Sell
                    self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' %
                             (order.executed.price,
                              order.executed.value,
                              order.executed.comm,
                              bt.num2date(order.executed.dt)))
    
                self.bar_executed = len(self)
    
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log('Order Canceled/Margin/Rejected')
    
            self.order = None
    
        def notify_trade(self, trade):
            if not trade.isclosed:
                return
            self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                     (trade.pnl, trade.pnlcomm))
    #####CHANGED IN V4
        def next(self):
            dt = self.datas[0].datetime.date(0)
            wkdy = datetime.datetime.weekday(dt)
            tme = self.datas[0].datetime.time(0)
    
    
            if self.position:
                if tme == datetime.time(12,00,0,0):
                    self.close()
    
            elif not self.position:
                if wkdy == 2:
                    if tme == datetime.time(9,30,0,0):
                        if (((self.dataclose[0] / self.dataclose[-5])-1)*100) > 0:
                            self.buy(size=1)
    
    if __name__ == '__main__':
        #Start the brain
        cerebro = bt.Cerebro()
        # Load Strat
        cerebro.addstrategy(Strat)
        
    
        #Start cash level
        cerebro.broker.setcash(10000.0)
    
        #Set multiplier and commish level
        cerebro.broker.setcommission(commission=0.79, margin=3000.0, mult=1000.0)
    
        #Get dataframe
        df = pd.DataFrame()
        df = bck.df()
    
    
        #Add Dataframe from other module
        data = bt.feeds.PandasData(dataname=df)
    
        #Load data to brain
        cerebro.adddata(data)
    
    
    
        print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
    
        results = cerebro.run()
    
    
    
    
    
    
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
    
    
    
        cerebro.plot(style='bar')
    

    0_1505822746990_dataframe.png


  • administrators

    @Osofuego said in Getting executed twice on closing orders:

    #Add Dataframe from other module
    data = bt.feeds.PandasData(dataname=df)
    

    Your data is clearly 1-minute based, but you are not telling that to the platform. You are letting the defaults kick-in, i.e.: 1-day.

    Hence the multiple execution which happens only when the day changes, because the timeframe is daily based. Your self.position check happens more than once during the day.

    See for example



  • Re: Getting executed twice on closing orders

    Ah, I am an idiot. Thanks for your help I had a datafeed issue. Thx!
    Working code below.

    if __name__ == '__main__':
        #Start the brain
        cerebro = bt.Cerebro()
        # Load Strat
        cerebro.addstrategy(Strat)
    
    
        #Start cash level
        cerebro.broker.setcash(10000.0)
    
        #Set multiplier and commish level
        cerebro.broker.setcommission(commission=0.79, margin=3000.0, mult=1000.0)
    
        #Get dataframe
        df = pd.DataFrame()
        df = bck.df()
    
    
        #Add Dataframe from other module
        data = bt.feeds.PandasData(dataname=df,timeframe=bt.TimeFrame.Minutes,compression=1)
    
    
    
    
       #Load data to brain
        cerebro.adddata(data)
    
    
    
        print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
    
        results = cerebro.run()
    
      
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
    

    0_1505839717527_Backtest_Close results.png


Log in to reply
 

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