help with indicator based on multiple data feeds not synchronised
-
Hi,
I would like to implement an indicator that first calculates the bid-ask midpoint on two separate minute-bar data feeds, one for bid and the other for ask. These data feeds are not synchronised i.e. there are minutes when one has value and the other does not. Although the value of the indicator is correct, its length is not. When the second feed does not have a minute bar of the first feed, it just overwrites the indicator value.
Many thanks for the help.
import backtrader as bt import sys import os class StrategyBidAsk(bt.Strategy): def next(self): output_str = "" for i in range(len(self.datas)): output_str += "{}: {}, {}|".format(self.datas[i]._name, self.datas[i].datetime.datetime(0), self.datas[i].lines.close[0]) output_str = output_str[:-1] print(output_str) for ind in self.getindicators_lines(): line_names = ind.getlinealiases() for idx in range(len(line_names)): print("{} {} {} {} {}".format(ind.plotinfo.plotname or ind.__class__.__name__, line_names[idx], ind.lines[idx][0], ind.lines[idx][-1], len(ind))) class MidPriceIndicator(bt.Indicator): lines = ('toy_mid',) def __init__(self): self.lines.toy_mid = (self.datas[0]+self.datas[1])/2 def main(argv): folder = "data" files = [['Toy_Ask.csv', 'Toy_Bid.csv']] cash = 100000.0 cerebro = bt.Cerebro() cerebro.broker.setcash(cash) cerebro.broker.set_shortcash(False) cerebro.broker.setcommission(commission=0) cerebro.broker.set_coc(False) for file in files: if not isinstance(file, list): file = [file] data_list = [] for i, f in enumerate(file): data = bt.feeds.GenericCSVData( dataname=os.path.join(folder, f), dtformat='%Y-%m-%d %H:%M:%S', # default datetime=0, # default time=-1, # default close=1, high=-1, low=-1, open=-1, volume=-1, # default openinterest=-1, # default for not present timeframe=bt.TimeFrame.Minutes, compression=1) # default if i != 0 and len(file) == 2: data.compensate(data_list[0]) data_list.append(data) cerebro.adddata(data, name=os.path.splitext(f)[0]) idx = cerebro.addstrategy(StrategyBidAsk) cerebro.addsizer_byidx(idx, bt.sizers.SizerFix, stake=100) cerebro.addindicator(MidPriceIndicator, cerebro.datasbyname["Toy_Bid"]._getline("close"), cerebro.datasbyname["Toy_Ask"]._getline("close")) cerebro.run(runonce=False, preload=True) cerebro.plot(volume=False, numfigs=1) if __name__ == "__main__": main(sys.argv) # # Output # Toy_Ask: 2018-08-08 00:00:01, 3.0|Toy_Bid: 2018-08-08 00:00:01, 5.0 # MidPriceIndicator toy_mid 4.0 4.0 1 # Toy_Ask: 2018-08-08 00:02:01, 3.0|Toy_Bid: 2018-08-08 00:02:01, 6.0 # MidPriceIndicator toy_mid 4.5 4.0 2 # Toy_Ask: 2018-08-08 00:02:01, 3.0|Toy_Bid: 2018-08-08 00:03:01, 7.0 # MidPriceIndicator toy_mid 5.0 4.5 3 # Toy_Ask: 2018-08-08 00:04:01, 0.0|Toy_Bid: 2018-08-08 00:03:01, 7.0 # MidPriceIndicator toy_mid 3.5 4.5 3 # Toy_Ask: 2018-08-08 00:08:01, 1.0|Toy_Bid: 2018-08-08 00:08:01, 2.0 # MidPriceIndicator toy_mid 1.5 3.5 4
-
@momentum said in help with indicator based on multiple data feeds not synchronised:
Although the value of the indicator is correct, its length is not. When the second feed does not have a minute bar of the first feed, it just overwrites the indicator value.
The indicator has the right length and the right value. If the data feeds have different paces, the 1st data feed is the clock for the indicator and marks the tempo. The indicator cannot add the length of both data feeds because it would then have a greater length than the system itself.
-
Thanks for your reply and help. By system you mean the strategy? Because in this case, strategy will have length 5 while indicator length 4.
# Toy_Ask: 2018-08-08 00:00:01, 3.0|Toy_Bid: 2018-08-08 00:00:01, 5.0 # MidPriceIndicator toy_mid 4.0 4.0 1 1 # Toy_Ask: 2018-08-08 00:02:01, 3.0|Toy_Bid: 2018-08-08 00:02:01, 6.0 # MidPriceIndicator toy_mid 4.5 4.0 2 2 # Toy_Ask: 2018-08-08 00:02:01, 3.0|Toy_Bid: 2018-08-08 00:03:01, 7.0 # MidPriceIndicator toy_mid 5.0 4.5 3 3 # Toy_Ask: 2018-08-08 00:04:01, 0.0|Toy_Bid: 2018-08-08 00:03:01, 7.0 # MidPriceIndicator toy_mid 3.5 4.5 3 4 # Toy_Ask: 2018-08-08 00:08:01, 1.0|Toy_Bid: 2018-08-08 00:08:01, 2.0 # MidPriceIndicator toy_mid 1.5 3.5 4 5 import backtrader as bt import sys import os class StrategyBidAsk(bt.Strategy): def next(self): output_str = "" for i in range(len(self.datas)): output_str += "{}: {}, {}|".format(self.datas[i]._name, self.datas[i].datetime.datetime(0), self.datas[i].lines.close[0]) output_str = output_str[:-1] print(output_str) for ind in self.getindicators_lines(): line_names = ind.getlinealiases() for idx in range(len(line_names)): print("{} {} {} {} {} {}".format(ind.plotinfo.plotname or ind.__class__.__name__, line_names[idx], ind.lines[idx][0], ind.lines[idx][-1], len(ind), len(self))) class MidPriceIndicator(bt.Indicator): lines = ('toy_mid',) def __init__(self): self.lines.toy_mid = (self.datas[0]+self.datas[1])/2 def main(argv): folder = "data" files = [['Toy_Ask.csv', 'Toy_Bid.csv']] cash = 100000.0 cerebro = bt.Cerebro() cerebro.broker.setcash(cash) cerebro.broker.set_shortcash(False) cerebro.broker.setcommission(commission=0) cerebro.broker.set_coc(False) for file in files: if not isinstance(file, list): file = [file] data_list = [] for i, f in enumerate(file): data = bt.feeds.GenericCSVData( dataname=os.path.join(folder, f), dtformat='%Y-%m-%d %H:%M:%S', # default datetime=0, # default time=-1, # default close=1, high=-1, low=-1, open=-1, volume=-1, # default openinterest=-1, # default for not present timeframe=bt.TimeFrame.Minutes, compression=1) # default if i != 0 and len(file) == 2: data.compensate(data_list[0]) data_list.append(data) cerebro.adddata(data, name=os.path.splitext(f)[0]) idx = cerebro.addstrategy(StrategyBidAsk) cerebro.addsizer_byidx(idx, bt.sizers.SizerFix, stake=100) cerebro.addindicator(MidPriceIndicator, cerebro.datasbyname["Toy_Bid"]._getline("close"), cerebro.datasbyname["Toy_Ask"]._getline("close")) cerebro.run(runonce=False, preload=True) cerebro.plot(volume=False, numfigs=1) if __name__ == "__main__": main(sys.argv)
-
The system can be longer than the underlying elements. If not, it would impossible to operate with different timeframes simultaneously.
But it cannot be shorter.