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/

    Adding Multiple CSV data feeds

    General Code/Help
    csv datafeed multiple data
    3
    5
    33
    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.
    • H
      HexaBraum last edited by

      Hello guys I am currently starting with backtrader and i am struggling to add multiple data feeds.
      The following code ends with exit code 0 however does only consider the very last csv file ("AM.CVX.csv"). Thanks for your help and I know that this is a very basic question but everyone has to start somewhere.
      P.S. The example in the documentation did not really help me.

      import backtrader as bt
      import backtrader.feeds as btfeed
      from datetime import datetime
      
      class dataFeed(btfeed.GenericCSVData):
          params = (
              ('dtformat', '%Y-%m-%d %H:%M:%S'),
              ('datetime', 0),
              ('open', 1),
              ('high', 2),
              ('low', 3),
              ('close', 4),
              ('volume', 5),
              ('openinterest', -1)
          )
      
      
      class firstStrategy(bt.Strategy):
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              for i, d in enumerate(self.datas):
                  dt = dt or self.datas[i].datetime.date(0)
                  print('%s, %s' % (dt.isoformat(), txt))
      
          def __init__(self):
              for i, d in enumerate(self.datas):
                  self.dataclose = self.datas[i].close
      
      
          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, %.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')
      
              # Write down: no pending order
              #self.order = None
      
          def next(self):
              for i, d in enumerate(self.datas):
                  self.dataclose = self.datas[i].close
                  dt, dn = self.datetime.date(), d._name
                  pos = self.getposition(d).size
              # Simply log the closing price of the series from the reference
              self.log('Close, %.2f' % self.dataclose[0])
      
              # Check if an order is pending ... if yes, we cannot send a 2nd one
              #if self.order:
              #    return
      
              # Check if we are in the market
              if not self.position:
      
                  # Not yet ... we MIGHT BUY if ...
                  if self.dataclose[0] < self.dataclose[-1]:
                          # current close less than previous close
      
                          if self.dataclose[-1] < self.dataclose[-2]:
                              # previous close less than the previous close
      
                              # BUY, BUY, BUY!!! (with default parameters)
                              self.log('BUY CREATE, %.2f' % self.dataclose[0])
      
                              # Keep track of the created order to avoid a 2nd order
                              self.order = self.buy()
      
              else:
      
                  # Already in the market ... we might sell
                  if len(self) >= (self.bar_executed + 5):
                      # SELL, SELL, SELL!!! (with all possible default parameters)
                      self.log('SELL CREATE, %.2f' % self.dataclose[0])
      
                      # Keep track of the created order to avoid a 2nd order
                      self.order = self.sell()
      
      
      if __name__ == '__main__':
          # Create a cerebro entity
          cerebro = bt.Cerebro()
          startcash = 10000
      
          # Add a strategy
          cerebro.addstrategy(firstStrategy)
      
          datalist = [("AM.ATVI.csv"), ("AM.MO.csv"), ("AM.GM.csv"), ("AM.CL.csv")
              , ("AM.FDX.csv"), ("AM.NAKD.csv"), ("AM.NVDA.csv"), ("AM.OCGN.csv"), ("AM.ON.csv")
              , ("AM.PDD.csv"), ("AM.PLUG.csv"), ("AM.QCOM.csv"), ("AM.MDLZ.csv"), ("AM.ADP.csv")
              , ("AM.C.csv"), ("AM.AZN.csv"), ("AM.PEP.csv"), ("AM.ORCL.csv"), ("AM.QTT.csv")
              , ("AM.RUN.csv"), ("AM.SABR.csv"), ("AM.SNDL.csv"), ("AM.TSLA.csv"), ("AM.UAL.csv")
              , ("AM.UXIN.csv"), ("AM.WEN.csv"), ("AM.WFC.csv"), ("AM.YY.csv"), ("AM.ZNGA.csv")
              , ("AM.MSFT.csv"), ("AM.AAPL.csv"), ("AM.FB.csv"), ("AM.BABA.csv"), ("AM.TSM.csv")
              , ("AM.V.csv"), ("AM.JPM.csv"), ("AM.JNJ.csv")
              , ("AM.PG.csv"), ("AM.BAC.csv"), ("AM.INTC.csv"), ("AM.VZ.csv"), ("AM.NKE.csv")
              , ("AM.XOM.csv"), ("AM.KO.csv"), ("AM.T.csv"), ("AM.PFE.csv")
              , ("AM.MRK.csv"), ("AM.MS.csv"), ("AM.AAL.csv"), ("AM.GT.csv"), ("AM.UBER.csv")
              , ("AM.AMD.csv"), ("AM.PDD.csv"), ("AM.CVX.csv")]
      #the files are located in my python project
          for i in range(len(datalist)):
              data = dataFeed(dataname=datalist[i], timeframe=bt.TimeFrame.Minutes, compression=60)
              cerebro.adddata(data, name=datalist[i])
      
          # Set our desired cash start
          cerebro.broker.setcash(startcash)
      
          # Set the commission
          #cerebro.broker.setcommission(commission=0.0005)
      
          # Add a sizer
          #cerebro.addsizer(bt.sizers.PercentSizer, percents=50)
      
          cerebro.run()
          # Print out the starting conditions
          print('Starting Portfolio Value: %.2f' % startcash)
      
          # Get final portfolio Value
          portvalue = cerebro.broker.getvalue()
          pnl = portvalue - startcash
      
          # Print out the final result
          print('Final Portfolio Value: ${}'.format(portvalue))
          print('P/L: ${}'.format(pnl))
      vladisld run-out 2 Replies Last reply Reply Quote 0
      • vladisld
        vladisld @HexaBraum last edited by

        @hexabraum said in Adding Multiple CSV data feeds:

        def __init__(self):
            for i, d in enumerate(self.datas):
                self.dataclose = self.datas[i].close
        

        It seems you are overriding the same instance variable self.dataclose for each data feed. So self.dataclose will just point to the latest symbol close line.

        1 Reply Last reply Reply Quote 2
        • run-out
          run-out @HexaBraum last edited by

          @hexabraum said in Adding Multiple CSV data feeds:

          for i, d in enumerate(self.datas):
          self.dataclose = self.datas[i].close
          dt, dn = self.datetime.date(), d._name
          pos = self.getposition(d).size
          # Simply log the closing price of the series from the reference
          self.log('Close, %.2f' % self.dataclose[0])

          In addition to my very learned collegue's @vladisld above, you don't really need that code in the init, nor the enumerate in next. self.datas is a list of data and you can just use the data in your work for keys and the like. You could write the next code as follows:

          for d in self.datas:
              dt, dn = self.datetime.date(), d._name    
              pos = self.getposition(d).size
              # Simply log the closing price of the series from the reference
              self.log('Close, %.2f' % d.close[0])
          
          H 1 Reply Last reply Reply Quote 1
          • H
            HexaBraum @run-out last edited by

            @run-out Thanks for your answer. Now each csv file is being considered but the logging output looks really weird.

            [...]
            2021-02-18, SELL CREATE, 102.31
            2021-02-18, SELL CREATE, 102.31
            2021-02-18, SELL CREATE, 102.31
            2021-02-18, SELL CREATE, 102.31
            2021-02-18, SELL EXECUTED, 102.30
            2021-02-18, SELL EXECUTED, 102.30
            2021-02-18, SELL EXECUTED, 102.30
            2021-02-18, SELL EXECUTED, 102.30
            2021-02-18, Close, 102.22
            2021-02-18, Close, 102.22
            2021-02-18, Close, 102.22
            2021-02-18, Close, 102.22
            2021-02-18, Close, 43.62
            2021-02-18, Close, 43.62
            2021-02-18, Close, 43.62
            2021-02-18, Close, 43.62
            2021-02-18, Close, 52.13
            2021-02-18, Close, 52.13
            2021-02-18, Close, 52.13
            2021-02-18, Close, 52.13
            2021-02-18, Close, 78.65
            2021-02-18, Close, 78.65
            2021-02-18, Close, 78.65
            2021-02-18, Close, 78.65
            2021-02-18, Close, 102.21
            2021-02-18, Close, 102.21
            2021-02-18, Close, 102.21
            2021-02-18, Close, 102.21
            2021-02-18, Close, 43.62
            2021-02-18, Close, 43.62
            2021-02-18, Close, 43.62
            2021-02-18, Close, 43.62
            2021-02-18, Close, 52.10
            2021-02-18, Close, 52.10
            2021-02-18, Close, 52.10
            2021-02-18, Close, 52.10
            2021-02-18, Close, 78.63
            2021-02-18, Close, 78.63
            2021-02-18, Close, 78.63
            2021-02-18, Close, 78.63
            2021-02-18, Close, 102.28
            2021-02-18, Close, 102.28
            2021-02-18, Close, 102.28
            2021-02-18, Close, 102.28
            2021-02-18, Close, 43.61
            2021-02-18, Close, 43.61
            2021-02-18, Close, 43.61
            2021-02-18, Close, 43.61
            2021-02-18, Close, 52.14
            2021-02-18, Close, 52.14
            2021-02-18, Close, 52.14
            2021-02-18, Close, 52.14
            2021-02-18, Close, 78.71
            2021-02-18, Close, 78.71
            2021-02-18, Close, 78.71
            2021-02-18, Close, 78.71
            Starting Portfolio Value: 10000.00
            Final Portfolio Value: $9979.769999999993
            P/L: $-20.23000000000684
            

            Each closing price, selling action and buying action is getting printed 4 times when my datalist includes 4 Files, 3 times when it includes 3 files etc.

            H 1 Reply Last reply Reply Quote 0
            • H
              HexaBraum @HexaBraum last edited by

              @hexabraum i fixed it by deleting the for loop in the log function.

              1 Reply Last reply Reply Quote 0
              • 1 / 1
              • First post
                Last post
              Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
              $(document).ready(function () { app.coldLoad(); }); }