diff --git a/lib/common/static/hedge_plan.js b/lib/common/static/hedge_plan.js index db9700e..2f5d8a6 100644 --- a/lib/common/static/hedge_plan.js +++ b/lib/common/static/hedge_plan.js @@ -177,6 +177,7 @@ const acctLabel = d.account_label || "合约账户"; const tag = $("hp-perp-acct-tag"); if (tag) tag.textContent = acctLabel; + const amtPrec = d.amount_precision != null ? Number(d.amount_precision) : 4; const q = $("hp-perp-quote"); if (q) { q.innerHTML = @@ -186,7 +187,7 @@ acctLabel + "可用 " + fmt(d.available_usdt, 2) + - " U
标记 " + + " USDT
标记 " + fmt(d.mark, 2) + " · 最新 " + fmt(d.last, 2) + @@ -195,7 +196,15 @@ " · 买一 " + fmt(d.bid, 2) + " · 面值 " + - fmt(d.contract_size, 4); + fmt(d.contract_size, 4) + + " · 张精度 " + + amtPrec + + " 位"; + } + const contractsInput = $("hp-contracts"); + if (contractsInput) { + const step = amtPrec <= 0 ? "1" : String(Math.pow(10, -amtPrec)); + contractsInput.step = step; } const sz = $("hp-sizing-line"); if (sz) { @@ -206,25 +215,73 @@ acctLabel + "):保证金 " + fmt(s.margin_capital, 2) + - "U × " + + " USDT × " + s.leverage + "x → 名义 " + fmt(s.notional_value, 2) + - "U · 建议约 " + - fmt(d.suggest_contracts, 4) + - " 张"; + " USDT · 建议 " + + fmt(d.suggest_contracts, amtPrec) + + " 合约张(已按交易所精度)"; } else { sz.textContent = "非全仓或不具备保证金数据时仅手动填张数;永期开仓需全仓."; } } const entry = $("hp-entry"); if (entry && d.entry_ref && !entry.value) entry.value = d.entry_ref; - const contracts = $("hp-contracts"); - if (contracts && d.suggest_contracts != null && !contracts.value) { - contracts.value = d.suggest_contracts; + if (contractsInput && d.suggest_contracts != null && !contractsInput.value) { + contractsInput.value = fmt(d.suggest_contracts, amtPrec); } const label = $("hp-opt-type-label"); if (label) label.textContent = d.suggested_opt_type === "C" ? "Call" : "Put"; + updatePerpPnlHint(); + } + + function updatePerpPnlHint() { + const el = $("hp-perp-pnl-line"); + if (!el) return; + const entry = Number(($("hp-entry") && $("hp-entry").value) || NaN); + const tp = Number(($("hp-tp") && $("hp-tp").value) || NaN); + const sl = Number(($("hp-sl") && $("hp-sl").value) || NaN); + const contracts = Number(($("hp-contracts") && $("hp-contracts").value) || NaN); + const cs = Number((state.market && state.market.contract_size) || 0.01); + const dir = (($("hp-direction") && $("hp-direction").value) || "long").toLowerCase(); + if (!(entry > 0) || !(contracts > 0) || !(cs > 0)) { + el.textContent = "填写开仓价与张数后,输入止盈/止损可看永续盈亏金额(USDT)"; + return; + } + function pnlAt(exitPx) { + const coins = contracts * cs; + if (dir === "short") return (entry - exitPx) * coins; + return (exitPx - entry) * coins; + } + const parts = []; + if (tp > 0) { + const p = pnlAt(tp); + parts.push( + "止盈预期 = 0 ? "hp-pnl-pos" : "hp-pnl-neg") + + "\">" + + (p >= 0 ? "+" : "") + + fmt(p, 2) + + " USDT" + ); + } else { + parts.push("止盈预期 —"); + } + if (sl > 0) { + const p = pnlAt(sl); + parts.push( + "止损预期 = 0 ? "hp-pnl-pos" : "hp-pnl-neg") + + "\">" + + (p >= 0 ? "+" : "") + + fmt(p, 2) + + " USDT" + ); + } else { + parts.push("止损预期 —"); + } + el.innerHTML = parts.join(" · "); } function fillExpSelect(sel, chain) { @@ -632,6 +689,10 @@ }); }); } + ["hp-entry", "hp-tp", "hp-sl", "hp-contracts"].forEach(function (id) { + const el = $(id); + if (el) el.addEventListener("input", updatePerpPnlHint); + }); if ($("hp-refresh")) $("hp-refresh").addEventListener("click", function () { void refreshAll(); diff --git a/lib/common/static/instance_theme.css b/lib/common/static/instance_theme.css index 76acfb7..41b61ba 100644 --- a/lib/common/static/instance_theme.css +++ b/lib/common/static/instance_theme.css @@ -3212,6 +3212,28 @@ html[data-theme="light"] .opt-be-dist-down { font-weight: 500; margin-left: 4px; } +.hedge-plan-page-wrap .hp-unit { + font-size: 0.66rem; + color: #8892b0; + font-weight: 500; + margin-right: 2px; +} +.hedge-plan-page-wrap .hp-unit-hint { + font-size: 0.68rem; + margin: 2px 0 6px; + line-height: 1.4; +} +.hedge-plan-page-wrap #hp-perp-pnl-line { + font-size: 0.74rem; + margin: 4px 0 6px; + line-height: 1.45; +} +.hedge-plan-page-wrap .hp-pnl-pos { + color: #7ee787; +} +.hedge-plan-page-wrap .hp-pnl-neg { + color: #ff8a8a; +} .hedge-plan-page-wrap .form-row label, .hedge-plan-page-wrap .form-row select, .hedge-plan-page-wrap .form-row input, diff --git a/lib/hedge_plan/hedge_plan_calc_lib.py b/lib/hedge_plan/hedge_plan_calc_lib.py index 1507482..d200785 100644 --- a/lib/hedge_plan/hedge_plan_calc_lib.py +++ b/lib/hedge_plan/hedge_plan_calc_lib.py @@ -69,6 +69,23 @@ def suggest_contracts_from_notional( return float(notional) / (float(entry) * float(contract_size)) +def floor_contracts_to_precision(contracts: float, decimals: int) -> float: + """按交易所张数精度向下取整,避免建议张数超过可用保证金.""" + import math + + raw = float(contracts or 0.0) + if raw <= 0: + return 0.0 + try: + d = int(decimals) + except (TypeError, ValueError): + d = 0 + if d <= 0: + return float(math.floor(raw + 1e-12)) + scale = 10**d + return math.floor(raw * scale + 1e-12) / scale + + def build_perp_options_preview( *, direction: str, diff --git a/lib/hedge_plan/hedge_plan_register.py b/lib/hedge_plan/hedge_plan_register.py index 548e3c6..f49cad9 100644 --- a/lib/hedge_plan/hedge_plan_register.py +++ b/lib/hedge_plan/hedge_plan_register.py @@ -10,10 +10,12 @@ from jinja2 import ChoiceLoader, FileSystemLoader from lib.hedge_plan.hedge_plan_calc_lib import ( build_options_options_preview, build_perp_options_preview, + floor_contracts_to_precision, gate_status, option_premium_total, suggest_contracts_from_notional, ) +from lib.hub.hub_calculator_market_lib import amount_decimals_from_exchange from lib.trade.position_sizing_lib import ( compute_full_margin_sizing, load_position_sizing_mode, @@ -305,6 +307,11 @@ def _fetch_perp_market(cfg: dict[str, Any], base: str) -> tuple[dict[str, Any], entry = float(mark or last or 0) sizing = None suggest_contracts = None + amount_precision = 4 + try: + amount_precision = int(amount_decimals_from_exchange(ex, sym)) + except Exception: + amount_precision = 4 if available is not None and entry > 0: sizing, _serr = compute_full_margin_sizing( symbol=sym, @@ -316,11 +323,20 @@ def _fetch_perp_market(cfg: dict[str, Any], base: str) -> tuple[dict[str, Any], funds_decimals=int(cfg.get("funds_decimals") or 2), ) if sizing: - suggest_contracts = suggest_contracts_from_notional( + raw_contracts = suggest_contracts_from_notional( notional=float(sizing["notional_value"]), entry=entry, contract_size=cs, ) + # 优先走交易所 amount_to_precision;失败则按精度位数向下取整 + suggest_contracts = None + try: + precise = float(ex.amount_to_precision(sym, raw_contracts)) + if precise > raw_contracts + 1e-12: + precise = floor_contracts_to_precision(raw_contracts, amount_precision) + suggest_contracts = precise + except Exception: + suggest_contracts = floor_contracts_to_precision(raw_contracts, amount_precision) return { "exchange_symbol": sym, @@ -331,7 +347,11 @@ def _fetch_perp_market(cfg: dict[str, Any], base: str) -> tuple[dict[str, Any], "contract_size": cs, "available_usdt": available, "full_margin_sizing": sizing, - "suggest_contracts": round(suggest_contracts, 6) if suggest_contracts is not None else None, + "suggest_contracts": suggest_contracts, + "amount_precision": amount_precision, + "unit_quote": "USDT", + "unit_contracts": "合约张", + "unit_note": "价格单位 USDT;张数=交易所永续合约张(与下单精度一致);名义≈张数×面值×价格", "entry_ref": entry or None, }, None diff --git a/lib/hedge_plan/templates/hedge_plan_panel.html b/lib/hedge_plan/templates/hedge_plan_panel.html index 3bab432..732d1b7 100644 --- a/lib/hedge_plan/templates/hedge_plan_panel.html +++ b/lib/hedge_plan/templates/hedge_plan_panel.html @@ -39,12 +39,14 @@
加载中…
+

单位说明:价格=USDT · 张数=交易所永续合约张(精度与 OKX 下单一致) · 盈亏=USDT

- - - - + + + +
+

@@ -75,9 +77,10 @@
- +
+

单位说明:权利金结算币=USDC · 张数=期权张(整张) · 卖一/买一=价格/张

@@ -192,4 +195,4 @@ - + diff --git a/lib/instance/templates/embed_shell.html b/lib/instance/templates/embed_shell.html index cf9921b..60fcc9a 100644 --- a/lib/instance/templates/embed_shell.html +++ b/lib/instance/templates/embed_shell.html @@ -7,7 +7,7 @@ - + {{ exchange_display }} · 加密货币 | 交易监控复盘系统 diff --git a/lib/instance/templates/index.html b/lib/instance/templates/index.html index 53d512b..d91d18a 100644 --- a/lib/instance/templates/index.html +++ b/lib/instance/templates/index.html @@ -17,7 +17,7 @@ {{ exchange_display }} · 加密货币 | 交易监控复盘系统 - +