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

Multiple Timeframes with Multiple Datafeeds



  • When I use a single time frame I have no trouble resampling my data and implementing it into init exactly the way its shown in the BT documantation:

    def __init__(self):
    
            self.atr = bt.indicators.ATR(self.data, period=self.params.atr_per)
            self.stoch = bt.indicators.Stochastic(self.data, period=self.params.stoch_per,
                period_dslow=self.params.dslow_per)
    
            self.daily_atr = bt.indicators.ATR(self.data1, period=self.params.datr_per)
    

    When I work with multiple data feed I use following code to add it to cerebro:

    for i in range(len(symbols)):
        dataframe = pandas.read_csv(symbols[i][0], index_col=0, 
                                    parse_dates=True, 
                                    dayfirst=True
                                    )
        data = PandasData(dataname=dataframe, timeframe=bt.TimeFrame.Minutes, compression=5)
        cerebro.adddata(data, name=symbols[i][1])
    

    and then following code to implement it into init:

     def __init__(self):
    
            self.inds = dict()
            for i, d in enumerate(self.datas):
                self.inds[d] = dict()
                self.inds[d]['atr'] = bt.indicators.ATR(d, period=self.params.atr_per)
                self.inds[d]['stoch'] = bt.indicators.Stochastic(d, period=self.params.stoch_per,
                                        period_dslow=self.params.dslow_per)
    

    The code above works perfectly witha single timeframe.

    For a single datafeed and multiple timeframe, I have self.data for my intraday data and self.data1 for my daily data which I can pass to the indicators I want and from there on my strategy works as expected.

    For multiple datafeeds however, looks like backtrader includes both the 5 min and daily timeframes in same set of feeds (self.datas) and from here on I cannot pass the data I want to the relevant indicators. Not only this but the daily data also messes around with my intraday indicators.

    I tried to replicate the above code during init:

            self.daily_inds = dict()
            for i, d1 in enumerate(self.data1):
                self.daily_inds[d1] = dict()
                self.daily_inds[d1]['d_atr'] = bt.indicators.ATR(d1, period=5)
    

    but it simply wouldnt work.

    Is there a way to prevent daily data messing around with my intraday indicators and use it only for the calculation of the daily indicators?

    Daily ATR is important to me as it presents the average daily range for the past few days.

    thanks,
    Rum


  • administrators

    @Rumen-Nenov said in Multiple Timeframes with Multiple Datafeeds:

    For multiple datafeeds however, looks like backtrader includes both the 5 min and daily timeframes in same set of feeds (self.datas)

    For a single data feed too. Each and every data feed is present in the self.datas iterable, exactly in the order in which they were introduced in the system.

    @Rumen-Nenov said in Multiple Timeframes with Multiple Datafeeds:

    and from here on I cannot pass the data I want to the relevant indicators

    And why not? They are data feeds, they can be passed to any indicator.

    @Rumen-Nenov said in Multiple Timeframes with Multiple Datafeeds:

    Not only this but the daily data also messes around with my intraday indicators.

    Exactly how? This would be the first time.

    @Rumen-Nenov said in Multiple Timeframes with Multiple Datafeeds:

    for i, d1 in enumerate(self.data1):

    Sorry but self.data1 is a data feed and not and array of data feeds. This is for sure not in the documentation. It seems you assume that daily data feeds get magically all packed inside self.data1. No.

    See here for what self.data1 means: Docs - Platform Concepts

    What you need is to have a convention for the addition order of the data feeds to cerebro. If you add a 5-min / 1-day data feeds per instrument, you can use something like for i in range(0, len(self.datas), 2), where self.datas[i]will have the5-minfeed andself.datas[i + 1]will have the1-day` feed.



  • Great! thanks very much!

    I simply created 2 new lists inside init

    self.m5_data = self.datas[::2]
    self.d1_data = self.datas[1::2]
    
    self.inds = dict()
    for i, d in enumerate(self.m5_data):
          self.inds[d] = dict()
          self.inds[d]['atr'] = bt.indicators.ATR(d, period=self.params.atr_per)
          self.inds[d]['stoch'] = bt.indicators.Stochastic(d, period=self.params.stoch_per,
                                        period_dslow=self.params.dslow_per)
    self.daily_inds = dict()
    for i, d in enumerate(self.d1_data):
          self.daily_inds[d] = dict()
          self.daily_inds[d]['d_atr'] = bt.indicators.ATR(d, period=self.params.d_atr_per)
    

    Now however I've got trouble using it during next. For single time frame following code does the trick:

    def next(self):
    
            for i, d in enumerate(self.datas):
                dt, dn = self.datetime.datetime(), d._name
                pos = self.getposition(d).size
                
                if pos==0:
                       # And then follows the logic of the strategy
    

    but for multiple time frame i couldn't enumerate both lists simultaneously. I tried following

            for i, d in enumerate(zip(self.m5_data, self.d1_data)):
                dt, dn = self.datetime.datetime(), d._name
                pos = self.getposition(d).size
    # and also
            for i, d in enumerate(self.m5_data + self.d1_data):
                dt, dn = self.datetime.datetime(), d._name
                pos = self.getposition(d).size
    

    neither of them worked. Further ahead in the process I believe that time frames are matched by d._name and self.datetime.datetime, and they should not necessarily be enumerated simultaneously. What would be the solution here?



  • Solved!

    def next(self):
    
            for i, (d, d1) in enumerate(zip(self.m5_data, self.d1_data)):
                dt, (dn, d1n) = self.datetime.datetime(), (d._name, d1._name)
    


  • Hello @Rumen-Nenov,

    I have a common problem. Here is my code:

    import backtrader as bt
    import backtrader.feeds as btfeeds
    #import backtrader.indicators as btind
    import pandas as pd 
    import math
    
    #gutes Forum Problem 2 Timeframes und mehrere datenfeeds (aktien)
    # https://community.backtrader.com/topic/2285/multiple-timeframes-with-multiple-datafeeds
    
    class simpleStrategy1307(bt.Strategy):
        params = (
            ('Risk_perTrade', 0.01),
        )
    
        def __init__(self):
            self.m60_data = self.datas[::2]
            self.d1_data = self.datas[1::2]
    
            self.inds = dict()
            for i, d in enumerate(self.m60_data):
                self.inds[d] = dict()
                self.inds[d]['atr'] = bt.indicators.ATR(d)
                #self.inds[d]['stoch'] = bt.indicators.Stochastic(d)
            self.daily_inds = dict()
            for i, d in enumerate(self.d1_data):
                self.daily_inds[d] = dict()
                self.daily_inds[d]['d_atr'] = bt.indicators.ATR(d)
            print("__init__ durchlaufen :)")
    
    
        def next(self):
            print("Hallo")
            # d = 60min & d1 = Daily Data
            # dn = 60Minuten Sock Name & d1n ist Daily Stock Name
            for i, (d, d1) in enumerate(zip(self.m60_data, self.d1_data)):
                dt, (dn, d1n) = self.datetime.datetime(), (d._name, d1._name)
    
                if self.inds[d]['atr'] > self.inds[d1]['atr']:
                    self.buy(d)
                else:
                    self.sell(d)
    
                #print(d)
                #print(dn)
            #print(d.date)
                
    def runstrat():
    
        cerebro = bt.Cerebro()
    
        cerebro.addstrategy(simpleStrategy1307)
    
        
        # get all symbols
        # read symbols from csv and read path of Stock and Index 
        sheet = pd.read_csv("/Users/christianbrendel/Desktop/allgemein/Visual Studio/Grap StockData/Aktiensymbole/SPX_für_Tiingo Kopie.csv")
        Stock_60min_path = "/Users/christianbrendel/Desktop/allgemein/Visual Studio/Stock Data/S&P500 Aktien 1H/" 
        Index_Daily_path = "/Users/christianbrendel/Desktop/allgemein/Visual Studio/Stock Data/Index EOD Data/^GSPC.csv"
        #erstelle excel
        w, h = 2, len(sheet.index)
        symbols = [[0 for x in range(w)] for y in range(h)] 
        for i in range (0,len(sheet.index)):
            # in erste Spalte path z.B. "/Users/christianbrendel/Desktop/allgemein/Visual Studio/Stock Data/S&P500 Aktien 1H/A"
            symbols[i][0] = Stock_60min_path + sheet.iloc[i][0] + ".csv"
            # in der zeiten spalte den Name z.B. "A" einfügen
            symbols[i][1] = sheet.iloc[i][0]
    
        for i in range(len(symbols)):
            dataframe = pd.read_csv(symbols[i][0], index_col=1, 
                                        parse_dates=True, 
                                        dayfirst=True,
                                        infer_datetime_format=True,
                                        )
            #stock_prices = pd.read_csv(path, index_col=1, parse_dates=True, infer_datetime_format=True)
            m60_data = bt.feeds.PandasData(dataname=dataframe, timeframe=bt.TimeFrame.Minutes, compression=60)
            cerebro.adddata(m60_data, name=symbols[i][1])
    
        Indexdataframe = pd.read_csv(Index_Daily_path, index_col=0, 
                                    parse_dates=True, 
                                    dayfirst=True,
                                    infer_datetime_format=True,
                                    )
        Indexdata = bt.feeds.PandasData(dataname=Indexdataframe, timeframe=bt.TimeFrame.Days)
        cerebro.adddata(Indexdata, name="SPX")
    
        #print('Starting Portfolio Value: {0:8.2f}'.format(cerebro.broker.getvalue()))
    
        cerebro.run()
    
        
    
    if __name__ == "__main__":
        runstrat()
        print("data added to Cerebro :)")
        #print('Starting Portfolio Value: {0:8.2f}'.format(cerebro.broker.getvalue()))   
    

    The code starts and than nothing happens..
    1. Do you think my way to fill my data feed is correct?
    2. Is my init Method right?
    3. Can I use my data feed like I have done in the next function?

    thank you for your help!

    best regards
    Christian


Log in to reply
 

});