Add OKX trading-account USDC auto-swap and lock exit target while in position.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -133,28 +133,38 @@ class SimFundsWallets:
|
||||
direction: str,
|
||||
amount: float,
|
||||
rate: float = 1.0,
|
||||
account: str = "funding",
|
||||
) -> dict[str, Any]:
|
||||
"""资金账户内 USDT↔USDC 兑换。"""
|
||||
"""USDT↔USDC 兑换。默认资金账户;account=trading 时在交易账户内兑(对齐 OKX 现货)。"""
|
||||
amt = float(amount)
|
||||
if amt <= 0:
|
||||
return {"ok": False, "detail": "数量须大于 0"}
|
||||
r = float(rate) if rate and rate > 0 else 1.0
|
||||
d = (direction or "").strip().lower()
|
||||
acct = (account or "funding").strip().lower()
|
||||
if acct not in ("funding", "trading"):
|
||||
return {"ok": False, "detail": "account 须为 funding / trading"}
|
||||
snap = self.snapshot()
|
||||
if acct == "funding":
|
||||
usdt_key, usdc_key = "funding_usdt", "options_funding_usdc"
|
||||
label = "资金账户"
|
||||
else:
|
||||
usdt_key, usdc_key = "trading_usdt", "options_trading_usdc"
|
||||
label = "交易账户"
|
||||
if d == "usdt_to_usdc":
|
||||
src = float(snap["funding_usdt"])
|
||||
src = float(snap[usdt_key])
|
||||
if amt > src + 1e-9:
|
||||
return {"ok": False, "detail": f"资金账户 USDT 不足(可用 {src:.4f})"}
|
||||
return {"ok": False, "detail": f"{label} USDT 不足(可用 {src:.4f})"}
|
||||
usdc = amt / r
|
||||
snap["funding_usdt"] = src - amt
|
||||
snap["options_funding_usdc"] = float(snap["options_funding_usdc"]) + usdc
|
||||
snap[usdt_key] = src - amt
|
||||
snap[usdc_key] = float(snap[usdc_key]) + usdc
|
||||
elif d == "usdc_to_usdt":
|
||||
src = float(snap["options_funding_usdc"])
|
||||
src = float(snap[usdc_key])
|
||||
if amt > src + 1e-9:
|
||||
return {"ok": False, "detail": f"资金账户 USDC 不足(可用 {src:.4f})"}
|
||||
return {"ok": False, "detail": f"{label} USDC 不足(可用 {src:.4f})"}
|
||||
usdt = amt * r
|
||||
snap["options_funding_usdc"] = src - amt
|
||||
snap["funding_usdt"] = float(snap["funding_usdt"]) + usdt
|
||||
snap[usdc_key] = src - amt
|
||||
snap[usdt_key] = float(snap[usdt_key]) + usdt
|
||||
else:
|
||||
return {"ok": False, "detail": "direction 须为 usdt_to_usdc 或 usdc_to_usdt"}
|
||||
self._set(**snap)
|
||||
@@ -165,6 +175,7 @@ class SimFundsWallets:
|
||||
"direction": d,
|
||||
"amount": amt,
|
||||
"rate": r,
|
||||
"account": acct,
|
||||
"wallets": self.view(),
|
||||
"total_usdt_equiv": total,
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
@@ -21,6 +22,8 @@ from .pricing import (
|
||||
resolve_option_close_bid,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 禁止新开仓的本地仓位状态(实盘防卡)
|
||||
BLOCKING_STATUSES = frozenset(
|
||||
{"open", "half_open", "option_closed_perp_pending", "opening"}
|
||||
@@ -332,6 +335,15 @@ class Matcher:
|
||||
)
|
||||
self.db._conn.commit()
|
||||
|
||||
try:
|
||||
from ..strategy.exits import lock_trade_exit_target
|
||||
|
||||
lock_trade_exit_target(
|
||||
self.db, group_id=group_id, initial_premium=initial_premium
|
||||
)
|
||||
except Exception:
|
||||
logger.exception("lock exit target failed group=%s", group_id)
|
||||
|
||||
return OpenResult(
|
||||
ok=True,
|
||||
group_id=group_id,
|
||||
@@ -585,7 +597,8 @@ class Matcher:
|
||||
"""UPDATE positions SET
|
||||
group_id=NULL, perp_side=NULL, perp_qty_eth=0, perp_entry_px=NULL,
|
||||
option_inst_id=NULL, option_side=NULL, option_qty_eth=0, option_qty_contracts=0,
|
||||
option_entry_px=NULL, entry_index_px=NULL, initial_premium=0, status='flat'
|
||||
option_entry_px=NULL, entry_index_px=NULL, initial_premium=0,
|
||||
exit_target_usdt=NULL, status='flat'
|
||||
WHERE id=1"""
|
||||
)
|
||||
self.db._conn.commit()
|
||||
@@ -756,7 +769,8 @@ class Matcher:
|
||||
"""UPDATE positions SET
|
||||
group_id=NULL, perp_side=NULL, perp_qty_eth=0, perp_entry_px=NULL,
|
||||
option_inst_id=NULL, option_side=NULL, option_qty_eth=0, option_qty_contracts=0,
|
||||
option_entry_px=NULL, entry_index_px=NULL, initial_premium=0, status='flat'
|
||||
option_entry_px=NULL, entry_index_px=NULL, initial_premium=0,
|
||||
exit_target_usdt=NULL, status='flat'
|
||||
WHERE id=1"""
|
||||
)
|
||||
self.db._conn.commit()
|
||||
@@ -1098,6 +1112,11 @@ class Matcher:
|
||||
"move_points": move,
|
||||
"move_pct": move_pct,
|
||||
"initial_premium": initial_premium,
|
||||
"exit_target_usdt": (
|
||||
float(pos["exit_target_usdt"])
|
||||
if pos.get("exit_target_usdt") is not None
|
||||
else None
|
||||
),
|
||||
"premium_gap": premium_gap,
|
||||
"status": pos.get("status"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user