Ejemplo n.º 1
0
 def test_level2_of(self):
     # Sample of level2. {'msgid': 21014, 'quotes': {'QJSIM¦SBER': {'lines': {'22806':
     # {'b': 234, 's': 0, 'by': 0, 'sy': 0}, '22841': {'b': 437, 's': 0, 'by': 0, 'sy': 0},
     # '22853': {'b': 60, 's': 0, 'by': 0, 'sy': 0}, '22878': {'b': 82, 's': 0, 'by': 0, 'sy': 0},
     # '22886': {'b': 138, 's': 0, 'by': 0, 'sy': 0}, '22895': {'b': 1, 's': 0, 'by': 0, 'sy': 0},...
     data = {1: {'b': 4, 's': 7, 'by': 0, 'sy': 0},
             2: {'b': 5, 's': 8, 'by': 0, 'sy': 0},
             3: {'b': 6, 's': 9, 'by': 0, 'sy': 0}}
     level2 = WebQuikFeed._level2_of(datetime(2021, 7, 23, 12, 51), Asset("code1", "sec1"), data)
     self.assertEqual(level2.dt, datetime(2021, 7, 23, 12, 51))
     self.assertEqual(level2.asset, Asset("code1", "sec1"))
     self.assertEqual([1, 2, 3], [item.price for item in level2.items])
     self.assertEqual([4, 5, 6], [item.bid_vol for item in level2.items])
     self.assertEqual([7, 8, 9], [item.ask_vol for item in level2.items])
Ejemplo n.º 2
0
 def on_trade_session_open(self, msg):
     """
     On start, trade session is opened. Now we can request data and set orders
     """
     self._logger.debug(f"Trade session opened. Requesting feeds for subscribers: {self._feed_subscribers}")
     for asset in filter(lambda a: a != Asset.any_asset(), self._feed_subscribers):
         self._request_feed(asset)
Ejemplo n.º 3
0
 def test_quote_of(self):
     data = {"bid": 1, "offer": 2, "last": 3, "lastchange": 4}
     quote = WebQuikFeed._quote_of("stock1¦asset1", data)
     self.assertIsNotNone(quote.dt)
     self.assertEqual(Asset("stock1", "asset1"), quote.asset)
     self.assertEqual(1, quote.bid)
     self.assertEqual(2, quote.ask)
     self.assertEqual(3, quote.last)
     self.assertEqual(4, quote.last_change)
Ejemplo n.º 4
0
 def _asset_of(quik_str: str) -> Optional[Asset]:
     # Example: "QJSIM¦SBER¦0", we need to streap trailing \0
     if not quik_str:
         return None
     # groups = re.search('([\\w\\d]+(?=\\|))*\\|*([\\w\\d]+)?', quik_str)
     # groups = re.match('(?P<class_code>[\\w\\d]+(?=\\|))?\\|?(?P<sec_code>[\\w\\d]+)', quik_str)
     groups = re.match('(?P<class_code>[\\w\\d]+(?=¦))?¦?(?P<sec_code>[\\w\\d]+)', quik_str)
     asset = Asset(groups["class_code"], groups["sec_code"])
     return asset
Ejemplo n.º 5
0
 def test_ohlcv_of(self):
     data = {"d": "2019-10-01 10:02:00", "o": 1, "c": 2, "h": 3, "l": 4, "v": 5}
     ohlcv = WebQuikFeed._ohlcv_of("stock1¦asset1", data)
     self.assertEqual(ohlcv.asset, Asset("stock1","asset1"))
     self.assertEqual(ohlcv.dt, datetime(2019, 10, 1, 10, 2, 0))
     self.assertEqual(ohlcv.o, 1)
     self.assertEqual(ohlcv.h, 3)
     self.assertEqual(ohlcv.l, 4)
     self.assertEqual(ohlcv.c, 2)
     self.assertEqual(ohlcv.v, 5)
Ejemplo n.º 6
0
    def _on_level2(self, data: dict):
        """
        Level 2 data handler. Quik sends us full level2 snapshot.
        """
        # Sample of level2. {'msgid': 21014, 'quotes': {'QJSIM¦SBER': {'lines': {'22806':
        # {'b': 234, 's': 0, 'by': 0, 'sy': 0}, '22841': {'b': 437, 's': 0, 'by': 0, 'sy': 0},
        # '22853': {'b': 60, 's': 0, 'by': 0, 'sy': 0}, '22878': {'b': 82, 's': 0, 'by': 0, 'sy': 0},
        # '22886': {'b': 138, 's': 0, 'by': 0, 'sy': 0}, '22895': {'b': 1, 's': 0, 'by': 0, 'sy': 0},...

        # Go through all assets in level2 message
        # Todo: get rid of nested check
        for asset_str in data['quotes']:
            # asset_class, asset_code = self._connector.asset2tuple(asset_str)
            asset = WebQuikFeed._asset_of(asset_str)
            if asset not in self._feed_subscribers:
                continue
            # {'22806':  {'b': 234, 's': 0, 'by': 0, 'sy': 0}, ..}
            level2_quik: dict = data['quotes'][asset_str]['lines']
            # level2 = {}
            # Level2(datetime.now())
            # Fill in level2 items
            items = []
            for key in level2_quik.keys():
                price = int(key)
                bid = level2_quik[key]['b']
                if bid == 0:
                    bid = None
                ask = level2_quik[key]['s']
                if ask == 0:
                    ask = None
                items.append(Level2Item(price, bid, ask))

            level2 = Level2.of(datetime.now(),asset, items)

            # If somebody subscribed to level2 of this asset, send her this data.
            subscribers = self._feed_subscribers[asset] + self._feed_subscribers[Asset.any_asset()]
            for subscriber in filter(lambda s: s.on_level2, subscribers):
                subscriber.on_level2(level2)
Ejemplo n.º 7
0
 def test_ticker_of_empty(self):
     ticker = WebQuikFeed._ticker_of(Asset("", ""))
     self.assertEqual("|", ticker)
Ejemplo n.º 8
0
 def test_ticker_of_None(self):
     ticker = WebQuikFeed._ticker_of(Asset(None, None))
     self.assertEqual("None|None", ticker)
Ejemplo n.º 9
0
 def test_ticker_of_full_asset(self):
     ticker = WebQuikFeed._ticker_of(Asset("class1", "sec1"))
     self.assertEqual("class1|sec1", ticker)
Ejemplo n.º 10
0
 def _on_quotes(self, data: dict):
     """
     Bid/ask spreads callback
     Msg sample: {"msgid":21011,"dataResult":{"CETS\u00A6BYNRUBTODTOM":{"bid":0, "ask":10, last":0,"lastchange":...
     """
     self._logger.debug('Got bid/ask quotes: %s', data)
     for quik_asset in data['dataResult'].keys():
         asset = WebQuikFeed._asset_of(quik_asset)
         if asset in self._feed_subscribers.keys():
             quote = WebQuikFeed._quote_of(quik_asset, data['dataResult'][quik_asset])
             # Send to subscriber
             for subscriber in self._feed_subscribers[asset] + self._feed_subscribers[Asset.any_asset()]:
                 subscriber.on_quote(quote)