Use daily open as perp-hedge entry and toggle buy-straddle vs perp overlays.
Amp-stats now prices premium from each day's open, and the form switches mutually between straddle and perpetual-options对照. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+71
-43
@@ -279,7 +279,7 @@ def enrich_rows_pnl(
|
||||
change=float(item.get("change") or 0),
|
||||
open_px=float(item.get("open") or 0),
|
||||
close_px=float(item.get("close") or 0),
|
||||
premium_total=float(hedge["premium_total"]),
|
||||
option_leverage=float(hedge["option_leverage"]),
|
||||
opt_coins=float(hedge["opt_coins"]),
|
||||
)
|
||||
else:
|
||||
@@ -291,22 +291,21 @@ def enrich_rows_pnl(
|
||||
def normalize_perp_hedge_params(raw: Any) -> Optional[dict[str, float]]:
|
||||
"""永期对冲对照参数.缺必填则返回 None(不做对照).
|
||||
|
||||
接受 dict 或带 spot/target_profit_u/perp_leverage/option_leverage 的对象字段.
|
||||
入场价按日开盘;表单只需目标盈利/杠杆/比例.旧字段 spot 可忽略.
|
||||
"""
|
||||
if raw is None or raw == "":
|
||||
return None
|
||||
if not isinstance(raw, dict):
|
||||
return None
|
||||
spot = _safe_float(raw.get("spot"))
|
||||
target = _safe_float(raw.get("target_profit_u") if "target_profit_u" in raw else raw.get("target"))
|
||||
p_lev = _safe_float(raw.get("perp_leverage"))
|
||||
o_lev = _safe_float(raw.get("option_leverage"))
|
||||
rp = _safe_float(raw.get("ratio_perp"))
|
||||
ro = _safe_float(raw.get("ratio_opt"))
|
||||
ct = _safe_float(raw.get("ct_mult"))
|
||||
if spot is None or target is None or p_lev is None or o_lev is None:
|
||||
if target is None or p_lev is None or o_lev is None:
|
||||
return None
|
||||
if spot <= 0 or target < 0 or p_lev <= 0 or o_lev <= 0:
|
||||
if target < 0 or p_lev <= 0 or o_lev <= 0:
|
||||
return None
|
||||
if rp is None or rp <= 0:
|
||||
rp = 1.0
|
||||
@@ -314,33 +313,38 @@ def normalize_perp_hedge_params(raw: Any) -> Optional[dict[str, float]]:
|
||||
ro = 2.0
|
||||
if ct is None or ct <= 0:
|
||||
ct = 0.01
|
||||
prem_per_coin = spot / o_lev
|
||||
opt_coins = 1.0 * (ro / rp)
|
||||
premium_total = opt_coins * prem_per_coin
|
||||
return {
|
||||
"spot": spot,
|
||||
"target_profit_u": target,
|
||||
"perp_leverage": p_lev,
|
||||
"option_leverage": o_lev,
|
||||
"ratio_perp": rp,
|
||||
"ratio_opt": ro,
|
||||
"ct_mult": ct,
|
||||
"prem_per_coin": prem_per_coin,
|
||||
"opt_coins": opt_coins,
|
||||
"opt_sheets": opt_coins / ct,
|
||||
"premium_total": premium_total,
|
||||
}
|
||||
|
||||
|
||||
def perp_hedge_day_premium(*, open_px: float, option_leverage: float, opt_coins: float) -> float:
|
||||
"""单日权利金总额 = 开盘 / 期权杠杆 × 期权币数."""
|
||||
o = float(open_px or 0)
|
||||
lev = float(option_leverage or 0)
|
||||
coins = float(opt_coins or 0)
|
||||
if o <= 0 or lev <= 0 or coins < 0:
|
||||
return 0.0
|
||||
return coins * (o / lev)
|
||||
|
||||
|
||||
def perp_hedge_day_pnl(
|
||||
*,
|
||||
change: float,
|
||||
open_px: float,
|
||||
close_px: float,
|
||||
premium_total: float,
|
||||
option_leverage: float,
|
||||
opt_coins: float,
|
||||
) -> float:
|
||||
"""单日组合净利(永续多1币 + 买期权).
|
||||
"""单日组合净利(永续多1币 + 买期权);入场/权利金按当日开盘.
|
||||
|
||||
上涨: change − 权利金 − 永续开平手续费
|
||||
下跌: |change|×(opt_coins−1) − 权利金
|
||||
@@ -348,7 +352,9 @@ def perp_hedge_day_pnl(
|
||||
from lib.trade.trade_fee_lib import estimate_roundtrip_fee_usdt
|
||||
|
||||
chg = float(change or 0)
|
||||
prem = float(premium_total or 0)
|
||||
prem = perp_hedge_day_premium(
|
||||
open_px=open_px, option_leverage=option_leverage, opt_coins=opt_coins
|
||||
)
|
||||
coins = float(opt_coins or 0)
|
||||
if chg >= 0:
|
||||
fee = 0.0
|
||||
@@ -363,54 +369,74 @@ def perp_hedge_stats(
|
||||
rows: list[dict[str, Any]],
|
||||
hedge: dict[str, float],
|
||||
) -> dict[str, Any]:
|
||||
"""永期对冲:所需点数达标 + 按日组合盈亏汇总."""
|
||||
"""永期对冲:所需点数达标 + 按日组合盈亏汇总.
|
||||
|
||||
日盈亏权利金按当日开盘;推所需点数用样本开盘中位数作入场参照.
|
||||
"""
|
||||
from lib.hub.hub_perp_options_calc_lib import calc_perp_options_points
|
||||
|
||||
points_data, points_err = calc_perp_options_points(
|
||||
base="ETH",
|
||||
spot=hedge["spot"],
|
||||
capital_usdt=max(hedge["spot"] / hedge["perp_leverage"] * 2, 1000.0),
|
||||
target_profit_u=hedge["target_profit_u"],
|
||||
perp_leverage=hedge["perp_leverage"],
|
||||
option_leverage=hedge["option_leverage"],
|
||||
ratio_perp=hedge["ratio_perp"],
|
||||
ratio_opt=hedge["ratio_opt"],
|
||||
ct_mult=hedge["ct_mult"],
|
||||
opens = [float(r.get("open") or 0) for r in (rows or []) if float(r.get("open") or 0) > 0]
|
||||
spot_ref = statistics.median(opens) if opens else None
|
||||
prem_ref = (
|
||||
perp_hedge_day_premium(
|
||||
open_px=spot_ref,
|
||||
option_leverage=hedge["option_leverage"],
|
||||
opt_coins=hedge["opt_coins"],
|
||||
)
|
||||
if spot_ref is not None
|
||||
else None
|
||||
)
|
||||
prem_per_coin_ref = (spot_ref / hedge["option_leverage"]) if spot_ref is not None else None
|
||||
|
||||
move_a = None
|
||||
move_b = None
|
||||
if points_data:
|
||||
move_a = float((points_data.get("case_a") or {}).get("move_points") or 0) or None
|
||||
mb = (points_data.get("case_b") or {}).get("move_points_portfolio")
|
||||
move_b = float(mb) if mb is not None else None
|
||||
points_err = None
|
||||
if spot_ref is not None and spot_ref > 0:
|
||||
points_data, points_err = calc_perp_options_points(
|
||||
base="ETH",
|
||||
spot=spot_ref,
|
||||
capital_usdt=max(spot_ref / hedge["perp_leverage"] * 2, 1000.0),
|
||||
target_profit_u=hedge["target_profit_u"],
|
||||
perp_leverage=hedge["perp_leverage"],
|
||||
option_leverage=hedge["option_leverage"],
|
||||
ratio_perp=hedge["ratio_perp"],
|
||||
ratio_opt=hedge["ratio_opt"],
|
||||
ct_mult=hedge["ct_mult"],
|
||||
)
|
||||
if points_data:
|
||||
move_a = float((points_data.get("case_a") or {}).get("move_points") or 0) or None
|
||||
mb = (points_data.get("case_b") or {}).get("move_points_portfolio")
|
||||
move_b = float(mb) if mb is not None else None
|
||||
else:
|
||||
points_err = "样本无有效开盘价,无法推所需点数"
|
||||
|
||||
# 使用已 enrich 的 perp_hedge_pnl;若无则当场补算
|
||||
# 按日开盘重算盈亏(不沿用固定权利金)
|
||||
work: list[dict[str, Any]] = []
|
||||
for r in rows or []:
|
||||
item = dict(r)
|
||||
if item.get("perp_hedge_pnl") is None:
|
||||
item["perp_hedge_pnl"] = perp_hedge_day_pnl(
|
||||
change=float(item.get("change") or 0),
|
||||
open_px=float(item.get("open") or 0),
|
||||
close_px=float(item.get("close") or 0),
|
||||
premium_total=float(hedge["premium_total"]),
|
||||
opt_coins=float(hedge["opt_coins"]),
|
||||
)
|
||||
item["perp_hedge_pnl"] = perp_hedge_day_pnl(
|
||||
change=float(item.get("change") or 0),
|
||||
open_px=float(item.get("open") or 0),
|
||||
close_px=float(item.get("close") or 0),
|
||||
option_leverage=float(hedge["option_leverage"]),
|
||||
opt_coins=float(hedge["opt_coins"]),
|
||||
)
|
||||
work.append(item)
|
||||
n = len(work)
|
||||
empty = {
|
||||
"enabled": True,
|
||||
"spot": round(hedge["spot"], 4),
|
||||
"entry": "open",
|
||||
"spot": None if spot_ref is None else round(spot_ref, 4),
|
||||
"target_profit_u": round(hedge["target_profit_u"], 4),
|
||||
"perp_leverage": round(hedge["perp_leverage"], 4),
|
||||
"option_leverage": round(hedge["option_leverage"], 4),
|
||||
"ratio_perp": round(hedge["ratio_perp"], 4),
|
||||
"ratio_opt": round(hedge["ratio_opt"], 4),
|
||||
"ratio_label": f"{hedge['ratio_perp']:g}:{hedge['ratio_opt']:g}",
|
||||
"prem_per_coin": round(hedge["prem_per_coin"], 4),
|
||||
"prem_per_coin": None if prem_per_coin_ref is None else round(prem_per_coin_ref, 4),
|
||||
"opt_coins": round(hedge["opt_coins"], 4),
|
||||
"opt_sheets": round(hedge["opt_sheets"], 4),
|
||||
"premium_total": round(hedge["premium_total"], 4),
|
||||
"premium_total": None if prem_ref is None else round(prem_ref, 4),
|
||||
"move_a": None if move_a is None else round(move_a, 4),
|
||||
"move_b": None if move_b is None else round(move_b, 4),
|
||||
"points_error": points_err,
|
||||
@@ -995,7 +1021,9 @@ def build_export_csv(payload: dict[str, Any]) -> str:
|
||||
"【永期对冲对照】",
|
||||
"比例",
|
||||
ph.get("ratio_label"),
|
||||
"现价",
|
||||
"入场",
|
||||
"按日开盘",
|
||||
"推点数开盘中位",
|
||||
ph.get("spot"),
|
||||
"目标",
|
||||
ph.get("target_profit_u"),
|
||||
@@ -1003,9 +1031,9 @@ def build_export_csv(payload: dict[str, Any]) -> str:
|
||||
)
|
||||
w.writerow(
|
||||
[
|
||||
"单币权利金",
|
||||
"单币权利金(开盘中位)",
|
||||
ph.get("prem_per_coin"),
|
||||
"权利金总额",
|
||||
"权利金总额(开盘中位)",
|
||||
ph.get("premium_total"),
|
||||
"期权币数",
|
||||
ph.get("opt_coins"),
|
||||
|
||||
Reference in New Issue
Block a user