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/

    Multiple assets with custom pandas dataframe

    General Code/Help
    2
    8
    312
    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.
    • B
      btr last edited by

      Hello,

      I am trying to run strategy on multiple assets that have custom pandas dataframe.

      class PandasData(bt.feeds.PandasData):
          lines = ('pe')
          params = (
              ('pe', 'pe'),
          )
      

      There is a list of dataframes that has information for different assets

      for data in list:
          df=PandasData(dataname=data)
          cerebro.adddata(df, name='abc')
          cerebro.run()
      

      I am able to use this for single asset in next() using

      for i, d in enumerate(self.datas):
          dt, dn = self.datas[0].datetime.date(0)), d._name
          pos = self.getposition(d).size
      

      How can I create multiple 'pe' lines for multiple assets and use it in the next()?

      run-out 1 Reply Last reply Reply Quote 0
      • run-out
        run-out @btr last edited by

        @btr said in Multiple assets with custom pandas dataframe:

        How can I create multiple 'pe' lines for multiple assets and use it in the next()?

        I would say yes. You can create a custom loader that has extra lines. You will need to assign the p/e from your dataframe to a custom p/e line in backtrader. That logic you have to sort out. So maybe pe_largcap and pe_international. However you are splitting them out. To set up your custom loader, you create the following class:

        class CustomPandasLoader(bt.feeds.PandasData):
            lines = (
                "pe_largcap",
                "pe_international",
            )
            params = (
                ("pe_largcap", -1),
                ("pe_international", -1),
            )
            datafields = bt.feeds.PandasData.datafields + (
                [
                    "pe_largcap",
                    "pe_international",
                ]
            )
        

        The -1 means backtrader will seek out the column if it exist.

        You can load the custom loader as follows:

        data = CustomPandasLoader(
                    dataname=df,
                )
        cerebro.adddata(data)
        
        

        Now of course when using it in next you simply call the dataline of your asset say data number 3 and:

        self.datas[3].pe_international[0]
        

        If you try to call it on another dataline where pe_interntional wans't used, you get an error. So you need to manage that in next.

        B 1 Reply Last reply Reply Quote 0
        • B
          btr @run-out last edited by

          @run-out
          I am able to do this. I have custom loader that has extra columns and I am feeding it to cerebro and using it next. The issue I am facing is with applying the same logic to multiple datafeeds.

          Multiple data feeds means there would be pe_largcap and pe_international for all data feeds. So, if the cerebro is feed with 2 assets data, it should have 4 lines. and somehow I need to check those 4 lines in next depending on the data feed.

          B 1 Reply Last reply Reply Quote 0
          • B
            btr @btr last edited by

            @run-out
            I am trying to follow this https://backtest-rookies.com/2017/08/22/backtrader-multiple-data-feeds-indicators/ but instead of using backtrader indicators, I want to use the lines create from custom dataframe in next. I was able to implement this with single data feed. Creating the lines from custom pandas data and using that line in next.

            I am having issues extending the same with multiple data feeds

            1 Reply Last reply Reply Quote 0
            • run-out
              run-out last edited by

              I like using pandas this way as well. If you want all the p/e's from the different assets to be compiled under one p/s inside backtrader, then just change the column name in your data frame to p/e and add it in.

              I feel like my answer is too simple and I'm missing your problem. Let me know.

              B 1 Reply Last reply Reply Quote 1
              • B
                btr @run-out last edited by

                @run-out
                Yes, there's misunderstanding here. p/e is just an example. Take a simple moving average strategy. I have a dataframe that already has sma crossover calculated. I am sending that dataframe to custom pandas data function and creating a line. Like this:

                class PandasData(bt.feeds.PandasData):
                    lines = ('crossover')
                    params = (
                        ('crossover', 'crossover'),
                    )
                

                and feeding it to cerebro

                df=PandasData(dataname=current_df)
                     cerebro.adddata(df, name=current_df['symbol'][0])
                

                Now, I use this in next as following:

                if self.datas[0].crossover > 0:
                     buy()
                if self.datas[0].crossover < 0:
                    sell()
                

                This works perfectly fine. Now I am extending my strategy so that it can run over multiple assets as the same time. I am sending single dataframes to single data feed like:
                resp is a list of dataframe where each has crossover already calculated

                for df in resp:
                      data=PandasData(dataname=df)
                      cerebro.adddata(df, name='data0') #name here would be dynamic so I can get the name in next and find which asset/dataframe's order is placed
                      cerebro.run()
                

                and then in next:

                for i, d in enumerate(self.datas):
                        dt, dn = self.datas[0].datetime.date(), d._name
                        pos = self.getposition(d).size
                        if not pos:
                

                In order to do this in next, I would need multiple lines of crossover from custom pandas data function, one for each asset/datafeed/dataframe

                1 Reply Last reply Reply Quote 0
                • run-out
                  run-out last edited by

                  It seems like you are doing everything right to get the datas into cerebro with one exception:

                  @btr said in Multiple assets with custom pandas dataframe:

                  for df in resp:
                        data=PandasData(dataname=df)
                        cerebro.adddata(df, name='data0') 
                        cerebro.run()
                  

                  cerebro.run should not be part of this loop. This will run backtrader individually for the first data line. If this is just a typo let me know.

                  If you are not getting the dataframes properly loaded and cerebro.run actually is outside the loop, please provide a bit more detail as to what difficulty you are having. It seems like you are on the right track.

                  1 Reply Last reply Reply Quote 1
                  • B
                    btr last edited by

                    @run-out
                    Thanks for your help. I found out that I was not using the enumerate for loop in init function so that it can run for each data feed

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