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 SMAThanks
-
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.