hyperquant 0.4__py3-none-any.whl → 0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,19 +22,20 @@ class Book(DataStore):
22
22
  Channel: push.depth.step
23
23
 
24
24
  用于存储和管理订单簿深度数据,包含买卖盘的价格和数量信息
25
- Keys: ["symbol", "side", "px"]
26
- - symbol: 交易对符号
27
- - side: 买卖方向 (A: ask卖出, B: bid买入)
28
- - px: 价格
25
+ Keys: ["s", "S", "p"]
26
+ - s: 交易对符号
27
+ - S: 买卖方向 (A: ask卖出, B: bid买入)
28
+ - p: 价格
29
29
 
30
30
 
31
31
  """
32
32
 
33
- _KEYS = ["symbol", "side", "i"]
33
+ _KEYS = ["s", "S", "p"]
34
34
 
35
35
  def _init(self) -> None:
36
36
  # super().__init__()
37
37
  self._time: int | None = None
38
+ self.limit = 1
38
39
 
39
40
  def _on_message(self, msg: dict[str, Any]) -> None:
40
41
 
@@ -43,29 +44,29 @@ class Book(DataStore):
43
44
  asks = data.get("asks", [])
44
45
  bids = data.get("bids", [])
45
46
  # 提速 默认 5当前
46
- asks = asks[:5]
47
- bids = bids[:5]
47
+ asks = asks[:self.limit]
48
+ bids = bids[:self.limit]
48
49
 
49
50
  timestamp = data.get("ct") # 使用服务器时间
50
51
 
51
52
  data_to_insert: list[Item] = []
52
53
 
53
54
  # 先删除旧的订单簿数据
54
- self._find_and_delete({"symbol": symbol})
55
+ self._find_and_delete({"s": symbol})
55
56
 
56
57
  # 处理买卖盘数据
57
- for side_id, levels in (("B", bids), ("A", asks)):
58
+ for side_id, levels in (("b", bids), ("a", asks)):
58
59
  for i, level in enumerate(levels):
59
60
  # level格式: [price, size, count]
60
61
  if len(level) >= 3:
61
62
  price, size, count = level[0:3]
62
63
  data_to_insert.append(
63
64
  {
64
- "symbol": symbol,
65
- "side": side_id,
66
- "px": str(price),
67
- "sz": str(size),
68
- "count": count,
65
+ "s": symbol,
66
+ "S": side_id,
67
+ "p": str(price),
68
+ "q": str(size),
69
+ "ct": count,
69
70
  "i": i
70
71
  }
71
72
  )
@@ -79,31 +80,17 @@ class Book(DataStore):
79
80
  """返回最后更新时间"""
80
81
  return self._time
81
82
 
82
- @property
83
- def sorted(self) -> dict[str, list[Item]]:
84
- """获取排序后的订单簿数据
85
-
86
- Returns:
87
- 返回按价格排序的买卖盘数据,卖盘升序,买盘降序
88
-
89
- .. code-block:: python
83
+ def sorted(
84
+ self, query: Item | None = None, limit: int | None = None
85
+ ) -> dict[str, list[Item]]:
90
86
 
91
- {
92
- "asks": [
93
- {"symbol": "BTC_USDT", "side": "A", "px": "110152.5", "sz": "53539", "count": 1},
94
- {"symbol": "BTC_USDT", "side": "A", "px": "110152.6", "sz": "95513", "count": 2}
95
- ],
96
- "bids": [
97
- {"symbol": "BTC_USDT", "side": "B", "px": "110152.4", "sz": "76311", "count": 1},
98
- {"symbol": "BTC_USDT", "side": "B", "px": "110152.3", "sz": "104688", "count": 2}
99
- ]
100
- }
101
- """
102
87
  return self._sorted(
103
- item_key="side",
104
- item_asc_key="A", # asks 升序
105
- item_desc_key="B", # bids 降序
106
- sort_key="px",
88
+ item_key="S",
89
+ item_asc_key="a", # asks 升序
90
+ item_desc_key="b", # bids 降序
91
+ sort_key="p",
92
+ query=query,
93
+ limit=limit,
107
94
  )
108
95
 
109
96
 
@@ -146,15 +133,19 @@ class Orders(DataStore):
146
133
  def _fmt(self, order:dict):
147
134
  return {
148
135
  "order_id": order.get("orderId"),
136
+ "position_id": order.get("positionId"),
149
137
  "symbol": order.get("symbol"),
150
- "px": order.get("price"),
138
+ "price": order.get("price"),
151
139
  "vol": order.get("vol"),
152
140
  "lev": order.get("leverage"),
153
141
  "side": "buy" if order.get("side") == 1 else "sell",
154
- "deal_vol": order.get("dealVol"),
155
- "deal_avg_px": order.get("dealAvgPrice"),
142
+ "deal_quantity": order.get("dealVol"),
143
+ "avg_price": order.get("dealAvgPrice"),
156
144
  "create_ts": order.get("createTime"),
157
145
  "update_ts": order.get("updateTime"),
146
+ "fee": order.get("makerFee"),
147
+ "profit": order.get("profit"),
148
+ "used_margin": order.get("usedMargin"),
158
149
  "state": "open"
159
150
  }
160
151
 
@@ -192,6 +183,13 @@ class Orders(DataStore):
192
183
  self._find_and_delete({
193
184
  "order_id": order.get("order_id")
194
185
  })
186
+ else:
187
+ order = self._fmt(data)
188
+ order["state"] = f"unknown_{state}"
189
+ self._update([order])
190
+ self._find_and_delete({
191
+ "order_id": order.get("order_id")
192
+ })
195
193
 
196
194
  class Detail(DataStore):
197
195
  _KEYS = ["symbol"]
@@ -214,7 +212,8 @@ class Detail(DataStore):
214
212
  "io": detail.get("io"),
215
213
  "contract_sz": detail.get("cs"),
216
214
  "minv": detail.get("minV"),
217
- "maxv": detail.get("maxV")
215
+ "maxv": detail.get("maxV"),
216
+ "online_time": detail.get("tcd")
218
217
  }
219
218
  )
220
219
  self._update(data_to_insert)
@@ -225,27 +224,27 @@ class Position(DataStore):
225
224
 
226
225
  def _fmt(self, position:dict):
227
226
  return {
228
- "position_id": position.get("positionId"),
229
- "symbol": position.get("symbol"),
230
- "side": "short" if position.get("positionType") == 2 else "long",
231
- "open_type": position.get("openType"),
232
- "state": position.get("state"),
233
- "hold_vol": position.get("holdVol"),
234
- "frozen_vol": position.get("frozenVol"),
235
- "close_vol": position.get("closeVol"),
236
- "hold_avg_price": position.get("holdAvgPriceFullyScale"),
237
- "open_avg_price": position.get("openAvgPriceFullyScale"),
238
- "close_avg_price": str(position.get("closeAvgPrice")),
239
- "liquidate_price": str(position.get("liquidatePrice")),
240
- "oim": position.get("oim"),
241
- "im": position.get("im"),
242
- "hold_fee": position.get("holdFee"),
243
- "realised": position.get("realised"),
244
- "leverage": position.get("leverage"),
245
- "margin_ratio": position.get("marginRatio"),
246
- "create_ts": position.get("createTime"),
247
- "update_ts": position.get("updateTime"),
248
- }
227
+ "position_id": position.get("positionId"),
228
+ "symbol": position.get("symbol"),
229
+ "side": "short" if position.get("positionType") == 2 else "long",
230
+ "open_type": position.get("openType"),
231
+ "state": position.get("state"),
232
+ "hold_vol": position.get("holdVol"),
233
+ "frozen_vol": position.get("frozenVol"),
234
+ "close_vol": position.get("closeVol"),
235
+ "hold_avg_price": position.get("holdAvgPriceFullyScale"),
236
+ "open_avg_price": position.get("openAvgPriceFullyScale"),
237
+ "close_avg_price": str(position.get("closeAvgPrice")),
238
+ "liquidate_price": str(position.get("liquidatePrice")),
239
+ "oim": position.get("oim"),
240
+ "im": position.get("im"),
241
+ "hold_fee": position.get("holdFee"),
242
+ "realised": position.get("realised"),
243
+ "leverage": position.get("leverage"),
244
+ "margin_ratio": position.get("marginRatio"),
245
+ "create_ts": position.get("createTime"),
246
+ "update_ts": position.get("updateTime"),
247
+ }
249
248
 
250
249
  def _onresponse(self, data: dict[str, Any]):
251
250
  positions = data.get("data", [])
@@ -405,8 +404,8 @@ class OurbitSwapDataStore(DataStoreCollection):
405
404
  "io": ["binance", "mexc"], # 交易所列表
406
405
  "contract_sz": 1,
407
406
  "minv": 1,
408
- "maxv": 10000
409
-
407
+ "maxv": 10000,
408
+ "online_time": 1625247600000 # 上线时间
410
409
  }
411
410
  ]
412
411
  """
@@ -415,32 +414,37 @@ class OurbitSwapDataStore(DataStoreCollection):
415
414
  @property
416
415
  def book(self) -> Book:
417
416
  """订单簿深度数据流
418
-
417
+
418
+ 提供实时订单簿深度数据,包含买卖双方价格和数量信息
419
+
419
420
  Data type: Mutable
420
-
421
- Keys: ("symbol", "side", "px")
421
+
422
+ Keys: ("s", "S", "p")
423
+ - s: 交易对符号,如 "BTC_USDT"
424
+ - S: 买卖方向,"a" 表示卖单(ask),"b" 表示买单(bid)
425
+ - p: 价格
422
426
 
423
427
  Data structure:
424
428
 
425
429
  .. code:: python
426
430
 
427
431
  [
428
- {
429
- "symbol": "BTC_USDT", # 交易对
430
- "side": "A", # 卖出方向
431
- "px": "110152.5", # 价格
432
- "sz": "53539", # 数量
433
- "count": 1 # 订单数量
434
- "i" 0 # 价格档位索引
435
- },
436
- {
437
- "symbol": "BTC_USDT", # 交易对
438
- "side": "B", # 买入方向
439
- "px": "110152.4", # 价格
440
- "sz": "76311", # 数量
441
- "count": 1 # 订单数量
442
- "i" 0 # 价格档位索引
443
- }
432
+ {
433
+ "s": "BTC_USDT", # 交易对符号
434
+ "S": "a", # 卖单方向(ask)
435
+ "p": "110152.5", # 价格
436
+ "q": "53539", # 数量
437
+ "ct": 1, # 该价格的订单数量
438
+ "i": 0 # 价格档位索引(从0开始)
439
+ },
440
+ {
441
+ "s": "BTC_USDT", # 交易对符号
442
+ "S": "b", # 买单方向(bid)
443
+ "p": "110152.4", # 价格
444
+ "q": "76311", # 数量
445
+ "ct": 1, # 该价格的订单数量
446
+ "i": 0 # 价格档位索引(从0开始)
447
+ }
444
448
  ]
445
449
  """
446
450
  return self._get("book", Book)
@@ -592,7 +596,11 @@ class SpotBalance(DataStore):
592
596
  def _on_message(self, msg: dict[str, Any]) -> None:
593
597
  data = msg.get("d", {})
594
598
  item = self._fmt_ws(data)
595
- self._update([item])
599
+ av = float(item.get("available", 0))
600
+ if av == 0:
601
+ self._find_and_delete({'currency': item.get("currency")})
602
+ else:
603
+ self._update([item])
596
604
 
597
605
 
598
606
  # SpotOrders: 现货订单数据存储
@@ -601,17 +609,22 @@ class SpotOrders(DataStore):
601
609
 
602
610
 
603
611
  def _fmt(self, order: dict) -> dict:
604
- state = order.get("state")
605
- if state == 1 or state == 2:
606
- state = "open"
607
- elif state == 3:
608
- state = "filled"
609
- elif state == 4:
610
- state = "canceled"
612
+ # 状态映射:1=open, 2=filled(整单成交), 3=partially_filled, 4=canceled
613
+ state_num = order.get("state") or order.get("status")
614
+ if state_num == 1:
615
+ state_txt = "open"
616
+ elif state_num == 2:
617
+ state_txt = "filled" # ✔ 2 才是整单成交
618
+ elif state_num == 3:
619
+ state_txt = "partially_filled"
620
+ elif state_num == 4:
621
+ state_txt = "canceled"
622
+ else:
623
+ state_txt = "unknown"
611
624
 
