Accessing indicator lines in multiple datafeeds
-
Following this extremely helpful guide to run strategy over multiple datafeeds: https://backtest-rookies.com/2017/08/22/backtrader-multiple-data-feeds-indicators/, I am having trouble accessing the different lines an indicator has to offer.
Indicator construction:
self.inds = dict() for i, d in enumerate(self.datas): self.inds[d] = dict() self.inds[d]["bb"] = bt.indicators.BollingerBands( d, period=self.params.BB_MA, devfactor=self.params.BB_SD) self.inds[d]['sma2'] = bt.indicators.SimpleMovingAverage( d.close, period=self.params.sma2)
next()
method:if self.inds[d]["sma2"][0] < self.params.SMA_VAL: if (d.close[-1] > self.inds[d]["bb"].lines[i].top[-1]) and ( d.close[0] <= self.inds[d]["bb"].lines[i].top[0] ): self.order = self.sell(data=d) self.stopprice = self.inds[d]["bb"].lines[i].top[0] self.closepos = self.buy(exectype=bt.Order.Stop, price=self.stopprice)
Going by my understanding thus far,
self.inds[d]["bb"]
can access the regular indicator. And then we can take that one step further by accessing the ith element of the current datafeed related to the line. But I get this error:if (d.close[-1] > self.inds[d]["bb"].lines[i].top[-1]) and ( AttributeError: 'LineBuffer' object has no attribute 'top'
I also tried
self.inds[i][d]["bb"].lines.top[0]
to no avail. With this the error becomes:KeyError: 0
. -
I was able to solve this by removing
[i]
altogether. After rereading the documentation from the link above:"When we loop through the data feeds, we can simply pass that data feed object to the dictionary as a key reference to then access the indicators for that particular feed."
The ith index isn't needed as the reference to each datafeed is stored in the dth key value.
It would be nice to get confirmation if this understanding is correct though.
-
@leggomaeggo I guess you are right. I mean the 'd' index makes that job already right?
-
@jas2210 Yup. I believe so.
-
@leggomaeggo If I'm not mistaken, I believe you can also dispense with
lines
. I would write this like:For the current bar: self.inds[d]["bb"].top[0] For the previous bar: self.inds[d]["bb"].top[-1]
-
@run-out Just tried it out. That's awesome! Thank you.