Add mutual-exclusion gate between hedge plans and standalone options.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
"""对冲计划与单独期权开仓互斥门控.
|
||||
|
||||
默认开启:有进行中对冲计划时禁止单独开期权;有纯期权持仓时禁止启动对冲计划.
|
||||
关闭 HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE 后两边可同时开.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
|
||||
def _env_bool(key: str, default: bool = False) -> bool:
|
||||
v = (os.getenv(key) or "").strip().lower()
|
||||
if not v:
|
||||
return default
|
||||
return v in ("1", "true", "yes", "on")
|
||||
|
||||
|
||||
def mutual_exclusive_enabled() -> bool:
|
||||
return _env_bool("HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE", True)
|
||||
|
||||
|
||||
def block_standalone_option_open_msg(conn: Any) -> Optional[str]:
|
||||
"""若应拦截单独开期权,返回中文原因;否则 None."""
|
||||
if not mutual_exclusive_enabled():
|
||||
return None
|
||||
try:
|
||||
from lib.hedge_plan.hedge_plan_db import count_active_plans, init_hedge_plan_tables
|
||||
|
||||
init_hedge_plan_tables(conn)
|
||||
if count_active_plans(conn) > 0:
|
||||
return "存在进行中对冲计划,禁止单独开期权(可在 env「对冲与期权互斥门控」关闭)"
|
||||
except Exception:
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
def _pos_nonzero(raw: dict[str, Any]) -> bool:
|
||||
try:
|
||||
return abs(float(raw.get("pos") or 0)) > 1e-12
|
||||
except (TypeError, ValueError):
|
||||
return False
|
||||
|
||||
|
||||
def has_standalone_option_position(conn: Any, raw_positions: list[dict[str, Any]] | None) -> bool:
|
||||
"""交易所期权持仓中,是否存在未挂在进行中对冲计划腿上的仓位."""
|
||||
if not raw_positions:
|
||||
return False
|
||||
from lib.instance.instance_dashboard_lib import _resolve_options_source
|
||||
|
||||
for p in raw_positions:
|
||||
if not isinstance(p, dict) or not _pos_nonzero(p):
|
||||
continue
|
||||
inst = str(p.get("instId") or p.get("inst_id") or "").strip()
|
||||
if not inst:
|
||||
continue
|
||||
source, _, _ = _resolve_options_source(conn, inst)
|
||||
if source == "option":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def block_hedge_plan_start_msg(
|
||||
conn: Any,
|
||||
*,
|
||||
fetch_positions: Optional[Callable[[Any], Any]] = None,
|
||||
exchange: Any = None,
|
||||
raw_positions: list[dict[str, Any]] | None = None,
|
||||
) -> Optional[str]:
|
||||
"""若应拦截启动对冲计划,返回中文原因;否则 None."""
|
||||
if not mutual_exclusive_enabled():
|
||||
return None
|
||||
rows = raw_positions
|
||||
if rows is None:
|
||||
if fetch_positions is None or exchange is None:
|
||||
return None
|
||||
try:
|
||||
rows = fetch_positions(exchange) or []
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
if has_standalone_option_position(conn, rows):
|
||||
return "存在单独期权持仓,禁止启动对冲计划(可在 env「对冲与期权互斥门控」关闭)"
|
||||
except Exception:
|
||||
return None
|
||||
return None
|
||||
Reference in New Issue
Block a user