|
18 | 18 | luld_mapping_v2, |
19 | 19 | cancel_error_mapping_v2, |
20 | 20 | correction_mapping_v2, |
| 21 | + orderbook_mapping_v2, |
21 | 22 | Trade, |
22 | 23 | Quote, |
23 | 24 | Bar, |
|
26 | 27 | CancelErrorV2, |
27 | 28 | CorrectionV2, |
28 | 29 | NewsV2, |
| 30 | + OrderbookV2, |
29 | 31 | ) |
30 | 32 |
|
31 | 33 | log = logging.getLogger(__name__) |
@@ -219,16 +221,7 @@ async def _unsubscribe(self, |
219 | 221 | bars=(), |
220 | 222 | updated_bars=(), |
221 | 223 | daily_bars=()): |
222 | | - if trades or quotes or bars or updated_bars or daily_bars: |
223 | | - await self._ws.send( |
224 | | - msgpack.packb({ |
225 | | - 'action': 'unsubscribe', |
226 | | - 'trades': trades, |
227 | | - 'quotes': quotes, |
228 | | - 'bars': bars, |
229 | | - 'updatedBars': updated_bars, |
230 | | - 'dailyBars': daily_bars, |
231 | | - })) |
| 224 | + raise NotImplementedError() |
232 | 225 |
|
233 | 226 | async def _run_forever(self): |
234 | 227 | self._loop = asyncio.get_running_loop() |
@@ -311,8 +304,9 @@ def unsubscribe_bars(self, *symbols): |
311 | 304 |
|
312 | 305 | def unsubscribe_updated_bars(self, *symbols): |
313 | 306 | if self._running: |
314 | | - asyncio.get_event_loop().run_until_complete( |
315 | | - self._unsubscribe(updated_bars=symbols)) |
| 307 | + asyncio.run_coroutine_threadsafe( |
| 308 | + self._unsubscribe(updated_bars=symbols), |
| 309 | + self._loop).result() |
316 | 310 | for symbol in symbols: |
317 | 311 | del self._handlers['updatedBars'][symbol] |
318 | 312 |
|
@@ -482,8 +476,63 @@ def __init__(self, |
482 | 476 | raw_data=raw_data, |
483 | 477 | websocket_params=websocket_params, |
484 | 478 | ) |
| 479 | + self._handlers['orderbooks'] = {} |
485 | 480 | self._name = 'crypto data' |
486 | 481 |
|
| 482 | + def _cast(self, msg_type, msg): |
| 483 | + result = super()._cast(msg_type, msg) |
| 484 | + if not self._raw_data: |
| 485 | + if msg_type == 'o': |
| 486 | + result = OrderbookV2({ |
| 487 | + orderbook_mapping_v2[k]: v |
| 488 | + for k, v in msg.items() if k in orderbook_mapping_v2 |
| 489 | + }) |
| 490 | + return result |
| 491 | + |
| 492 | + async def _dispatch(self, msg): |
| 493 | + msg_type = msg.get('T') |
| 494 | + symbol = msg.get('S') |
| 495 | + if msg_type == 'o': |
| 496 | + handler = self._handlers['orderbooks'].get( |
| 497 | + symbol, self._handlers['orderbooks'].get('*', None)) |
| 498 | + if handler: |
| 499 | + await handler(self._cast(msg_type, msg)) |
| 500 | + else: |
| 501 | + await super()._dispatch(msg) |
| 502 | + |
| 503 | + async def _unsubscribe(self, |
| 504 | + trades=(), |
| 505 | + quotes=(), |
| 506 | + orderbooks=(), |
| 507 | + bars=(), |
| 508 | + updated_bars=(), |
| 509 | + daily_bars=()): |
| 510 | + if ( |
| 511 | + trades or quotes or orderbooks or bars or updated_bars |
| 512 | + or daily_bars |
| 513 | + ): |
| 514 | + await self._ws.send( |
| 515 | + msgpack.packb({ |
| 516 | + 'action': 'unsubscribe', |
| 517 | + 'trades': trades, |
| 518 | + 'quotes': quotes, |
| 519 | + 'orderbooks': orderbooks, |
| 520 | + 'bars': bars, |
| 521 | + 'updatedBars': updated_bars, |
| 522 | + 'dailyBars': daily_bars, |
| 523 | + })) |
| 524 | + |
| 525 | + def subscribe_orderbooks(self, handler, *symbols): |
| 526 | + self._subscribe(handler, symbols, self._handlers['orderbooks']) |
| 527 | + |
| 528 | + def unsubscribe_orderbooks(self, *symbols): |
| 529 | + if self._running: |
| 530 | + asyncio.run_coroutine_threadsafe( |
| 531 | + self._unsubscribe(orderbooks=symbols), |
| 532 | + self._loop).result() |
| 533 | + for symbol in symbols: |
| 534 | + del self._handlers['orderbooks'][symbol] |
| 535 | + |
487 | 536 |
|
488 | 537 | class NewsDataStream(_DataStream): |
489 | 538 | def __init__(self, |
@@ -529,7 +578,7 @@ async def _unsubscribe(self, news=()): |
529 | 578 | if news: |
530 | 579 | await self._ws.send( |
531 | 580 | msgpack.packb({ |
532 | | - 'action': 'unsubscribe', |
| 581 | + 'action': 'unsubscribe', |
533 | 582 | 'news': news, |
534 | 583 | })) |
535 | 584 |
|
@@ -779,6 +828,9 @@ def subscribe_crypto_updated_bars(self, handler, *symbols): |
779 | 828 | def subscribe_crypto_daily_bars(self, handler, *symbols): |
780 | 829 | self._crypto_ws.subscribe_daily_bars(handler, *symbols) |
781 | 830 |
|
| 831 | + def subscribe_crypto_orderbooks(self, handler, *symbols): |
| 832 | + self._crypto_ws.subscribe_orderbooks(handler, *symbols) |
| 833 | + |
782 | 834 | def subscribe_news(self, handler, *symbols): |
783 | 835 | self._news_ws.subscribe_news(handler, *symbols) |
784 | 836 |
|
@@ -842,7 +894,7 @@ def decorator(func): |
842 | 894 |
|
843 | 895 | return decorator |
844 | 896 |
|
845 | | - def on_corrections(self, *symbols): |
| 897 | + def on_correction(self, *symbols): |
846 | 898 | def decorator(func): |
847 | 899 | self._data_ws.register_handler("corrections", func, *symbols) |
848 | 900 | return func |
@@ -884,6 +936,13 @@ def decorator(func): |
884 | 936 |
|
885 | 937 | return decorator |
886 | 938 |
|
| 939 | + def on_crypto_orderbook(self, *symbols): |
| 940 | + def decorator(func): |
| 941 | + self.subscribe_crypto_orderbooks(func, *symbols) |
| 942 | + return func |
| 943 | + |
| 944 | + return decorator |
| 945 | + |
887 | 946 | def on_news(self, *symbols): |
888 | 947 | def decorator(func): |
889 | 948 | self.subscribe_news(func, *symbols) |
@@ -929,6 +988,9 @@ def unsubscribe_crypto_updated_bars(self, *symbols): |
929 | 988 | def unsubscribe_crypto_daily_bars(self, *symbols): |
930 | 989 | self._crypto_ws.unsubscribe_daily_bars(*symbols) |
931 | 990 |
|
| 991 | + def unsubscribe_crypto_orderbooks(self, *symbols): |
| 992 | + self._crypto_ws.unsubscribe_orderbooks(*symbols) |
| 993 | + |
932 | 994 | def unsubscribe_news(self, *symbols): |
933 | 995 | self._news_ws.unsubscribe_news(*symbols) |
934 | 996 |
|
|
0 commit comments