How to associate each strategy with it's data feed.
-
Hi all
Is there a convenient way to associate the Strategy class with a particular data feed?
I'm trying to understand how to implement a portfolio system where each instrument uses a slightly different variation of the trading rules.
I have read these to blog posts (very good), but I want to check my understanding before going much further.
https://www.backtrader.com/blog/posts/2017-04-09-multi-example/multi-example/
https://backtest-rookies.com/2017/08/22/backtrader-multiple-data-feeds-indicators/I think the strategy code needs to identify which data feed to use and this example shows how I do it, but is there a better way already provided?
I'm loving Backtrader but still learning.
I'd appreciate any guidance.
Tony
from datetime import datetime import backtrader as bt class MyStrategy(bt.Strategy): params=(('data_name', ''),) def __init__(self): pass def next(self): # Find the data feed we need. data_idx = 0 for i, d in enumerate(self.datas): if self.datas[i]._name == self.params.data_name: data_idx = i # From here, use only datas[data_idx]... # Print what was selected. dt = self.datas[data_idx].datetime.date(0) dn = self.datas[data_idx]._name inst = self.params.data_name print(f'{dt.isoformat():s}: instrument is {inst:s}') print(f' datas[{data_idx:d}] is {dn:s}') if __name__ == '__main__': instruments = ['NQ=F', 'GC=F'] from_date = datetime(2019, 12, 1) to_date = datetime(2020, 1, 1) # Create the brain. cerebro = bt.Cerebro() for inst in instruments: # Add the instrument data feeds. data_file = '../../Data/Yahoo Data/' + inst + '.csv' data = bt.feeds.YahooFinanceCSVData(dataname=data_file, name=inst, fromdate=from_date, todate=to_date) cerebro.adddata(data) # Add one strategy for each instrument (data feed). strat = cerebro.addstrategy(MyStrategy, data_name=inst) print('Strategy added for instrument ' + inst) cerebro.run()
-
Hi all
Just after I posted that question, I found a better way by using getdatabyname(). See below.
However, I still want to clarify my understanding that the Strategy class needs to identify which datas[] to use. Right?class MyStrategy(bt.Strategy): params=(('data_name', ''),) def __init__(self): pass def next(self): # Find the data feed we need. inst = self.params.data_name inst_data = self.getdatabyname(inst) # Print what was selected. dt = inst_data.datetime.date(0) dn = inst_data._name print(f'{dt.isoformat():s}: instrument is {inst:s}') print(f' inst_data is {dn:s}')
Tony
-
@tony-shacklock said in How to associate each strategy with it's data feed.:
still want to clarify my understanding that the Strategy class needs to identify which datas[] to use. Right?
That's right. Also, the
datas
array is already available during strategy's__init__
so you may just search for the correct data inside the__init__
call and cache is instead of doing it on everynext
call. -
@vladisld Thanks. That makes sense. Much cleaner to do it in
__init__()
.