feat(hedge): replace OO breakout targets with premium profit RR

期期改用盈亏比×权利金止盈(默认2);不达标持有至到期。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-11 10:21:47 +08:00
parent 860ebef4a7
commit 3b56e15fb1
12 changed files with 433 additions and 133 deletions
+58 -31
View File
@@ -537,27 +537,25 @@ def _persist_oo(cfg: dict[str, Any], result: dict[str, Any], body: dict[str, Any
premium = (float(a.get("premium") or 0) if a_ok else 0.0) + (
float(b.get("premium") or 0) if b_ok else 0.0
)
rr_raw = body.get("oo_profit_rr")
if rr_raw in (None, ""):
rr_raw = body.get("profit_rr")
try:
oo_rr = float(rr_raw) if rr_raw not in (None, "") else 2.0
except (TypeError, ValueError):
oo_rr = 2.0
if oo_rr <= 0:
oo_rr = 2.0
plan_id = insert_plan(
conn,
{
"plan_type": "options_options",
"status": "partial" if is_partial else "active",
"underlying": str(body.get("underlying") or "ETH").upper(),
"target_price": float(
body.get("target_price_up")
or body.get("target_price")
or 0
),
"target_price_up": float(
body.get("target_price_up")
or body.get("target_price")
or 0
),
"target_price_down": float(
body.get("target_price_down")
or body.get("target_price")
or 0
),
"target_price": None,
"target_price_up": None,
"target_price_down": None,
"oo_profit_rr": oo_rr,
"sizing_mode_at_open": load_position_sizing_mode(),
"premium_total": premium,
"oo_close_mode": _normalize_oo_close_mode(body.get("oo_close_mode")),
@@ -1238,20 +1236,24 @@ def _preview_po(body: dict[str, Any]) -> dict[str, Any]:
def _preview_oo(body: dict[str, Any]) -> dict[str, Any]:
from lib.hedge_plan.hedge_plan_moneyness_lib import validate_oo_legs_moneyness
up = body.get("target_price_up")
down = body.get("target_price_down")
legacy = body.get("target_price")
if up in (None, "") and legacy not in (None, ""):
up = legacy
if down in (None, "") and legacy not in (None, ""):
down = legacy
if up in (None, "") or down in (None, ""):
raise ValueError("请填写上破与下破目标价")
up_f = float(up)
down_f = float(down)
if up_f <= down_f:
raise ValueError("上破目标价必须大于下破目标价")
index_px = float(body.get("index_px") or ((up_f + down_f) / 2))
rr_raw = body.get("oo_profit_rr")
if rr_raw in (None, ""):
rr_raw = body.get("profit_rr")
rr = None
if rr_raw not in (None, ""):
try:
rr = float(rr_raw)
except (TypeError, ValueError) as e:
raise ValueError("盈亏比无效") from e
if rr <= 0:
raise ValueError("盈亏比须大于 0")
index_px = body.get("index_px")
try:
index_px_f = float(index_px) if index_px not in (None, "") else 0.0
except (TypeError, ValueError):
index_px_f = 0.0
leg_a = body.get("leg_a") or {}
leg_b = body.get("leg_b") or {}
for name, leg in (("leg_a", leg_a), ("leg_b", leg_b)):
@@ -1265,13 +1267,38 @@ def _preview_oo(body: dict[str, Any]) -> dict[str, Any]:
)
if leg.get("premium_paid") is None:
raise ValueError(f"缺少 {name} 权利金")
money_err = validate_oo_legs_moneyness(leg_a, leg_b, index_px=index_px)
money_err = validate_oo_legs_moneyness(leg_a, leg_b, index_px=index_px_f or None)
if money_err:
raise ValueError(money_err)
if rr is not None:
return build_options_options_preview(
profit_rr=rr,
index_px=index_px_f,
leg_a=leg_a,
leg_b=leg_b,
)
# 兼容旧上破/下破
up = body.get("target_price_up")
down = body.get("target_price_down")
legacy = body.get("target_price")
if up in (None, "") and legacy not in (None, ""):
up = legacy
if down in (None, "") and legacy not in (None, ""):
down = legacy
if up in (None, "") or down in (None, ""):
raise ValueError("请填写盈亏比(相对权利金,默认2)")
up_f = float(up)
down_f = float(down)
if up_f <= down_f:
raise ValueError("上破目标价必须大于下破目标价")
if index_px_f <= 0:
index_px_f = (up_f + down_f) / 2
return build_options_options_preview(
target_price_up=up_f,
target_price_down=down_f,
index_px=index_px,
index_px=index_px_f,
leg_a=leg_a,
leg_b=leg_b,
)