Align funds to OKX funding/trading only; fold rules; match settings width.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-29 17:59:28 +08:00
parent 80c561bdce
commit 81e51236c0
8 changed files with 198 additions and 178 deletions
+47 -36
View File
@@ -1,4 +1,4 @@
"""SIM 多账户资金:资金/交易 USDT + 期权资金/交易 USDC(对齐 OKX 展示)。"""
"""SIM 资金钱包:资金账户 / 交易账户 × USDT|USDC(对齐 OKX,无期权分账户)。"""
from __future__ import annotations
@@ -7,24 +7,19 @@ from typing import Any
from ..models.db import Database, get_db
# DB 列名(历史兼容:USDC 存在 options_*_usdc 列,语义为资金/交易账户 USDC)
WALLET_KEYS = (
"funding_usdt",
"trading_usdt",
"options_funding_usdc",
"options_trading_usdc",
"options_funding_usdt",
"options_trading_usdt",
"options_funding_usdc", # = funding_usdc
"options_trading_usdc", # = trading_usdc
"options_funding_usdt", # 废弃,恒为 0
"options_trading_usdt", # 废弃,恒为 0
)
# 划转账户映射
_ACCT_MAP = {
("funding", "usdt"): "funding_usdt",
("trading", "usdt"): "trading_usdt",
("options_funding", "usdc"): "options_funding_usdc",
("options_trading", "usdc"): "options_trading_usdc",
("options_funding", "usdt"): "options_funding_usdt",
("options_trading", "usdt"): "options_trading_usdt",
# 简化别名:funding/trading + usdc → 期权侧
("funding", "usdc"): "options_funding_usdc",
("trading", "usdc"): "options_trading_usdc",
}
@@ -44,10 +39,36 @@ class SimFundsWallets:
return {k: 0.0 for k in WALLET_KEYS}
return {k: float(row[k] or 0) for k in WALLET_KEYS}
def view(self) -> dict[str, float]:
"""对外口径:funding/trading × usdt/usdc。"""
s = self.snapshot()
return {
"funding_usdt": float(s["funding_usdt"]),
"trading_usdt": float(s["trading_usdt"]),
"funding_usdc": float(s["options_funding_usdc"]),
"trading_usdc": float(s["options_trading_usdc"]),
}
def total_usdt_equiv(self, snap: dict[str, float] | None = None) -> float:
"""USDC 按 1:1 计入总资金(与 crypto_monitor 一致)"""
s = snap or self.snapshot()
return round(sum(float(s.get(k) or 0) for k in WALLET_KEYS), 8)
"""USDC 按 1:1 计入总资金。"""
if snap is None:
v = self.view()
elif "funding_usdc" in snap:
v = snap
else:
v = {
"funding_usdt": float(snap.get("funding_usdt") or 0),
"trading_usdt": float(snap.get("trading_usdt") or 0),
"funding_usdc": float(snap.get("options_funding_usdc") or 0),
"trading_usdc": float(snap.get("options_trading_usdc") or 0),
}
return round(
float(v.get("funding_usdt") or 0)
+ float(v.get("trading_usdt") or 0)
+ float(v.get("funding_usdc") or 0)
+ float(v.get("trading_usdc") or 0),
8,
)
def reset_from_equity(self, equity: float) -> dict[str, float]:
"""重置:全部放入资金账户 USDT。"""
@@ -71,22 +92,20 @@ class SimFundsWallets:
self.db.execute(
"""UPDATE funds_wallets SET
funding_usdt=?, trading_usdt=?, options_funding_usdc=?, options_trading_usdc=?,
options_funding_usdt=?, options_trading_usdt=?, updated_at_ms=?
options_funding_usdt=0, options_trading_usdt=0, updated_at_ms=?
WHERE id=1""",
(
snap["funding_usdt"],
snap["trading_usdt"],
snap["options_funding_usdc"],
snap["options_trading_usdc"],
snap["options_funding_usdt"],
snap["options_trading_usdt"],
now,
),
)
return snap
def mirror_cash(self, amount: float, *, kind: str) -> None:
"""策略账本变动镜像到对应钱包(SIM)。"""
"""策略账本变动镜像到交易账户(永续 USDT / 期权 USDC)。"""
amt = float(amount)
if abs(amt) < 1e-12:
return
@@ -94,16 +113,12 @@ class SimFundsWallets:
k = (kind or "").lower()
if "option" in k:
key = "options_trading_usdc"
elif "perp" in k or "funding" in k:
key = "trading_usdt"
else:
key = "trading_usdt"
snap[key] = float(snap.get(key) or 0) + amt
# 允许短暂为负(与 ledger allow_negative 对齐时由调用方保证);展示侧夹到合理范围不在此做
self._set(**snap)
def sync_ledger_equity(self) -> float:
"""兑换/划转后把总权益同步到 ledger_meta(不重置钱包分配)。"""
total = self.total_usdt_equiv()
now = _now_ms()
self.db.execute(
@@ -119,11 +134,7 @@ class SimFundsWallets:
amount: float,
rate: float = 1.0,
) -> dict[str, Any]:
"""
SIM 兑换(默认在「资金账户」内 USDT↔USDC,对齐 crypto_monitor 主路径)。
direction: usdt_to_usdc | usdc_to_usdt
rate: 1 USDC = rate USDT(默认 1.0
"""
"""资金账户内 USDT↔USDC 兑换。"""
amt = float(amount)
if amt <= 0:
return {"ok": False, "detail": "数量须大于 0"}
@@ -140,7 +151,7 @@ class SimFundsWallets:
elif d == "usdc_to_usdt":
src = float(snap["options_funding_usdc"])
if amt > src + 1e-9:
return {"ok": False, "detail": f"期权资金账户 USDC 不足(可用 {src:.4f}"}
return {"ok": False, "detail": f"资金账户 USDC 不足(可用 {src:.4f}"}
usdt = amt * r
snap["options_funding_usdc"] = src - amt
snap["funding_usdt"] = float(snap["funding_usdt"]) + usdt
@@ -154,7 +165,7 @@ class SimFundsWallets:
"direction": d,
"amount": amt,
"rate": r,
"wallets": self.snapshot(),
"wallets": self.view(),
"total_usdt_equiv": total,
}
@@ -166,26 +177,26 @@ class SimFundsWallets:
from_account: str,
to_account: str,
) -> dict[str, Any]:
"""SIM 划转:funding/trading/options_funding/options_trading × USDT|USDC"""
"""仅资金账户 ↔ 交易账户"""
amt = float(amount)
if amt <= 0:
return {"ok": False, "detail": "划转金额须大于 0"}
ccy_l = (ccy or "USDC").strip().lower()
fa = (from_account or "").strip().lower()
ta = (to_account or "").strip().lower()
allowed = {"funding", "trading"}
if fa not in allowed or ta not in allowed:
return {"ok": False, "detail": "账户仅支持 funding / trading"}
if fa == ta:
return {"ok": False, "detail": "来源与目标账户不能相同"}
src_key = _ACCT_MAP.get((fa, ccy_l))
dst_key = _ACCT_MAP.get((ta, ccy_l))
if not src_key or not dst_key:
return {
"ok": False,
"detail": "账户须为 funding/trading/options_funding/options_trading,币种 USDT|USDC",
}
return {"ok": False, "detail": "币种须为 USDT 或 USDC"}
snap = self.snapshot()
src_bal = float(snap[src_key])
if amt > src_bal + 1e-9:
return {"ok": False, "detail": f"{src_key} 余额不足(可用 {src_bal:.4f}"}
return {"ok": False, "detail": f"余额不足(可用 {src_bal:.4f}"}
snap[src_key] = src_bal - amt
snap[dst_key] = float(snap[dst_key]) + amt
self._set(**snap)
@@ -197,6 +208,6 @@ class SimFundsWallets:
"amount": amt,
"from": fa,
"to": ta,
"wallets": self.snapshot(),
"wallets": self.view(),
"total_usdt_equiv": total,
}