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/

    Example indicator to build larger timeframe from minute data feed (smaller timeframe), without using replay

    Indicators/Strategies/Analyzers
    1
    2
    103
    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
      Batman last edited by

      I had difficulties using replay in the case of multiple symbols (multiple feeds) and different timeframes. For example:

      • the strategy runs 10 stocks (10 feeds)
      • the feed files use 1 minute data (need 1 minute resolution)
      • but the indicator is calculated on the daily timeframe (instead of 1 minute)

      A simple solution that I'm using:

      • always use only the 1 minute feed (no resample, no replay)
      • in the indicator, build the larger timeframe using the 1 minute feed (for example build the daily or weekly from minute)
      • calculate the indicator “by hand” using python lists

      Maybe not a “pretty” solution, but it solved my problem.

      Sample code if someone needs to do something similar:

      import datetime as dt
      import backtrader as bt
      import statistics
      
      class BaseMinuteIndicator(bt.Indicator):
          
          params = (('larger_timeframe', 'D1'), )
      
          def init(self):
              self.open = list()
              self.high = list()
              self.low = list()
              self.close = list()
              self.datetime = list()
              self.last_period = list()
              
          def process_new_item(self):
              
              add_new_item = False
      
              current_period = None        
              if self.p.larger_timeframe == 'D1':
                  current_period = self.data.datetime.datetime(0).day
              elif self.p.larger_timeframe == 'H1':
                  current_period = self.data.datetime.datetime(0).hour
              elif self.p.larger_timeframe == 'W1':
                  current_period = self.data.datetime.date(0).isocalendar()[1]
      
              if len(self.last_period) != 0:
                  if self.last_period[-1] == current_period:
                      
                      if self.data.high[0] > self.high[-1]:
                          self.high[-1] = self.data.high[0]
                          
                      if self.data.low[0] < self.low[-1]:
                          self.low[-1] = self.data.low[0]
                      
                      self.close[-1] = self.data.close[0]
                  
                  else:
                      add_new_item = True
      
              else:
                  add_new_item = True
                  
              if add_new_item:
                  self.open.append(self.data.open[0])
                  self.high.append(self.data.high[0])
                  self.low.append(self.data.low[0])
                  self.close.append(self.data.close[0])
                  self.datetime.append(self.data.datetime[0])
                  self.last_period.append(current_period)
      
              return add_new_item
      
      
      class MeanIndicatorExample(BaseMinuteIndicator):
          
          lines = ('l_mean', )
          params = (('period', 200), )
          plotlines = dict(l_mean=dict(ls='-', color='cyan'), )
          plotinfo = dict(subplot=False)
      
          def __init__(self):
              self.init()
              self.mean = list()
              
          def next(self):
      
              # New item        
              add_new_item = self.process_new_item()
                  
              if add_new_item:
                  self.mean.append(0)
      
              # Mean        
              i = len(self.datetime) - 1
      
              if len(self.datetime) >= self.p.period:
                  self.mean[i] = statistics.mean(self.close[-self.p.period:]) 
                  self.l.l_mean[0] =  self.mean[i] 
      
      
      class TestStrategy(bt.Strategy):
          
          def __init__(self):
              self.indicator = MeanIndicatorExample( )
             
          def next(self):
              pass
      
      
      def run():
      
          csv_file =  '...'
          
          data = bt.feeds.GenericCSVData(dataname=csv_file,
                                     timeframe=bt.TimeFrame.Minutes, 
                                     fromdate = dt.datetime(2012, 1, 1), 
                                     todate=dt.datetime(2022, 1, 1))
          cerebro = bt.Cerebro()
          cerebro.adddata(data)
          cerebro.addstrategy(TestStrategy, )
          cerebro.run()
          cerebro.plot()
      
      
      if __name__ == '__main__':
          run()
          
                 
                  
                 
      
      B 1 Reply Last reply Reply Quote 1
      • B
        Batman @Batman last edited by

        Some details to clarify the difficulties I had with the use of replay (and why I implemented the solution above). I need to take volume into account because sometimes I use low volume instruments where the use of a Volume Filler makes big difference.

        I was using minute replay on daily chart: it worked fine in my simulation initially, but the issues I had were :

        1. The main issue: I needed to access the volume of each minute but calculate indicators on the daily chart (I need minute volume information for my custom Volume Filler). In replay mode, the volume is the accumulated volume for the day, not the volume of the minute (that I needed).
        2. The chart in replay mode shows daily bars, but as I do multiple trades a day, I couldn't see the details. With minute chart it is possible.
        3. I had a lot of trouble debugging when I made a multi-symbol version using replay. The version with minute chart is now simpler for me to debug, because multi symbol in replay can become complex. For example: the complexity of syncing feeds with missing minutes in history, where one feed may have fewer minute bars than others.
        1 Reply Last reply Reply Quote 1
        • 1 / 1
        • First post
          Last post
        Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors