Gate opens when ATM-spot offset exceeds configurable max (default 3).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-25 12:32:36 +08:00
parent a4bcc3ab0d
commit ee0ec57f89
12 changed files with 93 additions and 13 deletions
+25 -6
View File
@@ -12,6 +12,8 @@ from ..exchange import get_exchange, set_exchange, build_exchange
from ..exchange.protocol import ExchangeMarket
from ..exchange.types import MarketSnapshot, OptionPair
from .selection import (
atm_allows_open,
atm_open_offset,
hours_until_expiry,
list_eligible_expiry_ymds,
option_leverage,
@@ -34,7 +36,8 @@ def _has_open_position() -> bool:
return False
def _strategy_floats() -> tuple[float, float]:
def _strategy_floats() -> tuple[float, float, float]:
"""min_hours, min_leverage, max_atm_open_offset"""
s = get_settings()
try:
from ..models.db import get_db
@@ -48,9 +51,13 @@ def _strategy_floats() -> tuple[float, float]:
db.get_setting("min_option_leverage", str(s.min_option_leverage))
or s.min_option_leverage
)
return hours, lev
atm_off = float(
db.get_setting("max_atm_open_offset", str(s.max_atm_open_offset))
or s.max_atm_open_offset
)
return hours, lev, atm_off
except Exception:
return s.min_option_hours, s.min_option_leverage
return s.min_option_hours, s.min_option_leverage, s.max_atm_open_offset
@dataclass(slots=True)
@@ -135,7 +142,7 @@ class StrategySession:
mark = self.ex.fetch_mark(s.perp_inst_id) or idx
if mark is None or mark <= 0:
raise RuntimeError("无法获取标的标记/指数价格,无法选 ATM")
min_hours, _ = _strategy_floats()
min_hours, _, _ = _strategy_floats()
contracts = self.ex.list_option_contracts(s.option_inst_family)
pair = select_option_pair(contracts, mark_px=float(mark), min_hours=min_hours)
if pair is None:
@@ -148,7 +155,7 @@ class StrategySession:
from .signal import decide
s = self.settings
min_hours, min_lev = _strategy_floats()
min_hours, min_lev, max_atm_off = _strategy_floats()
idx = self.ex.fetch_index(s.index_inst_id)
mark = self.ex.fetch_mark(s.perp_inst_id) or idx
if mark is None or mark <= 0:
@@ -164,6 +171,18 @@ class StrategySession:
pair = select_option_pair(contracts, mark_px=underlying, expiry_ymd=ymd)
if pair is None:
continue
offset = atm_open_offset(pair.strike, underlying)
if not atm_allows_open(
pair.strike, underlying, max_offset=max_atm_off
):
logger.info(
"skip expiry=%s strike=%.0f atm_offset=%.1f > max=%.1f",
ymd,
pair.strike,
offset,
max_atm_off,
)
continue
call_bids, call_asks, _ = self.ex.fetch_book(pair.call_inst_id, depth=5)
put_bids, put_asks, _ = self.ex.fetch_book(pair.put_inst_id, depth=5)
call_ask = call_asks[0].px if call_asks else None
@@ -257,7 +276,7 @@ class StrategySession:
def atm_needs_realign(self, mark_px: float | None = None) -> bool:
if self._pair is None:
return True
min_hours, _ = _strategy_floats()
min_hours, _, _ = _strategy_floats()
if (
hours_until_expiry(self._pair.expiry_ymd, expiry_ms=self._pair.expiry_ms)
+ 1e-9