hyperquant 0.8__py3-none-any.whl → 0.9__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.

Potentially problematic release.


This version of hyperquant might be problematic. Click here for more details.

@@ -0,0 +1,290 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import json
5
+ import logging
6
+ from typing import Any, Awaitable, TYPE_CHECKING
7
+ import zlib
8
+
9
+ from aiohttp import ClientResponse
10
+ from pybotters.store import DataStore, DataStoreCollection
11
+
12
+ if TYPE_CHECKING:
13
+ from pybotters.typedefs import Item
14
+ from pybotters.ws import ClientWebSocketResponse
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ # {"event_rep":"","channel":"market_e_wlfiusdt_depth_step0","data":null,"tick":{"asks":[[0.1402,9864],[0.1403,23388],[0.1404,9531],[0.1405,4995],[0.1406,3074],[0.1407,18736],[0.1408,3514],[0.1409,6326],[0.141,13217],[0.1411,18253],[0.1412,12214],[0.1413,15243],[0.1414,3606],[0.1415,14894],[0.1416,7932],[0.1417,4973],[0.1418,13031],[0.1419,19793],[0.142,17093],[0.1421,19395],[0.1422,12793],[0.1423,17846],[0.1424,15320],[0.1425,13313],[0.1426,20405],[0.1427,6611],[0.1428,17688],[0.1429,16308],[0.143,10073],[0.1431,15438]],"buys":[[0.1401,9473],[0.14,17486],[0.1399,11957],[0.1398,4824],[0.1397,18447],[0.1396,16929],[0.1395,19859],[0.1394,7283],[0.1393,19609],[0.1392,13638],[0.1391,4146],[0.139,3924],[0.1389,21574],[0.1388,14692],[0.1387,13772],[0.1386,21153],[0.1385,19533],[0.1384,20164],[0.1383,2645],[0.1382,17852],[0.1381,21453],[0.138,19162],[0.1379,17365],[0.1378,9061],[0.1377,14713],[0.1376,12023],[0.1375,11245],[0.1374,9633],[0.1373,5124],[0.1372,5140]]},"ts":1761239630000,"status":"ok"}
19
+
20
+ class Book(DataStore):
21
+
22
+ _KEYS = ["s", "S", "p"]
23
+
24
+ def _init(self) -> None:
25
+ self.limit: int | None = None
26
+
27
+ def _on_message(self, msg: Any) -> None:
28
+ asks = msg["tick"]["asks"]
29
+ bids = msg["tick"]["buys"]
30
+ if self.limit is not None:
31
+ asks = asks[: self.limit]
32
+ bids = bids[: self.limit]
33
+ chanel = msg["channel"]
34
+ symbol = chanel.split("_")[2].upper()
35
+ asks = [
36
+ {"s": symbol, "S": "a", "p": float(price), "q": float(quantity)} for price, quantity in asks
37
+ ]
38
+ bids = [
39
+ {"s": symbol, "S": "b", "p": float(price), "q": float(quantity)} for price, quantity in bids
40
+ ]
41
+ self._clear()
42
+ self._insert(asks + bids)
43
+
44
+ class Detail(DataStore):
45
+
46
+ _KEYS = ["symbol"]
47
+
48
+ def _onresponse(self, data: Any) -> None:
49
+ data = data.get("data", {})
50
+ clist = data.get("contractList", [])
51
+ # coinResultVo -> marginCoinPrecision 取出来
52
+ for c in clist:
53
+ p = c.get("coinResultVo", {}).get("marginCoinPrecision")
54
+ p = 10 ** (-p)
55
+ c["tick_size"] = p
56
+ c['TickSize'] = p # 兼容用大写开头的字段
57
+ self._update(clist)
58
+
59
+ class Position(DataStore):
60
+
61
+ _KEYS = ["symbol"]
62
+
63
+ def _onresponse(self, data: Any) -> None:
64
+ data = data.get("data", [])
65
+ p_list = data.get("positionList", [])
66
+ self._clear()
67
+ self._update(p_list)
68
+
69
+ class Balance(DataStore):
70
+
71
+ _KEYS = ["symbol"]
72
+
73
+ def _onresponse(self, data: Any) -> None:
74
+ data = data.get("data", [])
75
+ b_list = data.get("accountList", [])
76
+ self._clear()
77
+ self._update(b_list)
78
+
79
+ class Orders(DataStore):
80
+
81
+ _KEYS = ["orderId"]
82
+
83
+ @staticmethod
84
+ def _normalize(entry: dict[str, Any]) -> dict[str, Any] | None:
85
+ order_id = entry.get("orderId")
86
+ if order_id is None:
87
+ return None
88
+ normalized = dict(entry)
89
+ normalized["orderId"] = str(order_id)
90
+ return normalized
91
+
92
+ def _onresponse(self, data: Any) -> None:
93
+ payload: Any = data
94
+ if isinstance(data, dict):
95
+ payload = data.get("data") or data
96
+ if isinstance(payload, dict):
97
+ payload = payload.get("orderList") or payload.get("orders") or []
98
+
99
+ items: list[dict[str, Any]] = []
100
+ if isinstance(payload, list):
101
+ for entry in payload:
102
+ if not isinstance(entry, dict):
103
+ continue
104
+ normalized = self._normalize(entry)
105
+ if normalized:
106
+ items.append(normalized)
107
+
108
+ self._clear()
109
+ if items:
110
+ self._insert(items)
111
+
112
+ class CoinUpDataStore(DataStoreCollection):
113
+ def _init(self) -> None:
114
+ self._create("book", datastore_class=Book)
115
+ self._create("detail", datastore_class=Detail)
116
+ self._create("position", datastore_class=Position)
117
+ self._create("balance", datastore_class=Balance)
118
+ self._create("orders", datastore_class=Orders)
119
+
120
+ def onmessage(self, msg: Item, ws: ClientWebSocketResponse | None = None) -> None:
121
+ decompressed = zlib.decompress(msg, 16 + zlib.MAX_WBITS)
122
+ text = decompressed.decode("utf-8")
123
+ data = json.loads(text)
124
+ chanel = data.get("channel", "")
125
+ if 'depth' in chanel:
126
+ self.book._on_message(data)
127
+
128
+ def onresponse(self, data: Any) -> None:
129
+ pass
130
+
131
+
132
+ @property
133
+ def book(self) -> Book:
134
+ """
135
+ .. code:: json
136
+
137
+ {
138
+ "s": "BTCUSDT",
139
+ "S": "a", # 卖单
140
+ "p": "95640.3",
141
+ "q": "0.807"
142
+ }
143
+
144
+ """
145
+ return self._get("book")
146
+
147
+ @property
148
+ def detail(self) -> Detail:
149
+ """
150
+ .. code:: json
151
+
152
+ {
153
+ "id": 117,
154
+ "contractName": "E-RESOLV-USDT",
155
+ "symbol": "RESOLV-USDT",
156
+ "contractType": "E",
157
+ "coType": "E",
158
+ "contractShowType": "USDT合约",
159
+ "deliveryKind": "0",
160
+ "contractSide": 1,
161
+ "multiplier": 22.8000000000000000,
162
+ "multiplierCoin": "RESOLV",
163
+ "marginCoin": "USDT",
164
+ "originalCoin": "USDT",
165
+ "marginRate": 1.00000000,
166
+ "capitalStartTime": 0,
167
+ "capitalFrequency": 8,
168
+ "settlementFrequency": 1,
169
+ "brokerId": 1,
170
+ "base": "RESOLV",
171
+ "quote": "USDT",
172
+ "coinResultVo": {
173
+ "symbolPricePrecision": 5,
174
+ "depth": [
175
+ "5",
176
+ "4",
177
+ "3"
178
+ ],
179
+ "minOrderVolume": 1,
180
+ "minOrderMoney": 1,
181
+ "maxMarketVolume": 5000000,
182
+ "maxMarketMoney": 6411360,
183
+ "maxLimitVolume": 5000000,
184
+ "maxLimitMoney": 5000000.0000000000000000,
185
+ "priceRange": 0.3000000000,
186
+ "marginCoinPrecision": 4,
187
+ "fundsInStatus": 1,
188
+ "fundsOutStatus": 1
189
+ },
190
+ "sort": 100,
191
+ "maxLever": 75,
192
+ "minLever": 1,
193
+ "contractOtherName": "RESOLV/USDT",
194
+ "subSymbol": "e_resolvusdt",
195
+ "classification": 1,
196
+ "nextCapitalSettTime": 1761292800000,
197
+ "tick_size": 0.0001
198
+ }
199
+ """
200
+ return self._get("detail")
201
+
202
+ @property
203
+ def position(self) -> Position:
204
+ """
205
+ _key: symbol
206
+
207
+ .. code:: json
208
+
209
+ {
210
+ "id": 256538,
211
+ "contractId": 169,
212
+ "contractName": "E-WLFI-USDT",
213
+ "contractOtherName": "WLFI/USDT",
214
+ "symbol": "WLFI-USDT",
215
+ "positionVolume": 1.0,
216
+ "canCloseVolume": 1.0,
217
+ "closeVolume": 0.0,
218
+ "openAvgPrice": 0.1409,
219
+ "indexPrice": 0.14040034,
220
+ "reducePrice": -0.9769279224708908,
221
+ "holdAmount": 16.53718437074,
222
+ "marginRate": 7.852395215348719,
223
+ "realizedAmount": 0.0,
224
+ "returnRate": -0.0177310149041873,
225
+ "orderSide": "BUY",
226
+ "positionType": 1,
227
+ "canUseAmount": 16.11598335074,
228
+ "canSubMarginAmount": 0,
229
+ "openRealizedAmount": -0.0074949,
230
+ "keepRate": 0.015,
231
+ "maxFeeRate": 2.0E-4,
232
+ "unRealizedAmount": -0.0074949,
233
+ "leverageLevel": 5,
234
+ "positionBalance": 2.1060051,
235
+ "tradeFee": "-0.0004",
236
+ "capitalFee": "0",
237
+ "closeProfit": "0",
238
+ "settleProfit": "0",
239
+ "shareAmount": "0",
240
+ "historyRealizedAmount": "-0.0004227",
241
+ "profitRealizedAmount": "-0.0004",
242
+ "openAmount": 0.4227,
243
+ "adlLevel": 2
244
+ }
245
+
246
+ """
247
+ return self._get("position")
248
+
249
+ @property
250
+ def balance(self) -> Balance:
251
+ """
252
+ _key: symbol
253
+
254
+ .. code:: json
255
+
256
+ {
257
+ "symbol": "USDT",
258
+ "originalCoin": "USDT",
259
+ "unRealizedAmount": "-0.0074949",
260
+ "realizedAmount": "0",
261
+ "totalMargin": "16.53718437074",
262
+ "totalAmount": "16.53718437074",
263
+ "canUseAmount": 16.11598335074,
264
+ "availableAmount": 16.11598335074,
265
+ "isolateMargin": "0",
266
+ "walletBalance": "16.54467927074",
267
+ "lockAmount": "0",
268
+ "accountNormal": "16.54467927074",
269
+ "totalMarginRate": "7.8523952153487187"
270
+ }
271
+ """
272
+ return self._get("balance")
273
+
274
+ @property
275
+ def orders(self) -> Orders:
276
+ """
277
+ _key: orderId
278
+
279
+ .. code:: json
280
+
281
+ {
282
+ "orderId": "2951913499074783723",
283
+ "contractId": 169,
284
+ "side": "SELL",
285
+ "price": 0.15,
286
+ "volume": 1,
287
+ "status": 0
288
+ }
289
+ """
290
+ return self._get("orders")