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/

    next() called multiple times with resampled data feeds

    General Discussion
    2
    4
    619
    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.
    • N
      nimrare last edited by

      Hello backtrader community

      First of all, thanks for this awesome piece of software. My favorite backtesting framework by far. ;)
      Recently, I started working with mixed time frames and stumbled upon the following problem.
      I have a daily data feed and a weekly data feed. At the end of the week, when the weekly bar forms, next seems to be called twice. The output for the code below looks like the following:

      2018-02-02 27.3 27.3
      2018-02-05 36.51 27.3
      2018-02-06 35.5 27.3
      2018-02-07 36.94 27.3
      2018-02-08 45.79 27.3
      2018-02-09 41.48 27.3
      2018-02-09 41.48 41.48

      2018-02-12 39.71 41.48
      2018-02-13 39.75 41.48
      2018-02-14 35.16 41.48
      2018-02-15 34.41 41.48
      2018-02-16 34.95 41.48
      2018-02-16 34.95 34.95

      2018-02-20 36.4 34.95
      2018-02-21 36.81 34.95
      2018-02-22 36.3 34.95
      2018-02-23 33.49 34.95
      2018-02-23 33.49 33.49

      2018-02-26 32.1 33.49
      2018-02-27 35.13 33.49
      2018-02-28 36.7 35.13

      import matplotlib.pyplot as plt
      
      import backtrader as bt
      import backtrader.indicators as btind
      import backtrader.analyzers as btanalyzers
      
      import pandas as pd
      
      class MultiTimeFrameStrategy(bt.Strategy):
      
      	def __init__(self):
      		pass
      
              def next(self):
      		print(self.datetime.date(), self.datas[0].close[0], self.datas[1].close[0])
      
      	def stop(self):
      		pass
      
      def run_strategy():
      
      	fromdate = "2018-02-01"
      	todate = "2018-03-01"
      
      	fromdate = datetime.datetime.strptime(fromdate, "%Y-%m-%d")
      	todate = datetime.datetime.strptime(todate, "%Y-%m-%d")
      
      	cerebro = bt.Cerebro()
      
      	# add a strategy
      	cerebro.addstrategy(
      		MultiTimeFrameStrategy
      	)
      
      	try:
      		# load data
      		dataframe = pd.read_csv("/path/to/data.csv")
      		dataframe = dataframe[["timestamp", "open", "high", "low", "close", "volume"]].copy()
      		dataframe = dataframe.set_index("timestamp")
      		dataframe.index = pd.to_datetime(dataframe.index)
      
      		# convert the dataframe to a data feed, the timeframe of the original data feed must be set
      		data = bt.feeds.PandasData(dataname=dataframe, timeframe=bt.TimeFrame.Minutes, compression=1, fromdate=fromdate, todate=todate, plot=True)
      
      		# add the original data feed to cerebro
      		#cerebro.adddata(data)
      
      		# add upsampled data feeds
      		cerebro.resampledata(data, timeframe=bt.TimeFrame.Days, compression=1)
      		cerebro.resampledata(data, timeframe=bt.TimeFrame.Weeks, compression=1)
      
      	except Exception as e:
      		print(e)
      
      	cerebro.broker.setcash(100000)
      
      	results = cerebro.run()
      
      if __name__ == "__main__":
      	run_strategy()
      

      I don't really understand this behavior. Maybe you could help me out. When I plot the results, the bars seem to be correctly aligend. Thanks a lot for your help.

      1 Reply Last reply Reply Quote 0
      • N
        nimrare last edited by

        UPDATE: I found out that this does not seem to be happening if I use the original data feed and only one resampled data feed like so:

        # convert the dataframe to a data feed, the timeframe of the original data feed must be set
        data = bt.feeds.PandasData(dataname=dataframe, timeframe=bt.TimeFrame.Minutes, compression=1, fromdate=fromdate, todate=todate, plot=True)
        
        # add the original data feed to cerebro
        cerebro.adddata(data)
        
        # add upsampled data feeds
        cerebro.resampledata(data, timeframe=bt.TimeFrame.Days, compression=1)
        

        If I run this, I don't get the duplicated timestamps as shown above. However, another thing that I noticed is that the close of a resampled bar will only be available during the next bar of the fast data feed (in the case above the minute data feed). Is this expected behavior?

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

          next is NOT called multiple times. It delivers you what it can.

          You are not using a trading calendar and the platform does not know when the trading week ends ... until it sees the start of the next trading week (which is usually a Monday, but must not be). And it then gives you the last resampling.

          You could easily argue that when it is Friday, the trading week is over, but that doesn't always apply, because a Friday can be a trading holiday and some assets may trade 7 days a week.

          Use a trading calendar and the synchronization will be perfect. You can use pre-existing ones or create your own.

          See Docs - Trading Calendars - https://www.backtrader.com/docu/tradingcalendar/tradingcalendar/

          N 1 Reply Last reply Reply Quote 0
          • N
            nimrare @backtrader last edited by

            @backtrader

            Hello backtrader

            Thanks for your reply. What you say makes sense and I will use the trading calendar feature. But just to make sure I understand the behavior correctly, let's look at the duplicate timestamp of 2018-02-09 shown in my first post above.

            2018-02-09 is a Friday. So the the backtrader resampling mechanism creates a daily bar at the end of the day 2018-02-09. At this point it cannot know whether trading might continue on the weekend so it basically looks at the days 2018-02-10 and 2018-02-11. It cannot find that data, so it produces a weekly bar with the timestamp 2018-02-09 in a separate call to next().

            Am I assuming correctly that backtrader assumes by default that a week is ending on Sunday if nothing else is specified in terms of trading calendars?

            Also in the above code you see that I am using two resampled data feeds but NOT the original data feed. If I am using the original data feed together with one resampled data feed this alignment problem does not seem to happen. I understand that you may need more information to give an answer to this but maybe it's obvious and I am missing something.

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