hyperquant 0.73__py3-none-any.whl → 0.75__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.
@@ -136,6 +136,162 @@ class Lbank:
136
136
 
137
137
  await self.store.initialize(*requests)
138
138
 
139
+ async def query_trade(
140
+ self,
141
+ order_id: str | None = None,
142
+ *,
143
+ product_group: str = "SwapU",
144
+ page_index: int = 1,
145
+ page_size: int = 20,
146
+ ) -> list[dict[str, Any]]:
147
+ """Fetch trade executions linked to a given OrderSysID.
148
+
149
+ Example response payload::
150
+
151
+ [
152
+ {
153
+ "TradeUnitID": "e1b03fb1-6849-464f-a",
154
+ "ProductGroup": "SwapU",
155
+ "CloseProfit": 0,
156
+ "BusinessNo": 1001770339345505,
157
+ "TradeID": "1000162046503720",
158
+ "PositionID": "1000632926272299",
159
+ "DeriveSource": "0",
160
+ "OrderID": "",
161
+ "Direction": "0",
162
+ "InstrumentID": "SOLUSDT",
163
+ "OffsetFlag": "0",
164
+ "Remark": "def",
165
+ "DdlnTime": "0",
166
+ "UseMargin": 0.054213,
167
+ "Currency": "USDT",
168
+ "Turnover": 5.4213,
169
+ "SettlementGroup": "SwapU",
170
+ "Leverage": 100,
171
+ "OrderSysID": "1000632948114584",
172
+ "ExchangeID": "Exchange",
173
+ "AccountID": "e1b03fb1-6849-464f-a986-94b9a6e625e6",
174
+ "TradeTime": 1760161085,
175
+ "Fee": 0.00325278,
176
+ "OrderPrice": 180.89,
177
+ "InsertTime": 1760161085,
178
+ "MemberID": "e1b03fb1-6849-464f-a986-94b9a6e625e6",
179
+ "MatchRole": "1",
180
+ "ClearCurrency": "USDT",
181
+ "Price": 180.71,
182
+ "Volume": 0.03,
183
+ "OpenPrice": 182.94,
184
+ "MasterAccountID": "",
185
+ "PriceCurrency": "USDT",
186
+ "FeeCurrency": "USDT"
187
+ }
188
+ ]
189
+ """
190
+
191
+ if not order_id:
192
+ raise ValueError("order_id is required to query order executions")
193
+
194
+ params = {
195
+ "ProductGroup": product_group,
196
+ "OrderSysID": order_id,
197
+ "pageIndex": page_index,
198
+ "pageSize": page_size,
199
+ }
200
+
201
+ res = await self.client.get(
202
+ f"{self.front_api}/cfd/query/v1.0/Trade",
203
+ params=params,
204
+ headers=self._rest_headers,
205
+ )
206
+ data = await res.json()
207
+ payload = self._ensure_ok("query_trade", data)
208
+
209
+ if isinstance(payload, dict):
210
+ rows = payload.get("data")
211
+ if isinstance(rows, list):
212
+ return rows
213
+ elif isinstance(payload, list): # pragma: no cover - defensive fallback
214
+ return payload
215
+
216
+ return []
217
+
218
+ async def query_order(
219
+ self,
220
+ order_id: str | None = None,
221
+ *,
222
+ product_group: str = "SwapU",
223
+ page_index: int = 1,
224
+ page_size: int = 20,
225
+ ) -> dict[str, Any]:
226
+ """
227
+ 返回值示例:
228
+
229
+ .. code:: json
230
+
231
+ {
232
+ "order_id": "1000632478428573",
233
+ "instrument_id": "SOLUSDT",
234
+ "position_id": "1000632478428573",
235
+ "direction": "0",
236
+ "offset_flag": "0",
237
+ "trade_time": 1760123456,
238
+ "avg_price": 182.5,
239
+ "volume": 0.03,
240
+ "turnover": 5.475,
241
+ "fee": 0.003285,
242
+ "trade_count": 1
243
+ }
244
+
245
+ 如果没有订单成交返回
246
+ {
247
+ "order_id": "1000632478428573",
248
+ "trade_count": 0
249
+ }
250
+ """
251
+
252
+ if not order_id:
253
+ raise ValueError("order_id is required to query order statistics")
254
+
255
+ trades = await self.query_trade(
256
+ order_id,
257
+ product_group=product_group,
258
+ page_index=page_index,
259
+ page_size=page_size,
260
+ )
261
+
262
+ if not trades:
263
+ return {
264
+ "order_id": order_id,
265
+ "trade_count": 0,
266
+ }
267
+
268
+ def _to_float(value: Any) -> float:
269
+ try:
270
+ return float(value)
271
+ except (TypeError, ValueError):
272
+ return 0.0
273
+
274
+ total_volume = sum(_to_float(trade.get("Volume")) for trade in trades)
275
+ total_turnover = sum(_to_float(trade.get("Turnover")) for trade in trades)
276
+ total_fee = sum(_to_float(trade.get("Fee")) for trade in trades)
277
+
278
+ avg_price = total_turnover / total_volume if total_volume else None
279
+ last_trade = trades[-1]
280
+
281
+ return {
282
+ "order_id": order_id,
283
+ "instrument_id": last_trade.get("InstrumentID"),
284
+ "position_id": last_trade.get("PositionID"),
285
+ "direction": last_trade.get("Direction"),
286
+ "offset_flag": last_trade.get("OffsetFlag"),
287
+ "trade_time": last_trade.get("TradeTime"),
288
+ "avg_price": avg_price,
289
+ "volume": total_volume,
290
+ "turnover": total_turnover,
291
+ "fee": total_fee,
292
+ "trade_count": len(trades),
293
+ }
294
+
139
295
  def _resolve_instrument(self) -> str | None:
