For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

# Volume in multidata

• Hi All,

I am facing issue to access for multi-data, please refer the code below:

``````    params = dict(
selcperc=0.10,  # percentage of stocks to select from the universe
rperiod=1,  # period for the returns calculation, default 1 period
vperiod=36,  # lookback period for volatility - default 36 periods
mperiod=12,  # lookback period for momentum - default 12 periods
reserve=5,  # 5% reserve capital
)

def log(self, arg):
print('{} {}'.format(self.datetime.date(), arg))

def __init__(self):
# calculate 1st the amount of stocks that will be selected
self.selnum = int(len(self.datas) * self.p.selcperc)
print(int(len(self.datas) * self.p.selcperc))
# allocation perc per stock
# reserve kept to make sure orders are not rejected due to
# margin. Prices are calculated when known (close), but orders can only
# be executed next day (opening price). Price can gap upwards
self.perctarget = (100 - self.p.reserve) / self.selnum
print((100 - self.p.reserve) / self.selnum)
# returns, volatilities and momentums
rs = [bt.ind.PctChange(d, period=self.p.rperiod) for d in self.datas]
vs = [bt.ind.StdDev(ret, period=self.p.vperiod) for ret in rs]
ms = [bt.ind.ROC(d, period=self.p.mperiod) for d in self.datas]
volume = [bt.indicators.MovingAverageSimple(d, period = 2) for d in self.datas.volume]

# simple rank formula: (momentum * net payout) / volatility
# the highest ranked: low vol, large momentum, large payout
# self.ranks = {d: d.npy * m / v for d, v, m in zip(self.datas, vs, ms)}
self.ranks = {d: bt.DivByZero(m, v) for d, v, m, volu in zip(self.datas, vs, ms, volume) if volu > 100000}

``````

Above is giving error:

``````    self.ranks = {d: bt.DivByZero(m, v) for d, v, m, volu in zip(self.datas, vs, ms, volume) if volu > 100000}
TypeError: __bool__ should return bool, returned LineOwnOperation
``````

I am not an expert, any pointers to fix the issue?

• volu refers to volume which is I think list comprehenion of SMA indicator objects. You won't be able to compare each value with a scalar.

• thanks @run-out , is there any other way? I am trying to filter out stocks whose average volume is greater than certain value.

• @gten Yes, you create an dictionary to keep track of your indicators for each datas you have put into the backtest.

Then in init you loop through the datas to create your indicator. If you use > you will have a line of binary 1 or 0. You can then call these values at each 'next' to determine the truth value an any bar of your data volume being greater than the threshold. Here is the sample code:

``````import backtrader as bt
import yfinance as yf

class Strategy(bt.Strategy):

def log(self, txt, dt=None):
""" Logging function fot this strategy"""
dt = dt or self.data.datetime
if isinstance(dt, float):
dt = bt.num2date(dt)
print("%s, %s" % (dt, txt))

def __init__(self):
self.sma_dict = {}
self.p.volume_threshold = 15000000

# Average volume over threshold
for d in self.datas:
self.sma_dict[d] = bt.ind.SMA(d.volume, period=30) > self.p.volume_threshold

def next(self):
for d in self.datas:
self.log(f"{d._name},\tvolume: {int(d.volume):10,d},\tave_volume_gt: {int(self.sma_dict[d]):2d}")
print("\n")
return

def runstrategy():

cerebro = bt.Cerebro()

fromdate = "2020-01-15"
todate = "2020-06-19"

interval = "1d"

data0 = bt.feeds.PandasData(
"AAPL", start=fromdate, stop=todate, interval=interval
),
name="AAPL",
)

data1 = bt.feeds.PandasData(
"MSFT", start=fromdate, stop=todate, interval=interval
),
name="MSFT",
)

data2 = bt.feeds.PandasData(
"TSLA", start=fromdate, stop=todate, interval=interval
),
name="TSLA",
)

cerebro.run()

if __name__ == "__main__":
runstrategy()

``````

• Thank you @run-out, makes sense.

});