Fix btc_eth watching entry, preview sizing, and coin-to-U settlement.
Use dual indices for watch/preview; perp entry uses ETH mark; expiry/close convert coin PnL via option index; align legacy long→Call; omit combo U when index missing. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1282,10 +1282,15 @@ def validate_start_body(plan_type: str, body: dict[str, Any]) -> Optional[str]:
|
||||
opt_type = "C"
|
||||
if opt_type not in ("P", "C"):
|
||||
return "缺少期权类型(Put/Call)"
|
||||
if direction == "long" and opt_type != "P":
|
||||
return "做多永期对冲须用 Put"
|
||||
if direction == "short" and opt_type != "C":
|
||||
return "做空永期对冲须用 Call"
|
||||
# 与 opt_type_for_view 一致:做多→Call+空永续,做空→Put+多永续
|
||||
from lib.hedge_plan.hedge_plan_option_primary_lib import opt_type_for_view
|
||||
|
||||
want = opt_type_for_view(direction)
|
||||
if opt_type != want:
|
||||
return (
|
||||
f"做{'多' if direction == 'long' else '空'}永期对冲须用 "
|
||||
f"{'Call' if want == 'C' else 'Put'}"
|
||||
)
|
||||
if direction == "long" and not (sl < entry < tp):
|
||||
return "做多须满足 止损 < 入场 < 止盈"
|
||||
if direction == "short" and not (tp < entry < sl):
|
||||
@@ -1775,34 +1780,38 @@ def execute_manual_close_plan(cfg: dict[str, Any], conn: Any, plan_id: int) -> d
|
||||
notes.append("卖币失败: " + str(sell_r.get("msg") or ""))
|
||||
|
||||
total = float(opt_pnl) + float(perp_pnl)
|
||||
# 期权币本位盈亏换算到 U:用期权标的指数(跨币=BTC,禁止×ETH)
|
||||
# 币本位期权盈亏一律 × 期权指数折 U(跨币=BTC);不再用 |pnl|<10 启发式
|
||||
try:
|
||||
from lib.hedge_plan.hedge_plan_live_positions_lib import resolve_option_index_px
|
||||
from lib.hedge_plan.hedge_po_mode_lib import get_hedge_po_mode, is_cross_asset, option_underlying
|
||||
from lib.options.options_pricing_lib import _quote_in_coin_from_context
|
||||
|
||||
mode = str(plan.get("po_mode") or get_hedge_po_mode())
|
||||
opt_u = str(plan.get("option_underlying") or plan.get("underlying") or option_underlying(mode) or uly).upper()
|
||||
ex_idx = cfg.get("exchange_options") or cfg.get("exchange")
|
||||
if callable(ex_idx):
|
||||
try:
|
||||
ex_idx = ex_idx()
|
||||
except Exception:
|
||||
ex_idx = None
|
||||
idx = float(
|
||||
resolve_option_index_px(
|
||||
cfg,
|
||||
opt_u,
|
||||
ex_opt=ex_idx,
|
||||
cross_asset=is_cross_asset(mode),
|
||||
perp_fallback=None,
|
||||
inst = ""
|
||||
if opt:
|
||||
inst = str(opt.get("inst_id") or "")
|
||||
coin = bool(_quote_in_coin_from_context(inst_id=inst)) if inst else True
|
||||
if coin:
|
||||
ex_idx = cfg.get("exchange_options") or cfg.get("exchange")
|
||||
if callable(ex_idx):
|
||||
try:
|
||||
ex_idx = ex_idx()
|
||||
except Exception:
|
||||
ex_idx = None
|
||||
idx = float(
|
||||
resolve_option_index_px(
|
||||
cfg,
|
||||
opt_u,
|
||||
ex_opt=ex_idx,
|
||||
cross_asset=is_cross_asset(mode),
|
||||
perp_fallback=None,
|
||||
)
|
||||
or 0
|
||||
)
|
||||
or 0
|
||||
)
|
||||
# opt_pnl 可能已是币;若为币且绝对值很小则 × 指数
|
||||
if abs(opt_pnl) < 10 and idx > 0 and abs(opt_pnl * idx) > abs(opt_pnl):
|
||||
opt_pnl_u = opt_pnl * idx
|
||||
opt_pnl_u = float(opt_pnl) * idx if idx > 0 else float(opt_pnl)
|
||||
else:
|
||||
opt_pnl_u = opt_pnl
|
||||
opt_pnl_u = float(opt_pnl)
|
||||
except Exception:
|
||||
opt_pnl_u = opt_pnl
|
||||
|
||||
|
||||
Reference in New Issue
Block a user