140
296
  detail_entries = self.store.detail.find()
141
297
  if detail_entries:
@@ -212,7 +368,71 @@ class Lbank:
212
368
  order_proportion: str = "0.0000",
213
369
  client_order_id: str | None = None,
214
370
  ) -> dict[str, Any]:
215
- """Create an order using documented REST parameters."""
371
+ """Create an order using documented REST parameters.
372
+
373
+ 返回示例:
374
+
375
+ .. code:: json
376
+
377
+ {
378
+ "offsetFlag": "5",
379
+ "orderType": "1",
380
+ "reserveMode": "0",
381
+ "fee": "0.0066042",
382
+ "frozenFee": "0",
383
+ "ddlnTime": "0",
384
+ "userID": "lbank_exchange_user",
385
+ "masterAccountID": "",
386
+ "exchangeID": "Exchange",
387
+ "accountID": "e1b03fb1-6849-464f-a986-94b9a6e625e6",
388
+ "orderSysID": "1000633129818889",
389
+ "volumeRemain": "0",
390
+ "price": "183.36",
391
+ "businessValue": "1760183423813",
392
+ "frozenMargin": "0",
393
+ "instrumentID": "SOLUSDT",
394
+ "posiDirection": "2",
395
+ "volumeMode": "1",
396
+ "volume": "0.06",
397
+ "insertTime": "1760183423",
398
+ "copyMemberID": "",
399
+ "position": "0.06",
400
+ "tradePrice": "183.45",
401
+ "leverage": "100",
402
+ "businessResult": "",
403
+ "availableUse": "0",
404
+ "orderStatus": "1",
405
+ "openPrice": "182.94",
406
+ "frozenMoney": "0",
407
+ "remark": "def",
408
+ "reserveUse": "0",
409
+ "sessionNo": "41",
410
+ "isCrossMargin": "1",
411
+ "closeProfit": "0.0306",
412
+ "businessNo": "1001770756852986", # 订单有成交会并入仓位 businessNo
413
+ "relatedOrderSysID": "",
414
+ "positionID": "1000632926272299",
415
+ "mockResp": false,
416
+ "deriveSource": "0",
417
+ "copyOrderID": "",
418
+ "currency": "USDT",
419
+ "turnover": "11.007",
420
+ "frontNo": "-68",
421
+ "direction": "1",
422
+ "orderPriceType": "4",
423
+ "volumeCancled": "0",
424
+ "updateTime": "1760183423",
425
+ "localID": "1000633129818889",
426
+ "volumeTraded": "0.06",
427
+ "appid": "WEB",
428
+ "tradeUnitID": "e1b03fb1-6849-464f-a",
429
+ "businessType": "P",
430
+ "memberID": "e1b03fb1-6849-464f-a986-94b9a6e625e6",
431
+ "timeCondition": "0",
432
+ "copyProfit": "0"
433
+ }
434
+
435
+ """
216
436
 
217
437
  direction_code = self._normalize_direction(direction)
218
438
  offset_code = self._normalize_offset(offset_flag)
@@ -244,9 +464,7 @@ class Lbank:
244
464
  # logger.warning("Price is ignored for market orders")
245
465
  pass
246
466
 
247
- # if client_order_id:
248
- # payload["LocalID"] = client_order_id
249
- print(payload)
467
+
250
468
  res = await self.client.post(
251
469
  f"{self.front_api}/cfd/cff/v1/SendOrderInsert",
252
470
  json=payload,
@@ -271,6 +271,7 @@ class Position(DataStore):
271
271
  if not entry:
272
272
  return None
273
273
  position_id = entry.get("PositionID")
274
+ bus_id = entry.get("BusinessNo")
274
275
  if not position_id:
275
276
  return None
276
277
 
@@ -279,6 +280,7 @@ class Position(DataStore):
279
280
 
280
281
  return {
281
282
  "position_id": position_id,
283
+ "bus_id": bus_id,
282
284
  "symbol": entry.get("InstrumentID"),
283
285
  "side": side,
284
286
  "quantity": entry.get("Position"),
@@ -473,6 +475,7 @@ class LbankDataStore(DataStoreCollection):
473
475
  [
474
476
  {
475
477
  "position_id": <仓位ID>,
478
+ "bus_id": <订单ID覆盖>,
476
479
  "symbol": <合约ID>,
477
480
  "side": "long" / "short" / "net",
478
481
  "quantity": <持仓数量>,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperquant
3
- Version: 0.73
3
+ Version: 0.75
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
@@ -8,7 +8,7 @@ hyperquant/broker/auth.py,sha256=Wst7mTBuUS2BQ5hZd0a8FNNs5Uc01ac9WzJpseTuyAY,767
8
8
  hyperquant/broker/bitget.py,sha256=PEzULGJJQeQ91TKa4F56WhEpcnUHC3WpIx1pi5UXpVQ,9182
9
9
  hyperquant/broker/edgex.py,sha256=TqUO2KRPLN_UaxvtLL6HnA9dAQXC1sGxOfqTHd6W5k8,18378
10
10
  hyperquant/broker/hyperliquid.py,sha256=7MxbI9OyIBcImDelPJu-8Nd53WXjxPB5TwE6gsjHbto,23252
11
- hyperquant/broker/lbank.py,sha256=dZUbi0a_Vhkp4pJ1V11X6nEM7I4HhQIVRgpSMeGcAMU,11681
11
+ hyperquant/broker/lbank.py,sha256=lWpRH4SQR_Ock096MEFZB4917KwQ1aHQxGPKRfN15XM,18995
12
12
  hyperquant/broker/ourbit.py,sha256=NUcDSIttf-HGWzoW1uBTrGLPHlkuemMjYCm91MigTno,18228
13
13
  hyperquant/broker/ws.py,sha256=9Zu5JSLj-ylYEVmFmRwvZDDnVYKwb37cLHfZzA0AZGc,2200
14
14
  hyperquant/broker/lib/edgex_sign.py,sha256=lLUCmY8HHRLfLKyGrlTJYaBlSHPsIMWg3EZnQJKcmyk,95785
@@ -18,12 +18,12 @@ hyperquant/broker/lib/util.py,sha256=iMU1qF0CHj5zzlIMEQGwjz-qtEVosEe7slXOCuB7Rcw
18
18
  hyperquant/broker/models/bitget.py,sha256=0RwDY75KrJb-c-oYoMxbqxWfsILe-n_Npojz4UFUq7c,11389
19
19
  hyperquant/broker/models/edgex.py,sha256=vPAkceal44cjTYKQ_0BoNAskOpmkno_Yo1KxgMLPc6Y,33954
20
20
  hyperquant/broker/models/hyperliquid.py,sha256=c4r5739ibZfnk69RxPjQl902AVuUOwT8RNvKsMtwXBY,9459
21
- hyperquant/broker/models/lbank.py,sha256=_ztqhYGDqEHpmSITfYp_cpEJiJrhfJ9dwZ52K_PhE2A,18969
21
+ hyperquant/broker/models/lbank.py,sha256=2RkhwA8vpC1ex5TslNcfNpL0CcPhtg1KXv2uZjPc0q0,19088
22
22
  hyperquant/broker/models/ourbit.py,sha256=xMcbuCEXd3XOpPBq0RYF2zpTFNnxPtuNJZCexMZVZ1k,41965
23
23
  hyperquant/datavison/_util.py,sha256=92qk4vO856RqycO0YqEIHJlEg-W9XKapDVqAMxe6rbw,533
24
24
  hyperquant/datavison/binance.py,sha256=3yNKTqvt_vUQcxzeX4ocMsI5k6Q6gLZrvgXxAEad6Kc,5001
25
25
  hyperquant/datavison/coinglass.py,sha256=PEjdjISP9QUKD_xzXNzhJ9WFDTlkBrRQlVL-5pxD5mo,10482
26
26
  hyperquant/datavison/okx.py,sha256=yg8WrdQ7wgWHNAInIgsWPM47N3Wkfr253169IPAycAY,6898
27
- hyperquant-0.73.dist-info/METADATA,sha256=nAkYdNGtpPFIhgtTm1JWCQCK46kJyAv2EdLrcfTh1nU,4317
28
- hyperquant-0.73.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
- hyperquant-0.73.dist-info/RECORD,,
27
+ hyperquant-0.75.dist-info/METADATA,sha256=q_UNNDJWJ_FNiI-9tJsD-L_IaaM7kmfnatSRdy6olk4,4317
28
+ hyperquant-0.75.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
+ hyperquant-0.75.dist-info/RECORD,,