hyperquant 0.51__py3-none-any.whl → 0.52__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,15 +44,15 @@ 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
58
  for side_id, levels in (("B", bids), ("A", asks)):
@@ -61,11 +62,11 @@ class Book(DataStore):
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),
65
+ "s": symbol,
66
+ "S": side_id,
67
+ "p": str(price),
67
68
  "sz": str(size),
68
- "count": count,
69
+ "ct": count,
69
70
  "i": i
70
71
  }
71
72
  )
@@ -80,7 +81,9 @@ class Book(DataStore):
80
81
  return self._time
81
82
 
82
83
  @property
83
- def sorted(self) -> dict[str, list[Item]]:
84
+ def sorted(
85
+ self, query: Item | None = None, limit: int | None = None
86
+ ) -> dict[str, list[Item]]:
84
87
  """获取排序后的订单簿数据
85
88
 
86
89
  Returns:
@@ -100,10 +103,12 @@ class Book(DataStore):
100
103
  }
101
104
  """
102
105
  return self._sorted(
103
- item_key="side",
104
- item_asc_key="A", # asks 升序
105
- item_desc_key="B", # bids 降序
106
- sort_key="px",
106
+ item_key="S",
107
+ item_asc_key="a", # asks 升序
108
+ item_desc_key="b", # bids 降序
109
+ sort_key="p",
110
+ query=query,
111
+ limit=limit,
107
112
  )
108
113
 
109
114
 
@@ -147,14 +152,17 @@ class Orders(DataStore):
147
152
  return {
148
153
  "order_id": order.get("orderId"),
149
154
  "symbol": order.get("symbol"),
150
- "px": order.get("price"),
155
+ "price": order.get("price"),
151
156
  "vol": order.get("vol"),
152
157
  "lev": order.get("leverage"),
153
158
  "side": "buy" if order.get("side") == 1 else "sell",
154
- "deal_vol": order.get("dealVol"),
155
- "deal_avg_px": order.get("dealAvgPrice"),
159
+ "deal_quantity": order.get("dealVol"),
160
+ "avg_price": order.get("dealAvgPrice"),
156
161
  "create_ts": order.get("createTime"),
157
162
  "update_ts": order.get("updateTime"),
163
+ "fee": order.get("makerFee"),
164
+ "profit": order.get("profit"),
165
+ "used_margin": order.get("usedMargin"),
158
166
  "state": "open"
159
167
  }
160
168
 
@@ -192,6 +200,13 @@ class Orders(DataStore):
192
200
  self._find_and_delete({
193
201
  "order_id": order.get("order_id")
194
202
  })
203
+ else:
204
+ order = self._fmt(data)
205
+ order["state"] = "unknown"
206
+ self._update([order])
207
+ self._find_and_delete({
208
+ "order_id": order.get("order_id")
209
+ })
195
210
 
196
211
  class Detail(DataStore):
197
212
  _KEYS = ["symbol"]
@@ -225,27 +240,27 @@ class Position(DataStore):
225
240
 
226
241
  def _fmt(self, position:dict):
227
242
  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
- }
243
+ "position_id": position.get("positionId"),
244
+ "symbol": position.get("symbol"),
245
+ "side": "short" if position.get("positionType") == 2 else "long",
246
+ "open_type": position.get("openType"),
247
+ "state": position.get("state"),
248
+ "hold_vol": position.get("holdVol"),
249
+ "frozen_vol": position.get("frozenVol"),
250
+ "close_vol": position.get("closeVol"),
251
+ "hold_avg_price": position.get("holdAvgPriceFullyScale"),
252
+ "open_avg_price": position.get("openAvgPriceFullyScale"),
253
+ "close_avg_price": str(position.get("closeAvgPrice")),
254
+ "liquidate_price": str(position.get("liquidatePrice")),
255
+ "oim": position.get("oim"),
256
+ "im": position.get("im"),
257
+ "hold_fee": position.get("holdFee"),
258
+ "realised": position.get("realised"),
259
+ "leverage": position.get("leverage"),
260
+ "margin_ratio": position.get("marginRatio"),
261
+ "create_ts": position.get("createTime"),
262
+ "update_ts": position.get("updateTime"),
263
+ }
249
264
 
