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/

    Back Testing two time frame with large time frame candle partially created

    Indicators/Strategies/Analyzers
    3
    13
    386
    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.
    • bhavishya goyal
      bhavishya goyal last edited by

      We are trying to back-test out strategy with two time frame 5 Min and 1 Hour . As per following documentation i can do by passing two time frame data .
      https://www.backtrader.com/docu/data-multitimeframe/data-multitimeframe/

      But Large time frame is getting updated when candle completely formed what i want. I need to access 1 Hour candle partially created and what is indicator value for current hourly candle . Is that possible . I am new to backtrader so just trying to figure it out . any help would be really appreciated

      run-out 2 Replies Last reply Reply Quote 2
      • run-out
        run-out @bhavishya goyal last edited by

        @bhavishya-goyal said in Back Testing two time frame with large time frame candle partially created:

        But Large time frame is getting updated when candle completely formed what i want. I need to access 1 Hour candle partially created and what is indicator value for current hourly candle .

        Are you looking for the the indicator value on the 5 minute data then?

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

          @run-out yes you are right

          bhavishya goyal 1 Reply Last reply Reply Quote 0
          • bhavishya goyal
            bhavishya goyal @bhavishya goyal last edited by

            @run-out Hi, ay i request to please help if that is possible

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

              @bhavishya-goyal said in Back Testing two time frame with large time frame candle partially created:

              But Large time frame is getting updated when candle completely formed what i want. I need to access 1 Hour candle partially created and what is indicator value for current hourly candle . Is that possible . I am new to backtrader so just trying to figure it out . any help would be really appreciated

              You can access indicators in both time frames. You input two datalines with the smaller timeframe first. Create an indicator for each time frame, and then you can access the information in each indicator at the shortest timeframe. If you implement the following:

              import backtrader as bt
              import backtrader.feeds as btfeeds
              import backtrader.indicators as btind
              
              
              class TimeFrameStrategy(bt.Strategy):
                  def __init__(self):
                      self.sma_small_tf = btind.SMA(self.data, period=10)
                      self.sma_large_tf = btind.SMA(self.data1, period=30)
              
                  def next(self):
                      print("{}, sma small {:.2f},  sma large {:.2f}".format(self.data.datetime.datetime(), self.sma_small_tf[0], self.sma_large_tf[0]))
              
              def runstrat():
              
                  cerebro = bt.Cerebro()
              
                  cerebro.addstrategy(TimeFrameStrategy)
              
                  datapath = "data/dev.csv"
                  data = btfeeds.GenericCSVData(
                      dataname=datapath,
                      timeframe=bt.TimeFrame.Minutes,
                      compression=1,
                      format="%Y-%m-%d %H:%M:%S",
                  )
              
                  cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=5)
                  cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=60)
              
                  cerebro.run()
              
              if __name__ == "__main__":
                  runstrat()
              

              You get output like:

              2020-01-08 11:00:00, sma small 3232.25,  sma large 3228.93
              2020-01-08 11:05:00, sma small 3231.62,  sma large 3228.93
              2020-01-08 11:10:00, sma small 3231.40,  sma large 3228.93
              2020-01-08 11:15:00, sma small 3231.45,  sma large 3228.93
              2020-01-08 11:20:00, sma small 3231.78,  sma large 3228.93
              2020-01-08 11:25:00, sma small 3232.12,  sma large 3228.93
              2020-01-08 11:30:00, sma small 3232.78,  sma large 3228.93
              2020-01-08 11:35:00, sma small 3233.35,  sma large 3228.93
              2020-01-08 11:40:00, sma small 3234.75,  sma large 3228.93
              2020-01-08 11:45:00, sma small 3236.50,  sma large 3228.93
              2020-01-08 11:50:00, sma small 3238.25,  sma large 3228.93
              2020-01-08 11:55:00, sma small 3240.20,  sma large 3228.93
              2020-01-08 12:00:00, sma small 3241.55,  sma large 3229.22
              2020-01-08 12:05:00, sma small 3243.00,  sma large 3229.22
              2020-01-08 12:10:00, sma small 3244.22,  sma large 3229.22
              2020-01-08 12:15:00, sma small 3245.40,  sma large 3229.22
              2020-01-08 12:20:00, sma small 3246.28,  sma large 3229.22
              2020-01-08 12:25:00, sma small 3247.45,  sma large 3229.22
              2020-01-08 12:30:00, sma small 3248.03,  sma large 3229.22
              2020-01-08 12:35:00, sma small 3247.97,  sma large 3229.22
              2020-01-08 12:40:00, sma small 3247.75,  sma large 3229.22
              2020-01-08 12:45:00, sma small 3247.40,  sma large 3229.22
              2020-01-08 12:50:00, sma small 3247.53,  sma large 3229.22
              2020-01-08 12:55:00, sma small 3247.45,  sma large 3229.22
              2020-01-08 13:00:00, sma small 3247.43,  sma large 3229.74
              2020-01-08 13:05:00, sma small 3247.55,  sma large 3229.74
              2020-01-08 13:10:00, sma small 3247.43,  sma large 3229.74
              2020-01-08 13:15:00, sma small 3247.28,  sma large 3229.74
              2020-01-08 13:20:00, sma small 3246.97,  sma large 3229.74
              2020-01-08 13:25:00, sma small 3246.82,  sma large 3229.74
              2020-01-08 13:30:00, sma small 3246.85,  sma large 3229.74
              2020-01-08 13:35:00, sma small 3246.90,  sma large 3229.74
              2020-01-08 13:40:00, sma small 3246.88,  sma large 3229.74
              2020-01-08 13:45:00, sma small 3246.82,  sma large 3229.74
              2020-01-08 13:50:00, sma small 3246.75,  sma large 3229.74
              2020-01-08 13:55:00, sma small 3246.57,  sma large 3229.74
              2020-01-08 14:00:00, sma small 3246.43,  sma large 3230.25
              2020-01-08 14:05:00, sma small 3246.45,  sma large 3230.25
              2020-01-08 14:10:00, sma small 3246.62,  sma large 3230.25
              
              bhavishya goyal 1 Reply Last reply Reply Quote 1
              • bhavishya goyal
                bhavishya goyal @run-out last edited by

                @run-out Thanks but issue is large time frame SMA should be updated in each 5 min as well since close price of last candle(Present 1 Hour candle which is being constructed ) is getting changed with each 5 minute data and that should change SMA as well for Hourly data.

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

                  I could be mistaken, but I don't think the one hour candle is 'being constructed'. It just gets constructed at the end of the hour. For what you are trying to do I think you would need to code a custom indicator that builds the one hour candle every five minutes and starts over every hour?

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

                    @run-out If we talk about Live trading every candle is continuously getting update like on each 5min or 1 min, hourly candle would have new high,low,close so basically i want to use latest value of current hourly candle so any indicator can be applied on that .

                    If I build custom indicator then for each indicator i need to change

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

                      As @run-out said, if you just inspect the resampled hourly data every 5 minutes - you will see the same old bar until the next hour bar will be available.

                      However, theoretically, you are right - the resampled bar is updated every time the underlying data is updated (and not only in live trading). The only thing is that this update is kept in internal implementation and is not easily accessible.

                      TL;DR

                      Inside the Backtrader framework resampling is implemented using filters.

                      So when the resampledata method is used, like in your code:

                      cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=5)
                      

                      what actually happens is that a special filter - Resampler is added to the data.

                      Multiple filters could be attached to the data - so the Resampler filter is just one such filter.

                      The accumulated resampled bar is maintained as an internal state of such a filter. So in order to access this bar, you actually need to dive deeply into the private state of the Resampler filter - but first, you need to find it among other filters.

                      The internals of the Resampler filter is not documented since the framework author probably does not see a good reason to support your use case.

                      1 Reply Last reply Reply Quote 1
                      • run-out
                        run-out @bhavishya goyal last edited by

                        @bhavishya-goyal I found this to be an interesting question and made a custom indicator for it.

                        import argparse
                        from collections import deque
                        
                        import backtrader as bt
                        import backtrader.feeds as btfeeds
                        
                        
                        class SMAExpand(bt.Indicator):
                            """
                            Custom indicator for hourly simple moving average, expanding with each bar in the hour.
                            Period must divide into an hour and be minimum of the resample
                            :param compression: The compression used for the minute data in the datafeed. e.g. 5 minutes.
                            :param period: number of hours to use in the SMA.
                            :result sma_large: Simple moving average line.
                            """
                        
                            lines = ("sma_large",)
                        
                            def __init__(self, compression=5, period=10):
                                self.compression = compression
                                self.period = period
                                self.addminperiod = self.period
                        
                                self.hourly_close = deque([], maxlen=int(self.period - 1))
                                self.close = self.datas[0].close
                        
                            def next(self):
                                # Current bar datetime, time.
                                dt = self.data.datetime[0]
                                if isinstance(dt, float):
                                    dt = bt.num2date(dt)
                                minutes = dt.minute
                        
                                if len(self.hourly_close) >= self.period - 1:
                                    self.l.sma_large[0] = (sum(self.hourly_close) + self.close[0]) / self.period
                        
                                if minutes == 0:
                                    self.hourly_close.append(self.close[0])
                        
                        class Strategy(bt.Strategy):
                            params = dict(compression=5, period=30)
                        
                            def __init__(self):
                                print(f"check params: {self.p.period}")
                                self.sma_expand = SMAExpand(compression=self.p.compression, period=self.p.period)
                                self.sma_hour = bt.ind.SMA(self.datas[1], period=self.p.period)
                        
                            def log(self, txt, dt=None):
                                """ Logging function for this strategy"""
                                dt = dt or self.data.datetime[0]
                                if isinstance(dt, float):
                                    dt = bt.num2date(dt)
                                print("%s, %s" % (dt, txt))
                        
                            def print_signal(self):
                                """Print to terminal ohlcv."""
                                self.log(
                                    "o {} \th {} \tl {} \tc {}\tv {}".format(
                                        self.datas[0].open[0],
                                        self.datas[0].high[0],
                                        self.datas[0].low[0],
                                        self.datas[0].close[0],
                                        self.datas[0].volume[0],
                                    )
                                )
                        
                            def next(self):
                                # self.print_signal()
                                self.log(
                                    f"close {self.sma_expand.close[0]:8.2f}, "
                                    f"\tsma expand {self.sma_expand.sma_large[0]:8.2f}"
                                    f"\tsma hour {self.sma_hour[0]:8.2f}"
                                )
                        
                        def runstrat(args=None):
                            args = parse_args(args)
                        
                            cerebro = bt.Cerebro()
                        
                            cerebro.addstrategy(Strategy, compression=args.compression, period=args.period)
                        
                            # Data feed kwargs
                            kwargs = dict(
                                dataname=args.data0,
                                timeframe=bt.TimeFrame.Minutes,
                                compression=1,
                                format="%Y-%m-%d %H:%M:%S",
                                datetime=0,
                                time=-1,
                                open=3,
                                high=1,
                                low=2,
                                close=4,
                                cumvol=5,
                                volume=6,
                            )
                        
                            data = btfeeds.GenericCSVData(**kwargs)
                        
                            cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=args.compression)
                            cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=60)
                        
                            cerebro.run()
                        
                        def parse_args(pargs=None):
                            parser = argparse.ArgumentParser(
                                formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                                description=(
                                    'Cheat-On-Open Sample'
                                )
                            )
                        
                            parser.add_argument('--data0', default='data/dev.csv',
                                                required=False, help='Data to read in')
                        
                            parser.add_argument('--period', type=int, required=False, default=30, help='Lookback period for sma integer in hours.')
                            parser.add_argument('--compression', type=int, required=False, default=5, help='Main data compression.')
                        
                            return parser.parse_args(pargs)
                        
                        
                        if __name__ == "__main__":
                            runstrat()
                        
                        
                        run-out 1 Reply Last reply Reply Quote 0
                        • run-out
                          run-out @run-out last edited by

                          @run-out Here's some output for the above indicator.

                          2020-01-08 11:00:00, close  3231.25, 	sma expand  3228.93	sma hour  3228.93
                          2020-01-08 11:05:00, close  3230.75, 	sma expand  3228.68	sma hour  3228.93
                          2020-01-08 11:10:00, close  3233.25, 	sma expand  3228.77	sma hour  3228.93
                          2020-01-08 11:15:00, close  3234.00, 	sma expand  3228.79	sma hour  3228.93
                          2020-01-08 11:20:00, close  3235.50, 	sma expand  3228.84	sma hour  3228.93
                          2020-01-08 11:25:00, close  3234.50, 	sma expand  3228.81	sma hour  3228.93
                          2020-01-08 11:30:00, close  3238.75, 	sma expand  3228.95	sma hour  3228.93
                          2020-01-08 11:35:00, close  3236.00, 	sma expand  3228.86	sma hour  3228.93
                          2020-01-08 11:40:00, close  3242.75, 	sma expand  3229.08	sma hour  3228.93
                          2020-01-08 11:45:00, close  3248.25, 	sma expand  3229.27	sma hour  3228.93
                          2020-01-08 11:50:00, close  3248.75, 	sma expand  3229.28	sma hour  3228.93
                          2020-01-08 11:55:00, close  3250.25, 	sma expand  3229.33	sma hour  3228.93
                          2020-01-08 12:00:00, close  3246.75, 	sma expand  3229.22	sma hour  3229.22
                          2020-01-08 12:05:00, close  3248.50, 	sma expand  3229.78	sma hour  3229.22
                          2020-01-08 12:10:00, close  3247.75, 	sma expand  3229.75	sma hour  3229.22
                          2020-01-08 12:15:00, close  3246.25, 	sma expand  3229.70	sma hour  3229.22
                          2020-01-08 12:20:00, close  3247.50, 	sma expand  3229.74	sma hour  3229.22
                          2020-01-08 12:25:00, close  3247.75, 	sma expand  3229.75	sma hour  3229.22
                          2020-01-08 12:30:00, close  3248.50, 	sma expand  3229.78	sma hour  3229.22
                          2020-01-08 12:35:00, close  3247.75, 	sma expand  3229.75	sma hour  3229.22
                          2020-01-08 12:40:00, close  3246.50, 	sma expand  3229.71	sma hour  3229.22
                          2020-01-08 12:45:00, close  3246.75, 	sma expand  3229.72	sma hour  3229.22
                          2020-01-08 12:50:00, close  3248.00, 	sma expand  3229.76	sma hour  3229.22
                          2020-01-08 12:55:00, close  3247.75, 	sma expand  3229.75	sma hour  3229.22
                          2020-01-08 13:00:00, close  3247.50, 	sma expand  3229.74	sma hour  3229.74
                          2020-01-08 13:05:00, close  3247.50, 	sma expand  3230.34	sma hour  3229.74
                          2020-01-08 13:10:00, close  3246.25, 	sma expand  3230.30	sma hour  3229.74
                          2020-01-08 13:15:00, close  3246.25, 	sma expand  3230.30	sma hour  3229.74
                          2020-01-08 13:20:00, close  3245.50, 	sma expand  3230.28	sma hour  3229.74
                          2020-01-08 13:25:00, close  3246.25, 	sma expand  3230.30	sma hour  3229.74
                          2020-01-08 13:30:00, close  3246.75, 	sma expand  3230.32	sma hour  3229.74
                          2020-01-08 13:35:00, close  3247.25, 	sma expand  3230.33	sma hour  3229.74
                          2020-01-08 13:40:00, close  3247.75, 	sma expand  3230.35	sma hour  3229.74
                          2020-01-08 13:45:00, close  3247.25, 	sma expand  3230.33	sma hour  3229.74
                          2020-01-08 13:50:00, close  3246.75, 	sma expand  3230.32	sma hour  3229.74
                          2020-01-08 13:55:00, close  3245.75, 	sma expand  3230.28	sma hour  3229.74
                          2020-01-08 14:00:00, close  3244.75, 	sma expand  3230.25	sma hour  3230.25
                          2020-01-08 14:05:00, close  3246.50, 	sma expand  3230.72	sma hour  3230.25
                          
                          bhavishya goyal 1 Reply Last reply Reply Quote 0
                          • bhavishya goyal
                            bhavishya goyal @run-out last edited by

                            @run-out Thanks for that. Can this be made generic so it can work with any indicator ? With this i have to create new indicator for each Indicator .

                            Another thing can we call one indicator from other indicator ?

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

                              You can definitely call one indicator from another indicator. Just treat it like a 'data line' in your new indicator.

                              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(); }); }