612
625
  return {
613
- "order_id": order.get("id"),
614
- "symbol": order.get("symbol"),
626
+ "order_id": order.get("id") or order.get("orderId"),
627
+ "symbol": order.get("symbol") or order.get("s"),
615
628
  "currency": order.get("currency"),
616
629
  "market": order.get("market"),
617
630
  "trade_type": order.get("tradeType"),
@@ -622,15 +635,14 @@ class SpotOrders(DataStore):
622
635
  "deal_quantity": order.get("dealQuantity"),
623
636
  "deal_amount": order.get("dealAmount"),
624
637
  "avg_price": order.get("avgPrice"),
625
- "state": order.get("state"),
626
- "source": order.get("source"),
638
+ "state": state_txt,
639
+ "source": order.get("source") or order.get("internal"),
627
640
  "fee": order.get("fee"),
628
641
  "create_ts": order.get("createTime"),
629
642
  "unique_id": order.get("uniqueId"),
630
643
  }
631
644
 
632
645
 
633
-
634
646
  def _onresponse(self, data: dict[str, Any]):
635
647
  orders = (data.get("data") or {}).get("resultList", [])
636
648
  items = [self._fmt(order) for order in orders]
@@ -639,9 +651,9 @@ class SpotOrders(DataStore):
639
651
  self._insert(items)
640
652
 
641
653
  def _on_message(self, msg: dict[str, Any]) -> None:
642
- d:dict = msg.get("d", {})
654
+ d: dict = msg.get("d", {})
643
655
 
