hyperquant 1.2__tar.gz → 1.21__tar.gz

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.
Files changed (63) hide show
  1. {hyperquant-1.2 → hyperquant-1.21}/PKG-INFO +1 -1
  2. {hyperquant-1.2 → hyperquant-1.21}/pyproject.toml +1 -1
  3. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/bitmart.py +45 -25
  4. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/bitmart.py +58 -3
  5. {hyperquant-1.2 → hyperquant-1.21}/tests/test_bitmart.py +126 -25
  6. {hyperquant-1.2 → hyperquant-1.21}/uv.lock +1 -1
  7. {hyperquant-1.2 → hyperquant-1.21}/.gitignore +0 -0
  8. {hyperquant-1.2 → hyperquant-1.21}/.python-version +0 -0
  9. {hyperquant-1.2 → hyperquant-1.21}/README.md +0 -0
  10. {hyperquant-1.2 → hyperquant-1.21}/apis.json +0 -0
  11. {hyperquant-1.2 → hyperquant-1.21}/data/alpine_smoke.log +0 -0
  12. {hyperquant-1.2 → hyperquant-1.21}/data/logs/notikit.log +0 -0
  13. {hyperquant-1.2 → hyperquant-1.21}/data/logs/test_order_sync.log +0 -0
  14. {hyperquant-1.2 → hyperquant-1.21}/data/records_swap.csv +0 -0
  15. {hyperquant-1.2 → hyperquant-1.21}/data/records_swapc.csv +0 -0
  16. {hyperquant-1.2 → hyperquant-1.21}/doc/bitmart.md +0 -0
  17. {hyperquant-1.2 → hyperquant-1.21}/doc/coinup.md +0 -0
  18. {hyperquant-1.2 → hyperquant-1.21}/doc/lbank.md +0 -0
  19. {hyperquant-1.2 → hyperquant-1.21}/pub.sh +0 -0
  20. {hyperquant-1.2 → hyperquant-1.21}/requirements-dev.lock +0 -0
  21. {hyperquant-1.2 → hyperquant-1.21}/requirements.lock +0 -0
  22. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/__init__.py +0 -0
  23. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/auth.py +0 -0
  24. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/bitget.py +0 -0
  25. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/coinup.py +0 -0
  26. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/coinw.py +0 -0
  27. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/edgex.py +0 -0
  28. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/hyperliquid.py +0 -0
  29. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/lbank.py +0 -0
  30. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/lib/edgex_sign.py +0 -0
  31. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/lib/hpstore.py +0 -0
  32. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/lib/hyper_types.py +0 -0
  33. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/lib/util.py +0 -0
  34. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/lighter.py +0 -0
  35. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/bitget.py +0 -0
  36. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/coinup.py +0 -0
  37. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/coinw.py +0 -0
  38. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/edgex.py +0 -0
  39. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/hyperliquid.py +0 -0
  40. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/lbank.py +0 -0
  41. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/lighter.py +0 -0
  42. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/models/ourbit.py +0 -0
  43. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/ourbit.py +0 -0
  44. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/broker/ws.py +0 -0
  45. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/core.py +0 -0
  46. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/datavison/_util.py +0 -0
  47. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/datavison/binance.py +0 -0
  48. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/datavison/coinglass.py +0 -0
  49. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/datavison/okx.py +0 -0
  50. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/db.py +0 -0
  51. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/draw.py +0 -0
  52. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/logkit.py +0 -0
  53. {hyperquant-1.2 → hyperquant-1.21}/src/hyperquant/notikit.py +0 -0
  54. {hyperquant-1.2 → hyperquant-1.21}/test.py +0 -0
  55. {hyperquant-1.2 → hyperquant-1.21}/tests/test_bitget.py +0 -0
  56. {hyperquant-1.2 → hyperquant-1.21}/tests/test_coinup.py +0 -0
  57. {hyperquant-1.2 → hyperquant-1.21}/tests/test_coinw.py +0 -0
  58. {hyperquant-1.2 → hyperquant-1.21}/tests/test_draw.py +0 -0
  59. {hyperquant-1.2 → hyperquant-1.21}/tests/test_edgex.py +0 -0
  60. {hyperquant-1.2 → hyperquant-1.21}/tests/test_lbank.py +0 -0
  61. {hyperquant-1.2 → hyperquant-1.21}/tests/test_lighter.py +0 -0
  62. {hyperquant-1.2 → hyperquant-1.21}/tests/test_ourbit.py +0 -0
  63. {hyperquant-1.2 → hyperquant-1.21}/tests/tmp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperquant
3
- Version: 1.2
3
+ Version: 1.21
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,6 +1,6 @@
1
1
  [project]
2
2
  name = "hyperquant"
3
- version = "1.02"
3
+ version = "1.21"
4
4
  description = "A minimal yet hyper-efficient backtesting framework for quantitative trading"
5
5
  authors = [
6
6
  { name = "MissinA", email = "1421329142@qq.com" }
@@ -30,6 +30,7 @@ class Bitmart:
30
30
  self.private_api = "https://derivatives.bitmart.com"
31
31
  self.forward_api = f'{self.private_api}/gw-api/contract-tiger/forward'
32
32
  self.ws_url = ws_url or "wss://contract-ws-v2.bitmart.com/v1/ifcontract/realTime"
33
+ self.api_ws_url = "wss://openapi-ws-v2.bitmart.com/api?protocol=1.1"
33
34
 
34
35
  self.account_index = account_index
35
36
  self.apis = apis
@@ -281,6 +282,7 @@ class Bitmart:
281
282
  *,
282
283
  depth: str = "Depth",
283
284
  depth_limit: int | None = None,
285
+ use_api_ws: bool = True,
284
286
  ) -> pybotters.ws.WebSocketApp:
285
287
  """Subscribe order book channel(s)."""
286
288
 
@@ -289,37 +291,55 @@ class Bitmart:
289
291
 
290
292
  if not symbols:
291
293
  raise ValueError("symbols must not be empty")
292
-
293
- missing = [sym for sym in symbols if self.get_contract_id(sym) is None]
294
- if missing:
295
- await self.update("detail")
296
- still_missing = [sym for sym in missing if self.get_contract_id(sym) is None]
297
- if still_missing:
298
- raise ValueError(f"Unknown symbols: {', '.join(still_missing)}")
299
-
300
294
  if depth_limit is not None:
301
295
  self.store.book.limit = depth_limit
296
+ if not use_api_ws:
297
+ missing = [sym for sym in symbols if self.get_contract_id(sym) is None]
298
+ if missing:
299
+ await self.update("detail")
300
+ still_missing = [sym for sym in missing if self.get_contract_id(sym) is None]
301
+ if still_missing:
302
+ raise ValueError(f"Unknown symbols: {', '.join(still_missing)}")
302
303
 
303
- channels: list[str] = []
304
- for symbol in symbols:
305
- contract_id = self.get_contract_id(symbol)
306
- if contract_id is None:
307
- continue
308
- self.store.book.id_to_symbol[str(contract_id)] = symbol
309
- channels.append(f"{depth}:{contract_id}")
310
304
 
311
- if not channels:
312
- raise ValueError("No channels resolved for subscription")
313
305
 
314
- payload = {"action": "subscribe", "args": channels}
315
- # print(payload)
306
+ channels: list[str] = []
307
+ for symbol in symbols:
308
+ contract_id = self.get_contract_id(symbol)
309
+ if contract_id is None:
310
+ continue
311
+ self.store.book.id_to_symbol[str(contract_id)] = symbol
312
+ channels.append(f"{depth}:{contract_id}")
313
+
314
+ if not channels:
315
+ raise ValueError("No channels resolved for subscription")
316
+
317
+ payload = {"action": "subscribe", "args": channels}
318
+ # print(payload)
319
+
320
+ ws_app = self.client.ws_connect(
321
+ self.api_ws_url,
322
+ send_json=payload,
323
+ hdlr_json=self.store.onmessage,
324
+ )
325
+ else:
326
+ channels: list[str] = []
327
+ for symbol in symbols:
328
+ channels.append(f"futures/depthAll5:{symbol}@100ms")
329
+
330
+ if not channels:
331
+ raise ValueError("No channels resolved for subscription")
332
+
333
+ payload = {"action": "subscribe", "args": channels}
334
+ # print(payload)
335
+
336
+ ws_app = self.client.ws_connect(
337
+ self.api_ws_url,
338
+ send_json=payload,
339
+ hdlr_json=self.store.onmessage,
340
+ autoping=False,
341
+ )
316
342
 
317
- ws_app = self.client.ws_connect(
318
- self.ws_url,
319
- send_json=payload,
320
- hdlr_json=self.store.onmessage,
321
- autoping=False,
322
- )
323
343
  await ws_app._event.wait()
324
344
  return ws_app
325
345
 
@@ -62,6 +62,7 @@ class Book(DataStore):
62
62
  def _on_message(self, msg: dict[str, Any]) -> None:
63
63
  data = msg.get("data")
64
64
  group = msg.get("group")
