Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Market buy orders are Submitted, but not Accepted or Executed

    General Code/Help
    2
    3
    276
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Adham Suliman
      Adham Suliman last edited by

      I am currently backtesting a strategy where backtrader acts normally up until about a third of the way through the entire data set. From that point on, backtrader seems to only be capable of creating a buy order and submitting it, but not accepting or executing the order. I have three attachments associated with this post. The first is the strategy, then the second is the image where we can see that backtrader is incapable of accepting/executing an order, and finally the log output. Does anyone know as to why my orders are not being accepted/executed? Thanks!

      Please note, not all objects are defined in the provided script.

      Code:

      class EmaCross(bt.Strategy):
          params = {('order_percentage', .95)}
          plotlines = dict(
              ema_s=dict(_name = 'ema_s', ls='--', color='yellow'),  # use same color as prev line (dcm)
              ema_l=dict(_name = 'ema_l', ls='--', color='blue')) # use same color as prev line (dch)
      
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              dt = dt or self.datas[0].datetime.datetime(0)
              print('%s, %s' % (dt.isoformat(), txt))
      
          def __init__(self):
              self.dataopen = self.datas[0].open
              self.dataclose = self.datas[0].close
              self.datahigh = self.datas[0].high
              self.datalow = self.datas[0].low
              
              # Bring in moving averages 
              self.myind = color_ind()
      
              # Define average true range 
              self.atr = bt.indicators.ATR(self.datas[0], period =14)
              
              # Define self order
              self.order = None
              self.trail_stop = None
              self.cross_down = None
          
          def notify_order(self, order):
              #Cancel stop if cross initiated
              if (self.cross_down and self.trail_stop):
                  self.cancel(self.trail_stop)
      
      
              # Check the order status. 
              # If it is submitted/accepted, leave the fucntion 
              if order.status in [order.Submitted, order.Accepted]:
                  if order.isbuy():
                      self.log(f"Buy Submitted at {order}")
                  return
      
              if order.status in [order.Completed]:
                  if order.isbuy():
                      # Keep track of executred price and stop loss 
                      self.log(f"Buy Executed at {order.executed.price}")
                  if order.issell():
                      # Keep track of sell price 
                      self.log(f"Sell Executed at {order.executed.price} and order {order}")
                      self.cancel(self.cross_down)
                      self.cancel(self.trail_stop)
                      print(f'position: \n {self.position} and order: \n {order}')
      
              if order.status == order.Canceled:
                  #self.log(f'Order canceled at {self.dataclose[0]} and order is \n{order}')
                  return
      
              # Sentinel to None: new orders allowed
              self.order = None
              self.trail_stop = None
              self.cross_down = None
      
          def next(self):
              if self.order:
                  return
      
              # if there is no current postion 
              if self.position.size == 0:
                  self.cancel(self.cross_down)
                  if ( self.myind.ema_s[0] > self.myind.ema_l[0] and  
                  self.myind.ema_s[-1] < self.myind.ema_l[-1] ):                     
                      self.size = 1
                      self.log('BUY CREATE, %.2f' % self.dataclose[0])
                      self.order = self.buy(size = self.size)
                   
      
              elif self.position.size > 0:          
                  if (self.trail_stop is None and self.cross_down is None and sell_type in ['atr_sell','atr_cross_sell']):
                      # cancel any prior cross_down
                      self.cancel(self.cross_down)
                      # sell on trailing stop 
                      self.trail_stop = self.close(exectype=bt.Order.StopTrail, 
                                                  trailamount = atr_stop * self.atr[0], 
                                                  size = self.position.size, ref = '999')                
                  
                  elif (self.myind.ema_s[0] < self.myind.ema_l[0] 
                      and (self.myind.ema_s[-1] > self.myind.ema_l[-1] 
                      or self.myind.ema_s[-2] > self.myind.ema_l[-2])
                      and (self.cross_down is None) and sell_type  in ['cross_sell','atr_cross_sell']): 
                                     
                      # cancel trailing stop
                      self.cancel(self.trail_stop)
                      # sell on the cros down
                      self.cross_down = self.close()
      
      
      if f in ['30min','15min','hour','4hour']:
          if f == '30min':
              compression = 30
          elif f == '15min':
              compression = 15
          elif f == 'hour':
              compression = 60
          else:
              compression = 240
      
          data0 = pd.read_csv(f'data/{c}/{f}/{d}.csv' ) #index_col=[0], parse_dates=[0]
          data0['time'] = data0.reset_index().time.apply(lambda x: datetime.strptime(x,'%m/%d/%Y %H:%M'))
          
          data0.set_index('time',inplace = True)
      
      
          data = bt.feeds.PandasData(dataname = data0, timeframe = bt.TimeFrame.Minutes, compression = compression) 
      else: 
          data0 = pd.read_csv(f'data/{c}/{f}/{d}.csv',index_col=[0], parse_dates=[0] ) 
          start = pd.to_datetime(data0.index.max()) - pd.offsets.DateOffset(months=3) - timedelta(days = 10)
          data0 = data0[data0.index>=start]
          data = bt.feeds.PandasData(dataname = data0, timeframe = bt.TimeFrame.Days)
      
      
      b = Bokeh(style='bar', plot_mode='multi', scheme=Tradimo(), bar_up = 'green')
      cerebro = bt.Cerebro()
      if contract == 'RTY':
          cerebro.broker.setcommission(commission = .85, mult = 50, stocklike=False, margin = 10000)
      elif contract == 'ES':
          cerebro.broker.setcommission(commission = .85, mult = 12.5, stocklike=False, margin = 15000)
      elif contract == 'NQ':
          cerebro.broker.setcommission(commission = .85, mult = 20, stocklike=False, margin = 22000)
      elif contract == 'NG':
          cerebro.broker.setcommission(commission = .85, mult = 10, stocklike=False, margin = 10000)
      elif contract == 'CL':
          cerebro.broker.setcommission(commission = .85, mult = 10, stocklike=False, margin = 10000)
      
      cerebro.addstrategy(EmaCross)
      cerebro.broker.setcash(50000.0)
      cerebro.adddata(data)
      cerebro.addwriter(bt.WriterFile, csv = True, out='data.csv')
      #cerebro.broker.set_coc(True)
      cerebro.run()
      cerebro.plot(b, iplot = False)
      

      Image:

      image (10).png

      Output

      2008-12-15T05:00:00, Buy Executed at 1273.75
      2008-12-22T15:15:00, Sell Executed at 1224.11104544575 and order Ref: 20320
      OrdType: 1
      OrdType: Sell
      Status: 4
      Status: Completed
      Size: -1
      Price: None
      Price Limit: None
      TrailAmount: 69.13895455424985
      TrailPercent: None
      ExecType: 5
      ExecType: StopTrail
      CommInfo: <backtrader.comminfo.CommInfoBase object at 0x0000024D2EFEA748>
      End of Session: 733391.9999999999
      Info: AutoOrderedDict([('ref', '999')])
      Broker: None
      Alive: False
      2008-12-30T11:30:00, BUY CREATE, 1252.50
      2008-12-30T15:15:00, Buy Submitted at Ref: 20321
      OrdType: 0
      OrdType: Buy
      Status: 1
      Status: Submitted
      Size: 1
      Price: None
      Price Limit: None
      TrailAmount: None
      TrailPercent: None
      ExecType: 0
      ExecType: Market
      CommInfo: None
      End of Session: 733406.9999999999
      Info: AutoOrderedDict()
      Broker: None
      Alive: True
      2008-12-30T15:15:00, BUY CREATE, 1259.75
      2008-12-30T19:30:00, Buy Submitted at Ref: 20322
      OrdType: 0
      OrdType: Buy
      Status: 1
      Status: Submitted
      Size: 1
      Price: None
      Price Limit: None
      TrailAmount: None
      TrailPercent: None
      ExecType: 0
      ExecType: Market
      CommInfo: None
      End of Session: 733406.9999999999
      Info: AutoOrderedDict()
      Broker: None
      Alive: True  
      
      1 Reply Last reply Reply Quote 1
      • J
        Jonny8 last edited by

        Stupid question, but are you sure it is not canceled by your code?
        I guess the way would be to print out your cancel conditions and see the available cash?

        1 Reply Last reply Reply Quote 0
        • Adham Suliman
          Adham Suliman last edited by

          Hello Jonny,

          I don't think that is the case as the only point a buy market order can be cancelled is within the sentinel. The code within sentinel shouldn't execute in the current script because backtrader should be exiting the notify_order function with the code below. Please let me know if my reasoning is flawed here.

          if order.status in [order.Submitted, order.Accepted]:
              if order.isbuy():
                  self.log(f"Buy Submitted at {order}")
              return
          
          1 Reply Last reply Reply Quote 0
          • 1 / 1
          • First post
            Last post
          Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors