Hello,

I am trying to use volume bars by implementing ClassicalRenkoConsolidator.

I am getting an error: 

Runtime Error: 'QuoteBar' object has no attribute 'Volume'
at <lambda>
self.equivolume_consolidator = ClassicRenkoConsolidator(int(volume_daily_mean / 10) in main.py: line 100

I don't understand where QuoteBars comes from.

Here is the code (can't attach code with error):

# region imports
from AlgorithmImports import *
# endregion

class WellDressedFluorescentYellowFly(QCAlgorithm):

def Initialize(self):

# params
self.frequency = Resolution.Minute

# set up
self.SetStartDate(2020, 1, 1)
self.SetEndDate(2020, 3, 1)
self.SetCash(100000)
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)

# Add QC500 Universe
equity = self.AddEquity("SPY", Resolution.Minute)
self.spy = equity.Symbol
self.Securities[self.spy].SetDataNormalizationMode(DataNormalizationMode.Raw)
self.SetBenchmark(lambda dt: self.Securities[self.spy].Price)
self.AddUniverse(self.CoarseSelectionFunction)
self.UniverseSettings.Resolution = Resolution.Minute

# init
self.Data = {}
self.excess_window = RollingWindow[float](10)
self.day = -1

def CoarseSelectionFunction(self, coarse):

# rebalancing
if self.day == self.Time.day:
return Universe.Unchanged
self.day = self.Time.day

# filter n stocks with highest dollar volume
filtered_coarse = [x for x in coarse if x.HasFundamentalData and x.AdjustedPrice > 5]
selected = sorted(filtered_coarse, key=lambda x: x.DollarVolume, reverse=True)

return [x.Symbol for x in selected[:5]]

def OnSecuritiesChanged(self, changes):

# added securities
def DataDictInitialization():
for security in changes.AddedSecurities:
symbol = security.Symbol
if symbol not in self.Data:
self.Data[symbol] = SelectionData(self, symbol)
self.Train(DataDictInitialization)

# removed securities
for security in changes.RemovedSecurities:
symbol = security.Symbol
if symbol in self.Data:
symbolData = self.Data.pop(symbol, None)

def OnData(self, data):

# if there are no bars data (only stok splits, dividends etc) than cont
if self.spy not in data.Bars: return
if not data.Bars.ContainsKey(self.spy): return
if not data.ContainsKey(self.spy): return

# calculate sums of above and below and their difference
self.Debug(f"Dat keys {self.Data.keys()}")
self.Debug(f"Data diff window {[list(self.Data[symbol].excess_diff_window) for symbol in self.Data.keys()]}")


class SelectionData(object):

def __init__(self, algorithm, symbol):

# set up
self.algorithm = algorithm
self.symbol = symbol

# rolling windows
self.close_window = RollingWindow[float](100)
self.excess_diff_window = RollingWindow[float](10)
self.daily_volume_window = RollingWindow[float](6)

# consolidators
self.daily_consolidator = self.algorithm.Consolidate(symbol, Resolution.Daily, self.DailyBarHandler)

# warm up daily volume
history = self.algorithm.History([self.symbol], 6 + 1, Resolution.Daily)
if history.shape[0] == 0:
self.algorithm.Log('DataFrame is empty!')
return
for tuple in history.loc[self.symbol].itertuples():
self.daily_volume_window.Add(tuple.volume)

# classical renko volume bar
if self.daily_volume_window.IsReady:
volume_window = list(self.daily_volume_window)
volume_daily_mean = sum(volume_window) / len(volume_window)
self.algorithm.Debug(f"Daily mean volume is {int(volume_daily_mean / 10)}.")
self.equivolume_consolidator = ClassicRenkoConsolidator(int(volume_daily_mean / 10), selector = lambda data: data.Volume)
self.equivolume_consolidator.DataConsolidated += self.OnDataConsolidated
self.algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.equivolume_consolidator)

# warm up volume bars
if self.daily_volume_window.IsReady:
history = self.algorithm.History([symbol], 500, Resolution.Minute)
if history.shape[0] == 0:
self.algorithm.Log('DataFrame is empty!')
return
if 'volume' not in history.columns:
self.algorithm.Log(f"No volume: {symbol}\n{history.to_string()}")
return
for tuple in history.loc[self.symbol].itertuples():
tradebar = TradeBar(tuple.Index, self.symbol, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume)
self.equivolume_consolidator.Update(tradebar)

def DailyBarHandler(self, consolidated):
if "Volume" is consolidated.values():
self.Debug("No volume!")
return
self.daily_volume_window.Add(consolidated.Volume)

def OnDataConsolidated(self, sender, data):
self.close_window.Add(data.Close)
if self.close_window.IsReady:
pass

# def update(self, price):
# self.close_window.Add(price)# Your New Python Fileimport numpy as np