Align hedge UI/fees: drop 未启动, premium coin/U, equity incl perp margin, OKX option fees.
Option net uses Min(0.03%×coin, 7%×premium) with bid/ask fills (no slip); live PnL colors fixed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,9 +4,10 @@ from __future__ import annotations
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any, Optional
|
||||
|
||||
from lib.hedge_plan.hedge_plan_option_primary_lib import (
|
||||
from lib.hedge_plan.hedge_plan_option_primary_lib import (
|
||||
estimate_combo_net_pnl,
|
||||
fee_rate,
|
||||
option_fee_rate,
|
||||
opt_type_for_view,
|
||||
option_bid_liquidity_ok,
|
||||
perp_direction_for_view,
|
||||
@@ -129,6 +130,7 @@ def build_live_hedge_cards(cfg: dict[str, Any], conn: Any) -> list[dict[str, Any
|
||||
get_cs = cfg.get("get_contract_size")
|
||||
fetch_idx = cfg.get("fetch_index_price")
|
||||
fr = fee_rate()
|
||||
fr_opt = option_fee_rate()
|
||||
now_ms = int(datetime.now(tz=_BJ).timestamp() * 1000)
|
||||
out: list[dict[str, Any]] = []
|
||||
|
||||
@@ -226,11 +228,15 @@ def build_live_hedge_cards(cfg: dict[str, Any], conn: Any) -> list[dict[str, Any
|
||||
contracts=float(contracts or 0),
|
||||
contract_size=float(cs or 0.01),
|
||||
fee=fr,
|
||||
option_fee=fr_opt,
|
||||
)
|
||||
opt_net_coin = float(net.get("opt_net") or 0)
|
||||
# 币→U:用当前指数(与买币参考价同口径)
|
||||
opt_net_usdt = round(opt_net_coin * float(idx or 0), 4) if idx else None
|
||||
perp_net = float(net.get("perp_net") or 0)
|
||||
combo_usdt = round((opt_net_usdt or 0) + perp_net, 4) if opt_net_usdt is not None else round(perp_net, 4)
|
||||
prem_coin = float(net.get("premium") or (float(avg_open or 0) * float(sheets or 0) * float(ct or 0.01)))
|
||||
prem_usdt = round(prem_coin * float(idx or 0), 2) if idx else None
|
||||
|
||||
opened_at = plan.get("opened_at")
|
||||
opened_ms = _parse_opened_ms(opened_at)
|
||||
@@ -253,6 +259,7 @@ def build_live_hedge_cards(cfg: dict[str, Any], conn: Any) -> list[dict[str, Any
|
||||
"remain_sec": remain_sec,
|
||||
"index_px": idx,
|
||||
"fee_rate": fr,
|
||||
"option_fee_rate": fr_opt,
|
||||
"option": {
|
||||
"inst_id": inst_id or "—",
|
||||
"opt_type": opt_type,
|
||||
@@ -266,6 +273,8 @@ def build_live_hedge_cards(cfg: dict[str, Any], conn: Any) -> list[dict[str, Any
|
||||
"leverage": opt_leverage,
|
||||
"liq_ok": bool(liq_ok),
|
||||
"liq_msg": liq_msg or "",
|
||||
"premium_coin": round(prem_coin, 4),
|
||||
"premium_usdt": prem_usdt,
|
||||
"net_coin": opt_net_coin,
|
||||
"net_usdt": opt_net_usdt,
|
||||
"live": bool(opt_raw),
|
||||
|
||||
@@ -38,12 +38,29 @@ def is_option_primary(body_or_plan: dict[str, Any] | None) -> bool:
|
||||
|
||||
|
||||
def fee_rate() -> float:
|
||||
"""永续 taker 费率(默认 0.05%)."""
|
||||
try:
|
||||
return max(0.0, float(os.getenv("HEDGE_PLAN_FEE_RATE") or os.getenv("OKX_TAKER_FEE") or "0.0005"))
|
||||
except (TypeError, ValueError):
|
||||
return 0.0005
|
||||
|
||||
|
||||
def option_fee_rate() -> float:
|
||||
"""币本位期权 taker 费率(OKX 普通档默认 0.03%)."""
|
||||
try:
|
||||
return max(
|
||||
0.0,
|
||||
float(
|
||||
os.getenv("HEDGE_PLAN_OPTION_FEE_RATE")
|
||||
or os.getenv("OKX_OPTIONS_TAKER_FEE")
|
||||
or os.getenv("SIM_OPTION_FEE_RATE")
|
||||
or "0.0003"
|
||||
),
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
return 0.0003
|
||||
|
||||
|
||||
def floor2(v: float) -> float:
|
||||
"""ETH 数量向下取两位小数."""
|
||||
if v <= 0:
|
||||
@@ -201,17 +218,30 @@ def estimate_combo_net_pnl(
|
||||
contracts: float,
|
||||
contract_size: float,
|
||||
fee: Optional[float] = None,
|
||||
option_fee: Optional[float] = None,
|
||||
) -> dict[str, Any]:
|
||||
"""组合净利(扣费);平仓/卖出手续费按买入费率估算."""
|
||||
fr = fee if fee is not None else fee_rate()
|
||||
"""组合净利(扣开平双边手续费).
|
||||
|
||||
期权:吃卖一开/买一平(无滑点);费=Min(费率×标的币, 权利金×7%).
|
||||
永续:名义×费率(开+平).
|
||||
"""
|
||||
from lib.sim.pricing_lib import option_fee_coin
|
||||
|
||||
fr_perp = fee if fee is not None else fee_rate()
|
||||
fr_opt = option_fee if option_fee is not None else option_fee_rate()
|
||||
ct = float(ct_mult or 0.01)
|
||||
sh = float(sheets or 0)
|
||||
a = float(ask_open or 0)
|
||||
b = float(bid or 0)
|
||||
premium = a * sh * ct
|
||||
opt_proceeds = b * sh * ct
|
||||
opt_open_fee = premium * fr
|
||||
opt_close_fee = opt_proceeds * fr # 卖出费用按买入费率
|
||||
underlying = sh * ct
|
||||
premium = a * underlying
|
||||
opt_proceeds = b * underlying
|
||||
opt_open_fee = option_fee_coin(
|
||||
underlying_coin=underlying, premium_coin=premium, fee_rate=fr_opt
|
||||
)
|
||||
opt_close_fee = option_fee_coin(
|
||||
underlying_coin=underlying, premium_coin=opt_proceeds, fee_rate=fr_opt
|
||||
)
|
||||
opt_net = opt_proceeds - premium - opt_open_fee - opt_close_fee
|
||||
|
||||
coins = float(contracts or 0) * float(contract_size or 0.01)
|
||||
@@ -224,15 +254,20 @@ def estimate_combo_net_pnl(
|
||||
perp_gross = (mark - entry) * coins
|
||||
perp_notional_open = abs(entry * coins)
|
||||
perp_notional_close = abs(mark * coins)
|
||||
perp_open_fee = perp_notional_open * fr
|
||||
perp_close_fee = perp_notional_close * fr
|
||||
perp_open_fee = perp_notional_open * fr_perp
|
||||
perp_close_fee = perp_notional_close * fr_perp
|
||||
perp_net = perp_gross - perp_open_fee - perp_close_fee
|
||||
total = opt_net + perp_net
|
||||
return {
|
||||
"opt_net": round(opt_net, 4),
|
||||
"perp_net": round(perp_net, 4),
|
||||
"net": round(total, 4),
|
||||
"fee_rate": fr,
|
||||
"fee_rate": fr_perp,
|
||||
"option_fee_rate": fr_opt,
|
||||
"opt_open_fee": round(opt_open_fee, 8),
|
||||
"opt_close_fee": round(opt_close_fee, 8),
|
||||
"perp_open_fee": round(perp_open_fee, 4),
|
||||
"perp_close_fee": round(perp_close_fee, 4),
|
||||
"premium": round(premium, 4),
|
||||
"opt_proceeds": round(opt_proceeds, 4),
|
||||
}
|
||||
|
||||
@@ -1431,30 +1431,53 @@ def _fetch_perp_market(cfg: dict[str, Any], base: str) -> tuple[dict[str, Any],
|
||||
|
||||
|
||||
def _options_account_snapshot(cfg: dict[str, Any]) -> dict[str, Any]:
|
||||
"""期权账户资金快照(与期权页同源: exchange_options)."""
|
||||
"""期权账户资金快照(与期权页同源: exchange_options).
|
||||
|
||||
trading_usdt=展示权益(含永续全仓占用);trading_usdt_avail=可开仓余额.
|
||||
"""
|
||||
out: dict[str, Any] = {
|
||||
"label": cfg.get("options_account_label") or "期权账户",
|
||||
"trading_usdc": None,
|
||||
"funding_usdc": None,
|
||||
"trading_usdt": None,
|
||||
"funding_usdt": None,
|
||||
"trading_usdt_avail": None,
|
||||
"perp_margin_usdt": None,
|
||||
"margin_note": "永续全仓 · 期权逐仓",
|
||||
}
|
||||
ex = cfg.get("exchange_options")
|
||||
hdr = cfg.get("options_header_balances")
|
||||
if ex is None or not callable(hdr):
|
||||
if ex is None:
|
||||
return out
|
||||
try:
|
||||
trading_usdc, funding_usdc, funding_usdt, trading_usdt = hdr(ex, force=False)
|
||||
from lib.exchange.okx_options_lib import options_header_balance_pack
|
||||
|
||||
pack = options_header_balance_pack(ex, force=False) or {}
|
||||
out.update(
|
||||
{
|
||||
"trading_usdc": trading_usdc,
|
||||
"funding_usdc": funding_usdc,
|
||||
"trading_usdt": trading_usdt,
|
||||
"funding_usdt": funding_usdt,
|
||||
"trading_usdc": pack.get("trading_usdc"),
|
||||
"funding_usdc": pack.get("funding_usdc"),
|
||||
"trading_usdt": pack.get("trading_usdt"),
|
||||
"funding_usdt": pack.get("funding_usdt"),
|
||||
"trading_usdt_avail": pack.get("trading_usdt_avail", pack.get("trading_usdt")),
|
||||
"perp_margin_usdt": pack.get("perp_margin_usdt"),
|
||||
}
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
hdr = cfg.get("options_header_balances")
|
||||
if callable(hdr):
|
||||
try:
|
||||
trading_usdc, funding_usdc, funding_usdt, trading_usdt = hdr(ex, force=False)
|
||||
out.update(
|
||||
{
|
||||
"trading_usdc": trading_usdc,
|
||||
"funding_usdc": funding_usdc,
|
||||
"trading_usdt": trading_usdt,
|
||||
"funding_usdt": funding_usdt,
|
||||
"trading_usdt_avail": trading_usdt,
|
||||
}
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return out
|
||||
|
||||
|
||||
|
||||
@@ -431,4 +431,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/hedge_plan.js?v=58"></script>
|
||||
<script src="/static/hedge_plan.js?v=59"></script>
|
||||
|
||||
Reference in New Issue
Block a user