644
-
656
+ # 基础字段
645
657
  item = {
646
658
  "order_id": d.get("id"),
647
659
  "symbol": msg.get("s") or d.get("symbol"),
@@ -652,7 +664,6 @@ class SpotOrders(DataStore):
652
664
  "amount": d.get("amount"),
653
665
  "remain_quantity": d.get("remainQ"),
654
666
  "remain_amount": d.get("remainA"),
655
- "state": d.get("status"),
656
667
  "client_order_id": d.get("clientOrderId"),
657
668
  "is_taker": d.get("isTaker"),
658
669
  "create_ts": d.get("createTime"),
@@ -661,28 +672,78 @@ class SpotOrders(DataStore):
661
672
 
662
673
  state = d.get("status")
663
674
 
664
- if state == 2 or state == 1:
665
- item["state"] = "open"
666
- self._insert([item])
667
-
668
- elif state == 3:
669
- item["state"] = "filled"
670
-
671
- # 如果这三个字段存在追加
672
- if d.get("singleDealId") and d.get("singleDealPrice") and d.get("singleDealQuantity"):
673
- item.update({
674
- "unique_id": d.get("singleDealId"),
675
- "avg_price": d.get("singleDealPrice"),
676
- "deal_quantity": d.get("singleDealQuantity"),
677
- })
678
675
 
679
- self._update([item])
680
- self._find_and_delete({ "order_id": d.get("id") })
681
-
682
- elif state == 4:
683
- item["state"] = "canceled"
676
+
677
+ # 成交片段(部分/完全)
678
+ if d.get("singleDealPrice"):
679
+ # 单片段信息(可能多次推送;需做增量累计 + 去重)
680
+ single_id = d.get("singleDealId")
681
+ single_px = d.get("singleDealPrice")
682
+ single_qty = d.get("singleDealQuantity")
683
+ try:
684
+ px_i = float(single_px) if single_px is not None else 0.0
685
+ qty_i = float(single_qty) if single_qty is not None else 0.0
686
+ except Exception:
687
+ px_i, qty_i = 0.0, 0.0
688
+
689
+ old = self.get({"order_id": d.get("id")})
690
+ old_qty = float(old.get("deal_quantity") or 0.0) if old else 0.0
691
+ old_avg = float(old.get("avg_price") or 0.0) if old else 0.0
692
+ old_last_single = old.get("last_single_id") if old else None
693
+
694
+ # 去重:若与上一片段 ID 相同,认为是重复推送,直接按状态更新不累计
695
+ if old and single_id and old_last_single == single_id:
696
+ new_qty = old_qty
697
+ new_avg = old_avg
698
+ else:
699
+ # VWAP 累计
700
+ new_qty = old_qty + qty_i
701
+ if new_qty > 0:
702
+ new_avg = (old_avg * old_qty + px_i * qty_i) / new_qty
703
+ else:
704
+ new_avg = px_i
705
+
706
+ # 写回
707
+ item.update({
708
+ "avg_price": str(new_avg) if new_qty > 0 else old.get("avg_price") if old else None,
709
+ "deal_quantity": str(new_qty) if new_qty > 0 else old.get("deal_quantity") if old else None,
710
+ "single_id": single_id,
711
+ "last_single_id": single_id,
712
+ })
713
+
714
+ # 状态文本:2=filled(整单), 3=partially_filled
715
+ # item["state"] = "filled" if state == 2 else "partially_filled"
716
+ if state == 2:
717
+ item["state"] = "filled"
718
+ elif state == 3:
719
+ item["state"] = "partially_filled"
720
+ else:
721
+ item["state"] = "unknown_"+str(state)
722
+
684
723
  self._update([item])
685
- self._find_and_delete({ "order_id": d.get("id") })
724
+
725
+ # 整单成交 或者 部分取消 → 删除
726
+ if state == 2 or 'unknown' in item["state"]:
727
+ self._find_and_delete({"order_id": d.get("id")})
728
+ return
729
+ else:
730
+ # 新建 / 已挂出
731
+ if state == 1:
732
+ item["state"] = "open"
733
+ self._insert([item])
734
+ return
735
+
736
+ elif state == 4:
737
+ item["state"] = "canceled"
738
+ self._update([item])
739
+ self._find_and_delete({"order_id": d.get("id")})
740
+ return
741
+ else:
742
+
743
+ # 未知状态:更新后删除,避免脏数据残留
744
+ item["state"] = "unknown_"+str(state)
745
+ self._update([item])
746
+ self._find_and_delete({"order_id": d.get("id")})
686
747
 
687
748
 
688
749
 
@@ -693,69 +754,110 @@ class SpotBook(DataStore):
693
754
  # super().__init__()
694
755
  self._time: int | None = None
695
756
  self.limit = 1
757
+ self.loss = {} # 改为字典,按symbol跟踪
758
+ self.versions = {}
759
+ self.cache = []
696
760
 
697
761
  def _onresponse(self, data: dict[str, Any]):
762
+ data = data.get("data")
763
+ symbol = data.get("symbol")
764
+ book_data = data.get("data")
765
+ asks = book_data.get("asks", [])
766
+ bids = book_data.get("bids", [])
767
+ version = int(data.get("version", None))
698
768
 
699
- top = data.get("data") or data.get("d") or data
700
- symbol = (
701
- top.get("s")
702
- or top.get("symbol")
703
- or (top.get("data") or {}).get("symbol")
704
- )
705
769
 
706
- inner = top.get("data") or top
707
- asks = inner.get("asks") or []
708
- bids = inner.get("bids") or []
709
-
710
- items: list[Item] = []
711
- if symbol:
712
- # Snapshot semantics: rebuild entries for this symbol
713
- self._find_and_delete({"s": symbol})
714
-
715
- def extract_pq(level: Any) -> tuple[Any, Any] | None:
716
- # Accept dict {"p": x, "q": y} or list/tuple [p, q, ...]
717
- if isinstance(level, dict):
718
- p = level.get("p")
719
- q = level.get("q")
720
- return (p, q)
721
- if isinstance(level, (list, tuple)) and len(level) >= 2:
722
- return (level[0], level[1])
723
- return None
770
+ # 保存当前快照版本
771
+ self.versions[symbol] = version
772
+
773
+ # # 应用缓存的增量(只保留连续的部分)
774
+ # items: list = self.find({"s": symbol})
775
+ # items.sort(key=lambda x: x.get("fv", 0)) # 按 fromVersion 排序
776
+ # self._find_and_delete({"s": symbol})
777
+
778
+ # 应为我们先连接的ws, 所以可能有缓存需要去处理
779
+ items = [item for item in self.cache if item.get("s") == symbol]
780
+ items.sort(key=lambda x: x.get("fv", 0)) # fromVersion 排序
781
+ self.cache = [item for item in self.cache if item.get("s") != symbol]
724
782
 
725
783
  for side, S in ((asks, "a"), (bids, "b")):
726
- for level in side:
727
- pq = extract_pq(level)
728
- if not pq:
729
- continue
730
- p, q = pq
731
- if p is None or q is None:
732
- continue
733
- try:
734
- if float(q) == 0.0:
735
- continue
736
- except (TypeError, ValueError):
737
- continue
738
- items.append({"s": symbol, "S": S, "p": p, "q": q})
784
+ for item in side:
785
+ self._insert([{"s": symbol, "S": S, "p": item["p"], "q": item["q"]}])
739
786
 
740
787
  if items:
741
- self._insert(items)
742
-
743
- sort_data = self.sorted({'s': symbol}, self.limit)
744
- asks = sort_data.get('a', [])
745
- bids = sort_data.get('b', [])
746
- self._find_and_delete({'s': symbol})
747
- self._update(asks + bids)
748
-
788
+ min_version = min(item.get("fv", 0) for item in items)
789
+ max_version = max(item.get("tv", 0) for item in items)
790
+ # self.version = max_version
791
+ self.versions[symbol] = max_version
792
+
793
+ # if max_version == 0:
794
+ # print('vvv---')
795
+ # print(items)
796
+
797
+ if not (min_version <= self.versions[symbol] <= max_version):
798
+ self.loss[symbol] = True
799
+ logger.warning(f"SpotBook: Snapshot version {self.version} out of range ({min_version}, {max_version}) for symbol={symbol} (丢补丁)")
800
+ return
801
+
802
+ # 处理过往msg内容
803
+ self.loss[symbol] = False
804
+ for item in items:
805
+ fv, tv = item.get("fv", 0), item.get("tv", 0)
806
+ if self.versions[symbol] <= tv and self.versions[symbol] >= fv:
807
+ if float(item["q"]) == 0.0:
808
+ self._find_and_delete({"s": symbol, "S": item["S"], "p": item["p"]})
809
+ else:
810
+ self._insert([{ "s": symbol, "S": item["S"], "p": item["p"], "q": item["q"]}])
811
+
812
+ sort_data = self.sorted({'s': symbol}, self.limit)
813
+ asks = sort_data.get('a', [])
814
+ bids = sort_data.get('b', [])
815
+ self._find_and_delete({'s': symbol})
816
+ self._update(asks + bids)
817
+
818
+ else:
819
+ self.loss[symbol] = False
749
820
 
750
821
 
751
822
  def _on_message(self, msg: dict[str, Any]) -> None:
752
- ts = time.time() * 1000 # 预留时间戳(如需记录可用)
823
+
824
+ # ts = time.time() * 1000 # 预留时间戳(如需记录可用)
753
825
  data = msg.get("d", {}) or {}
754
826
  symbol = msg.get("s")
755
-
827
+ fv = int(data.get("fromVersion"))
828
+ tv = int(data.get("toVersion"))
829
+ if fv == 0 or tv == 0:
830
+ # print(f'发现fv或tv为0, msg:\n {msg}')
831
+ return
832
+
756
833
  asks: list = data.get("asks", []) or []
757
834
  bids: list = data.get("bids", []) or []
758
835
 
836
+ now_version = self.versions.get(symbol, None)
837
+
838
+ # 以下几张情况都会被认为正常
839
+ check_con = (
840
+ now_version is None or
841
+ fv <= now_version <= tv or
842
+ now_version + 1 == fv
843
+ )
844
+
845
+ if not check_con:
846
+ # logger.warning(f"(丢补丁) version:{now_version} fv:{fv} tv:{tv} ")
847
+ self.loss[symbol] = True # 暂时不这样做
848
+
849
+
850
+
851
+ if self.loss.get(symbol, True):
852
+ for item in asks:
853
+ self.cache.append({"s": symbol, "S": "a", "p": item["p"], "q": item["q"], "fv": fv, "tv": tv})
854
+ for item in bids:
855
+ self.cache.append({"s": symbol, "S": "b", "p": item["p"], "q": item["q"], "fv": fv, "tv": tv})
856
+ return
857
+
858
+ self.versions[symbol] = tv
859
+
860
+
759
861
  to_delete, to_update = [], []
760
862
  for side, S in ((asks, "a"), (bids, "b")):
761
863
  for item in side:
@@ -929,8 +1031,7 @@ class OurbitSpotDataStore(DataStoreCollection):
929
1031
  """
930
1032
  现货账户余额数据流
931
1033
 
932
- Data structure:
933
-
1034
+ _KEYS = ["currency"]
934
1035
  .. code:: python
935
1036
 
936
1037
  [
@@ -1015,7 +1116,7 @@ class OurbitSpotDataStore(DataStoreCollection):
1015
1116
  return self._get("order", SpotOrders)
1016
1117
 
1017
1118
  def onmessage(self, msg: Item, ws: ClientWebSocketResponse | None = None) -> None:
1018
-
1119
+ # print(msg, '\n')
1019
1120
  channel = msg.get("c")
1020
1121
  if 'msg' in msg:
1021
1122
  if 'invalid' in msg['msg']: