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

@@ -60,11 +60,10 @@ class Coinw:
60
60
  "all",
61
61
  ] = "all",
62
62
  *,
63
- instrument: str | None = None,
64
63
  position_type: Literal["execute", "plan", "planTrigger"] = "execute",
65
64
  page: int | None = None,
66
65
  page_size: int | None = None,
67
- open_ids: str | None = None,
66
+ instrument: str | None = None,
68
67
  ) -> None:
69
68
  """刷新本地缓存,使用 CoinW REST API。
70
69
 
@@ -108,16 +107,8 @@ class Coinw:
108
107
  )
109
108
 
110
109
  if include_position:
111
- if not instrument:
112
- raise ValueError("instrument is required when updating positions")
113
- params = {"instrument": instrument}
114
- if open_ids:
115
- params["openIds"] = open_ids
116
110
  requests.append(
117
- self.client.get(
118
- f"{self.rest_api}/v1/perpum/positions",
119
- params=params,
120
- )
111
+ self.client.get(f"{self.rest_api}/v1/perpum/positions/all")
121
112
  )
122
113
 
123
114
  if include_balance:
@@ -186,6 +177,51 @@ class Coinw:
186
177
  data = await res.json()
187
178
  return self._ensure_ok("place_order", data)
188
179
 
180
+ async def close_position(
181
+ self,
182
+ open_id: str | int,
183
+ *,
184
+ position_type: Literal["plan", "planTrigger", "execute"] = "plan",
185
+ close_num: str | float | int | None = None,
186
+ close_rate: str | float | int | None = None,
187
+ order_price: str | float | None = None,
188
+ instrument: str | None = None,
189
+ ) -> dict[str, Any]:
190
+ """关闭单个仓位(``DELETE /v1/perpum/positions``)。
191
+
192
+ Params
193
+ ------
194
+ open_id: ``openId`` / 持仓唯一 ID。
195
+ position_type: 订单类型 ``plan`` / ``planTrigger`` / ``execute``。
196
+ close_num: 按合约数量平仓(与 ``close_rate`` 至少指定其一)。
197
+ close_rate: 按比例平仓(0-1)。
198
+ order_price: 限价平仓时指定价格。
199
+ instrument: 交易品种(部分情况下需要传入,例如限价单)。
200
+ """
201
+
202
+ if close_num is None and close_rate is None:
203
+ raise ValueError("close_num or close_rate must be provided")
204
+
205
+ payload: dict[str, Any] = {
206
+ "id": str(open_id),
207
+ "positionType": position_type,
208
+ }
209
+ if close_num is not None:
210
+ payload["closeNum"] = str(close_num)
211
+ if close_rate is not None:
212
+ payload["closeRate"] = str(close_rate)
213
+ if order_price is not None:
214
+ payload["orderPrice"] = str(order_price)
215
+ if instrument is not None:
216
+ payload["instrument"] = instrument
217
+
218
+ res = await self.client.delete(
219
+ f"{self.rest_api}/v1/perpum/positions",
220
+ data=payload,
221
+ )
222
+ data = await res.json()
223
+ return self._ensure_ok("close_position", data)
224
+
189
225
  async def place_order_web(
190
226
  self,
191
227
  instrument: str,
@@ -282,20 +282,6 @@ class Position(DataStore):
282
282
 
283
283
  _KEYS = ["openId"]
284
284
 
285
- @staticmethod
286
- def _normalize(entry: dict[str, Any]) -> dict[str, Any] | None:
287
- open_id = entry.get("openId")
288
- if open_id is None:
289
- return None
290
- normalized = dict(entry)
291
- normalized["openId"] = str(open_id)
292
- normalized["status"] = str(entry.get("status") or entry.get("orderStatus") or "").lower()
293
- normalized["is_closed"] = normalized["status"] in {"close", "closed", "finish"}
294
- normalized["currentPiece"] = str(entry.get("currentPiece")) if entry.get("currentPiece") is not None else None
295
- normalized["closedPiece"] = str(entry.get("closedPiece")) if entry.get("closedPiece") is not None else None
296
- normalized["quantity"] = str(entry.get("quantity")) if entry.get("quantity") is not None else None
297
- normalized["updatedDate"] = entry.get("updatedDate")
298
- return normalized
299
285
 
300
286
  def _onresponse(self, data: Any) -> None:
301
287
  payload = []
@@ -308,9 +294,8 @@ class Position(DataStore):
308
294
  for entry in payload or []:
309
295
  if not isinstance(entry, dict):
310
296
  continue
311
- normalized = self._normalize(entry)
312
- if normalized:
313
- items.append(normalized)
297
+ entry['openId'] = str(entry.get("id"))
298
+ items.append(entry)
314
299
 
315
300
  self._clear()
316
301
  if items:
@@ -318,6 +303,7 @@ class Position(DataStore):
318
303
 
319
304
  def _on_message(self, msg: dict[str, Any]) -> None:
320
305
  data = msg.get("data")
306
+
321
307
  if isinstance(data, dict) and data.get("result") is not None:
322
308
  return
323
309
 
@@ -337,17 +323,14 @@ class Position(DataStore):
337
323
  for entry in entries:
338
324
  if not isinstance(entry, dict):
339
325
  continue
340
- normalized = self._normalize(entry)
341
- if not normalized:
342
- continue
326
+ normalized = entry
343
327
 
344
- criteria = {"openId": normalized["openId"]}
345
328
 
346
- if normalized.get("is_closed"):
347
- to_delete.append(criteria)
329
+ if normalized.get("status") == 'close':
330
+ to_delete.append(normalized)
348
331
  continue
349
332
 
350
- if self.find(criteria):
333
+ if self.find(normalized):
351
334
  to_update.append(normalized)
352
335
  else:
353
336
  to_insert.append(normalized)
@@ -460,6 +443,7 @@ class CoinwFuturesDataStore(DataStoreCollection):
460
443
 
461
444
  def onmessage(self, msg: Item, ws: ClientWebSocketResponse | None = None) -> None:
462
445
  msg_type = msg.get("type")
446
+ # print(msg)
463
447
  if msg_type == "depth":
464
448
  self.book._on_message(msg)
465
449
  elif msg_type == "order":
@@ -481,7 +465,7 @@ class CoinwFuturesDataStore(DataStoreCollection):
481
465
  self.ticker._onresponse(data)
482
466
  elif res.url.path == "/v1/perpum/orders/open":
483
467
  self.orders._onresponse(data)
484
- elif res.url.path == "/v1/perpum/positions":
468
+ elif res.url.path == "/v1/perpum/positions/all":
485
469
  self.position._onresponse(data)
486
470
  elif res.url.path == "/v1/perpum/account/getUserAssets":
487
471
  self.balance._onresponse(data)
@@ -666,17 +650,48 @@ class CoinwFuturesDataStore(DataStoreCollection):
666
650
  - REST: ``GET /v1/perpum/positions``
667
651
  - WebSocket: ``type == "position"``
668
652
 
669
- 数据结构(节选)::
653
+ .. code:: json
670
654
 
671
655
  {
672
- "id": 2435521222631982507,
673
- "instrument": "BTC",
674
- "direction": "short",
675
- "openPrice": 88230.5,
676
- "currentPiece": 1,
677
- "profitUnreal": 0.0086,
678
- "status": "open"
679
- }
656
+ "currentPiece": "0",
657
+ "isProfession": 0,
658
+ "leverage": "10",
659
+ "originalType": "execute",
660
+ "orderId": "33309059291614824",
661
+ "contractType": 1,
662
+ "openId": "2435521222638707873",
663
+ "fee": "0.00020724",
664
+ "openPrice": "0.3456",
665
+ "orderStatus": "finish",
666
+ "instrument": "JUP",
667
+ "quantityUnit": 1,
668
+ "source": "api",
669
+ "updatedDate": 1761192795412,
670
+ "positionModel": 1,
671
+ "feeRate": "0.0006",
672
+ "netProfit": "-0.00040724",
673
+ "baseSize": "1",
674
+ "quote": "usdt",
675
+ "liquidateBy": "manual",
676
+ "totalPiece": "1",
677
+ "orderPrice": "0",
678
+ "id": "23469279597150213",
679
+ "fundingSettle": "0",
680
+ "direction": "long",
681
+ "margin": "0.03435264",
682
+ "takerMaker": 1,
683
+ "indexPrice": "0.3455",
684
+ "quantity": "0.03456",
685
+ "userId": "1757458",
686
+ "closedPiece": "1",
687
+ "createdDate": 1761192793000,
688
+ "hedgeId": "23469279597150214",
689
+ "closePrice": "0.3454",
690
+ "positionMargin": "0.03435264",
691
+ "base": "jup",
692
+ "realPrice": "0.3454",
693
+ "status": "close"
694
+ }
680
695
  """
681
696
 
682
697
  return self._get("position", Position)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperquant
3
- Version: 0.88
3
+ Version: 0.89
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
@@ -6,7 +6,7 @@ hyperquant/logkit.py,sha256=nUo7nx5eONvK39GOhWwS41zNRL756P2J7-5xGzwXnTY,8462
6
6
  hyperquant/notikit.py,sha256=x5yAZ_tAvLQRXcRbcg-VabCaN45LUhvlTZnUqkIqfAA,3596
7
7
  hyperquant/broker/auth.py,sha256=xNZEQP0LRRV9BkT2uXBJ-vFfeahUnRVq1bjIT6YbQu8,10089
8
8
  hyperquant/broker/bitget.py,sha256=X_S0LKZ7FZAEb6oEMr1vdGP1fondzK74BhmNTpRDSEA,9488
9
- hyperquant/broker/coinw.py,sha256=hSUdMfezWn2jJ9LGTLMFx6waSTE5kuypINDY1q8us5I,15856
9
+ hyperquant/broker/coinw.py,sha256=SnJU0vASh77rfcpMGWaIfTblQSjQk3vjlW_4juYdbcs,17214
10
10
  hyperquant/broker/edgex.py,sha256=TqUO2KRPLN_UaxvtLL6HnA9dAQXC1sGxOfqTHd6W5k8,18378
11
11
  hyperquant/broker/hyperliquid.py,sha256=7MxbI9OyIBcImDelPJu-8Nd53WXjxPB5TwE6gsjHbto,23252
12
12
  hyperquant/broker/lbank.py,sha256=98M5wmSoeHwbBYMA3rh25zqLb6fQKVaEmwqALF5nOvY,22181
@@ -17,7 +17,7 @@ hyperquant/broker/lib/hpstore.py,sha256=LnLK2zmnwVvhEbLzYI-jz_SfYpO1Dv2u2cJaRAb8
17
17
  hyperquant/broker/lib/hyper_types.py,sha256=HqjjzjUekldjEeVn6hxiWA8nevAViC2xHADOzDz9qyw,991
18
18
  hyperquant/broker/lib/util.py,sha256=iMU1qF0CHj5zzlIMEQGwjz-qtEVosEe7slXOCuB7Rcw,566
19
19
  hyperquant/broker/models/bitget.py,sha256=0RwDY75KrJb-c-oYoMxbqxWfsILe-n_Npojz4UFUq7c,11389
20
- hyperquant/broker/models/coinw.py,sha256=XLrARTyT4ClF1SEhaZ9uZHVo7ntAvE7nKxaU_mzVmqU,21949
20
+ hyperquant/broker/models/coinw.py,sha256=LvLMVP7i-qkkTK1ubw8eBkMK2RQmFoKPxdKqmC4IToY,22157
21
21
  hyperquant/broker/models/edgex.py,sha256=vPAkceal44cjTYKQ_0BoNAskOpmkno_Yo1KxgMLPc6Y,33954
22
22
  hyperquant/broker/models/hyperliquid.py,sha256=c4r5739ibZfnk69RxPjQl902AVuUOwT8RNvKsMtwXBY,9459
23
23
  hyperquant/broker/models/lbank.py,sha256=vHkNKxIMzpoC_EwcZnEOPOupizF92yGWi9GKxvYYFUQ,19181
@@ -26,6 +26,6 @@ hyperquant/datavison/_util.py,sha256=92qk4vO856RqycO0YqEIHJlEg-W9XKapDVqAMxe6rbw
26
26
  hyperquant/datavison/binance.py,sha256=3yNKTqvt_vUQcxzeX4ocMsI5k6Q6gLZrvgXxAEad6Kc,5001
27
27
  hyperquant/datavison/coinglass.py,sha256=PEjdjISP9QUKD_xzXNzhJ9WFDTlkBrRQlVL-5pxD5mo,10482
28
28
  hyperquant/datavison/okx.py,sha256=yg8WrdQ7wgWHNAInIgsWPM47N3Wkfr253169IPAycAY,6898
29
- hyperquant-0.88.dist-info/METADATA,sha256=JGkF-AvAkw1MGD_XnNSS5wR4x9g1etWbmw5ifc36AdI,4317
30
- hyperquant-0.88.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
- hyperquant-0.88.dist-info/RECORD,,
29
+ hyperquant-0.89.dist-info/METADATA,sha256=NBPtmJcSeB4mhyzR_K0yISNPcMaiyzLqfjGkA_q6dME,4317
30
+ hyperquant-0.89.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
+ hyperquant-0.89.dist-info/RECORD,,