65
+ ms_t = msg.get("ms_t")
65
66
  if not isinstance(data, dict) or not isinstance(group, str):
66
67
  return
67
68
 
@@ -94,7 +95,57 @@ class Book(DataStore):
94
95
  for entry in depths
95
96
  ])
96
97
 
97
- self._last_update = time.time()
98
+ self._last_update = ms_t
99
+
100
+ def _on_message_api(self, msg: dict[str, Any]) -> None:
101
+ # {
102
+ # "data": {
103
+ # "symbol": "BTCUSDT",
104
+ # "asks": [
105
+ # {
106
+ # "price": "70294.4",
107
+ # "vol": "455"
108
+ # }
109
+ # ],
110
+ # "bids": [
111
+ # {
112
+ # "price": "70293.9",
113
+ # "vol": "1856"
114
+ # }
115
+ # ],
116
+ # "ms_t": 1730399750402
117
+ # },
118
+ # "group": "futures/depthAll20:BTCUSDT@200ms"
119
+ # }
120
+ data = msg.get("data")
121
+ if not isinstance(data, dict):
122
+ return
123
+ symbol = data.get("symbol")
124
+ asks = data.get("asks") or []
125
+ bids = data.get("bids") or []
126
+ if self.limit:
127
+ asks = asks[: self.limit]
128
+ bids = bids[: self.limit]
129
+
130
+ self._find_and_delete({'s': symbol})
131
+ self._update([
132
+ self._make_entry(
133
+ symbol,
134
+ "a",
135
+ entry.get("price", '0'),
136
+ entry.get("vol", '0'),
137
+ )
138
+ for entry in asks
139
+ ])
140
+ self._update([
141
+ self._make_entry(
142
+ symbol,
143
+ "b",
144
+ entry.get("price", '0'),
145
+ entry.get("vol", '0'),
146
+ )
147
+ for entry in bids
148
+ ])
98
149
 
99
150
  def sorted(self, query: Item | None = None, limit: int | None = None) -> dict[str, list[Item]]:
100
151
  return self._sorted(
@@ -278,8 +329,12 @@ class BitmartDataStore(DataStoreCollection):
278
329
  def onmessage(self, msg: Item, ws: ClientWebSocketResponse | None = None) -> None:
279
330
  if isinstance(msg, dict):
280
331
  group = msg.get("group")
281
- if isinstance(group, str) and group.startswith("Depth"):
282
- self.book._on_message(msg)
332
+
333
+ if isinstance(group, str):
334
+ if group.startswith("futures/depth"):
335
+ self.book._on_message_api(msg)
336
+ if group.startswith("Depth"):
337
+ self.book._on_message(msg)
283
338
 
284
339
  @property
285
340
  def book(self) -> Book:
@@ -10,9 +10,8 @@ from hyperquant.logkit import get_logger
10
10
  from hyperquant.broker.bitmart import Bitmart
11
11
 
12
12
 
13
-
14
13
  async def test_update():
15
- async with pybotters.Client(apis='./apis.json') as client:
14
+ async with pybotters.Client(apis="./apis.json") as client:
16
15
  async with Bitmart(client=client) as broker:
17
16
  # print(broker.store.detail.find()[0])
18
17
  # await broker.update('balances')
@@ -23,14 +22,14 @@ async def test_update():
23
22
  # await broker.update('history_orders')
24
23
  # print(broker.store.orders.find())
25
24
  # print(broker.store.orders.get({'order_id':3000237069605967}))
26
- await broker.update('positions')
25
+ await broker.update("positions")
27
26
  print(broker.store.positions.find())
28
27
 
29
28
  # print(broker.store.detail.find({'name':'PUMPUSDT'}))
30
29
 
31
30
 
32
31
  async def test_place():
33
- async with pybotters.Client(apis='./apis.json') as client:
32
+ async with pybotters.Client(apis="./apis.json") as client:
34
33
  async with Bitmart(client=client) as broker:
35
34
  # [2025-10-31 17:34:15] 🔵 准备建仓: VIRTUAL_USDT entry=short qty=20.498804 lag_px=1.4635 lead=binance
36
35
  # [2025-11-01 01:33:22] 🔵 准备建仓: PUMP_USDT entry=long qty=18872.375560 lag_px=0.004239 lead=binance
@@ -38,17 +37,19 @@ async def test_place():
38
37
  for i in range(2):
39
38
  start = time.time()
40
39
  oid = await broker.place_order(
41
- symbol='PUMPUSDT',
42
- side='sell',
43
- category='limit',
40
+ symbol="PUMPUSDT",
41
+ side="sell",
42
+ category="limit",
44
43
  price=0.004239,
45
44
  qty=18872.375560,
46
- mode='ioc',
47
- leverage=40
45
+ mode="ioc",
46
+ leverage=40,
48
47
  # qty_contract=1
49
48
  )
50
49
 
51
- print(f"Placed order ID: {oid}, 下单毫秒数: {(time.time() - start)*1000:.2f} ms")
50
+ print(
51
+ f"Placed order ID: {oid}, 下单毫秒数: {(time.time() - start)*1000:.2f} ms"
52
+ )
52
53
 
53
54
  # resp = await broker.cancel_order(
54
55
  # symbol='VIRTUALUSDT',
@@ -57,6 +58,7 @@ async def test_place():
57
58
 
58
59
  # print(f"Cancel response: {resp}")
59
60
 
61
+
60
62
  @dataclass
61
63
  class OrderSyncResult:
62
64
  position: dict[str, Any]
@@ -90,7 +92,7 @@ async def order_sync_polling(
90
92
  if logger:
91
93
  logger.warning(f"Order placement failed: {e}")
92
94
  return OrderSyncResult(position={}, order={})
93
-
95
+
94
96
  async def sync() -> OrderSyncResult:
95
97
  await broker.update("history_orders")
96
98
  await broker.update("positions")
@@ -104,7 +106,6 @@ async def order_sync_polling(
104
106
  position = positions[0]
105
107
  return OrderSyncResult(position=position or {}, order=order or {})
106
108
 
107
-
108
109
  for attempt in range(cancel_retry):
109
110
  await asyncio.sleep(1)
110
111
  await broker.update("history_orders")
@@ -124,16 +125,17 @@ async def order_sync_polling(
124
125
 
125
126
  return OrderSyncResult(position={}, order={})
126
127
 
128
+
127
129
  async def test_sub_book():
128
130
  async with pybotters.Client() as client:
129
131
  async with Bitmart(client=client) as broker:
130
132
  broker.store.book.limit = 1
131
- await broker.sub_orderbook(["TRXUSDT", 'XRPUSDT', 'DOTUSDT'])
133
+ await broker.sub_orderbook(["ASRUSDT"])
132
134
  while True:
133
135
  # await broker.store.book.wait()
134
136
  # print(broker.store.book.find())
135
- asks = broker.store.book.find({"S": "a", 's': 'TRXUSDT'})
136
- bids = broker.store.book.find({"S": "b", 's': 'TRXUSDT'})
137
+ asks = broker.store.book.find({"S": "a", "s": "ASRUSDT"})
138
+ bids = broker.store.book.find({"S": "b", "s": "ASRUSDT"})
137
139
  # 订单薄format化输出
138
140
  print("Asks:")
139
141
  for ask in asks:
@@ -144,20 +146,21 @@ async def test_sub_book():
144
146
  print("-" * 30)
145
147
  await asyncio.sleep(1)
146
148
 
147
-
148
149
  # with broker.store.book.watch() as stream:
149
150
  # async for change in stream:
150
151
  # print(change)
151
152
 
153
+
152
154
  async def test_auto_refresh():
153
- async with pybotters.Client(apis='./apis.json') as client:
154
- async with Bitmart(client=client, apis='./apis.json') as broker:
155
+ async with pybotters.Client(apis="./apis.json") as client:
156
+ async with Bitmart(client=client, apis="./apis.json") as broker:
155
157
  await broker.auto_refresh(0, test=True)
156
158
  await asyncio.sleep(2)
157
159
 
160
+
158
161
  async def test_sync_place():
159
162
  logger = get_logger("test_sync_place")
160
- async with pybotters.Client(apis='./apis.json') as client:
163
+ async with pybotters.Client(apis="./apis.json") as client:
161
164
  async with Bitmart(client=client) as broker:
162
165
  # place_task = broker.place_order(
163
166
  # symbol='VIRTUALUSDT',
@@ -170,10 +173,10 @@ async def test_sync_place():
170
173
 
171
174
  place_task = broker.place_order( # type: ignore[attr-defined]
172
175
  symbol="VELODROMEUSDT",
173
- side='sell',
176
+ side="sell",
174
177
  qty_contract=int(round(1.000000)),
175
178
  price=0.040645,
176
- category='market'
179
+ category="market",
177
180
  )
178
181
  result = await order_sync_polling(
179
182
  broker,
@@ -185,13 +188,111 @@ async def test_sync_place():
185
188
  )
186
189
  logger.info(f"Order Sync Result: {result}")
187
190
 
191
+
188
192
  async def test_set_leverage():
189
- async with pybotters.Client(apis='./apis.json') as client:
193
+ async with pybotters.Client(apis="./apis.json") as client:
190
194
  async with Bitmart(client=client) as broker:
191
- await broker.bind_leverage(symbol='BTCUSDT', leverage=10)
195
+ await broker.bind_leverage(symbol="BTCUSDT", leverage=10)
192
196
  # get current leverage
193
- lev_info = await broker.get_leverage(symbol='BTCUSDT')
197
+ lev_info = await broker.get_leverage(symbol="BTCUSDT")
194
198
  print(lev_info)
195
199
 
200
+
201
+ async def test_close_all():
202
+ async with pybotters.Client(apis="./apis.json") as client:
203
+ async with Bitmart(client=client) as broker:
204
+ await broker.place_order(
205
+ symbol="PORT3USDT",
206
+ side="buy",
207
+ qty_contract=5,
208
+ category="market",
209
+ price=0,
210
+ )
211
+
212
+
213
+ async def test_sub_book_compare():
214
+ async with pybotters.Client() as client:
215
+ async with Bitmart(client=client) as broker:
216
+ mst_t = None
217
+ a_counter = 0
218
+ a_last_time = None
219
+ a_total_interval = 0.0
220
+
221
+ def book_handler(msg: dict, ws):
222
+ nonlocal mst_t
223
+ nonlocal a_counter
224
+ nonlocal a_last_time
225
+ nonlocal a_total_interval
226
+ a_counter += 1
227
+ now = time.time() * 1000 # ms
228
+ if a_last_time is not None:
229
+ a_total_interval += (now - a_last_time)
230
+ a_last_time = now
231
+ mst_t = msg.get("data", {}).get("ms_t", None)
232
+
233
+ b_counter = 0
234
+ b_last_time = None
235
+ b_total_interval = 0.0
236
+
237
+ def book_handler_2(msg: dict, ws):
238
+ nonlocal mst_t
239
+ nonlocal b_counter
240
+ nonlocal b_last_time
241
+ nonlocal b_total_interval
242
+ way = msg.get("data", {}).get("way", None)
243
+ if way == 1:
244
+ b_counter += 1
245
+ now = time.time() * 1000 # ms
246
+ if b_last_time is not None:
247
+ b_total_interval += (now - b_last_time)
248
+ b_last_time = now
249
+ mst_t = msg.get("data", {}).get("ms_t", None)
250
+
251
+
252
+
253
+ await client.ws_connect(
254
+ url="wss://openapi-ws-v2.bitmart.com/api?protocol=1.1",
255
+ send_json=[
256
+ {"action": "subscribe", "args": ["futures/depth5:BTCUSDT@100ms"]}
257
+ ],
258
+ hdlr_json=book_handler,
259
+ )
260
+
261
+
262
+ await client.ws_connect(
263
+ url="wss://contract-ws-v2.bitmart.com/v1/ifcontract/realTime",
264
+ send_json=[
265
+ {
266
+ "action": "subscribe",
267
+ "args": [
268
+ "Depth:1",
269
+ ],
270
+ }
271
+ ],
272
+ hdlr_json=book_handler_2,
273
+ )
274
+
275
+ await asyncio.sleep(10)
276
+ print(f"Handler A received {a_counter} messages.")
277
+ if a_counter > 1:
278
+ print(f"Handler A average interval: {a_total_interval / (a_counter - 1):.2f} ms")
279
+ else:
280
+ print("Handler A average interval: N/A")
281
+
282
+ print(f"Handler B received {b_counter} messages.")
283
+ if b_counter > 1:
284
+ print(f"Handler B average interval: {b_total_interval / (b_counter - 1):.2f} ms")
285
+ else:
286
+ print("Handler B average interval: N/A")
287
+
288
+ async def test_sub_book_api():
289
+ async with pybotters.Client() as client:
290
+ async with Bitmart(client=client) as broker:
291
+ await broker.sub_orderbook(['TRXUSDT', 'DOTUSDT'], depth_limit=1, use_api_ws=True)
292
+ await broker.store.book.wait()
293
+ while True:
294
+ await broker.store.book.wait()
295
+ print(broker.store.book.find())
296
+
196
297
  if __name__ == "__main__":
197
- asyncio.run(test_set_leverage())
298
+ asyncio.run(test_sub_book_api())
@@ -921,7 +921,7 @@ wheels = [
921
921
 
922
922
  [[package]]
923
923
  name = "hyperquant"
924
- version = "1.1"
924
+ version = "1.2"
925
925
  source = { editable = "." }
926
926
  dependencies = [
927
927
  { name = "aiohttp" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes