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

IB - Switch between Multiple (Near) Online Datafeeds



  • In trying to understand the code and the used objects better I started with the Medium Example from Daniel

    Description: https://medium.com/@danjrod/interactive-brokers-in-python-with-backtrader-23dea376b2fc

    Having extracted and modified the code:

    https://gist.github.com/backtrader/456cf0891a7a62ceb2bbb5e4234c01e7

    Right now the strategy (as shown and reproduced from the example) with automated trading is not that important.

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    import backtrader as bt
    import datetime
    #import matplotlib
    import time 
    import pytz
    
    
    class St(bt.Strategy):
        #pr_St__class = St() #NameError: name 'St' is not defined
        #print('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pr_St__class', pr_St__class)
    
        #here he defines the structure of one record D-OHLC-V
        def logdata(self):
            txt = []
            txt.append('{}'.format(len(self))) #current object lenght of data, number of records for pricing  
            txt.append('{}'.format(self.data.datetime.datetime(0).isoformat()))
            txt.append('{:.2f}'.format(self.data.open[0]))
            txt.append('{:.2f}'.format(self.data.high[0]))
            txt.append('{:.2f}'.format(self.data.low[0]))
            txt.append('{:.2f}'.format(self.data.close[0]))
            txt.append('{:.2f}'.format(self.data.volume[0]))
            print(','.join(txt))
    
        def next(self):
            self.logdata()
    
    def run(args=None):
        cerebro = bt.Cerebro(stdstats=False) #with this i get clean data, no history. A clean structure 
        store = bt.stores.IBStore(port=7496, clientId=1001) #20200701 with TWS THIS finally worked well 
    
        data_s = store.getdata(dataname='EUR.USD-CASH-IDEALPRO', timeframe=bt.TimeFrame.Ticks,
                                        stopafter=10, #stopafter
                                        backfill_start=False, backfill=False, latethrough=True, tz='CET'
                                )
        cerebro.resampledata(data_s, timeframe=bt.TimeFrame.Seconds, compression=1)
    
        data_c = store.getdata(dataname='CHF.USD-CASH-IDEALPRO', timeframe=bt.TimeFrame.Ticks,
                                        stopafter=10, #stopafter
                                        backfill_start=False, backfill=False, latethrough=True, tz='CET'
                                )
        cerebro.resampledata(data_c, timeframe=bt.TimeFrame.Seconds, compression=1)
    
        cerebro.addstrategy(St)
    
        cerebro.run() #this will not stop,
    #    cerebro.plot(plotter=None, iplot=True) #Unfortunately I always get a lot of unneeded nformatio like platform Darwin, V 3.1.3, loaded modules, fonts
    
    
    if __name__ == '__main__':
        run()
    

    For testing purposes, if necessary, change port to 7497.
    Even with the most recent IB Gateway 978.2C the behavior is much different, compared to the well working TWS FAT Client SV: 979.4x TWS can be used, so its not an issue.

    Having used CSV samples multiple data feeds can be used.

    Unfortunately, even with the now added parameters in the code above

    (and even with testing the live data (which is not recommended)

    #DO NOT USE AS NOT RECOMMENDED
        data_s = bt.feeds.IBData(dataname='EUR.USD-CASH-IDEALPRO',
                                host='127.0.0.1', port=7496, clientId=1002,
                                        #stopafter=10,
                                        backfill_start=False, backfill=False, latethrough=True, tz='CET'
                                    )
    
        cerebro.resampledata(data_s, timeframe=bt.TimeFrame.Seconds, compression=1)
    

    I never managed to switch between the data feeds. That the question?

    Even when the 1st feed is up to date it seems cerebro is not letting it go and switching to the 2nd feed.

    Is there a solution oer where can i find some hints? Having two different programs running does not make sense as calculationsbetween the retrieved data should take place.

    When this is done, questions on

    • having an additional column for the stock name qith the records will come.
    • Also a question on whats possible with near online plotting the data.

    Regards, Klaus



  • @zkl said in IB - Switch between Multiple (Near) Online Datafeeds:

    Even when the 1st feed is up to date it seems cerebro is not letting it go and switching to the 2nd feed

    What do you mean by switching to the 2nd feed? Do you want to print the 2nd feed bars in next ? Or trading on 2nd feed?

    Basically both feeds are available in the next method. Currently you are logging only the first data. In order to log the second one the following code could probably be used:

    print(f'{self.datas[1].datetime.datetime(0).isoformat}:{self.datas[1].open[0] ....')
    


  • @vladisld said in IB - Switch between Multiple (Near) Online Datafeeds:

    print(f'{self.datas[1].datetime.datetime(0).isoformat}:{self.datas[1].open[0] ....')

    Re: "what do you mean..?" I had the impression that cerebro (ES: brain) did not collect the data for the 2nd feed.

    Your answer and your short example-hint helped a lot. I was wrong.

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    import backtrader as bt
    import datetime
    #import matplotlib
    import time 
    import pytz
    
    
    
    class St(bt.Strategy):
        #pr_St__class = St() #NameError: name 'St' is not defined
        #print('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pr_St__class', pr_St__class)
    
        #here he defines the structure of one record D-OHLC-V
        def logdata(self):
            txt = []
            txt.append('{}'.format(len(self))) #current object lenght of data, number of records for pricing  
            txt.append('    data_s') #1st datafeed
            txt.append('{}'.format(self.data.datetime.datetime(0).isoformat()))
            txt.append('{:.2f}'.format(self.data.open[0]))
            txt.append('{:.2f}'.format(self.data.high[0]))
            txt.append('{:.2f}'.format(self.data.low[0]))
            txt.append('{:.2f}'.format(self.data.close[0]))
            txt.append('{:.2f}'.format(self.data.volume[0]))
            txt.append('    data_c') #2nd datafeed
            txt.append('{}'.format(self.datas[1].datetime.datetime(0).isoformat()))
            txt.append('{:.2f}'.format(self.datas[1].open[0]))
            txt.append('{:.2f}'.format(self.datas[1].high[0]))
            txt.append('{:.2f}'.format(self.datas[1].low[0]))
            txt.append('{:.2f}'.format(self.datas[1].close[0]))
            txt.append('{:.2f}'.format(self.datas[1].volume[0]))
            print(','.join(txt))
    
        def next(self):
            self.logdata()
    
    
    def run(args=None):
        cerebro = bt.Cerebro(stdstats=False) #with this i get clean data, no history. A clean structure 
        store = bt.stores.IBStore(port=7496, clientId=1001) #20200701 with TWS THIS finally worked well 
    
        data_s = store.getdata(dataname='EUR.USD-CASH-IDEALPRO', timeframe=bt.TimeFrame.Ticks,
                                        stopafter=10, #stopafter
                                        backfill_start=False, backfill=False, latethrough=True, tz='CET'
                                )
        cerebro.resampledata(data_s, timeframe=bt.TimeFrame.Seconds, compression=1)
    
        data_c = store.getdata(dataname='CHF.USD-CASH-IDEALPRO', timeframe=bt.TimeFrame.Ticks,
                                        stopafter=10, #stopafter
                                        backfill_start=False, backfill=False, latethrough=True, tz='CET'
                                )
        cerebro.resampledata(data_c, timeframe=bt.TimeFrame.Seconds, compression=1)
    
        cerebro.addstrategy(St)
    
        cerebro.run() 
    #    cerebro.plot(plotter=None, iplot=True) #Unfortunately I always get a lot of unneeded nformatio like platform Darwin, V 3.1.3, loaded modules, fonts
    
    
    if __name__ == '__main__':
        run()
    

    Having changed the code above (based on your recommendation) now I see what data is there:

    Server Version: 76
    TWS Time at connection:20200702 22:27:13 CET
    1,    data_s,2020-07-02T22:27:14,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:27:14,1.06,1.06,1.06,1.06,0.00
    2,    data_s,2020-07-02T22:27:14,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:27:22,1.06,1.06,1.06,1.06,0.00
    3,    data_s,2020-07-02T22:27:31,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:27:22,1.06,1.06,1.06,1.06,0.00
    4,    data_s,2020-07-02T22:27:31,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:28:57,1.06,1.06,1.06,1.06,0.00
    5,    data_s,2020-07-02T22:28:58,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:28:57,1.06,1.06,1.06,1.06,0.00
    6,    data_s,2020-07-02T22:29:01,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:29:01,1.06,1.06,1.06,1.06,0.00
    7,    data_s,2020-07-02T22:29:01,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:29:08,1.06,1.06,1.06,1.06,0.00
    8,    data_s,2020-07-02T22:29:01,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:29:10,1.06,1.06,1.06,1.06,0.00
    9,    data_s,2020-07-02T22:29:01,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:29:14,1.06,1.06,1.06,1.06,0.00
    10,    data_s,2020-07-02T22:29:21,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:29:14,1.06,1.06,1.06,1.06,0.00
    11,    data_s,2020-07-02T22:29:21,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:29:25,1.06,1.06,1.06,1.06,0.00
    12,    data_s,2020-07-02T22:29:29,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:29:25,1.06,1.06,1.06,1.06,0.00
    13,    data_s,2020-07-02T22:29:37,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:29:25,1.06,1.06,1.06,1.06,0.00
    14,    data_s,2020-07-02T22:30:02,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:30:02,1.06,1.06,1.06,1.06,0.00
    15,    data_s,2020-07-02T22:30:02,1.12,1.12,1.12,1.12,0.00,    data_c,2020-07-02T22:30:07,1.06,1.06,1.06,1.06,0.00
    

    data_s is the 1st feed EUR.USD
    data_c is the 2nd feed CHF.USD

    As an outlook this is getting more interesting when displaying a stock and the corresponding option(s).

    It needs to be improved as I am using for the resampling the compression=1. Not always there is data. Increasing the compression to 10 could be a workaround. Even better when i leav it empty For now I can go ahead.

    My question is answered and solved so that i can go ahead. Thank you very much vladisld.



});