feat中控条件单可指令实例账户内划转,Bridge 暴露划转接口。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
"""期权账户内划转执行(本机设置 / 中控 Bridge 共用)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
def _safe_float(v: Any) -> float | None:
|
||||
if v is None or v == "":
|
||||
return None
|
||||
try:
|
||||
return float(v)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def _pick_stable(bal: dict[str, Any] | None, *, account: str, ccy: str) -> float | None:
|
||||
if not isinstance(bal, dict):
|
||||
return None
|
||||
acct = "trading" if account == "trading" else "funding"
|
||||
ccy_l = (ccy or "usdt").strip().lower() or "usdt"
|
||||
avail = _safe_float(bal.get(f"{acct}_{ccy_l}_avail"))
|
||||
if avail is not None:
|
||||
return round(float(avail), 8)
|
||||
total = _safe_float(bal.get(f"{acct}_{ccy_l}"))
|
||||
if total is not None:
|
||||
return round(float(total), 8)
|
||||
return None
|
||||
|
||||
|
||||
def execute_options_internal_transfer(
|
||||
cfg: dict[str, Any],
|
||||
*,
|
||||
amount: Any,
|
||||
from_acct: str = "funding",
|
||||
to_acct: str = "trading",
|
||||
ccy: str = "USDT",
|
||||
) -> dict[str, Any]:
|
||||
"""资金户↔交易户划转;持仓/待卖回拒绝.成功后附带最新 USDT 余额."""
|
||||
from lib.options.options_account_pnl_lib import transfer_blocked_by_position_msg
|
||||
from lib.options.options_db import init_options_tables
|
||||
|
||||
ex = cfg.get("exchange_options")
|
||||
ready_fn = cfg.get("options_api_ready")
|
||||
if callable(ready_fn):
|
||||
ok, reason = ready_fn(ex)
|
||||
if not ok:
|
||||
return {"ok": False, "msg": reason or "期权 API 未配置"}
|
||||
if ex is None:
|
||||
return {"ok": False, "msg": "交易所未就绪"}
|
||||
|
||||
src = (from_acct or "funding").strip().lower()
|
||||
dst = (to_acct or "trading").strip().lower()
|
||||
if src not in ("funding", "trading") or dst not in ("funding", "trading"):
|
||||
return {"ok": False, "msg": "仅支持 funding/trading"}
|
||||
if src == dst:
|
||||
return {"ok": False, "msg": "转出与转入账户不能相同"}
|
||||
ccy_u = (ccy or "USDT").strip().upper() or "USDT"
|
||||
if ccy_u not in ("USDT", "USDC"):
|
||||
return {"ok": False, "msg": "仅支持 USDT/USDC"}
|
||||
amt = _safe_float(amount)
|
||||
if amt is None or amt <= 0:
|
||||
return {"ok": False, "msg": "数量无效"}
|
||||
|
||||
get_db = cfg.get("get_db")
|
||||
if not callable(get_db):
|
||||
return {"ok": False, "msg": "数据库未就绪"}
|
||||
conn = get_db()
|
||||
try:
|
||||
block = transfer_blocked_by_position_msg(conn, ex)
|
||||
if block:
|
||||
return {"ok": False, "msg": block, "transfer_blocked": True}
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
xfer = cfg.get("transfer_ccy")
|
||||
if not callable(xfer):
|
||||
try:
|
||||
import lib.exchange.okx_options_lib as _opt_lib
|
||||
|
||||
xfer = getattr(_opt_lib, "transfer_ccy", None)
|
||||
except Exception:
|
||||
xfer = None
|
||||
if not callable(xfer):
|
||||
return {"ok": False, "msg": "划转不可用"}
|
||||
|
||||
result = xfer(ex, ccy_u, float(amt), src, dst)
|
||||
if not isinstance(result, dict):
|
||||
return {"ok": False, "msg": "划转返回异常"}
|
||||
out = dict(result)
|
||||
if not out.get("ok"):
|
||||
out.setdefault("msg", "划转失败")
|
||||
return out
|
||||
|
||||
conn2 = get_db()
|
||||
try:
|
||||
init_options_tables(conn2)
|
||||
conn2.execute(
|
||||
"""
|
||||
INSERT INTO options_transfer_log (ccy, amount, from_account, to_account, status, message)
|
||||
VALUES (?, ?, ?, ?, 'ok', ?)
|
||||
""",
|
||||
(ccy_u, float(amt), src, dst, ""),
|
||||
)
|
||||
conn2.commit()
|
||||
except Exception:
|
||||
try:
|
||||
conn2.rollback()
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
conn2.close()
|
||||
|
||||
try:
|
||||
from lib.exchange.okx_options_lib import invalidate_options_balance_cache
|
||||
from lib.instance.instance_live_push_lib import notify_instance_balance_changed
|
||||
|
||||
invalidate_options_balance_cache()
|
||||
app_mod = cfg.get("app_module")
|
||||
if app_mod is not None and hasattr(app_mod, "invalidate_account_balance_cache"):
|
||||
app_mod.invalidate_account_balance_cache()
|
||||
notify_instance_balance_changed()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
bal = {}
|
||||
try:
|
||||
fetch_bal = cfg.get("fetch_options_balances")
|
||||
if callable(fetch_bal):
|
||||
bal = fetch_bal(ex) or {}
|
||||
except Exception:
|
||||
bal = {}
|
||||
trading_usdt = _pick_stable(bal, account="trading", ccy="USDT")
|
||||
funding_usdt = _pick_stable(bal, account="funding", ccy="USDT")
|
||||
out.update(
|
||||
{
|
||||
"ok": True,
|
||||
"msg": out.get("msg") or "划转成功",
|
||||
"ccy": ccy_u,
|
||||
"amount": round(float(amt), 8),
|
||||
"from": src,
|
||||
"to": dst,
|
||||
"trading_usdt": trading_usdt,
|
||||
"funding_usdt": funding_usdt,
|
||||
"transfer_blocked": False,
|
||||
}
|
||||
)
|
||||
return out
|
||||
Reference in New Issue
Block a user