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.
@@ -26,7 +26,8 @@ class OurbitSwap:
26
26
  return self
27
27
 
28
28
  async def update(
29
- self, update_type: Literal["position", "orders", "balance", "ticker", "all"] = "all"
29
+ self,
30
+ update_type: Literal["position", "orders", "balance", "ticker", "all"] = "all",
30
31
  ):
31
32
  """由于交易所很多不支持ws推送,这里使用Rest"""
32
33
  all_urls = [
@@ -34,7 +35,7 @@ class OurbitSwap:
34
35
  f"{self.api_url}/api/v1/private/order/list/open_orders?page_size=200",
35
36
  f"{self.api_url}/api/v1/private/account/assets",
36
37
  f"{self.api_url}/api/v1/contract/ticker",
37
- f"{self.api_url}/api/platform/spot/market/v2/symbols"
38
+ f"{self.api_url}/api/platform/spot/market/v2/symbols",
38
39
  ]
39
40
 
40
41
  url_map = {
@@ -56,13 +57,8 @@ class OurbitSwap:
56
57
  async def sub_tickers(self):
57
58
  self.client.ws_connect(
58
59
  self.ws_url,
59
- send_json={
60
- "method": "sub.tickers",
61
- "param": {
62
- "timezone": "UTC+8"
63
- }
64
- },
65
- hdlr_json=self.store.onmessage
60
+ send_json={"method": "sub.tickers", "param": {"timezone": "UTC+8"}},
61
+ hdlr_json=self.store.onmessage,
66
62
  )
67
63
 
68
64
  async def sub_orderbook(self, symbols: str | list[str]):
@@ -74,27 +70,29 @@ class OurbitSwap:
74
70
 
75
71
  for symbol in symbols:
76
72
  step = self.store.detail.find({"symbol": symbol})[0].get("tick_size")
77
-
78
- send_jsons.append({
79
- "method": "sub.depth.step",
80
- "param": {
81
- "symbol": symbol,
82
- "step": str(step)
73
+ step_str = str(Decimal(str(step)).normalize())
74
+
75
+ send_jsons.append(
76
+ {
77
+ "method": "sub.depth.step",
78
+ "param": {
79
+ "symbol": symbol,
80
+ "step": step_str,
81
+ },
83
82
  }
84
- })
83
+ )
85
84
 
86
85
  await self.client.ws_connect(
87
- self.ws_url,
88
- send_json=send_jsons,
89
- hdlr_json=self.store.onmessage
86
+ self.ws_url, send_json=send_jsons, hdlr_json=self.store.onmessage
90
87
  )
91
88
 
92
89
  async def sub_personal(self):
93
- self.client.ws_connect(
90
+ wsapp = self.client.ws_connect(
94
91
  self.ws_url,
95
- send_json={ "method": "sub.personal.user.preference"},
96
- hdlr_json=self.store.onmessage
92
+ send_json={"method": "sub.personal.user.preference"},
93
+ hdlr_json=self.store.onmessage,
97
94
  )
95
+ await wsapp._event.wait()
98
96
 
99
97
  def ret_content(self, res: pybotters.FetchResult):
100
98
  match res.data:
@@ -102,13 +100,15 @@ class OurbitSwap:
102
100
  return res.data["data"]
103
101
  case _:
104
102
  raise Exception(f"Failed api {res.response.url}: {res.data}")
105
-
106
103
 
107
104
  def fmt_price(self, symbol, price: float) -> float:
108
105
  tick = self.store.detail.find({"symbol": symbol})[0].get("tick_size")
109
106
  tick_dec = Decimal(str(tick))
110
107
  price_dec = Decimal(str(price))
111
- return float((price_dec / tick_dec).quantize(Decimal("1"), rounding=ROUND_HALF_UP) * tick_dec)
108
+ return float(
109
+ (price_dec / tick_dec).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
110
+ * tick_dec
111
+ )
112
112
 
113
113
  async def place_order(
114
114
  self,
@@ -120,6 +120,7 @@ class OurbitSwap:
120
120
  usdt_amount: Optional[float] = None,
121
121
  leverage: Optional[int] = 20,
122
122
  position_id: Optional[int] = None,
123
+ quantity: float = None, # 兼容参数,不使用
123
124
  ):
124
125
  """
125
126
  size为合约张数, openType 1 为逐仓, 2为全仓
@@ -135,14 +136,13 @@ class OurbitSwap:
135
136
  raise ValueError("params err")
136
137
 
137
138
  max_lev = self.store.detail.find({"symbol": symbol})[0].get("max_lev")
138
-
139
+
139
140
  if usdt_amount is not None:
140
141
  cs = self.store.detail.find({"symbol": symbol})[0].get("contract_sz")
141
142
  size = max(int(usdt_amount / cs / price), 1)
142
143
 
143
144
  if price is not None:
144
145
  price = self.fmt_price(symbol, price)
145
-
146
146
 
147
147
  leverage = min(max_lev, leverage)
148
148
 
@@ -165,22 +165,28 @@ class OurbitSwap:
165
165
  data["price"] = str(price)
166
166
 
167
167
  if "close" in side:
168
- if side == 'close_buy':
168
+ if side == "close_buy":
169
169
  data["side"] = 2
170
- elif side == 'close_sell':
170
+ elif side == "close_sell":
171
171
  data["side"] = 4
172
-
172
+
173
173
  if position_id is None:
174
174
  raise ValueError("position_id is required for closing position")
175
175
  data["positionId"] = position_id
176
- # import time
177
- # print(time.time(), '下单')
178
- res = await self.client.fetch(
176
+
177
+ res = await self.client.fetch(
179
178
  "POST", f"{self.api_url}/api/v1/private/order/create", data=data
180
179
  )
181
- return self.ret_content(res)
182
-
183
- async def place_tpsl(self,
180
+ # 'orderId' =
181
+ # '226474723700166962'
182
+ # 'ts' =
183
+ # 1758034181833
184
+ ret_c = self.ret_content(res)
185
+ # 只返回 orderId
186
+ return ret_c["orderId"]
187
+
188
+ async def place_tpsl(
189
+ self,
184
190
  position_id: int,
185
191
  take_profit: Optional[float] = None,
186
192
  stop_loss: Optional[float] = None,
@@ -214,12 +220,9 @@ class OurbitSwap:
214
220
  data["takeProfitPrice"] = take_profit
215
221
  if stop_loss is not None:
216
222
  data["stopLossPrice"] = stop_loss
217
-
218
223
 
219
224
  res = await self.client.fetch(
220
- "POST",
221
- f"{self.api_url}/api/v1/private/stoporder/place",
222
- data=data
225
+ "POST", f"{self.api_url}/api/v1/private/stoporder/place", data=data
223
226
  )
224
227
 
225
228
  return self.ret_content(res)
@@ -312,7 +315,7 @@ class OurbitSwap:
312
315
 
313
316
  class OurbitSpot:
314
317
 
315
- def __init__(self, client: pybotters.Client):
318
+ def __init__(self, client: pybotters.Client, personal_msg_cb: callable=None):
316
319
  """
317
320
  ✅ 完成:
318
321
  下单, 撤单, 查询资金, 查询持有订单, 查询历史订单
@@ -322,6 +325,7 @@ class OurbitSpot:
322
325
  self.store = OurbitSpotDataStore()
323
326
  self.api_url = "https://www.ourbit.com"
324
327
  self.ws_url = "wss://www.ourbit.com/ws"
328
+ self.personal_msg_cb = personal_msg_cb
325
329
 
326
330
  async def __aenter__(self) -> "OurbitSpot":
327
331
  client = self.client
@@ -330,171 +334,217 @@ class OurbitSpot:
330
334
  )
331
335
  return self
332
336
 
333
- async def update(self, update_type: Literal["orders", "balance", "ticker", "book", "all"] = "all"):
337
+ async def update(
338
+ self, update_type: Literal["orders", "balance", "ticker", "book", "all"] = "all"
339
+ ):
334
340
 
335
341
  all_urls = [
336
342
  f"{self.api_url}/api/platform/spot/order/current/orders/v2?orderTypes=1%2C2%2C3%2C4%2C5%2C100&pageNum=1&pageSize=100&states=0%2C1%2C3",
337
343
  f"{self.api_url}/api/assetbussiness/asset/spot/statistic",
338
- f"{self.api_url}/api/platform/spot/market/v2/tickers"
344
+ f"{self.api_url}/api/platform/spot/market/v2/tickers",
339
345
  ]
340
346
 
341
347
  # orderTypes=1%2C2%2C3%2C4%2C5%2C100&pageNum=1&pageSize=100&states=0%2C1%2C3
342
-
348
+
343
349
  url_map = {
344
350
  "orders": [all_urls[0]],
345
351
  "balance": [all_urls[1]],
346
352
  "ticker": [all_urls[2]],
347
- "all": all_urls
353
+ "all": all_urls,
348
354
  }
349
355
 
350
356
  try:
351
357
  urls = url_map[update_type]
352
358
  except KeyError:
353
359
  raise ValueError(f"Unknown update type: {update_type}")
354
-
360
+
355
361
  # 直接传协程进去,initialize 会自己 await
356
362
  await self.store.initialize(*(self.client.get(url) for url in urls))
357
363
 
358
-
359
364
  async def sub_personal(self):
360
365
  """订阅个人频道"""
361
366
  # https://www.ourbit.com/ucenter/api/ws_token
362
- res = await self.client.fetch(
363
- 'GET', f"{self.api_url}/ucenter/api/ws_token"
364
- )
365
-
366
- token = res.data['data'].get("wsToken")
367
+ res = await self.client.fetch("GET", f"{self.api_url}/ucenter/api/ws_token")
367
368
 
369
+ token = res.data["data"].get("wsToken")
368
370
 
369
- self.client.ws_connect(
371
+ app = self.client.ws_connect(
370
372
  f"{self.ws_url}?wsToken={token}&platform=web",
371
373
  send_json={
372
374
  "method": "SUBSCRIPTION",
373
375
  "params": [
374
376
  "spot@private.orders",
375
377
  "spot@private.trigger.orders",
376
- "spot@private.balances"
378
+ "spot@private.balances",
377
379
  ],
378
- "id": 1
380
+ "id": 1,
379
381
  },
380
- hdlr_json=self.store.onmessage
382
+ hdlr_json=(
383
+ self.store.onmessage
384
+ if self.personal_msg_cb is None
385
+ else [self.store.onmessage, self.personal_msg_cb]
386
+ ),
381
387
  )
382
388
 
389
+ await app._event.wait()
390
+
383
391
  async def sub_orderbook(self, symbols: str | list[str]):
384
392
  """订阅订单簿深度数据
385
-
393
+
386
394
  Args:
387
395
  symbols: 交易对符号,可以是单个字符串或字符串列表
388
396
  """
397
+ import logging
398
+
399
+ logger = logging.getLogger("OurbitSpot")
400
+
389
401
  if isinstance(symbols, str):
390
402
  symbols = [symbols]
391
403
 
392
- # 并发获取每个交易对的初始深度数据
393
- tasks = [
394
- self.client.fetch('GET', f"{self.api_url}/api/platform/spot/market/depth?symbol={symbol}")
395
- for symbol in symbols
396
- ]
397
-
398
- # 等待所有请求完成
399
- responses = await asyncio.gather(*tasks)
400
-
401
- # 处理响应数据
402
- for response in responses:
403
- self.store.book._onresponse(response.data)
404
-
405
404
  # 构建订阅参数
406
405
  subscription_params = []
407
406
  for symbol in symbols:
408
407
  subscription_params.append(f"spot@public.increase.aggre.depth@{symbol}")
409
408
 
410
-
411
409
  # 一次sub20个,超过需要分开订阅
412
410
  for i in range(0, len(subscription_params), 20):
413
- self.client.ws_connect(
414
- 'wss://www.ourbit.com/ws?platform=web',
411
+ wsapp = self.client.ws_connect(
412
+ "wss://www.ourbit.com/ws?platform=web",
415
413
  send_json={
416
414
  "method": "SUBSCRIPTION",
417
- "params": subscription_params[i:i + 20],
418
- "id": 2
415
+ "params": subscription_params[i : i + 20],
416
+ "id": 2,
419
417
  },
420
- hdlr_json=self.store.onmessage
418
+ hdlr_json=self.store.onmessage,
419
+ )
420
+ await wsapp._event.wait()
421
+
422
+ # await asyncio.sleep(1) # 等待ws连接稳定
423
+
424
+ # 并发获取每个交易对的初始深度数据
425
+ tasks = [
426
+ self.client.fetch(
427
+ "GET", f"{self.api_url}/api/platform/spot/market/depth?symbol={symbol}"
421
428
  )
429
+ for symbol in symbols
430
+ ]
431
+
432
+ # 等待所有请求完成
433
+ responses = await asyncio.gather(*tasks)
434
+
435
+ # 处理响应数据
436
+ for idx, response in enumerate(responses):
437
+ symbol = symbols[idx]
438
+ self.store.book._onresponse(response.data)
439
+
440
+ async def check_loss():
441
+ await asyncio.sleep(1)
442
+ while True:
443
+ loss = self.store.book.loss
444
+ for symbol, is_loss in loss.items():
445
+ if is_loss:
446
+ resp = await self.client.fetch(
447
+ "GET",
448
+ f"{self.api_url}/api/platform/spot/market/depth?symbol={symbol}",
449
+ )
450
+ self.store.book._onresponse(resp.data)
451
+ await asyncio.sleep(1)
452
+
453
+ asyncio.create_task(check_loss())
422
454
 
423
455
  async def place_order(
424
456
  self,
425
457
  symbol: str,
426
458
  side: Literal["buy", "sell"],
427
- price: float,
459
+ price: float = None,
428
460
  quantity: float = None,
429
461
  order_type: Literal["market", "limit"] = "limit",
430
- usdt_amount: float = None
462
+ usdt_amount: float = None,
431
463
  ):
432
464
  """现货下单
433
-
465
+
434
466
  Args:
435
467
  symbol: 交易对,如 "SOL_USDT"
436
468
  side: 买卖方向 "buy" 或 "sell"
437
- price: 价格
469
+ price: 价格,市价单可为None
438
470
  quantity: 数量
439
471
  order_type: 订单类型 "market" 或 "limit"
440
472
  usdt_amount: USDT金额,如果指定则根据价格计算数量
441
-
473
+
442
474
  Returns:
443
475
  订单响应数据
444
476
  """
477
+ # 参数检查
478
+ if order_type == "limit" and price is None:
479
+ raise ValueError("Limit orders require a price")
480
+ if quantity is None and usdt_amount is None:
481
+ raise ValueError("Either quantity or usdt_amount must be specified")
482
+
445
483
  # 解析交易对
446
- currency, market = symbol.split("_")
484
+ parts = symbol.split("_")
485
+ if len(parts) != 2:
486
+ raise ValueError(f"Invalid symbol format: {symbol}")
447
487
 
448
- detail = self.store.detail.get({
449
- 'name': currency
450
- })
488
+ currency, market = parts
451
489
 
490
+ # 获取交易对详情
491
+ detail = self.store.detail.get({"name": currency})
452
492
  if not detail:
453
493
  raise ValueError(f"Unknown currency: {currency}")
454
494
 
455
- price_scale = detail.get('price_scale')
456
- quantity_scale = detail.get('quantity_scale')
495
+ price_scale = detail.get("price_scale")
496
+ quantity_scale = detail.get("quantity_scale")
457
497
 
458
-
459
- # 如果指定了USDT金额,重新计算数量
460
- if usdt_amount is not None:
461
- if side == "buy":
462
- quantity = usdt_amount / price
463
- else:
464
- # 卖出时usdt_amount表示要卖出的币种价值
465
- quantity = usdt_amount / price
466
-
467
- # 格式化价格和数量
468
- if price_scale is not None:
469
- price = round(price, price_scale)
470
-
471
- if quantity_scale is not None:
472
- quantity = round(quantity, quantity_scale)
473
-
474
498
  # 构建请求数据
475
- data = {
476
- "currency": currency,
477
- "market": market,
478
- "tradeType": side.upper(),
479
- "quantity": str(quantity),
480
- }
481
-
499
+ data = {"currency": currency, "market": market, "tradeType": side.upper()}
500
+
501
+ # 处理市价单和限价单的不同参数
482
502
  if order_type == "limit":
483
503
  data["orderType"] = "LIMIT_ORDER"
484
- data["price"] = str(price)
504
+ data["price"] = str(
505
+ round(price, price_scale) if price_scale is not None else price
506
+ )
507
+
508
+ # 计算并设置数量
509
+ if quantity is None and usdt_amount is not None and price:
510
+ quantity = usdt_amount / price
511
+
512
+ if quantity_scale is not None:
513
+ quantity = round(quantity, quantity_scale)
514
+ data["quantity"] = str(quantity)
515
+
485
516
  elif order_type == "market":
486
517
  data["orderType"] = "MARKET_ORDER"
487
- # 市价单通常不需要价格参数
488
-
489
- res = await self.client.fetch(
490
- "POST",
491
- f"{self.api_url}/api/platform/spot/order/place",
492
- json=data
493
- )
494
-
518
+
519
+ # 市价单可以使用数量或金额,但不能同时使用
520
+ if usdt_amount is not None:
521
+ data["amount"] = str(usdt_amount)
522
+ else:
523
+ if quantity_scale is not None:
524
+ quantity = round(quantity, quantity_scale)
525
+ data["quantity"] = str(quantity)
526
+
527
+ if price:
528
+ data["price"] = str(price)
529
+
530
+ # 确定API端点
531
+ url = f'{self.api_url}/api/platform/spot/{"v4/order/place" if order_type == "market" else "order/place"}'
532
+ # print(f"Placing {symbol}: {data}")
533
+ # 发送请求
534
+ res = await self.client.fetch("POST", url, json=data)
535
+
495
536
  # 处理响应
496
- match res.data:
497
- case {"msg": 'success'}:
498
- return res.data["data"]
499
- case _:
500
- raise Exception(f"Failed to place order: {res.data}")
537
+ if res.data.get("msg") == "success":
538
+ return res.data["data"]
539
+ raise Exception(f"Failed to place order: {res.data}")
540
+
541
+ async def cancel_orders(self, order_ids: list[str]):
542
+
543
+ for order_id in order_ids:
544
+ url = f"{self.api_url}/api/platform/spot/order/cancel/v2?orderId={order_id}"
545
+ await self.client.fetch("DELETE", url)
546
+
547
+ async def cancel_order(self, order_id: str):
548
+
549
+ url = f"{self.api_url}/api/platform/spot/order/cancel/v2?orderId={order_id}"
550
+ res = await self.client.fetch("DELETE", url)
hyperquant/core.py CHANGED
@@ -269,10 +269,10 @@ class ExchangeBase:
269
269
  )
270
270
 
271
271
  class Exchange(ExchangeBase):
272
- def __init__(self, trade_symbols, fee=0.0002, initial_balance=10000, recorded=False):
272
+ def __init__(self, trade_symbols:list=[], fee=0.0002, initial_balance=10000, recorded=False):
273
273
  super().__init__(initial_balance=initial_balance, recorded=recorded)
274
274
  self.fee = fee
275
- self.trade_symbols = trade_symbols
275
+ self.trade_symbols:list = trade_symbols
276
276
  self.id_gen = 0
277
277
  self.account['USDT'].update({
278
278
  'hold': 0,
@@ -280,8 +280,12 @@ class Exchange(ExchangeBase):
280
280
  'short': 0
281
281
  })
282
282
  for symbol in trade_symbols:
283
- self.account[symbol] = {'amount': 0, 'hold_price': 0, 'value': 0, 'price': 0,
284
- 'realised_profit': 0, 'unrealised_profit': 0, 'fee': 0}
283
+ self.account[symbol] = self._act_template
284
+
285
+ @property
286
+ def _act_template(self):
287
+ return {'amount': 0, 'hold_price': 0, 'value': 0, 'price': 0,
288
+ 'realised_profit': 0, 'unrealised_profit': 0, 'fee': 0}.copy()
285
289
 
286
290
  def Trade(self, symbol, direction, price, amount, **kwargs):
287
291
  if self.recorded and 'time' not in kwargs:
@@ -307,8 +311,7 @@ class Exchange(ExchangeBase):
307
311
 
308
312
  if symbol not in self.trade_symbols:
309
313
  self.trade_symbols.append(symbol)
310
- self.account[symbol] = {'amount': 0, 'hold_price': 0, 'value': 0, 'price': 0,
311
- 'realised_profit': 0, 'unrealised_profit': 0, 'fee': 0}
314
+ self.account[symbol] = self._act_template
312
315
 
313
316
  cover_amount = 0 if direction * self.account[symbol]['amount'] >= 0 else min(abs(self.account[symbol]['amount']), amount)
314
317
  open_amount = amount - cover_amount
@@ -332,6 +335,9 @@ class Exchange(ExchangeBase):
332
335
  self.account[symbol]['realised_profit'] += profit
333
336
  self.account[symbol]['amount'] -= -direction * cover_amount
334
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
+
335
341
  self.account[symbol]['hold_price'] = 0 if self.account[symbol]['amount'] == 0 else self.account[symbol]['hold_price']
336
342
 
337
343
  if open_amount > 0:
@@ -343,6 +349,7 @@ class Exchange(ExchangeBase):
343
349
 
344
350
  if kwargs:
345
351
  self.opt.update(kwargs)
352
+ self.account[symbol].update(kwargs)
346
353
 
347
354
  # 记录账户总资产到 history
348
355
  if self.recorded:
hyperquant/logkit.py CHANGED
@@ -146,10 +146,25 @@ class MinConsoleHandler(logging.StreamHandler):
146
146
  else:
147
147
  super().emit(record)
148
148
 
149
+ # ====================================================================================================
150
+ # ** NullLogger 类,用于禁用日志 **
151
+ # ====================================================================================================
152
+ class NullLogger:
153
+ def debug(self, *a, **k): pass
154
+ def info(self, *a, **k): pass
155
+ def ok(self, *a, **k): pass
156
+ def warning(self, *a, **k): pass
157
+ def error(self, *a, **k): pass
158
+ def critical(self, *a, **k): pass
159
+ def exception(self, *a, **k): pass
160
+ def divider(self, *a, **k): pass
161
+
149
162
  # ====================================================================================================
150
163
  # ** 功能函数 **
151
164
  # ====================================================================================================
152
- def get_logger(name=None, file_path=None, show_time=False, use_color=True, timezone="Asia/Shanghai") -> Logger:
165
+ def get_logger(name=None, file_path=None, show_time=False, use_color=True, timezone="Asia/Shanghai", level: object = None, enable_console: bool = True, enabled: bool = True):
166
+ if not enabled:
167
+ return NullLogger()
153
168
  if name is None:
154
169
  name = '_'
155
170
  logger_instance = Logger(name, show_time, use_color, timezone) # 传递时区参数
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperquant
3
- Version: 0.4
3
+ Version: 0.6
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,23 @@
1
1
  hyperquant/__init__.py,sha256=UpjiX4LS5jmrBc2kE8RiLR02eCfD8JDQrR1q8zkLNcQ,161
2
- hyperquant/core.py,sha256=7XrpuHvccWl9lNyVihqaptupqUMsG3xYmQr8eEDrwS4,20610
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
- hyperquant/logkit.py,sha256=WALpXpIA3Ywr5DxKKK3k5EKubZ2h-ISGfc5dUReQUBQ,7795
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
+ hyperquant/broker/edgex.py,sha256=qQtc8jZqB5ZODoGGVcG_aIVUlrJX_pRF9EyO927LiVM,6646
8
9
  hyperquant/broker/hyperliquid.py,sha256=7MxbI9OyIBcImDelPJu-8Nd53WXjxPB5TwE6gsjHbto,23252
9
- hyperquant/broker/ourbit.py,sha256=BWXH-FQoBZoEzBKYY0mCXYW9Iy3EgHTYan4McFp4-R8,15952
10
+ hyperquant/broker/ourbit.py,sha256=NUcDSIttf-HGWzoW1uBTrGLPHlkuemMjYCm91MigTno,18228
10
11
  hyperquant/broker/ws.py,sha256=umRzxwCaZaRIgIq4YY-AuA0wCXFT0uOBmQbIXFY8CK0,1555
11
12
  hyperquant/broker/lib/hpstore.py,sha256=LnLK2zmnwVvhEbLzYI-jz_SfYpO1Dv2u2cJaRAb84D8,8296
12
13
  hyperquant/broker/lib/hyper_types.py,sha256=HqjjzjUekldjEeVn6hxiWA8nevAViC2xHADOzDz9qyw,991
14
+ hyperquant/broker/models/edgex.py,sha256=KRJB9PIjP555P-GiVIYm01sFtlAWeYlk5y-YuoXhk9k,15606
13
15
  hyperquant/broker/models/hyperliquid.py,sha256=c4r5739ibZfnk69RxPjQl902AVuUOwT8RNvKsMtwXBY,9459
14
- hyperquant/broker/models/ourbit.py,sha256=-XgxQ9JB-hk7r6u2CmXsNx4055kpYr0lZWh0Su6SWIA,37539
16
+ hyperquant/broker/models/ourbit.py,sha256=xMcbuCEXd3XOpPBq0RYF2zpTFNnxPtuNJZCexMZVZ1k,41965
15
17
  hyperquant/datavison/_util.py,sha256=92qk4vO856RqycO0YqEIHJlEg-W9XKapDVqAMxe6rbw,533
16
18
  hyperquant/datavison/binance.py,sha256=3yNKTqvt_vUQcxzeX4ocMsI5k6Q6gLZrvgXxAEad6Kc,5001
17
19
  hyperquant/datavison/coinglass.py,sha256=PEjdjISP9QUKD_xzXNzhJ9WFDTlkBrRQlVL-5pxD5mo,10482
18
20
  hyperquant/datavison/okx.py,sha256=yg8WrdQ7wgWHNAInIgsWPM47N3Wkfr253169IPAycAY,6898
19
- hyperquant-0.4.dist-info/METADATA,sha256=CEAtZ3dZLsujTB7cj0BGAFOd9MUKd_EDGpgru09ozww,4316
20
- hyperquant-0.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
21
- hyperquant-0.4.dist-info/RECORD,,
21
+ hyperquant-0.6.dist-info/METADATA,sha256=lQSDRR5kM9kI_maMt9erlxLv_sPaX3EZ0la5uXj33ys,4316
22
+ hyperquant-0.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ hyperquant-0.6.dist-info/RECORD,,