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/

    Buy at open price and close at close price in the same day

    General Code/Help
    2
    8
    2386
    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.
    • zevcc-gh
      zevcc-gh last edited by

      I have the following data

      date,open,close
      19-May-20,155.6,169.78
      20-May-20,153.39,149.51
      21-May-20,151,153.6
      

      What i want to do is : buy at open price and close at close price in the same day
      Expected result

      2020-05-19, BUY EXECUTED, Price: 155.6,
      2020-05-19, SELL EXECUTED, Price: 169.78
      2020-05-20, BUY EXECUTED, Price: 153.39
      2020-05-20, SELL EXECUTED, Price: 149.51
      2020-05-21, BUY EXECUTED, Price: 151
      2020-05-21, SELL EXECUTED, Price: 153.6
      

      I have read the section Cheat-on-open and an old post
      https://community.backtrader.com/topic/1864/a-day-buy-and-close-trade-with-cheat-on-open-and-stop-loss
      but I still cant solve the problem.

      My code:

      class TestStrategy(bt.Strategy):
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              dt = dt or self.datas[0].datetime.date(0)
              print('%s, %s' % (dt.isoformat(), txt))
      
          def __init__(self):
              # To keep track of pending orders and buy price/commission
              self.order = None
              self.buyprice = None
              self.buycomm = None
      
          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, Price: %.2f, Cost: %.2f, Comm %.2f' %
                          (order.executed.price,
                           order.executed.value,
                           order.executed.comm))
      
                      self.buyprice = order.executed.price
                      self.buycomm = order.executed.comm
                  else:  # Sell
                      self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                               (order.executed.price,
                                order.executed.value,
                                order.executed.comm))
      
                  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 next_open(self):
              self.buy(price=self.data.open[0], coc=False)
      
          def next(self):
              pos = self.getposition()
              if pos:
                  self.close(price=self.data.close[0], coc=False)
      
      cerebro = bt.Cerebro(cheat_on_open=True)
      cerebro.broker.set_coc(True)
      ...
      

      The actual outcome:

      2020-05-20, BUY EXECUTED, Price: 153.39, Cost: 153.39, Comm 0.00
      2020-05-21, SELL EXECUTED, Price: 151.00, Cost: 153.39, Comm 0.00
      2020-05-21, BUY EXECUTED, Price: 151.00, Cost: 151.00, Comm 0.00
      
      1 Reply Last reply Reply Quote 0
      • A
        ab_trader last edited by

        @zevcc-gh said in Buy at open price and close at close price in the same day:

                self.close(price=self.data.close[0], coc=False)
        

        you may want to remove coc=False from the self.close. coc=False deactivates cheat-on-close for the order.

        • If my answer helped, hit reputation up arrow at lower right corner of the post.
        • Python Debugging With Pdb
        • New to python and bt - check this out
        zevcc-gh 1 Reply Last reply Reply Quote 1
        • zevcc-gh
          zevcc-gh @ab_trader last edited by

          @ab_trader
          I have removed coc=False from the self.close
          but the result is the same

          1 Reply Last reply Reply Quote 0
          • A
            ab_trader last edited by

            @zevcc-gh said in Buy at open price and close at close price in the same day:

            but the result is the same

            If the results are the same, than coc=False was not removed correctly. Results should be different. The approach proposed above works for me. This script buys open and sells close on every bar:

            import backtrader as bt
            
            class TestStr(bt.Strategy):
                
                def log(self, txt, dt=None):
                    dt = dt or self.data0.datetime.date(0)
                    tt = self.data.datetime.time(0)
                    print('%s, %s, %s' % (dt.isoformat(), tt.isoformat(), txt))
            
                def __init__(self):
                    pass
            
                def notify_order(self, order):
                    if order.status in [order.Submitted, order.Accepted]:
                        return
            
                    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)
            
                        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))
            
                def next_open(self):
                    self.buy(coc=False)
            
                def next(self):       
                    self.log('NEXT o %0.2f, h %0.2f, l %0.2f, c %0.2f' % (self.data.open[0],
                             self.data.high[0], self.data.low[0], self.data.close[0]))
                    if self.position:
                        self.close()
            
            
            cerebro = bt.Cerebro(cheat_on_open=True)
            cerebro.addstrategy(TestStr)
            data = ... data feed setup ...
            cerebro.adddata(data)
            cerebro.broker.setcash(100000.0)
            cerebro.broker.set_coc(True)
            cerebro.run()
            
            • If my answer helped, hit reputation up arrow at lower right corner of the post.
            • Python Debugging With Pdb
            • New to python and bt - check this out
            zevcc-gh 1 Reply Last reply Reply Quote 1
            • zevcc-gh
              zevcc-gh @ab_trader last edited by

              @ab_trader
              I have tried your code, the result is not as expected

              csv file:

              date,open,close
              19-May-20,155.6,169.78
              20-May-20,153.39,149.51
              21-May-20,151,153.6
              

              Code:

              import backtrader as bt
              
              class TestStr(bt.Strategy):
                  
                  def log(self, txt, dt=None):
                      dt = dt or self.data0.datetime.date(0)
                      tt = self.data.datetime.time(0)
                      print('%s, %s, %s' % (dt.isoformat(), tt.isoformat(), txt))
              
                  def __init__(self):
                      pass
              
                  def notify_order(self, order):
                      if order.status in [order.Submitted, order.Accepted]:
                          return
              
                      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)
              
                          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))
              
                  def next_open(self):
                      self.buy(coc=False)
              
                  def next(self):       
                      self.log('NEXT o %0.2f, h %0.2f, l %0.2f, c %0.2f' % (self.data.open[0],
                               self.data.high[0], self.data.low[0], self.data.close[0]))
                      if self.position:
                          self.close()
              
              cerebro = bt.Cerebro(cheat_on_open=True)
              cerebro.addstrategy(TestStr)
              data = btfeeds.GenericCSVData(dataname='test.csv',
                              nullvalue=0.0,
                              dtformat=('%d-%b-%y'),
                              datetime=0,
                              open=1,
                              high=-1,
                              low=-1,
                              close=2,
                              volume=-1,
                              openinterest=-1,)
              cerebro.adddata(data) 
              cerebro.broker.set_cash(cash=10000)
              cerebro.broker.set_coc(True)
              cerebro.run()
              cerebro.plot()
              

              The actual result:

              2020-05-19, 23:59:59.999989, NEXT o 155.60, h 0.00, l 0.00, c 169.78
              2020-05-20, 23:59:59.999989, BUY EXECUTED, 153.39
              2020-05-20, 23:59:59.999989, NEXT o 153.39, h 0.00, l 0.00, c 149.51
              2020-05-21, 23:59:59.999989, SELL EXECUTED, 149.51
              2020-05-21, 23:59:59.999989, BUY EXECUTED, 151.00
              2020-05-21, 23:59:59.999989, OPERATION PROFIT, GROSS -3.88, NET -3.88
              2020-05-21, 23:59:59.999989, NEXT o 151.00, h 0.00, l 0.00, c 153.60
              

              Two problems:

              1. No trade record on 2020-05-19
              2. The remaining records are incorrect (the executed date).
                I want to execute buy and sell orders in the same day.

              For the first problem, I have overridden the start method for the record on 2020-05-19, but cannot close the order as well

                  def start(self):
                      self.buy(coc=False)
                      self.close()
              

              Result:

              2020-05-19, 23:59:59.999989, BUY EXECUTED, 155.60
              2020-05-19, 23:59:59.999989, NEXT o 155.60, h 0.00, l 0.00, c 169.78
              2020-05-20, 23:59:59.999989, SELL EXECUTED, 169.78
              2020-05-20, 23:59:59.999989, BUY EXECUTED, 153.39
              2020-05-20, 23:59:59.999989, OPERATION PROFIT, GROSS 14.18, NET 14.18
              2020-05-20, 23:59:59.999989, NEXT o 153.39, h 0.00, l 0.00, c 149.51
              2020-05-21, 23:59:59.999989, SELL EXECUTED, 149.51
              2020-05-21, 23:59:59.999989, BUY EXECUTED, 151.00
              2020-05-21, 23:59:59.999989, OPERATION PROFIT, GROSS -3.88, NET -3.88
              2020-05-21, 23:59:59.999989, NEXT o 151.00, h 0.00, l 0.00, c 153.60
              

              For the second problem, I am really exhausted, I have tried coc=True/False, coo=True/False in different place, but still cannot solve it.

              A 1 Reply Last reply Reply Quote 0
              • A
                ab_trader @zevcc-gh last edited by

                @zevcc-gh orders executed as you want: buy order at open price, sell order at close price. For sell order notification comes next day, but this is how the cheat-on-close was implemented. First bar is typically skipped due to bt internal mechanics.

                • If my answer helped, hit reputation up arrow at lower right corner of the post.
                • Python Debugging With Pdb
                • New to python and bt - check this out
                zevcc-gh 1 Reply Last reply Reply Quote 1
                • zevcc-gh
                  zevcc-gh @ab_trader last edited by

                  @ab_trader
                  Thanks! I understand more on how cheat-on-close works!

                  I have two more problems

                  1. As the sell order notification always comes next day, the graph from cerebro.plot() is always "incorrect" (buy/sell symbols are on the wrong places)
                    I cannot correct the graph without modify the code in backtrader
                  2. How to handle the last bar? for the last bar, the sell order will not be executed as there is no next bar.
                  A 1 Reply Last reply Reply Quote 0
                  • A
                    ab_trader @zevcc-gh last edited by

                    @zevcc-gh as an idea - there is a data feed filter 'DaySplittter_Close(https://www.backtrader.com/docu/filters-reference/) which returns two sub-bars per each bar of data feed. Using this filter withcheat-on-openmight help: usenext_open()for operations, and issuebuyorder on the first sub-bar andsell` order on the second sub-bar. This solution may fix both items for you.

                    • If my answer helped, hit reputation up arrow at lower right corner of the post.
                    • Python Debugging With Pdb
                    • New to python and bt - check this out
                    1 Reply Last reply Reply Quote 3
                    • 1 / 1
                    • First post
                      Last post
                    Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors