hyperquant 0.87__tar.gz → 0.88__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.
- {hyperquant-0.87 → hyperquant-0.88}/PKG-INFO +1 -1
- {hyperquant-0.87 → hyperquant-0.88}/pyproject.toml +1 -1
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/coinw.py +1 -1
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/models/coinw.py +22 -11
- {hyperquant-0.87 → hyperquant-0.88}/tests/test_coinw.py +31 -20
- {hyperquant-0.87 → hyperquant-0.88}/uv.lock +1 -1
- {hyperquant-0.87 → hyperquant-0.88}/.gitignore +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/.python-version +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/README.md +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/apis.json +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/data/alpine_smoke.log +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/data/logs/notikit.log +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/data/logs/test_order_sync.log +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/data/records_swap.csv +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/data/records_swapc.csv +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/doc/lbank.md +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/pub.sh +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/requirements-dev.lock +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/requirements.lock +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/__init__.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/auth.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/bitget.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/edgex.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/hyperliquid.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/lbank.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/lib/edgex_sign.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/lib/hpstore.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/lib/hyper_types.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/lib/util.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/models/bitget.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/models/edgex.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/models/hyperliquid.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/models/lbank.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/models/ourbit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/ourbit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/broker/ws.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/core.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/datavison/_util.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/datavison/binance.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/datavison/coinglass.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/datavison/okx.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/db.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/draw.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/logkit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/src/hyperquant/notikit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/tests/test_bitget.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/tests/test_draw.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/tests/test_edgex.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/tests/test_lbank.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/tests/test_ourbit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.88}/tests/tmp.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperquant
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.88
|
|
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
|
|
@@ -292,7 +292,7 @@ class Coinw:
|
|
|
292
292
|
ws_app = await self._ensure_private_ws()
|
|
293
293
|
payloads = [
|
|
294
294
|
{"event": "sub", "params": {"biz": "futures", "type": "order"}},
|
|
295
|
-
{"event": "sub", "params": {"biz": "futures", "type": "position"}},
|
|
295
|
+
# {"event": "sub", "params": {"biz": "futures", "type": "position"}},
|
|
296
296
|
{"event": "sub", "params": {"biz": "futures", "type": "position_change"}},
|
|
297
297
|
{"event": "sub", "params": {"biz": "futures", "type": "assets"}},
|
|
298
298
|
]
|
|
@@ -280,15 +280,21 @@ class Orders(DataStore):
|
|
|
280
280
|
class Position(DataStore):
|
|
281
281
|
"""CoinW 当前持仓数据存储。"""
|
|
282
282
|
|
|
283
|
-
_KEYS = ["
|
|
283
|
+
_KEYS = ["openId"]
|
|
284
284
|
|
|
285
285
|
@staticmethod
|
|
286
286
|
def _normalize(entry: dict[str, Any]) -> dict[str, Any] | None:
|
|
287
|
-
|
|
288
|
-
if
|
|
287
|
+
open_id = entry.get("openId")
|
|
288
|
+
if open_id is None:
|
|
289
289
|
return None
|
|
290
290
|
normalized = dict(entry)
|
|
291
|
-
normalized["
|
|
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")
|
|
292
298
|
return normalized
|
|
293
299
|
|
|
294
300
|
def _onresponse(self, data: Any) -> None:
|
|
@@ -325,6 +331,7 @@ class Position(DataStore):
|
|
|
325
331
|
return
|
|
326
332
|
|
|
327
333
|
to_insert: list[dict[str, Any]] = []
|
|
334
|
+
to_update: list[dict[str, Any]] = []
|
|
328
335
|
to_delete: list[dict[str, Any]] = []
|
|
329
336
|
|
|
330
337
|
for entry in entries:
|
|
@@ -334,17 +341,21 @@ class Position(DataStore):
|
|
|
334
341
|
if not normalized:
|
|
335
342
|
continue
|
|
336
343
|
|
|
337
|
-
|
|
338
|
-
normalized_status = str(status).lower() if status is not None else ""
|
|
339
|
-
remove = normalized_status in {"close", "closed", "1", "2"}
|
|
344
|
+
criteria = {"openId": normalized["openId"]}
|
|
340
345
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
346
|
+
if normalized.get("is_closed"):
|
|
347
|
+
to_delete.append(criteria)
|
|
348
|
+
continue
|
|
349
|
+
|
|
350
|
+
if self.find(criteria):
|
|
351
|
+
to_update.append(normalized)
|
|
352
|
+
else:
|
|
344
353
|
to_insert.append(normalized)
|
|
345
354
|
|
|
346
355
|
if to_delete:
|
|
347
356
|
self._delete(to_delete)
|
|
357
|
+
if to_update:
|
|
358
|
+
self._update(to_update)
|
|
348
359
|
if to_insert:
|
|
349
360
|
self._insert(to_insert)
|
|
350
361
|
|
|
@@ -453,7 +464,7 @@ class CoinwFuturesDataStore(DataStoreCollection):
|
|
|
453
464
|
self.book._on_message(msg)
|
|
454
465
|
elif msg_type == "order":
|
|
455
466
|
self.orders._on_message(msg)
|
|
456
|
-
elif msg_type == "position":
|
|
467
|
+
elif msg_type == "position" or msg_type == "position_change":
|
|
457
468
|
self.position._on_message(msg)
|
|
458
469
|
elif msg_type == "assets":
|
|
459
470
|
self.balance._on_message(msg)
|
|
@@ -67,25 +67,36 @@ async def test_place_cancel() -> None:
|
|
|
67
67
|
async with pybotters.Client(apis="./apis.json") as client:
|
|
68
68
|
async with Coinw(client) as cw:
|
|
69
69
|
start = time.time()
|
|
70
|
-
order = await cw.place_order(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
# order = await cw.place_order(
|
|
71
|
+
# instrument="SOL",
|
|
72
|
+
# direction="long",
|
|
73
|
+
# quantity_unit=1,
|
|
74
|
+
# leverage=25,
|
|
75
|
+
# quantity=2,
|
|
76
|
+
# position_type="plan",
|
|
77
|
+
# price=175,
|
|
78
|
+
# position_model="cross",
|
|
79
|
+
# )
|
|
80
|
+
# latency = time.time() - start
|
|
81
|
+
# print(f'下单延迟: {latency*1000:.2f} ms')
|
|
82
|
+
# order_id = order.get("value") or order.get("data")
|
|
83
|
+
# print("place_order response:", order)
|
|
84
|
+
# if order_id:
|
|
85
|
+
# await asyncio.sleep(1)
|
|
86
|
+
# cancel_resp = await cw.cancel_order(order_id)
|
|
87
|
+
# print("cancel_order response:", cancel_resp)
|
|
88
|
+
|
|
89
|
+
# {'instrument': 'JUP', 'direction': 'short', 'leverage': 50, 'quantityUnit': 1, 'quantity': '57', 'positionModel': 1, 'positionType': 'plan', 'openPrice': 0.3527}
|
|
90
|
+
await cw.place_order(
|
|
91
|
+
instrument="JUP",
|
|
92
|
+
direction="short",
|
|
93
|
+
quantity_unit=1,
|
|
94
|
+
leverage=50,
|
|
95
|
+
quantity="57",
|
|
76
96
|
position_type="plan",
|
|
77
|
-
price=
|
|
78
|
-
position_model=
|
|
97
|
+
price=0.3527,
|
|
98
|
+
position_model=1,
|
|
79
99
|
)
|
|
80
|
-
latency = time.time() - start
|
|
81
|
-
print(f'下单延迟: {latency*1000:.2f} ms')
|
|
82
|
-
order_id = order.get("value") or order.get("data")
|
|
83
|
-
print("place_order response:", order)
|
|
84
|
-
if order_id:
|
|
85
|
-
await asyncio.sleep(1)
|
|
86
|
-
cancel_resp = await cw.cancel_order(order_id)
|
|
87
|
-
print("cancel_order response:", cancel_resp)
|
|
88
|
-
|
|
89
100
|
|
|
90
101
|
async def test_place_web() -> None:
|
|
91
102
|
"""Use the web interface to place an order (requires device/token)."""
|
|
@@ -196,9 +207,10 @@ async def test_subp() -> None:
|
|
|
196
207
|
async with pybotters.Client(apis="./apis.json") as client:
|
|
197
208
|
async with Coinw(client) as cw:
|
|
198
209
|
await cw.sub_personal()
|
|
199
|
-
with cw.store.
|
|
210
|
+
with cw.store.position.watch() as watcher:
|
|
200
211
|
async for change in watcher:
|
|
201
212
|
print(change)
|
|
213
|
+
print('\n\n----\n\n')
|
|
202
214
|
|
|
203
215
|
|
|
204
216
|
async def test_order_sync_polling() -> None:
|
|
@@ -222,6 +234,5 @@ async def test_order_sync_polling() -> None:
|
|
|
222
234
|
)
|
|
223
235
|
print("order_sync_polling result:", result)
|
|
224
236
|
|
|
225
|
-
|
|
226
237
|
if __name__ == "__main__":
|
|
227
|
-
asyncio.run(
|
|
238
|
+
asyncio.run(test_subp())
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|