Reject OO strikes more than 1% from amplitude high/low.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -192,8 +192,8 @@ def _hedge_mode() -> str:
|
||||
return "perp_option"
|
||||
|
||||
|
||||
def _oo_settings() -> tuple[float, float, float, float]:
|
||||
"""amplitude_pct, amplitude_hours, min_option_hours, min_leverage"""
|
||||
def _oo_settings() -> tuple[float, float, float, float, float]:
|
||||
"""amplitude_pct, amplitude_hours, min_option_hours, min_leverage, strike_max_dev_pct"""
|
||||
s = get_settings()
|
||||
try:
|
||||
from ..models.db import get_db
|
||||
@@ -210,6 +210,12 @@ def _oo_settings() -> tuple[float, float, float, float]:
|
||||
or s.oo_min_option_hours
|
||||
),
|
||||
float(db.get_setting("oo_min_leverage", str(s.oo_min_leverage)) or s.oo_min_leverage),
|
||||
float(
|
||||
db.get_setting(
|
||||
"oo_strike_max_dev_pct", str(s.oo_strike_max_dev_pct)
|
||||
)
|
||||
or s.oo_strike_max_dev_pct
|
||||
),
|
||||
)
|
||||
except Exception:
|
||||
return (
|
||||
@@ -217,6 +223,7 @@ def _oo_settings() -> tuple[float, float, float, float]:
|
||||
s.oo_amplitude_hours,
|
||||
s.oo_min_option_hours,
|
||||
s.oo_min_leverage,
|
||||
s.oo_strike_max_dev_pct,
|
||||
)
|
||||
|
||||
|
||||
@@ -450,7 +457,7 @@ class StrategySession:
|
||||
try:
|
||||
from ..exchange.candles import fetch_amplitude_hl_for_runtime
|
||||
|
||||
amp_pct, amp_hours, _, _ = _oo_settings()
|
||||
amp_pct, amp_hours, _, _, _ = _oo_settings()
|
||||
amp = fetch_amplitude_hl_for_runtime(amp_hours)
|
||||
if amp is None:
|
||||
return self._oo_amp
|
||||
@@ -477,7 +484,7 @@ class StrategySession:
|
||||
if _has_open_position():
|
||||
return self.align_to_held_position()
|
||||
s = self.settings
|
||||
amp_pct, amp_hours, min_hours, _min_lev = _oo_settings()
|
||||
amp_pct, amp_hours, min_hours, _min_lev, max_dev = _oo_settings()
|
||||
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:
|
||||
@@ -496,10 +503,11 @@ class StrategySession:
|
||||
low=amp_low,
|
||||
min_hours=float(min_hours),
|
||||
skip_expiry_ymds=skip,
|
||||
max_dev_pct=float(max_dev),
|
||||
)
|
||||
if picked is None:
|
||||
raise RuntimeError(
|
||||
f"未找到剩余≥{min_hours}h 的虚值 Call@高/Put@低"
|
||||
f"未找到剩余≥{min_hours}h 且贴高低≤{max_dev:g}% 的虚值 Call/Put"
|
||||
)
|
||||
ymd, ems, ck, pk, call_inst, put_inst = picked
|
||||
pair = OptionPair(
|
||||
@@ -527,7 +535,7 @@ class StrategySession:
|
||||
from .selection import _complete_by_expiry, option_leverage
|
||||
|
||||
s = self.settings
|
||||
amp_pct, amp_hours, min_hours, min_lev = _oo_settings()
|
||||
amp_pct, amp_hours, min_hours, min_lev, max_dev = _oo_settings()
|
||||
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:
|
||||
@@ -565,9 +573,13 @@ class StrategySession:
|
||||
low=float(amp.low),
|
||||
min_hours=float(min_hours),
|
||||
skip_expiry_ymds=skip,
|
||||
max_dev_pct=float(max_dev),
|
||||
)
|
||||
if picked is None:
|
||||
logger.info("oo: no OTM call/put pair for amplitude HL")
|
||||
logger.info(
|
||||
"oo: no OTM call/put within %.2f%% of amplitude HL",
|
||||
max_dev,
|
||||
)
|
||||
return None
|
||||
ymd, ems, ck, pk, call_inst, put_inst = picked
|
||||
call_bids, call_asks, _ = self.ex.fetch_book(call_inst, depth=5)
|
||||
@@ -840,7 +852,7 @@ class StrategySession:
|
||||
def oo_needs_realign(self) -> bool:
|
||||
if self._pair is None:
|
||||
return True
|
||||
_amp_pct, amp_hours, min_hours, _ = _oo_settings()
|
||||
_amp_pct, amp_hours, min_hours, _, max_dev = _oo_settings()
|
||||
if (
|
||||
hours_until_expiry(self._pair.expiry_ymd, expiry_ms=self._pair.expiry_ms)
|
||||
+ 1e-9
|
||||
@@ -877,6 +889,7 @@ class StrategySession:
|
||||
low=float(amp.low),
|
||||
min_hours=float(min_hours),
|
||||
skip_expiry_ymds=skip,
|
||||
max_dev_pct=float(max_dev),
|
||||
)
|
||||
if picked is None:
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user