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 Data Feed



  • Hi,
    I have a custom live data feed that is listening data from WebSocket.
    If I have timeframe as Daily, with the last bar is Today, when I have a new tick, how can I update the value of the Daily last bar
    If I try to update via self.lines then I will add one more data into the list and make wrong calculation for SMA

    Thanks



  • I can provide an example of myself

    import _thread
    from datetime import datetime
    import time
    import backtrader as bt
    from backtrader import date2num
    from backtrader.feeds import DataBase
    
    
    class LiveDataStream(DataBase):
    
        def __init__(self):
            self.isOpen = True
            self.i = 0
            _thread.start_new_thread(self._timerstart, (1,))
    
        def start(self):
            super(LiveDataStream, self).start()
    
        def _timerstart(self, n):
            while True:
                if self.isOpen == False:
                    self.isOpen = True
                time.sleep(n)
    
        def _load(self):
            if self.isOpen == True:
                # print(self.i)
                self.i += 1
                self.lines.datetime[0] = date2num(datetime.now())
                # Get the rest of the unpacked data
                self.lines.open[0] = 100 + self.i
                self.lines.high[0] = 120 + self.i
                self.lines.low[0] = 80 + self.i
                self.lines.close[0] = 90 + self.i
                self.lines.volume[0] = 2342 + self.i
                self.lines.openinterest[0] = 443 + self.i
                self.isOpen = False
                return True
            else:
                return None
    
        def islive(self):
            '''Returns ``True`` to notify ``Cerebro`` that preloading and runonce
            should be deactivated'''
            return True
    
        def stop(self):
            '''Stops and tells the store to stop'''
            super().stop()
    
    
    class MyStrategy(bt.Strategy):
        def __init__(self):
            pass
    
        def next(self):
            print('{} -- {} -- {}'.format(self.data.open[0], self.data.high[0], self.data.close[0]))
    
        def notify_data(self, data, status, *args, **kwargs):
            if status == data.LIVE:
                print("live data")
            elif status == data.DELAYED:
                print("DELAYED data")
    
    
    cerebro = bt.Cerebro()
    cerebro.addstrategy(MyStrategy)
    cerebro.adddata(LiveDataStream())
    cerebro.run()
    cerebro.plot()
    print("over")
    
    


  • @Xu-Liu emmm, ‘return None return’ None should be changed ‘continue’



  • Hey @Xu-Liu

    Thanks for the example. Using your example and by reading other posts in this forum I could get it started, but unable to get it to work correctly so far. I certainly see that price information is correctly streaming. But I cant feed this in to BT. My class is the following.

    class BrokerFeed(DataBase):
    
        params = (('dataname', None),
            # ('fromdate', datetime.datetime.min),
            # ('todate', datetime.datetime.max),
            ('name', ''),
            ('compression', 1),
            ('timeframe', TimeFrame.Ticks),
            ('sessionend', None),
            )
    
        def __init__(self, user_data, access_data, scrip_code):
    
            self.ws = broker_ws(user_data, access_data)
            self.scrip_code = scrip_code
            self.price = None
            
        def start(self):
        
            self.ws.on_ticks = self.on_price
            self.ws.on_connect = self.on_join
            self.ws.connect()
    
        def on_join(self, ws, response):
    
            self.ws.subscribe([self.scrip_code])
            self.ws.set_mode(ws.MODE_FULL, [self.scrip_code])
    
        def on_price(self, ws, price):
    
            self.price = price
            self._load()
    
        def _load(self):
            price = self.price
    
            t = price[0]['timestamp']
            o = price[0]['ohlc']['open']
            h = price[0]['ohlc']['high']
            l = price[0]['ohlc']['low']
            c = price[0]['ohlc']['close']
            v = price[0]['volume']
            oi = price[0]['oi'] 
            print (t,o,h,l,c,v,oi )
    
            dt = bt.date2num (t)
            
            # self.lines.datetime[0] = dt
            # self.lines.open[0] = o
            # self.lines.high[0] = h
            # self.lines.low[0] = l
            # self.lines.close[0] = c
            # self.lines.volume[0] = v
    
            return True
    
        def haslivedata(self):
             return True  # must be overriden for those that can
    
        def islive(self):
            return True
    
    data = BrokerFeed(user_data, access_data, scrip_code = 10567, timeframe=bt.TimeFrame.Ticks, compression=1 ).start()
    cerebro.adddata(data)
    

    Above class receives the data and print ( using print (t,o,h,l,c,v,oi ) in _load() ) the candles correctly as shown below.

    (base) GRACE:>>[516] python /Users/prabu/python/BT/BT_feed_test.py
    2020-11-20 09:50:41 3129.0 3129.0 3097.0 3093.0 18596 3020
    2020-11-20 09:50:42 3129.0 3129.0 3097.0 3093.0 18596 3020
    2020-11-20 09:50:42 3129.0 3129.0 3097.0 3093.0 18596 3020
    2020-11-20 09:50:43 3129.0 3129.0 3097.0 3093.0 18597 3021
    2020-11-20 09:50:44 3129.0 3129.0 3097.0 3093.0 18597 3021
    2020-11-20 09:50:44 3129.0 3129.0 3097.0 3093.0 18597 3021
    2020-11-20 09:50:45 3129.0 3129.0 3097.0 3093.0 18598 3021
    2020-11-20 09:50:47 3129.0 3129.0 3097.0 3093.0 18598 3021
    2020-11-20 09:50:48 3129.0 3129.0 3097.0 3093.0 18598 3021
    2020-11-20 09:50:48 3129.0 3129.0 3097.0 3093.0 18598 3021
    2020-11-20 09:50:48 3129.0 3129.0 3097.0 3093.0 18599 3022
    2020-11-20 09:50:49 3129.0 3129.0 3097.0 3093.0 18600 3022
    2020-11-20 09:50:50 3129.0 3129.0 3097.0 3093.0 18600 3022
    2020-11-20 09:50:50 3129.0 3129.0 3097.0 3093.0 18631 3009
    2020-11-20 09:50:51 3129.0 3129.0 3097.0 3093.0 18632 3009
    

    But when I try to load the data to the BT by removing the comment marks before the following lines in _load(self)

            self.lines.datetime[0] = dt
            self.lines.open[0] = o
            self.lines.high[0] = h
            self.lines.low[0] = l
            self.lines.close[0] = c
            self.lines.volume[0] = v
    

    I get the following error

    File "/Users/prabu/python/BT/BT_feed_test.py", line 47, in on_price
        self._load()
      File "/Users/prabu/python/BT/BT_feed_test.py", line 63, in _load
        self.lines.datetime[0] = dt
      File "/Users/prabu/opt/anaconda3/lib/python3.8/site-packages/backtrader/linebuffer.py", line 222, in __setitem__
        self.array[self.idx + ago] = value
    builtins.IndexError: array assignment index out of range
    

    I followed the example in Backtrader Binary data feed tutorial as well as the cctx thread @Ed-Bartosh example but couldn't make it to work. It could be my lack of OOP/decorators knowledge. Any advice would be very helpful. Thank in advance for your time and help.


Log in to reply
 

});