Non 0th data feed unexpected behavior in indicator (multiple data feeds)



  • I'm trying to create an indicator that operates on multiple data feeds. The indicator should use all the data feeds, not just the 0th indexed data feed.

    I've been trying to figure out how to pass multiple data feeds into an indicator and the best I've been able to figure out is to have the Strategy pass the self.datas object as a param to the indicator, like this: self.prediction = ExampleIndicator(feeds=self.datas).

    Unfortunately I'm finding that the object that represents those feeds, self.p.feeds, in ExampleIndicator doesn't behave like I would expect it to when accessing its data. Notably when trying to access today's data with [0] it works only for the 0th feed and returns nothing for the non-0th feed. Similarly, trying to access yesterday's data with [-1] work's only for the 0th feed and returns the last item (most recent) of the entire data feed for the non-0th data feed. Here's an example:

    class CustomStrat (bt.Strategy):
    
        def __init__(self):
            self.prediction = ExampleIndicator(feeds=self.datas)
    
        def next(self):
            print("Strategy next")
            for feed in self.datas:
                print(np.frombuffer(feed.open.get(ago=0, size= 1)))
    
    
    class ExampleIndicator(bt.Indicator):
        lines = ('out',)
    
        params = (('feeds', {}),)
    
        def __init__(self):
            self.i=0
    
        # Get a prediction here
        def next(self):
            print("Indicator next")
            print("total number of days {}".format(len(self.data)))
            for i, feed in enumerate(self.p.feeds):
                for ago in [0,-1]:
                    print ("Feed {0} [{1}] = {2}, length: {3}".format(
                            feed._name,
                            ago,
                            np.frombuffer(self.p.feeds[i].open.get(ago=ago, size= 3)),
                            len(feed)))
            self.i+=1
            if self.i >5: exit()
    

    Returns

    Indicator next
    total number of days 1
    Feed BCHARTS/BITSTAMPUSD [0] = [], length: 1
    Feed BCHARTS/BITSTAMPUSD [-1] = [], length: 1
    Feed BCHARTS/LOCALBTCUSD [0] = [], length: 0
    Feed BCHARTS/LOCALBTCUSD [-1] = [ 2848.26  4591.82  2476.97], length: 0
    Indicator next
    total number of days 2
    Feed BCHARTS/BITSTAMPUSD [0] = [], length: 2
    Feed BCHARTS/BITSTAMPUSD [-1] = [], length: 2
    Feed BCHARTS/LOCALBTCUSD [0] = [], length: 0
    Feed BCHARTS/LOCALBTCUSD [-1] = [ 2848.26  4591.82  2476.97], length: 0
    Indicator next
    total number of days 3
    Feed BCHARTS/BITSTAMPUSD [0] = [ 1191.16  1228.    1256.32], length: 3
    Feed BCHARTS/BITSTAMPUSD [-1] = [], length: 3
    Feed BCHARTS/LOCALBTCUSD [0] = [], length: 0
    Feed BCHARTS/LOCALBTCUSD [-1] = [ 2848.26  4591.82  2476.97], length: 0
    Indicator next
    total number of days 4
    Feed BCHARTS/BITSTAMPUSD [0] = [ 1228.    1256.32  1287.38], length: 4
    Feed BCHARTS/BITSTAMPUSD [-1] = [ 1191.16  1228.    1256.32], length: 4
    Feed BCHARTS/LOCALBTCUSD [0] = [], length: 0
    Feed BCHARTS/LOCALBTCUSD [-1] = [ 2848.26  4591.82  2476.97], length: 0
    Indicator next
    total number of days 5
    Feed BCHARTS/BITSTAMPUSD [0] = [ 1256.32  1287.38  1260.  ], length: 5
    Feed BCHARTS/BITSTAMPUSD [-1] = [ 1228.    1256.32  1287.38], length: 5
    Feed BCHARTS/LOCALBTCUSD [0] = [], length: 0
    Feed BCHARTS/LOCALBTCUSD [-1] = [ 2848.26  4591.82  2476.97], length: 0
    Indicator next
    total number of days 6
    Feed BCHARTS/BITSTAMPUSD [0] = [ 1287.38  1260.    1269.98], length: 6
    Feed BCHARTS/BITSTAMPUSD [-1] = [ 1256.32  1287.38  1260.  ], length: 6
    Feed BCHARTS/LOCALBTCUSD [0] = [], length: 0
    Feed BCHARTS/LOCALBTCUSD [-1] = [ 2848.26  4591.82  2476.97], length: 0
    

    Notice how the BCHARTS/LOCALBTCUSD [-1] always shows the same thing (which is the latest data on that feed). It's as if it's being treated like a normal python list, not like a BT feeds object.

    Ultimately, I'm just trying to get multiple data feeds into an indicator. Not sure the best way to do it.

    Any ideas/help here?

    Thanks!



  • You posted in other thread the same: https://community.backtrader.com/topic/467/feeding-multiple-data-feeds-in-indicators/

    Why not: MySuperIndicator(*self.datas)? That's the standard Python notation for passing an array in expanded form (i.e.: the standard *args)

    If you pass them as feeds=xxx, the system doesn't know you are passing data feeds. In that case and looking at the documetation referenced in the other thread:

    • https://www.backtrader.com/docu/concepts.html#omitting-the-data-feeds

      self.data has been completely removed from the invocation of SimpleMovingAverage. If this is done, the indicator
      (in this case the SimpleMovingAverage) receives the first data of the object in which is being created (the Strategy),
      which is self.data (aka self.data0 or self.datas[0])
      


  • @Paska-Houso Thanks for the reply, our messages just passed each other in the other thread. I appreciate the help. For those interested, please check out the linked thread for the full discussion.


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.