hyperquant 0.49__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.
- hyperquant/broker/models/ourbit.py +85 -63
- hyperquant/broker/ourbit.py +0 -1
- hyperquant/core.py +3 -0
- {hyperquant-0.49.dist-info → hyperquant-0.52.dist-info}/METADATA +1 -1
- {hyperquant-0.49.dist-info → hyperquant-0.52.dist-info}/RECORD +6 -6
- {hyperquant-0.49.dist-info → hyperquant-0.52.dist-info}/WHEEL +0 -0
@@ -22,19 +22,20 @@ class Book(DataStore):
|
|
22
22
|
Channel: push.depth.step
|
23
23
|
|
24
24
|
用于存储和管理订单簿深度数据,包含买卖盘的价格和数量信息
|
25
|
-
Keys: ["
|
26
|
-
-
|
27
|
-
-
|
28
|
-
-
|
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 = ["
|
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[:
|
47
|
-
bids = bids[:
|
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({"
|
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
|
-
"
|
65
|
-
"
|
66
|
-
"
|
65
|
+
"s": symbol,
|
66
|
+
"S": side_id,
|
67
|
+
"p": str(price),
|
67
68
|
"sz": str(size),
|
68
|
-
"
|
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(
|
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="
|
104
|
-
item_asc_key="
|
105
|
-
item_desc_key="
|
106
|
-
sort_key="
|
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
|
-
"
|
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
|
-
"
|
155
|
-
"
|
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
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
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
|
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
|
-
|
727
|
-
|
728
|
-
|
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/broker/ourbit.py
CHANGED
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.
|
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,21 +1,21 @@
|
|
1
1
|
hyperquant/__init__.py,sha256=UpjiX4LS5jmrBc2kE8RiLR02eCfD8JDQrR1q8zkLNcQ,161
|
2
|
-
hyperquant/core.py,sha256=
|
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
|
6
6
|
hyperquant/notikit.py,sha256=x5yAZ_tAvLQRXcRbcg-VabCaN45LUhvlTZnUqkIqfAA,3596
|
7
7
|
hyperquant/broker/auth.py,sha256=oA9Yw1I59-u0Tnoj2e4wUup5q8V5T2qpga5RKbiAiZI,2614
|
8
8
|
hyperquant/broker/hyperliquid.py,sha256=7MxbI9OyIBcImDelPJu-8Nd53WXjxPB5TwE6gsjHbto,23252
|
9
|
-
hyperquant/broker/ourbit.py,sha256=
|
9
|
+
hyperquant/broker/ourbit.py,sha256=Fza_nhfoSCf1Ulm7UHOlt969Wm37bKja9P5xpN93XqY,17902
|
10
10
|
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=
|
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.
|
20
|
-
hyperquant-0.
|
21
|
-
hyperquant-0.
|
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,,
|
File without changes
|