Backtrader Community

    • 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/

    Resampling data twice - Dual Timeframe

    General Code/Help
    3
    5
    1878
    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.
    • T
      ThatBlokeDave last edited by

      Hello all,
      I am trying to re-sample minute data into two timeframes I am interested in working on. When I copy the code from the documentation here:

      https://www.backtrader.com/docu/data-multitimeframe/data-multitimeframe.html

      All is good and it works well. However, the example only resamples the data once. In the code, it adds the first data without resampling and then adds the second resampled data.

      I have tried to resample the data twice and the result is the higher TF is not plotted on the graph. I would appreciate it if someone could show me how I should go about this. I am sure it is something I am missing.

      Here is my code: (mostly the same as the example)

      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      import argparse
      import datetime
      import backtrader as bt
      import backtrader.feeds as btfeeds
      import backtrader.indicators as btind
      
      
      class SMAStrategy(bt.Strategy):
          params = (
              ('period', 10),
              ('onlydaily', False),
          )
      
          def __init__(self):
              self.sma_small_tf = btind.SMA(self.data, period=self.p.period)
              if not self.p.onlydaily:
                  self.sma_large_tf = btind.SMA(self.data1, period=self.p.period)
      
          def nextstart(self):
              print('--------------------------------------------------')
              print('nextstart called with len', len(self))
              print('--------------------------------------------------')
      
              super(SMAStrategy, self).nextstart()
      
      
      def runstrat():
          args = parse_args()
      
          # Create a cerebro entity
          cerebro = bt.Cerebro(stdstats=False)
      
          # Add a strategy
          if not args.indicators:
              cerebro.addstrategy(bt.Strategy)
          else:
              cerebro.addstrategy(
                  SMAStrategy,
      
                  # args for the strategy
                  period=args.period,
                  onlydaily=args.onlydaily,
              )
      
      
          tframes = dict(minutes=bt.TimeFrame.Minutes,daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks,
                         monthly=bt.TimeFrame.Months)
      
      
          # Get the dates from the args
          fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d')
          todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')
      
          # Load the Data
          datapath = args.dataname or '../../datas/2006-day-001.txt'
          data = bt.feeds.GenericCSVData(
          dataname=datapath,
          nullvalue=0.0,
          dtformat=('%m/%d/%Y'),
          tmformat=('%H:%M:%S'),
          fromdate=fromdate,
          todate=todate,
          datetime=0,
          time=1,
          high=3,
          low=4,
          open=2,
          close=5,
          volume=6,
          openinterest=-1 #-1 means not used
          )
          #cerebro.adddata(data)  # First add the original data - smaller timeframe
          cerebro.resampledata(data, timeframe=tframes['minutes'],
                               compression=60)
      
      
          # Handy dictionary for the argument timeframe conversion
          # Resample the data
          if args.noresample:
              datapath = args.dataname2 or '../../datas/2006-week-001.txt'
              data2 = data = bt.feeds.GenericCSVData(
              dataname=datapath,
              nullvalue=0.0,
              dtformat=('%m/%d/%Y'),
              tmformat=('%H:%M:%S'),
              fromdate=fromdate,
              todate=todate,
              datetime=0,
              time=1,
              high=3,
              low=4,
              open=2,
              close=5,
              volume=6,
              openinterest=-1 #-1 means not used
              )
              # And then the large timeframe
              cerebro.adddata(data2)
          else:
              cerebro.resampledata(data, timeframe=tframes[args.timeframe],
                                   compression=args.compression)
      
          # Run over everything
          cerebro.run()
      
          # Plot the result
          cerebro.plot(style='bar')
      
      
      def parse_args():
          parser = argparse.ArgumentParser(
              description='Multitimeframe test')
      
          parser.add_argument('--dataname', default='', required=False,
                              help='File Data to Load')
      
          parser.add_argument('--dataname2', default='', required=False,
                              help='Larger timeframe file to load')
      
          parser.add_argument('--noresample', action='store_true',
                              help='Do not resample, rather load larger timeframe')
      
          parser.add_argument('--timeframe', default='weekly', required=False,
                              choices=['daily', 'weekly', 'monhtly'],
                              help='Timeframe to resample to')
      
          parser.add_argument('--compression', default=1, required=False, type=int,
                              help='Compress n bars into 1')
      
          parser.add_argument('--indicators', action='store_true',
                              help='Wether to apply Strategy with indicators')
      
          parser.add_argument('--onlydaily', action='store_true',
                              help='Indicator only to be applied to daily timeframe')
      
          parser.add_argument('--period', default=10, required=False, type=int,
                              help='Period to apply to indicator')
          parser.add_argument('--fromdate', '-f',
                              required=True,
                              help='Starting date in YYYY-MM-DD format')
      
          parser.add_argument('--todate', '-t',
                              required=True,
                              help='Ending date in YYYY-MM-DD format')
      
          return parser.parse_args()
      
      
      if __name__ == '__main__':
          runstrat()
      

      And this is what I get for output:

      When resampling once:
      0_1487738217007_reample once.png

      When Resampling twice:
      0_1487738235256_resample twice.png

      I would really appreciate any pointers.

      1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators last edited by

        1st theory. Check the original chart and see that the platform believes it to have a timeframe/compression of Days/1(you can read 1 Day). This is because the original creation of the GenericCSVData has no timeframe/compression specified.

        But most probably this is due to the current implementation model. If you have read the Community - v1.x -Quick Roadmap post, you may have seen that the plan is to change resampling back to the original model rather than have it implemented as a filter. If the 1st theory fails, there would be 2 options

        • Creating a 2nd GenericCSVData and resampling it to the desired timeframe/compression
          or
        • Manually creating a DataClone or your original feed and using it for resampledata
        1 Reply Last reply Reply Quote 0
        • T
          ThatBlokeDave last edited by ThatBlokeDave

          @backtrader , thank you for the pointer.

          Setting the timeframe/compression in the GenericCSVData data seemed to do the trick. I missed that it can be set there in the documents.

          It also sorted out the issue with the chart showing "Days" in the minute data.

          I had to do as you suggested, create 2 separate GenericCSVData instances and re-sample each.

          Really appreciate the help. You saved me a lot of head scratching.

          1 Reply Last reply Reply Quote 0
          • T
            ThatBlokeDave last edited by

            For reference if anyone has a similar issue and comes here through google, here is the cleaned up working version

            from __future__ import (absolute_import, division, print_function,
                                    unicode_literals)
            
            import argparse
            import datetime
            import backtrader as bt
            import backtrader.feeds as btfeeds
            import backtrader.indicators as btind
            
            
            class SMAStrategy(bt.Strategy):
                params = (
                    ('period', 10),
                    ('onlydaily', False),
                )
            
                def __init__(self):
                    self.sma_small_tf = btind.SMA(self.data, period=self.p.period)
                    if not self.p.onlydaily:
                        self.sma_large_tf = btind.SMA(self.data1, period=self.p.period)
            
                def nextstart(self):
                    print('--------------------------------------------------')
                    print('nextstart called with len', len(self))
                    print('--------------------------------------------------')
            
                    super(SMAStrategy, self).nextstart()
            
            
            def runstrat():
                args = parse_args()
            
                # Create a cerebro entity
                cerebro = bt.Cerebro(stdstats=False)
            
                # Add a strategy
                if not args.indicators:
                    cerebro.addstrategy(bt.Strategy)
                else:
                    cerebro.addstrategy(
                        SMAStrategy,
            
                        # args for the strategy
                        period=args.period,
                        onlydaily=args.onlydaily,
                    )
            
            
                tframes = dict(minutes=bt.TimeFrame.Minutes,daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks,
                               monthly=bt.TimeFrame.Months)
            
            
                # Get the dates from the args
                fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d')
                todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')
            
                # Load the Data
                datapath = args.dataname or '../../datas/2006-day-001.txt'
                data = bt.feeds.GenericCSVData(
                dataname=datapath,
                nullvalue=0.0,
                dtformat=('%m/%d/%Y'),
                tmformat=('%H:%M:%S'),
                timeframe = tframes[args.ltf_resample],
                compression = args.ltf_comp,
                fromdate=fromdate,
                todate=todate,
                datetime=0,
                time=1,
                high=3,
                low=4,
                open=2,
                close=5,
                volume=6,
                openinterest=-1 #-1 means not used
                )
            
                cerebro.resampledata(data, timeframe=tframes[args.ltf_resample],
                                     compression=args.ltf_comp)
            
            
                # Handy dictionary for the argument timeframe conversion
                # Resample the data
            
                data2 = bt.feeds.GenericCSVData(
                dataname=datapath,
                nullvalue=0.0,
                timeframe = tframes[args.htf_resample],
                compression = args.htf_comp,
                dtformat=('%m/%d/%Y'),
                tmformat=('%H:%M:%S'),
                fromdate=fromdate,
                todate=todate,
                datetime=0,
                time=1,
                high=3,
                low=4,
                open=2,
                close=5,
                volume=6,
                openinterest=-1 #-1 means not used
                )
            
                cerebro.resampledata(data2, timeframe=tframes[args.htf_resample],
                                     compression=args.htf_comp)
            
                # Run over everything
                cerebro.run()
            
                # Plot the result
                cerebro.plot(style='bar')
            
            
            def parse_args():
                parser = argparse.ArgumentParser(
                    description='Multitimeframe test')
            
                parser.add_argument('--dataname', default='', required=False,
                                    help='File Data to Load')
            
                parser.add_argument('--timeframe', default='weekly', required=False,
                                    choices=['daily', 'weekly', 'monhtly'],
                                    help='Timeframe to resample to')
            
                parser.add_argument('--indicators', action='store_true',
                                    help='Wether to apply Strategy with indicators')
            
                parser.add_argument('--ltf_comp', default=1, type=int,
                                    help='Compression setting for lower time frame resampling')
            
                parser.add_argument('--ltf_resample', required=True,
                                    help='resample data for LTF. Valid\
                                     intervals:\n monthly\n weekly\n daily\n minutes')
            
                parser.add_argument('--htf_comp', default=1, type=int,
                                    help='Compression setting for higher time frame resampling')
            
                parser.add_argument('--htf_resample', required=True,
                                    help='resample data for HTF. Valid\
                                     intervals:\n monthly\n weekly\n daily\n minutes')
            
                parser.add_argument('--period', default=10, required=False, type=int,
                                    help='Period to apply to indicator')
            
                parser.add_argument('--fromdate', '-f',
                                    required=True,
                                    help='Starting date in YYYY-MM-DD format')
            
                parser.add_argument('--todate', '-t',
                                    required=True,
                                    help='Ending date in YYYY-MM-DD format')
            
                return parser.parse_args()
            
            
            if __name__ == '__main__':
                runstrat()
            
            
            I 1 Reply Last reply Reply Quote 0
            • I
              invoker @ThatBlokeDave last edited by

              @thatblokedave it works good if the data source is csv,but what happen if the datasource is real time data,may be the return data0 and data1 is not equal

              1 Reply Last reply Reply Quote 0
              • 1 / 1
              • First post
                Last post
              Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors