Show semi risk-based open size from ask and unit ratio.

Semi sizing uses market ask with semi units; Plan panel previews option/perp qty under the form.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-08 14:27:19 +08:00
parent 7db8b724ac
commit b09d1b0886
9 changed files with 343 additions and 44 deletions
+52 -5
View File
@@ -430,6 +430,8 @@ def compute_risk_sizing(
db: Database | None = None,
perp_unit: float | None = None,
option_unit: float | None = None,
exit_unit: float | None = None,
leverage_basis: str | None = None,
) -> RiskSizingResult:
database = db or get_db()
ledger = Ledger(database)
@@ -440,9 +442,16 @@ def compute_risk_sizing(
perp_u = float(perp_unit)
if option_unit is not None and float(option_unit) > 0:
opt_u = float(option_unit)
basis_raw = ledger.get_setting_str(
"risk_leverage_basis", s.risk_leverage_basis
) or s.risk_leverage_basis
if exit_unit is not None and float(exit_unit) > 0:
exit_u = float(exit_unit)
basis_raw = (
leverage_basis
if leverage_basis is not None
else (
ledger.get_setting_str("risk_leverage_basis", s.risk_leverage_basis)
or s.risk_leverage_basis
)
)
min_opt_lev = ledger.get_setting_float(
"min_option_leverage", s.min_option_leverage
)
@@ -690,6 +699,8 @@ def apply_risk_sizing_to_ledger(
db: Database | None = None,
perp_unit: float | None = None,
option_unit: float | None = None,
exit_unit: float | None = None,
leverage_basis: str | None = None,
) -> RiskSizingResult:
"""计算并写入 perp/option/exit;非以损定仓模式直接 ok 跳过。持仓中拒绝改写。"""
database = db or get_db()
@@ -713,6 +724,8 @@ def apply_risk_sizing_to_ledger(
db=database,
perp_unit=perp_unit,
option_unit=option_unit,
exit_unit=exit_unit,
leverage_basis=leverage_basis,
)
if not r.ok:
return r
@@ -793,8 +806,38 @@ def preview_risk_sizing(db: Database | None = None) -> dict[str, Any]:
out["ok"] = False
out["detail"] = "暂无指数或期权卖一,无法预览"
return out
r = compute_risk_sizing(index_px=float(idx), option_ask=float(ask), db=database)
# 半自动:用本单配比/净利基数,并以盘口卖一定仓(与开仓一致)
semi_perp = semi_opt = semi_exit = None
semi_on = False
try:
from .semi_auto import is_semi_auto, read_semi_params
if is_semi_auto(ledger):
sp = read_semi_params(ledger)
semi_on = True
semi_perp = float(sp["perp_unit"])
semi_opt = float(sp["option_unit"])
semi_exit = float(sp["perp_exit_unit"])
except Exception:
logger.debug("preview semi units skipped", exc_info=True)
r = compute_risk_sizing(
index_px=float(idx),
option_ask=float(ask),
db=database,
perp_unit=semi_perp,
option_unit=semi_opt,
exit_unit=semi_exit,
leverage_basis="actual" if semi_on else None,
)
perp_u, opt_u, exit_u = read_risk_units(ledger)
if semi_perp is not None:
perp_u = float(semi_perp)
if semi_opt is not None:
opt_u = float(semi_opt)
if semi_exit is not None:
exit_u = float(semi_exit)
mg = resolve_martingale(database, ledger=ledger)
s = get_settings()
exit_mode = str(
@@ -806,7 +849,10 @@ def preview_risk_sizing(db: Database | None = None) -> dict[str, Any]:
)
exit_target = r.net_profit_target
exit_label = "基数×k"
if exit_mode == "premium_multiple":
if semi_on:
exit_label = "半自动净利基数×k"
exit_mode = "fixed_usdt"
elif exit_mode == "premium_multiple":
exit_label = f"权利金×{prem_mult:g}"
if r.ok and r.premium_est is not None:
exit_target = round(float(r.premium_est) * max(0.0, prem_mult), 2)
@@ -833,6 +879,7 @@ def preview_risk_sizing(db: Database | None = None) -> dict[str, Any]:
"perp_unit": perp_u,
"option_unit": opt_u,
"exit_unit": exit_u,
"semi_units": semi_on,
"martingale": mg,
"risk_effective_loss_pct": mg.get("effective_pct"),
}