250
265
  def _onresponse(self, data: dict[str, Any]):
251
266
  positions = data.get("data", [])
@@ -639,7 +654,6 @@ class SpotOrders(DataStore):
639
654
  }
640
655
 
641
656
 
642
-
643
657
  def _onresponse(self, data: dict[str, Any]):
644
658
  orders = (data.get("data") or {}).get("resultList", [])
645
659
  items = [self._fmt(order) for order in orders]
@@ -669,14 +683,10 @@ class SpotOrders(DataStore):
669
683
 
670
684
  state = d.get("status")
671
685
 
672
- # 新建 / 已挂出
673
- if state == 1:
674
- item["state"] = "open"
675
- self._insert([item])
676
- return
686
+
677
687
 
678
688
  # 成交片段(部分/完全)
679
- if state in (2, 3):
689
+ if d.get("singleDealPrice"):
680
690
  # 单片段信息(可能多次推送;需做增量累计 + 去重)
681
691
  single_id = d.get("singleDealId")
682
692
  single_px = d.get("singleDealPrice")
@@ -713,26 +723,38 @@ class SpotOrders(DataStore):
713
723
  })
714
724
 
715
725
  # 状态文本:2=filled(整单), 3=partially_filled
716
- item["state"] = "filled" if state == 2 else "partially_filled"
726
+ # item["state"] = "filled" if state == 2 else "partially_filled"
727
+ if state == 2:
728
+ item["state"] = "filled"
729
+ elif state == 3:
730
+ item["state"] = "partially_filled"
731
+ else:
732
+ item["state"] = "unknown_"+str(state)
717
733
 
718
734
  self._update([item])
719
735
 
720
- # 整单成交 → 删除
721
- if state == 2:
736
+ # 整单成交 或者 部分取消 → 删除
737
+ if state == 2 or 'unknown' in item["state"]:
722
738
  self._find_and_delete({"order_id": d.get("id")})
723
739
  return
740
+ else:
741
+ # 新建 / 已挂出
742
+ if state == 1:
743
+ item["state"] = "open"
744
+ self._insert([item])
745
+ return
746
+
747
+ elif state == 4:
748
+ item["state"] = "canceled"
749
+ self._update([item])
750
+ self._find_and_delete({"order_id": d.get("id")})
751
+ return
752
+ else:
724
753
 
725
- # 撤单
726
- if state == 4:
727
- item["state"] = "canceled"
728
- self._update([item])
729
- self._find_and_delete({"order_id": d.get("id")})
730
- return
731
-
732
- # 未知状态:更新后删除,避免脏数据残留
733
- item["state"] = "unknown"
734
- self._update([item])
735
- self._find_and_delete({"order_id": d.get("id")})
754
+ # 未知状态:更新后删除,避免脏数据残留
755
+ item["state"] = "unknown_"+str(state)
756
+ self._update([item])
757
+ self._find_and_delete({"order_id": d.get("id")})
736
758
 
737
759
 
738
760
 
@@ -764,7 +786,7 @@ class SpotBook(DataStore):
764
786
  # items.sort(key=lambda x: x.get("fv", 0)) # 按 fromVersion 排序
765
787
  # self._find_and_delete({"s": symbol})
766
788
 
767
- # 处理缓存
789
+ # 应为我们先连接的ws, 所以可能有缓存需要去处理
768
790
  items = [item for item in self.cache if item.get("s") == symbol]
769
791
  items.sort(key=lambda x: x.get("fv", 0)) # 按 fromVersion 排序
770
792
  self.cache = [item for item in self.cache if item.get("s") != symbol]
hyperquant/core.py CHANGED
@@ -335,6 +335,9 @@ class Exchange(ExchangeBase):
335
335
  self.account[symbol]['realised_profit'] += profit
336
336
  self.account[symbol]['amount'] -= -direction * cover_amount
337
337
  trade['pos'] = profit # 记录盈亏
