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

Live trading multiple strategies, each one on a separate data feed



  • I'm currently testing my strategy on a IB paper account. The scenario is that multiple instances of the same strategy should be run, each one running on its own data feed (instrument) using instrument specific parameters.

    Testing a single strategy on a single data feed works flawlessly - but once multiple strategies are added - strange things start to happen.

    The suspicious error I'm getting from IB broker:

    <error id=16777228, errorCode=420, errorMsg=Invalid Real-time Query:Historical data request pacing violation>
    

    Also no 'next' methods are called on any of the added strategies.

    Searching through the forum I found several example using multiple strategies on a single data feed or a single strategy on multiple data feeds. However it seems that my case a little bit different.

    Here my sample setup code (which doesn't work):

    for cfg in cfgs:
            datakwargs = dict(
                timeframe=cfg['timeframe'],
                compression=cfg['compression'],
                historical=False,
                fromdate=None,
                rtbar=cfg['rtbar'],
                qcheck=args.qcheck,
                what=None,  # use the default for the STK
                backfill_start=False,
                backfill=False,
                latethrough=False,
                tz=args.timezone
            )
    
            data = IBDataFactory(dataname=cfg['dataname'], **datakwargs)
            cerebro.adddata(data)
    
            # Add a strategy
            strategy_kwargs = dict(
                data_idx = data._id,
                use_lotdb=True,
                lotdb_path='some value here',
                start_price=cfg['start_price'],
                percentage=cfg['percentage'],
                lot_value=cfg['lot_value'],
                oor_gap=cfg['trailing_percentage']
            )
            cerebro.addstrategy(TestStrategy, **strategy_kwargs)
    
        cerebro.run(exactbars=args.exactbars)
    

    Here the 'cfgs' are just read from the persistent storage and specify which instrument to trade (equity) and with what parameters.

    Each strategy gets the data index as a parameter (actually the index is data._id -1 to be exact)

    Is such a scenario supported? Anything I'm doing wrong ?

    Thanks.
    Vlad



  • IB has limitations on amount of data user is able to get, and based on the error it seems that you are trying to get more data than you are allowed.

    Link - Pacing Violations for Small Bars



  • Thanks for the reply.

    As you said, the error definitely says about historical data pacing violation, however upon adding data I deliberately specifying 'historical=False' attribute (see the code above) - only live data is needed, no other indicators are added - so no waiting period. In addition the test is running using only 4 equities (which should not cause the violation AFAIU).

    Still the question remains, why no 'next' method is called on any of the strategies, even when running during the market session hours given that:

    • there is a proper data subscription with IB
    • using the _debug option for IBStore/IBBroker the real time quotes are logged correctly (the following sample log is outside the market session but the similar log is seen during the session as well)
    <realtimeBar reqId=16777229, time=1572339465, open=48.69, high=48.69, low=48.69, close=48.69, volume=0, wap=48.69, count=0>
    <realtimeBar reqId=16777235, time=1572339465, open=8.19, high=8.19, low=8.19, close=8.19, volume=0, wap=8.19, count=0>
    <realtimeBar reqId=16777217, time=1572339470, open=33.8, high=33.8, low=33.8, close=33.8, volume=0, wap=33.8, count=0>
    <realtimeBar reqId=16777219, time=1572339470, open=33.8, high=33.8, low=33.8, close=33.8, volume=0, wap=33.8, count=0>
    <realtimeBar reqId=16777222, time=1572339470, open=33.8, high=33.8, low=33.8, close=33.8, volume=0, wap=33.8, count=0>
    <realtimeBar reqId=16777226, time=1572339470, open=33.8, high=33.8, low=33.8, close=33.8, volume=0, wap=33.8, count=0>
    <realtimeBar reqId=16777231, time=1572339470, open=33.8, high=33.8, low=33.8, close=33.8, volume=0, wap=33.8, count=0>
    <realtimeBar reqId=16777229, time=1572339470, open=48.69, high=48.69, low=48.69, close=48.69, volume=0, wap=48.69, count=0>
    <realtimeBar reqId=16777224, time=1572339470, open=3.49, high=3.49, low=3.49, close=3.49, volume=0, wap=3.49, count=0>
    <realtimeBar reqId=16777233, time=1572339470, open=3.49, high=3.49, low=3.49, close=3.49, volume=0, wap=3.49, count=0>
    <realtimeBar reqId=16777235, time=1572339470, open=8.19, high=8.19, low=8.19, close=8.19, volume=0, wap=8.19, count=0>
    

    Will try to debug it further of cause.

    Thanks for help
    Vlad


  • administrators

    @vladisld said in Live trading multiple strategies, each one on a separate data feed:

    The suspicious error I'm getting from IB broker:
    <error id=16777228, errorCode=420, errorMsg=Invalid Real-time Query:Historical data request pacing violation>

    Also no 'next' methods are called on any of the added strategies.

    Because the error breaks data continuity?

    @vladisld said in Live trading multiple strategies, each one on a separate data feed:

    till the question remains, why no 'next' method is called on any of the strategies, even when running during the market session hours given that:

    • What is the warm-up period?
    • How can anyone know why your code isn't being called when no code is shown?
    • Why don't you scale down to 1 data feed, have no warm-up period and see what happens?


  • Thanks backtrader for a reply,

    First some answers to your follow up questions:

    @backtrader said in Live trading multiple strategies, each one on a separate data feed:

    What is the warm-up period?

    There is no warm-up period ( it least it should not be) - the setup code above just requests real-time bars for each data.

    @backtrader said in Live trading multiple strategies, each one on a separate data feed:

    How can anyone know why your code isn't being called when no code is shown?

    The strategy setup code is shown above - the strategy code itself if mostly standard (lets assume it just prints log)

    @backtrader said in Live trading multiple strategies, each one on a separate data feed:

    Why don't you scale down to 1 data feed, have no warm-up period and see what happens?

    As I've said at the very beginning - running just a single data feed with a single strategy works as expected.

    Now, debugging it little bit further I wonder if the following code in ibstore.py is working correctly in regard of pacing violation prevention:

        def startdatas(self):
            # kickstrat datas, not returning until all of them have been done
            ts = list()
            for data in self.datas:
                t = threading.Thread(target=data.reqdata)
                t.start()
                ts.append(t)
    
            for t in ts:
                t.join()
    

    given multiple data feeds and multiple strategies - it is called multiple times, resulting in reqRealTimeBars request sent to IB for the same contract in very short amount of time. The following stack shows the call sequence:

    startdatas, ibstore.py:402
    reconnect, ibstore.py:367
    _st_start, ibdata.py:635
    start, ibdata.py:402
    _start, feed.py:203
    runstrategies, cerebro.py:1210
    run, cerebro.py:1127
    

    Thanks,
    Vlad



  • It seems that even with a single strategy with multiple datas - the problem is still present. I've re-written my code to have a single strategy that wraps multiple strategies internally:

    class TestStrategyWrapper(bt.Strategy):
        params = (
            ('lotdb_path', ''),  # lotdb files root path
            ('cfgs', []),  # configurations to load
        )
    
        def __init__(self):
            self.strategies = []
            for cfg in self.p.cfgs:
                lotdb_path = os.path.join(self.p.lotdb_path, '{}.lot.csv'.format(cfg['dataname'].replace('-', '_')))
                # Add a strategy
                strategy_args = [cfg['data']]
                strategy_kwargs = dict(
                    use_lotdb=True,
                    lotdb_path=lotdb_path,
                    start_price=cfg['start_price'],
                    percentage=cfg['percentage'],
                    lot_value=cfg['lot_value'],
                    oor_gap=cfg['trailing_percentage']
                )
                self.strategies.append(TestStrategy(*strategy_args, **strategy_kwargs))
    
        def start(self):
            for strat in self.strategies:
                strat.start()
    
        def notify_store(self, msg, *args, **kwargs):
            self.logger.log(msg)
    
        def notify_order(self, order):
            for strat in self.strategies:
                if order.data is strat.data_feed:
                    strat.notify_order(order)
    
        def notify_trade(self, trade):
            for strat in self.strategies:
                strat.notify_trade(trade)
    
        def next(self):
            for strat in self.strategies:
                strat.next()
    

    The configuration is stored in an external csv file and, just for example, contains the startup info for 3 strategies:

    dataname,timeframe,compression,rtbar,start_price,percentage,lot_value,trailing_percentage
    FIT-STK-SMART-USD,3,5,1,0.0,0.95,10000,0.90
    NOK-STK-SMART-USD,3,5,1,0.0,0.95,10000,0.90
    MU-STK-SMART-USD,3,5,1,0.0,0.95,10000,0.90
    

    Running the above setup still produces 3 sets of REQ_REAL_TIME_BARS requests (code 50) in the TWS logs:

    0:50:30:449 -> 15-1-DU1461635-
    20:50:30:449 -> 9-1-8-
    20:50:30:449 -> 4-2--1-2107-HMDS data farm connection is inactive but should be available upon demand.ushmds-
    20:50:30:449 <- 62-
    20:50:30:449 <- 49-1-
    20:50:30:449 -> 49-1-1572807030-
    20:50:30:449 <- 6-2-1-DU1461635-
    20:50:30:465 -> 6-2-AccountCode-DU1461635--DU1461635-
    20:50:30:465 -> 6-2-AccountOrGroup-DU1461635-BASE-DU1461635-
    20:50:30:465 -> 6-2-AccountOrGroup-DU1461635-USD-DU1461635-
    20:50:30:465 -> 6-2-AccountReady-true--DU1461635-
    20:50:30:465 -> 6-2-AccountType-INDIVIDUAL--DU1461635-
    20:50:30:465 -> 6-2-AccruedCash-1142.53-BASE-DU1461635-
    20:50:30:465 -> 6-2-AccruedCash-1142.53-USD-DU1461635-
    20:50:30:465 -> 6-2-AccruedCash-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-AccruedCash-S-1142.53-USD-DU1461635-
    20:50:30:465 -> 6-2-AccruedDividend-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-AccruedDividend-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-AccruedDividend-S-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-AvailableFunds-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-AvailableFunds-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-AvailableFunds-S-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-Billable-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-Billable-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-Billable-S-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-BuyingPower-4010595.98-USD-DU1461635-
    20:50:30:465 -> 6-2-CashBalance-987870.78-BASE-DU1461635-
    20:50:30:465 -> 6-2-CashBalance-987870.78-USD-DU1461635-
    20:50:30:465 -> 6-2-CorporateBondValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-CorporateBondValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-Currency-BASE-BASE-DU1461635-
    20:50:30:465 -> 6-2-Currency-USD-USD-DU1461635-
    20:50:30:465 -> 6-2-Cushion-0.991783--DU1461635-
    20:50:30:465 -> 6-2-DayTradesRemaining--1--DU1461635-
    20:50:30:465 -> 6-2-DayTradesRemainingT+1--1--DU1461635-
    20:50:30:465 -> 6-2-DayTradesRemainingT+2--1--DU1461635-
    20:50:30:465 -> 6-2-DayTradesRemainingT+3--1--DU1461635-
    20:50:30:465 -> 6-2-DayTradesRemainingT+4--1--DU1461635-
    20:50:30:465 -> 6-2-EquityWithLoanValue-1010956.07-USD-DU1461635-
    20:50:30:465 -> 6-2-EquityWithLoanValue-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-EquityWithLoanValue-S-1010956.07-USD-DU1461635-
    20:50:30:465 -> 6-2-ExcessLiquidity-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-ExcessLiquidity-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-ExcessLiquidity-S-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-ExchangeRate-1.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-ExchangeRate-1.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullAvailableFunds-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullAvailableFunds-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullAvailableFunds-S-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullExcessLiquidity-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullExcessLiquidity-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullExcessLiquidity-S-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullInitMarginReq-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-FullInitMarginReq-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullInitMarginReq-S-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-FullMaintMarginReq-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-FullMaintMarginReq-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FullMaintMarginReq-S-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-FundValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-FundValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FutureOptionValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-FutureOptionValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FuturesPNL-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-FuturesPNL-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-FxCashBalance-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-FxCashBalance-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-GrossPositionValue-21942.76-USD-DU1461635-
    20:50:30:465 -> 6-2-GrossPositionValue-S-21942.76-USD-DU1461635-
    20:50:30:465 -> 6-2-Guarantee-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-Guarantee-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-Guarantee-S-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-IndianStockHaircut-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-IndianStockHaircut-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-IndianStockHaircut-S-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-InitMarginReq-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-InitMarginReq-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-InitMarginReq-S-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-IssuerOptionValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-IssuerOptionValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-Leverage-S-0.02--DU1461635-
    20:50:30:465 -> 6-2-LookAheadAvailableFunds-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadAvailableFunds-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadAvailableFunds-S-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadExcessLiquidity-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadExcessLiquidity-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadExcessLiquidity-S-1002649.00-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadInitMarginReq-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadInitMarginReq-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadInitMarginReq-S-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadMaintMarginReq-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadMaintMarginReq-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadMaintMarginReq-S-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-LookAheadNextChange-0--DU1461635-
    20:50:30:465 -> 6-2-MaintMarginReq-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-MaintMarginReq-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-MaintMarginReq-S-8307.08-USD-DU1461635-
    20:50:30:465 -> 6-2-MoneyMarketFundValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-MoneyMarketFundValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-MutualFundValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-MutualFundValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-NLVAndMarginInReview-false--DU1461635-
    20:50:30:465 -> 6-2-NetDividend-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-NetDividend-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-NetLiquidation-1010956.07-USD-DU1461635-
    20:50:30:465 -> 6-2-NetLiquidation-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-NetLiquidation-S-1010956.07-USD-DU1461635-
    20:50:30:465 -> 6-2-NetLiquidationByCurrency-1010956.0701-BASE-DU1461635-
    20:50:30:465 -> 6-2-NetLiquidationByCurrency-1010956.0701-USD-DU1461635-
    20:50:30:465 -> 6-2-NetLiquidationUncertainty-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-OptionMarketValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-OptionMarketValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PASharesValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PASharesValue-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PASharesValue-S-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PostExpirationExcess-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PostExpirationExcess-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PostExpirationExcess-S-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PostExpirationMargin-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PostExpirationMargin-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-PostExpirationMargin-S-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-RealCurrency-BASE-BASE-DU1461635-
    20:50:30:465 -> 6-2-RealCurrency-USD-USD-DU1461635-
    20:50:30:465 -> 6-2-RealizedPnL-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-RealizedPnL-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-RegTEquity-1010956.07-USD-DU1461635-
    20:50:30:465 -> 6-2-RegTEquity-S-1010956.07-USD-DU1461635-
    20:50:30:465 -> 6-2-RegTMargin-10971.38-USD-DU1461635-
    20:50:30:465 -> 6-2-RegTMargin-S-10971.38-USD-DU1461635-
    20:50:30:465 -> 6-2-SMA-999984.69-USD-DU1461635-
    20:50:30:465 -> 6-2-SMA-S-999984.69-USD-DU1461635-
    20:50:30:465 -> 6-2-SegmentTitle-C-US Commodities--DU1461635-
    20:50:30:465 -> 6-2-SegmentTitle-S-US Securities--DU1461635-
    20:50:30:465 -> 6-2-StockMarketValue-21942.76-BASE-DU1461635-
    20:50:30:465 -> 6-2-StockMarketValue-21942.76-USD-DU1461635-
    20:50:30:465 -> 6-2-TBillValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-TBillValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-TBondValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-TBondValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-TotalCashBalance-987870.78-BASE-DU1461635-
    20:50:30:465 -> 6-2-TotalCashBalance-987870.78-USD-DU1461635-
    20:50:30:465 -> 6-2-TotalCashValue-987870.78-USD-DU1461635-
    20:50:30:465 -> 6-2-TotalCashValue-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-TotalCashValue-S-987870.78-USD-DU1461635-
    20:50:30:465 -> 6-2-TotalDebitCardPendingCharges-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-TotalDebitCardPendingCharges-C-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-TotalDebitCardPendingCharges-S-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-TradingType-S-STKNOPT--DU1461635-
    20:50:30:465 -> 6-2-UnrealizedPnL-1912.05-BASE-DU1461635-
    20:50:30:465 -> 6-2-UnrealizedPnL-1912.05-USD-DU1461635-
    20:50:30:465 -> 6-2-WarrantValue-0.00-BASE-DU1461635-
    20:50:30:465 -> 6-2-WarrantValue-0.00-USD-DU1461635-
    20:50:30:465 -> 6-2-WhatIfPMEnabled-true--DU1461635-
    20:50:30:465 -> 7-8-197066570-FIT-STK--0-0--NYSE-USD-FIT-FIT-1694-7.0999999-12027.4-5.915-2007.39-0.0-DU1461635-
    20:50:30:465 -> 8-1-12:36-
    20:50:30:465 -> 7-8-661513-NOK-STK--0-0--NYSE-USD-NOK-NOK-2724-3.6400001-9915.36-3.675--95.34-0.0-DU1461635-
    20:50:30:465 -> 8-1-12:36-
    20:50:30:465 -> 8-1-20:48-
    20:50:30:465 -> 54-1-DU1461635-
    20:50:30:512 <- 9-7-16777216-0-FIT-STK--0---SMART-USD---0---
    20:50:30:607 -> 10-8-16777216-FIT-STK--0--SMART-USD-FIT-FIT-FIT-197066570-0.01--ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AVGCOST,BASKET,BENCHPX,COND,CONDORDER,DARKONLY,DARKPOLL,DAY,DEACT,DEACTDIS,DEACTEOD,DIS,GAT,GTC,GTD,GTT,HID,IBKRATS,ICE,IMB,IOC,LIT,LMT,LOC,MIT,MKT,MOC,MTL,NGCOMB,NODARK,NONALGO,OCA,OPG,OPGREROUT,PEGBENCH,POSTONLY,PREOPGRTH,REL,RPI,RTH,RTHIGNOPG,SCALE,SCALEODD,SCALERST,SMARTSTG,SNAPMID,SNAPMKT,SNAPREL,STP,STPLMT,SWEEP,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,WHATIF-SMART,AMEX,NYSE,CBOE,PHLX,ISE,CHX,ARCA,ISLAND,DRCTEDGE,BEX,BATS,EDGEA,CSFBALGO,JEFFALGO,BYX,IEX,EDGX,FOXRIVER,TPLUS1,NYSENAT,PSX-1-0-FITBIT INC - A-NYSE--Industrial-Electronics-Electronic Measur Instr-EST5EDT-20191103:CLOSED;20191104:0400-20191104:2000;20191105:0400-20191105:2000;20191106:0400-20191106:2000;20191107:0400-20191107:2000;20191108:0400-20191108:2000;20191109:CLOSED;20191110:CLOSED;20191111:0400-20191111:2000;20191112:0400-20191112:2000;20191113:0400-20191113:2000;20191114:0400-20191114:2000;20191115:0400-20191115:2000;20191116:CLOSED;20191117:CLOSED;20191118:0400-20191118:2000;20191119:0400-20191119:2000;20191120:0400-20191120:2000;20191121:0400-20191121:2000;20191122:0400-20191122:2000;20191123:CLOSED;20191124:CLOSED;20191125:0400-20191125:2000;20191126:0400-20191126:2000;20191127:0400-20191127:2000;20191128:0400-20191128:2000;20191129:0400-20191129:2000;20191130:CLOSED;20191201:CLOSED;20191202:0400-20191202:2000;20191203:0400-20191203:2000;20191204:0400-20191204:2000;20191205:0400-20191205:2000;20191206:0400-20191206:2000;20191207:CLOSED-20191103:CLOSED;20191104:0930-20191104:1600;20191105:0930-20191105:1600;20191106:0930-20191106:1600;20191107:0930-20191107:1600;20191108:0930-20191108:1600;20191109:CLOSED;20191110:CLOSED;20191111:0930-20191111:1600;20191112:0930-20191112:1600;20191113:0930-20191113:1600;20191114:0930-20191114:1600;20191115:0930-20191115:1600;20191116:CLOSED;20191117:CLOSED;20191118:0930-20191118:1600;20191119:0930-20191119:1600;20191120:0930-20191120:1600;20191121:0930-20191121:1600;20191122:0930-20191122:1600;20191123:CLOSED;20191124:CLOSED;20191125:0930-20191125:1600;20191126:0930-20191126:1600;20191127:0930-20191127:1600;20191128:0930-20191128:1600;20191129:0930-20191129:1600;20191130:CLOSED;20191201:CLOSED;20191202:0930-20191202:1600;20191203:0930-20191203:1600;20191204:0930-20191204:1600;20191205:0930-20191205:1600;20191206:0930-20191206:1600;20191207:CLOSED---0-
    20:50:30:607 -> 52-1-16777216-
    20:50:30:716 <- 50-2-16777217-197066570-FIT-STK--0.0---SMART-NYSE-USD-FIT-FIT-5-TRADES-0-
    20:50:30:732 <- 9-7-16777218-0-NOK-STK--0---SMART-USD---0---
    20:50:30:872 -> 10-8-16777218-NOK-STK--0--SMART-USD-NOK-NOK-NOK-661513-0.01--ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AVGCOST,BASKET,BENCHPX,COND,CONDORDER,DARKONLY,DARKPOLL,DAY,DEACT,DEACTDIS,DEACTEOD,DIS,GAT,GTC,GTD,GTT,HID,IBKRATS,ICE,IMB,IOC,LIT,LMT,LOC,MIT,MKT,MOC,MTL,NGCOMB,NODARK,NONALGO,OCA,OPG,OPGREROUT,PEGBENCH,POSTONLY,PREOPGRTH,REL,RPI,RTH,RTHIGNOPG,SCALE,SCALEODD,SCALERST,SMARTSTG,SNAPMID,SNAPMKT,SNAPREL,STP,STPLMT,SWEEP,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,WHATIF-SMART,AMEX,NYSE,CBOE,PHLX,ISE,CHX,ARCA,ISLAND,DRCTEDGE,BEX,BATS,EDGEA,CSFBALGO,JEFFALGO,BYX,IEX,EDGX,FOXRIVER,NYSENAT,PSX-1-0-NOKIA CORP-SPON ADR-NYSE--Communications-Telecommunications-Wireless Equipment-EST5EDT-20191103:CLOSED;20191104:0400-20191104:2000;20191105:0400-20191105:2000;20191106:0400-20191106:2000;20191107:0400-20191107:2000;20191108:0400-20191108:2000;20191109:CLOSED;20191110:CLOSED;20191111:0400-20191111:2000;20191112:0400-20191112:2000;20191113:0400-20191113:2000;20191114:0400-20191114:2000;20191115:0400-20191115:2000;20191116:CLOSED;20191117:CLOSED;20191118:0400-20191118:2000;20191119:0400-20191119:2000;20191120:0400-20191120:2000;20191121:0400-20191121:2000;20191122:0400-20191122:2000;20191123:CLOSED;20191124:CLOSED;20191125:0400-20191125:2000;20191126:0400-20191126:2000;20191127:0400-20191127:2000;20191128:0400-20191128:2000;20191129:0400-20191129:2000;20191130:CLOSED;20191201:CLOSED;20191202:0400-20191202:2000;20191203:0400-20191203:2000;20191204:0400-20191204:2000;20191205:0400-20191205:2000;20191206:0400-20191206:2000;20191207:CLOSED-20191103:CLOSED;20191104:0930-20191104:1600;20191105:0930-20191105:1600;20191106:0930-20191106:1600;20191107:0930-20191107:1600;20191108:0930-20191108:1600;20191109:CLOSED;20191110:CLOSED;20191111:0930-20191111:1600;20191112:0930-20191112:1600;20191113:0930-20191113:1600;20191114:0930-20191114:1600;20191115:0930-20191115:1600;20191116:CLOSED;20191117:CLOSED;20191118:0930-20191118:1600;20191119:0930-20191119:1600;20191120:0930-20191120:1600;20191121:0930-20191121:1600;20191122:0930-20191122:1600;20191123:CLOSED;20191124:CLOSED;20191125:0930-20191125:1600;20191126:0930-20191126:1600;20191127:0930-20191127:1600;20191128:0930-20191128:1600;20191129:0930-20191129:1600;20191130:CLOSED;20191201:CLOSED;20191202:0930-20191202:1600;20191203:0930-20191203:1600;20191204:0930-20191204:1600;20191205:0930-20191205:1600;20191206:0930-20191206:1600;20191207:CLOSED---0-
    20:50:30:872 -> 52-1-16777218-
    20:50:30:888 <- 50-2-16777219-197066570-FIT-STK--0.0---SMART-NYSE-USD-FIT-FIT-5-TRADES-0-
    20:50:30:888 <- 50-2-16777220-661513-NOK-STK--0.0---SMART-NYSE-USD-NOK-NOK-5-TRADES-0-
    20:50:30:888 <- 9-7-16777221-0-MU-STK--0---SMART-USD---0---
    20:50:31:107 -> 10-8-16777221-MU-STK--0--SMART-USD-MU-NMS-NMS-9939-0.01--ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AVGCOST,BASKET,BENCHPX,COND,CONDORDER,DARKONLY,DARKPOLL,DAY,DEACT,DEACTDIS,DEACTEOD,DIS,GAT,GTC,GTD,GTT,HID,IBKRATS,ICE,IMB,IOC,LIT,LMT,LOC,MIT,MKT,MOC,MTL,NGCOMB,NODARK,NONALGO,OCA,OPG,OPGREROUT,PEGBENCH,POSTONLY,PREOPGRTH,REL,RPI,RTH,SCALE,SCALEODD,SCALERST,SMARTSTG,SNAPMID,SNAPMKT,SNAPREL,STP,STPLMT,SWEEP,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,WHATIF-SMART,AMEX,NYSE,CBOE,PHLX,ISE,CHX,ARCA,ISLAND,DRCTEDGE,BEX,BATS,EDGEA,CSFBALGO,JEFFALGO,BYX,IEX,EDGX,FOXRIVER,TPLUS1,NYSENAT,PSX-1-0-MICRON TECHNOLOGY INC-NASDAQ--Technology-Semiconductors-Electronic Compo-Semicon-EST5EDT-20191103:CLOSED;20191104:0400-20191104:2000;20191105:0400-20191105:2000;20191106:0400-20191106:2000;20191107:0400-20191107:2000;20191108:0400-20191108:2000;20191109:CLOSED;20191110:CLOSED;20191111:0400-20191111:2000;20191112:0400-20191112:2000;20191113:0400-20191113:2000;20191114:0400-20191114:2000;20191115:0400-20191115:2000;20191116:CLOSED;20191117:CLOSED;20191118:0400-20191118:2000;20191119:0400-20191119:2000;20191120:0400-20191120:2000;20191121:0400-20191121:2000;20191122:0400-20191122:2000;20191123:CLOSED;20191124:CLOSED;20191125:0400-20191125:2000;20191126:0400-20191126:2000;20191127:0400-20191127:2000;20191128:0400-20191128:2000;20191129:0400-20191129:2000;20191130:CLOSED;20191201:CLOSED;20191202:0400-20191202:2000;20191203:0400-20191203:2000;20191204:0400-20191204:2000;20191205:0400-20191205:2000;20191206:0400-20191206:2000;20191207:CLOSED-20191103:CLOSED;20191104:0930-20191104:1600;20191105:0930-20191105:1600;20191106:0930-20191106:1600;20191107:0930-20191107:1600;20191108:0930-20191108:1600;20191109:CLOSED;20191110:CLOSED;20191111:0930-20191111:1600;20191112:0930-20191112:1600;20191113:0930-20191113:1600;20191114:0930-20191114:1600;20191115:0930-20191115:1600;20191116:CLOSED;20191117:CLOSED;20191118:0930-20191118:1600;20191119:0930-20191119:1600;20191120:0930-20191120:1600;20191121:0930-20191121:1600;20191122:0930-20191122:1600;20191123:CLOSED;20191124:CLOSED;20191125:0930-20191125:1600;20191126:0930-20191126:1600;20191127:0930-20191127:1600;20191128:0930-20191128:1600;20191129:0930-20191129:1600;20191130:CLOSED;20191201:CLOSED;20191202:0930-20191202:1600;20191203:0930-20191203:1600;20191204:0930-20191204:1600;20191205:0930-20191205:1600;20191206:0930-20191206:1600;20191207:CLOSED---0-
    20:50:31:107 -> 52-1-16777221-
    20:50:31:122 <- 50-2-16777222-197066570-FIT-STK--0.0---SMART-NYSE-USD-FIT-FIT-5-TRADES-0-
    20:50:31:122 <- 50-2-16777223-661513-NOK-STK--0.0---SMART-NYSE-USD-NOK-NOK-5-TRADES-0-
    20:50:31:122 <- 50-2-16777224-9939-MU-STK--0.0---SMART-NASDAQ-USD-MU-NMS-5-TRADES-0-
    20:50:31:876 -> 4-2--1-2106-HMDS data farm connection is OK:ushmds-
    20:50:32:189 -> 4-2-16777219-420-Invalid Real-time Query:Historical data request pacing violation-
    20:50:32:189 -> 4-2-16777222-420-Invalid Real-time Query:Historical data request pacing violation-
    20:50:32:189 -> 4-2-16777223-420-Invalid Real-time Query:Historical data request pacing violation-
    

    You may clearly see this by searching for the request 50. Here the relevant log records from the above:

    20:50:30:716 <- 50-2-16777217-197066570-FIT-STK--0.0---SMART-NYSE-USD-FIT-FIT-5-TRADES-0-
    20:50:30:888 <- 50-2-16777219-197066570-FIT-STK--0.0---SMART-NYSE-USD-FIT-FIT-5-TRADES-0-
    20:50:30:888 <- 50-2-16777220-661513-NOK-STK--0.0---SMART-NYSE-USD-NOK-NOK-5-TRADES-0-
    20:50:31:122 <- 50-2-16777222-197066570-FIT-STK--0.0---SMART-NYSE-USD-FIT-FIT-5-TRADES-0-
    20:50:31:122 <- 50-2-16777223-661513-NOK-STK--0.0---SMART-NYSE-USD-NOK-NOK-5-TRADES-0-
    20:50:31:122 <- 50-2-16777224-9939-MU-STK--0.0---SMART-NASDAQ-USD-MU-NMS-5-TRADES-0-
    20:50:32:189 -> 4-2-16777219-420-Invalid Real-time Query:Historical data request pacing violation-
    20:50:32:189 -> 4-2-16777222-420-Invalid Real-time Query:Historical data request pacing violation-
    20:50:32:189 -> 4-2-16777223-420-Invalid Real-time Query:Historical data request pacing violation-
    

    The violation is clear, since the request for the real-time bars for the same symbol is sent within 15 seconds.

    AFAIS, the problem is that the IBStore::startdatas (which is responsible for sending the reqRealTimeBars for all the registered datas), is called once for each separate IBData object- resulting in multiple requests for each symbol to be sent through TWS API.

    So if we are requesting data for 3 symbols (FIT,NOK,MU for example) there will be 3 calls for startdatas:

    • First one for FIT - the request will only be sent for FIT symbol obviously
    • Second one for NOK - the requests will be sent both for FIT and NOK, since datas are registered now
    • Third one for MU - the requests will be sent for all of them once again (FIT,NOK,MU).

    Which is what we see in the logs.



  • Thinking about fixing the way the data subscriptions logic is implemented, I see the following options:

    1. Each time the data subscription request is sent, issue the cancel request first (even if there were no previous subscription request sent )

    Pros:

    • pretty easy to implement, right in the IBData::reqdata probably

    Cons:

    • not sure if cancelling and re-subscribe for the same contract will not still result in pacing violation
    • doesn't address the underlying issue that allowed the multiple subscription requests to be sent for the same data in the first place
    • multiple cancellation/re-subscribing request will still be sent under current design.
    1. Maintaining the state in IBData class, indicating that subscription request was already sent. Reference this state inside the IBStore::startdatas, and only issue the subscription request for IBData objects with the above state cleared. Reset a subscription state once the connection error was reported ( or any error for that matter )

    Pros:

    • Ensures that only a single subscription request will be sent for each data, thus eliminating the cases for pacing violation

    Cons:

    • more complicated solution, involving maintaining an additional state inside the IBData objects
    • not clear whether a separate state need to be maintained for different kinds of subscriptions (historical, real time bars, delayed market data )

    Any other suggestions/comments? Will appreciate any feedback...



  • Ended up with just a small change that 'fixes' the issue for me (probably not the best fix of cause):

    diff --git a/backtrader/feeds/ibdata.py b/backtrader/feeds/ibdata.py
    index ab3c184..84cff62 100644
    --- a/backtrader/feeds/ibdata.py
    +++ b/backtrader/feeds/ibdata.py
    @@ -408,7 +408,7 @@ class IBData(with_metaclass(MetaIBData, DataBase)):
    
         def reqdata(self):
             '''request real-time data. checks cash vs non-cash) and param useRT'''
    -        if self.contract is None:
    +        if self.contract is None or self._state == self._ST_LIVE:
                 return
    
             if self._usertvol:
    

    Thanks


Log in to reply
 

});