永期改为市价选约:左同期权人工选,右去掉选约条件.

左侧到期/CallPut/全部实虚值/展开全部;右侧仅资金杠杆与出场;下单走已选合约立即开仓而非条件盯盘.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-14 15:19:17 +08:00
parent 73a1d5f709
commit c9e69ce8ef
4 changed files with 257 additions and 144 deletions
@@ -266,7 +266,10 @@ def validate_option_primary_moneyness(
return "行权价或指数无效"
m_want = (moneyness or "atm").strip().lower()
m_got = classify_moneyness(opt_type=o, strike=k, index_px=s)
if m_want == "itm":
if m_want in ("all", "any", ""):
# 市价人工选约:不限制虚实值
pass
elif m_want == "itm":
if not is_itm_or_atm(opt_type=o, strike=k, index_px=s):
return "所选须为实值或平值"
elif m_want == "atm":
@@ -280,17 +283,27 @@ def validate_option_primary_moneyness(
else:
return "期权类型(实/平/虚)无效"
interval = float(_sf(strike_interval) or DEFAULT_STRIKE_INTERVAL)
# 间隔/最短到期/杠杆门槛:仅条件单使用;传 0 表示市价下单跳过
interval_raw = _sf(strike_interval)
if interval_raw is None:
interval_raw = DEFAULT_STRIKE_INTERVAL
interval = float(interval_raw)
if interval > 0 and abs(k - s) > interval + 1e-9:
return f"行权价偏离指数 {abs(k - s):.1f} > 间隔 {interval:.0f}"
min_h = float(_sf(min_hours) or DEFAULT_MIN_HOURS)
min_h_raw = _sf(min_hours)
if min_h_raw is None:
min_h_raw = DEFAULT_MIN_HOURS
min_h = float(min_h_raw)
h = _sf(hours_to_expiry)
if min_h > 0 and h is not None and h < min_h:
return f"剩余到期约 {h:.1f}h,低于最短 {min_h:.0f}h"
a = _sf(ask)
min_lev = effective_min_opt_leverage(m_want if m_want != "atm" else m_got or "atm", min_opt_leverage)
lev_cfg = _sf(min_opt_leverage)
if lev_cfg is not None and lev_cfg <= 0:
return None
min_lev = effective_min_opt_leverage(m_want if m_want not in ("atm", "all", "any", "") else (m_got or "atm"), min_opt_leverage)
if min_lev > 0 and a is not None and a > 0:
lev = s / a
if lev < min_lev:
@@ -336,24 +349,27 @@ def validate_option_primary_watch(body: dict[str, Any]) -> Optional[str]:
def validate_option_primary_start(body: dict[str, Any]) -> Optional[str]:
market = body.get("market_order") in (True, 1, "1", "true", "yes", "on")
need = (
"direction",
"contracts",
"opt_inst_id",
"sheets",
"exchange_symbol",
"premium_budget",
"option_target_points",
"perp_target_points",
"option_perp_ratio",
)
if not market:
need = need + ("premium_budget",)
for k in need:
if body.get(k) in (None, ""):
return f"缺少字段: {k}"
try:
if float(body["contracts"]) <= 0 or float(body["sheets"]) <= 0:
return "张数必须大于 0"
if float(body["premium_budget"]) <= 0:
prem = _sf(body.get("premium_budget"))
if not market and (prem is None or prem <= 0):
return "权利金须大于 0"
if float(body["option_target_points"]) <= 0 or float(body["perp_target_points"]) <= 0:
return "目标位点数须大于 0"
@@ -374,6 +390,9 @@ def validate_option_primary_start(body: dict[str, Any]) -> Optional[str]:
want = opt_type_for_view(direction)
if opt_type != want:
return f"以期权为主时做{'多' if direction == 'long' else '空'}须用 {'Call' if want == 'C' else 'Put'}"
# 市价下单:左侧人工选约,跳过条件单(间隔/最短到期/杠杆门槛)
if market:
return None
moneyness = str(body.get("moneyness") or body.get("option_moneyness") or "otm").strip().lower()
from lib.hedge_plan.hedge_plan_moneyness_lib import parse_strike_from_inst