338
+
339
+ trade['pos_rate'] = -direction * (price / self.account[symbol]['hold_price'] - 1) if self.account[symbol]['hold_price'] != 0 else 0
340
+
338
341
  self.account[symbol]['hold_price'] = 0 if self.account[symbol]['amount'] == 0 else self.account[symbol]['hold_price']
339
342
 
340
343
  if open_amount > 0:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperquant
3
- Version: 0.51
3
+ Version: 0.52
4
4
  Summary: A minimal yet hyper-efficient backtesting framework for quantitative trading
5
5
  Project-URL: Homepage, https://github.com/yourusername/hyperquant
6
6
  Project-URL: Issues, https://github.com/yourusername/hyperquant/issues
@@ -1,5 +1,5 @@
1
1
  hyperquant/__init__.py,sha256=UpjiX4LS5jmrBc2kE8RiLR02eCfD8JDQrR1q8zkLNcQ,161
2
- hyperquant/core.py,sha256=iEI8qTNpyesB_w67SrKXeGoB9JllovBeJKI0EZFYew4,20631
2
+ hyperquant/core.py,sha256=RzRFbyImqzBiaA-9lQzvxPfxwcOvScdABZviS4y0kqM,20783
3
3
  hyperquant/db.py,sha256=i2TjkCbmH4Uxo7UTDvOYBfy973gLcGexdzuT_YcSeIE,6678
4
4
  hyperquant/draw.py,sha256=up_lQ3pHeVLoNOyh9vPjgNwjD0M-6_IetSGviQUgjhY,54624
5
5
  hyperquant/logkit.py,sha256=nUo7nx5eONvK39GOhWwS41zNRL756P2J7-5xGzwXnTY,8462
@@ -11,11 +11,11 @@ hyperquant/broker/ws.py,sha256=umRzxwCaZaRIgIq4YY-AuA0wCXFT0uOBmQbIXFY8CK0,1555
11
11
  hyperquant/broker/lib/hpstore.py,sha256=LnLK2zmnwVvhEbLzYI-jz_SfYpO1Dv2u2cJaRAb84D8,8296
12
12
  hyperquant/broker/lib/hyper_types.py,sha256=HqjjzjUekldjEeVn6hxiWA8nevAViC2xHADOzDz9qyw,991
13
13
  hyperquant/broker/models/hyperliquid.py,sha256=c4r5739ibZfnk69RxPjQl902AVuUOwT8RNvKsMtwXBY,9459
14
- hyperquant/broker/models/ourbit.py,sha256=rFJEFwzTravStHsB0kEwP5YhI2EQsn79Vv7aEiCIWLc,41585
14
+ hyperquant/broker/models/ourbit.py,sha256=ID_uOojyqfKiLNcIhT_3X3-IDFGsVud27kArut3mCMo,42299
15
15
  hyperquant/datavison/_util.py,sha256=92qk4vO856RqycO0YqEIHJlEg-W9XKapDVqAMxe6rbw,533
16
16
  hyperquant/datavison/binance.py,sha256=3yNKTqvt_vUQcxzeX4ocMsI5k6Q6gLZrvgXxAEad6Kc,5001
17
17
  hyperquant/datavison/coinglass.py,sha256=PEjdjISP9QUKD_xzXNzhJ9WFDTlkBrRQlVL-5pxD5mo,10482
18
18
  hyperquant/datavison/okx.py,sha256=yg8WrdQ7wgWHNAInIgsWPM47N3Wkfr253169IPAycAY,6898
19
- hyperquant-0.51.dist-info/METADATA,sha256=ZB9iF5hWyPtdDsqc3jcekGUswYvKSmJgsfEN6OqI37k,4317
20
- hyperquant-0.51.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
21
- hyperquant-0.51.dist-info/RECORD,,
19
+ hyperquant-0.52.dist-info/METADATA,sha256=SrzDREIrGQtsDdXOSsg-sYdut4mhtvcccsUkmIP-kSM,4317
20
+ hyperquant-0.52.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
21
+ hyperquant-0.52.dist-info/RECORD,,