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:
@@ -509,11 +509,24 @@ def _activate_watching_po(
|
||||
str((perp or {}).get("direction") or "")
|
||||
or perp_direction_for_view(view)
|
||||
)
|
||||
# 永续开仓价:优先成交回写,否则 body.entry(应为永续标的价,跨币=ETH)
|
||||
perp_avg = None
|
||||
try:
|
||||
order = (perp or {}).get("order") or {}
|
||||
perp_avg = float(
|
||||
order.get("average")
|
||||
or order.get("avgPx")
|
||||
or (order.get("info") or {}).get("avgPx")
|
||||
or body.get("entry")
|
||||
or 0
|
||||
) or None
|
||||
except (TypeError, ValueError):
|
||||
perp_avg = float(body.get("entry") or 0) or None
|
||||
update_plan(
|
||||
conn,
|
||||
int(plan_id),
|
||||
status="partial" if is_partial else "active",
|
||||
entry_mark=float(body.get("entry") or body.get("index_px") or 0) or None,
|
||||
entry_mark=perp_avg,
|
||||
perp_size=float((perp or {}).get("contracts") or body.get("contracts") or 0),
|
||||
leverage=float(body.get("leverage") or 100),
|
||||
premium_total=premium,
|
||||
@@ -531,7 +544,7 @@ def _activate_watching_po(
|
||||
"symbol": str(body.get("exchange_symbol") or ""),
|
||||
"side": perp_dir,
|
||||
"size": float((perp or {}).get("contracts") or body.get("contracts") or 0),
|
||||
"avg_open": float(body.get("entry") or 0) if perp_ok else None,
|
||||
"avg_open": perp_avg if perp_ok else None,
|
||||
"status": "open" if perp_ok else "pending",
|
||||
"exchange_ord_id": str((perp or {}).get("exchange_ord_id") or ""),
|
||||
"opened_at": result.get("opened_at") if perp_ok else None,
|
||||
@@ -1455,12 +1468,43 @@ def _preview_po(body: dict[str, Any]) -> dict[str, Any]:
|
||||
err = validate_option_primary_start(body)
|
||||
if err:
|
||||
raise ValueError(err)
|
||||
from lib.hedge_plan.hedge_po_mode_lib import (
|
||||
apply_mode_to_start_body,
|
||||
get_hedge_po_mode,
|
||||
is_cross_asset,
|
||||
option_underlying,
|
||||
perp_underlying,
|
||||
)
|
||||
|
||||
body = apply_mode_to_start_body(body)
|
||||
mode = str(body.get("po_mode") or get_hedge_po_mode())
|
||||
opt_idx = None
|
||||
perp_idx = None
|
||||
try:
|
||||
from lib.exchange.okx_public_http_lib import fetch_index_px
|
||||
|
||||
opt_idx = float(fetch_index_px(option_underlying(mode)) or 0) or None
|
||||
if is_cross_asset(mode):
|
||||
perp_idx = float(fetch_index_px(perp_underlying(mode)) or 0) or None
|
||||
else:
|
||||
perp_idx = opt_idx
|
||||
except Exception:
|
||||
opt_idx = perp_idx = None
|
||||
if opt_idx is None:
|
||||
try:
|
||||
opt_idx = float(body.get("index_px") or body.get("entry") or 0) or None
|
||||
except (TypeError, ValueError):
|
||||
opt_idx = None
|
||||
if perp_idx is None:
|
||||
perp_idx = opt_idx
|
||||
sized = size_from_premium(
|
||||
premium_budget=float(body.get("premium_budget") or 0),
|
||||
ask=float(body.get("ask") or 0),
|
||||
ct_mult=float(body.get("ct_mult") or 0.01),
|
||||
ratio=float(body.get("option_perp_ratio") or 2),
|
||||
contract_size=float(body.get("contract_size") or 0.01),
|
||||
option_index=opt_idx,
|
||||
perp_index=perp_idx,
|
||||
)
|
||||
if not sized.get("ok"):
|
||||
raise ValueError(sized.get("msg") or "定仓失败")
|
||||
@@ -1468,19 +1512,25 @@ def _preview_po(body: dict[str, Any]) -> dict[str, Any]:
|
||||
body["sheets"] = sized["sheets"]
|
||||
body["contracts"] = sized["contracts"]
|
||||
body["eth_qty"] = sized["eth_qty"]
|
||||
if not body.get("index_px") and opt_idx:
|
||||
body["index_px"] = opt_idx
|
||||
# entry=永续参考价(跨币用 ETH 指数);勿把 BTC 指数写入永续开仓价
|
||||
if not body.get("entry"):
|
||||
body["entry"] = body.get("index_px") or 0
|
||||
body["entry"] = perp_idx or opt_idx or body.get("index_px") or 0
|
||||
out = build_option_primary_preview(body)
|
||||
out["sizing"] = sized
|
||||
return out
|
||||
|
||||
from lib.hedge_plan.hedge_plan_option_primary_lib import opt_type_for_view
|
||||
|
||||
direction = str(body.get("direction") or "long").lower()
|
||||
entry = float(body["entry"])
|
||||
tp = float(body["tp"])
|
||||
sl = float(body["sl"])
|
||||
contracts = float(body["contracts"])
|
||||
contract_size = float(body.get("contract_size") or 0.01)
|
||||
opt_type = str(body.get("opt_type") or ("P" if direction == "long" else "C"))
|
||||
# 与以期权为主同口径:long→Call, short→Put(旧保险 long→Put 已废弃)
|
||||
opt_type = str(body.get("opt_type") or opt_type_for_view(direction))
|
||||
strike = float(body["strike"])
|
||||
sheets = float(body.get("sheets") or 1)
|
||||
ct_mult = float(body.get("ct_mult") or 0.01)
|
||||
|
||||
Reference in New Issue
Block a user