hyperquant 0.87__tar.gz → 0.89__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.89}/PKG-INFO +1 -1
- {hyperquant-0.87 → hyperquant-0.89}/pyproject.toml +1 -1
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/coinw.py +48 -12
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/models/coinw.py +58 -32
- {hyperquant-0.87 → hyperquant-0.89}/tests/test_coinw.py +76 -33
- {hyperquant-0.87 → hyperquant-0.89}/uv.lock +1 -1
- {hyperquant-0.87 → hyperquant-0.89}/.gitignore +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/.python-version +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/README.md +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/apis.json +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/data/alpine_smoke.log +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/data/logs/notikit.log +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/data/logs/test_order_sync.log +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/data/records_swap.csv +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/data/records_swapc.csv +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/doc/lbank.md +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/pub.sh +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/requirements-dev.lock +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/requirements.lock +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/__init__.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/auth.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/bitget.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/edgex.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/hyperliquid.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/lbank.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/lib/edgex_sign.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/lib/hpstore.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/lib/hyper_types.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/lib/util.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/models/bitget.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/models/edgex.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/models/hyperliquid.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/models/lbank.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/models/ourbit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/ourbit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/broker/ws.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/core.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/datavison/_util.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/datavison/binance.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/datavison/coinglass.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/datavison/okx.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/db.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/draw.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/logkit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/src/hyperquant/notikit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/tests/test_bitget.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/tests/test_draw.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/tests/test_edgex.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/tests/test_lbank.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/tests/test_ourbit.py +0 -0
- {hyperquant-0.87 → hyperquant-0.89}/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.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
|
|
@@ -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
|
-
|
|
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,
|
|
@@ -292,7 +328,7 @@ class Coinw:
|
|
|
292
328
|
ws_app = await self._ensure_private_ws()
|
|
293
329
|
payloads = [
|
|
294
330
|
{"event": "sub", "params": {"biz": "futures", "type": "order"}},
|
|
295
|
-
{"event": "sub", "params": {"biz": "futures", "type": "position"}},
|
|
331
|
+
# {"event": "sub", "params": {"biz": "futures", "type": "position"}},
|
|
296
332
|
{"event": "sub", "params": {"biz": "futures", "type": "position_change"}},
|
|
297
333
|
{"event": "sub", "params": {"biz": "futures", "type": "assets"}},
|
|
298
334
|
]
|
|
@@ -280,16 +280,8 @@ class Orders(DataStore):
|
|
|
280
280
|
class Position(DataStore):
|
|
281
281
|
"""CoinW 当前持仓数据存储。"""
|
|
282
282
|
|
|
283
|
-
_KEYS = ["
|
|
283
|
+
_KEYS = ["openId"]
|
|
284
284
|
|
|
285
|
-
@staticmethod
|
|
286
|
-
def _normalize(entry: dict[str, Any]) -> dict[str, Any] | None:
|
|
287
|
-
position_id = entry.get("id")
|
|
288
|
-
if position_id is None:
|
|
289
|
-
return None
|
|
290
|
-
normalized = dict(entry)
|
|
291
|
-
normalized["id"] = str(position_id)
|
|
292
|
-
return normalized
|
|
293
285
|
|
|
294
286
|
def _onresponse(self, data: Any) -> None:
|
|
295
287
|
payload = []
|
|
@@ -302,9 +294,8 @@ class Position(DataStore):
|
|
|
302
294
|
for entry in payload or []:
|
|
303
295
|
if not isinstance(entry, dict):
|
|
304
296
|
continue
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
items.append(normalized)
|
|
297
|
+
entry['openId'] = str(entry.get("id"))
|
|
298
|
+
items.append(entry)
|
|
308
299
|
|
|
309
300
|
self._clear()
|
|
310
301
|
if items:
|
|
@@ -312,6 +303,7 @@ class Position(DataStore):
|
|
|
312
303
|
|
|
313
304
|
def _on_message(self, msg: dict[str, Any]) -> None:
|
|
314
305
|
data = msg.get("data")
|
|
306
|
+
|
|
315
307
|
if isinstance(data, dict) and data.get("result") is not None:
|
|
316
308
|
return
|
|
317
309
|
|
|
@@ -325,26 +317,28 @@ class Position(DataStore):
|
|
|
325
317
|
return
|
|
326
318
|
|
|
327
319
|
to_insert: list[dict[str, Any]] = []
|
|
320
|
+
to_update: list[dict[str, Any]] = []
|
|
328
321
|
to_delete: list[dict[str, Any]] = []
|
|
329
322
|
|
|
330
323
|
for entry in entries:
|
|
331
324
|
if not isinstance(entry, dict):
|
|
332
325
|
continue
|
|
333
|
-
normalized =
|
|
334
|
-
if not normalized:
|
|
335
|
-
continue
|
|
326
|
+
normalized = entry
|
|
336
327
|
|
|
337
|
-
status = normalized.get("status")
|
|
338
|
-
normalized_status = str(status).lower() if status is not None else ""
|
|
339
|
-
remove = normalized_status in {"close", "closed", "1", "2"}
|
|
340
328
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
329
|
+
if normalized.get("status") == 'close':
|
|
330
|
+
to_delete.append(normalized)
|
|
331
|
+
continue
|
|
332
|
+
|
|
333
|
+
if self.find(normalized):
|
|
334
|
+
to_update.append(normalized)
|
|
335
|
+
else:
|
|
344
336
|
to_insert.append(normalized)
|
|
345
337
|
|
|
346
338
|
if to_delete:
|
|
347
339
|
self._delete(to_delete)
|
|
340
|
+
if to_update:
|
|
341
|
+
self._update(to_update)
|
|
348
342
|
if to_insert:
|
|
349
343
|
self._insert(to_insert)
|
|
350
344
|
|
|
@@ -449,11 +443,12 @@ class CoinwFuturesDataStore(DataStoreCollection):
|
|
|
449
443
|
|
|
450
444
|
def onmessage(self, msg: Item, ws: ClientWebSocketResponse | None = None) -> None:
|
|
451
445
|
msg_type = msg.get("type")
|
|
446
|
+
# print(msg)
|
|
452
447
|
if msg_type == "depth":
|
|
453
448
|
self.book._on_message(msg)
|
|
454
449
|
elif msg_type == "order":
|
|
455
450
|
self.orders._on_message(msg)
|
|
456
|
-
elif msg_type == "position":
|
|
451
|
+
elif msg_type == "position" or msg_type == "position_change":
|
|
457
452
|
self.position._on_message(msg)
|
|
458
453
|
elif msg_type == "assets":
|
|
459
454
|
self.balance._on_message(msg)
|
|
@@ -470,7 +465,7 @@ class CoinwFuturesDataStore(DataStoreCollection):
|
|
|
470
465
|
self.ticker._onresponse(data)
|
|
471
466
|
elif res.url.path == "/v1/perpum/orders/open":
|
|
472
467
|
self.orders._onresponse(data)
|
|
473
|
-
elif res.url.path == "/v1/perpum/positions":
|
|
468
|
+
elif res.url.path == "/v1/perpum/positions/all":
|
|
474
469
|
self.position._onresponse(data)
|
|
475
470
|
elif res.url.path == "/v1/perpum/account/getUserAssets":
|
|
476
471
|
self.balance._onresponse(data)
|
|
@@ -655,17 +650,48 @@ class CoinwFuturesDataStore(DataStoreCollection):
|
|
|
655
650
|
- REST: ``GET /v1/perpum/positions``
|
|
656
651
|
- WebSocket: ``type == "position"``
|
|
657
652
|
|
|
658
|
-
|
|
653
|
+
.. code:: json
|
|
659
654
|
|
|
660
655
|
{
|
|
661
|
-
"
|
|
662
|
-
"
|
|
663
|
-
"
|
|
664
|
-
"
|
|
665
|
-
"
|
|
666
|
-
"
|
|
667
|
-
"
|
|
668
|
-
|
|
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
|
+
}
|
|
669
695
|
"""
|
|
670
696
|
|
|
671
697
|
return self._get("position", Position)
|
|
@@ -23,8 +23,11 @@ async def test_update_private() -> None:
|
|
|
23
23
|
"""Refresh private endpoints (requires ./apis.json with coinw credentials)."""
|
|
24
24
|
async with pybotters.Client(apis="./apis.json") as client:
|
|
25
25
|
async with Coinw(client) as cw:
|
|
26
|
-
await cw.update("balance")
|
|
27
|
-
print(cw.store.balance.find())
|
|
26
|
+
# await cw.update("balance")
|
|
27
|
+
# print(cw.store.balance.find())
|
|
28
|
+
await cw.update("position")
|
|
29
|
+
print(cw.store.position.find())
|
|
30
|
+
|
|
28
31
|
# await cw.update("position", instrument="BTC")
|
|
29
32
|
# print(cw.store.position.find())
|
|
30
33
|
# await cw.update("orders", instrument="BTC")
|
|
@@ -67,25 +70,66 @@ async def test_place_cancel() -> None:
|
|
|
67
70
|
async with pybotters.Client(apis="./apis.json") as client:
|
|
68
71
|
async with Coinw(client) as cw:
|
|
69
72
|
start = time.time()
|
|
70
|
-
order = await cw.place_order(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
# order = await cw.place_order(
|
|
74
|
+
# instrument="SOL",
|
|
75
|
+
# direction="long",
|
|
76
|
+
# quantity_unit=1,
|
|
77
|
+
# leverage=25,
|
|
78
|
+
# quantity=2,
|
|
79
|
+
# position_type="plan",
|
|
80
|
+
# price=175,
|
|
81
|
+
# position_model="cross",
|
|
82
|
+
# )
|
|
83
|
+
# latency = time.time() - start
|
|
84
|
+
# print(f'下单延迟: {latency*1000:.2f} ms')
|
|
85
|
+
# order_id = order.get("value") or order.get("data")
|
|
86
|
+
# print("place_order response:", order)
|
|
87
|
+
# if order_id:
|
|
88
|
+
# await asyncio.sleep(1)
|
|
89
|
+
# cancel_resp = await cw.cancel_order(order_id)
|
|
90
|
+
# print("cancel_order response:", cancel_resp)
|
|
91
|
+
|
|
92
|
+
# {'instrument': 'JUP', 'direction': 'short', 'leverage': 50, 'quantityUnit': 1, 'quantity': '57', 'positionModel': 1, 'positionType': 'plan', 'openPrice': 0.3527}
|
|
93
|
+
await cw.place_order(
|
|
94
|
+
instrument="JUP",
|
|
95
|
+
direction="short",
|
|
96
|
+
quantity_unit=1,
|
|
97
|
+
leverage=50,
|
|
98
|
+
quantity="57",
|
|
76
99
|
position_type="plan",
|
|
77
|
-
price=
|
|
78
|
-
position_model=
|
|
100
|
+
price=0.3527,
|
|
101
|
+
position_model=1,
|
|
79
102
|
)
|
|
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
103
|
|
|
104
|
+
async def test_close_position():
|
|
105
|
+
async with pybotters.Client(apis="./apis.json") as client:
|
|
106
|
+
async with Coinw(client) as cw:
|
|
107
|
+
# await cw.update('position')
|
|
108
|
+
await cw.sub_personal()
|
|
109
|
+
with cw.store.position.watch() as watcher:
|
|
110
|
+
# 2435521222638707402
|
|
111
|
+
resp = await cw.place_order(
|
|
112
|
+
instrument="JUP",
|
|
113
|
+
direction="long",
|
|
114
|
+
quantity_unit=1,
|
|
115
|
+
leverage=10,
|
|
116
|
+
quantity=1,
|
|
117
|
+
position_model='cross',
|
|
118
|
+
position_type='execute'
|
|
119
|
+
)
|
|
120
|
+
print("开仓响应:", resp)
|
|
121
|
+
|
|
122
|
+
await asyncio.sleep(2)
|
|
123
|
+
|
|
124
|
+
for position in cw.store.position.find():
|
|
125
|
+
open_id = position.get('openId')
|
|
126
|
+
print(f'关闭持仓: {open_id}')
|
|
127
|
+
resp = await cw.close_position(open_id, position_type='execute', close_num=1)
|
|
128
|
+
print(resp)
|
|
129
|
+
|
|
130
|
+
async for change in watcher:
|
|
131
|
+
print(change)
|
|
132
|
+
print('\n\n----\n\n')
|
|
89
133
|
|
|
90
134
|
async def test_place_web() -> None:
|
|
91
135
|
"""Use the web interface to place an order (requires device/token)."""
|
|
@@ -134,7 +178,7 @@ async def order_sync_polling(
|
|
|
134
178
|
|
|
135
179
|
try:
|
|
136
180
|
async with asyncio.timeout(window_sec):
|
|
137
|
-
with broker.store.
|
|
181
|
+
with broker.store.position.watch() as stream:
|
|
138
182
|
started = int(time.time() * 1000)
|
|
139
183
|
resp = await broker.place_order(
|
|
140
184
|
instrument=instrument,
|
|
@@ -165,16 +209,13 @@ async def order_sync_polling(
|
|
|
165
209
|
order_id = str(raw_id)
|
|
166
210
|
|
|
167
211
|
async for change in stream:
|
|
168
|
-
|
|
212
|
+
print(change.data)
|
|
169
213
|
data = change.data or {}
|
|
170
|
-
if str(data.get("
|
|
214
|
+
if str(data.get("orderId")) != order_id:
|
|
171
215
|
continue
|
|
172
216
|
snapshot = data
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if change.operation == "delete":
|
|
176
|
-
return change.source
|
|
177
|
-
if status in {"finish", "cancel", "canceled"}:
|
|
217
|
+
order_finish = data.get('orderStatus') == 'finish'
|
|
218
|
+
if order_finish:
|
|
178
219
|
return snapshot
|
|
179
220
|
|
|
180
221
|
except TimeoutError:
|
|
@@ -196,9 +237,12 @@ async def test_subp() -> None:
|
|
|
196
237
|
async with pybotters.Client(apis="./apis.json") as client:
|
|
197
238
|
async with Coinw(client) as cw:
|
|
198
239
|
await cw.sub_personal()
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
240
|
+
await asyncio.sleep(1.0)
|
|
241
|
+
print(cw.store.position.find())
|
|
242
|
+
# with cw.store.position.watch() as watcher:
|
|
243
|
+
# async for change in watcher:
|
|
244
|
+
# print(change)
|
|
245
|
+
# print('\n\n----\n\n')
|
|
202
246
|
|
|
203
247
|
|
|
204
248
|
async def test_order_sync_polling() -> None:
|
|
@@ -209,9 +253,9 @@ async def test_order_sync_polling() -> None:
|
|
|
209
253
|
print("Placing order with order_sync_polling...")
|
|
210
254
|
result = await order_sync_polling(
|
|
211
255
|
broker=cw,
|
|
212
|
-
instrument="
|
|
256
|
+
instrument="JUP",
|
|
213
257
|
direction="long",
|
|
214
|
-
leverage=
|
|
258
|
+
leverage=10,
|
|
215
259
|
quantity=1,
|
|
216
260
|
quantity_unit=1,
|
|
217
261
|
position_model="cross",
|
|
@@ -222,6 +266,5 @@ async def test_order_sync_polling() -> None:
|
|
|
222
266
|
)
|
|
223
267
|
print("order_sync_polling result:", result)
|
|
224
268
|
|
|
225
|
-
|
|
226
269
|
if __name__ == "__main__":
|
|
227
|
-
asyncio.run(
|
|
270
|
+
asyncio.run(test_close_position())
|
|
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
|