Files
eth_hedge_sim/backend/app/strategy/amplitude_gate.py
T
dekun a88d708ea3 Add amplitude filter as first open gate for 永期 hedge.
Reuse OO amplitude settings (default off); Plan shows index/HL when filtering.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 21:41:51 +08:00

70 lines
2.0 KiB
Python

"""振幅过滤门:回看窗内 range% 须 ≤ 上限(可关)。永期开仓第一关 / 期期共用。"""
from __future__ import annotations
from typing import Any
from ..exchange.candles import AmplitudeHL
def evaluate_amplitude_gate(
*,
filter_enabled: bool,
amp: AmplitudeHL | None,
max_pct: float,
hours: float,
) -> dict[str, Any]:
"""
返回:
blocked: 过滤开启且未过关(无K线或超限)
ok: 展示用是否过关(过滤关视为 True)
reason: 拒开文案(未拒则为 None)
snapshot: 写入 session._oo_amp 的字典(amp 为 None 时仅含元数据)
"""
max_p = float(max_pct)
hrs = float(hours)
filt = bool(filter_enabled)
if amp is None:
snap = {
"high": None,
"low": None,
"mid": None,
"range_pct": None,
"hours": hrs,
"max_pct": max_p,
"filter_enabled": filt,
"ok": False if filt else True,
}
if filt:
return {
"blocked": True,
"ok": False,
"reason": f"振幅未过关:无法获取近 {hrs:g}h K 线高低",
"snapshot": snap,
}
return {"blocked": False, "ok": True, "reason": None, "snapshot": snap}
range_pct = float(amp.range_pct)
over = range_pct > max_p + 1e-12
ok = (not filt) or (not over)
snap = {
"high": float(amp.high),
"low": float(amp.low),
"mid": float(amp.mid),
"range_pct": range_pct,
"hours": hrs,
"max_pct": max_p,
"filter_enabled": filt,
"ok": ok,
}
if filt and over:
return {
"blocked": True,
"ok": False,
"reason": (
f"振幅未过关:{hrs:g}h 内 {range_pct:.2f}% > {max_p:g}%"
),
"snapshot": snap,
}
return {"blocked": False, "ok": ok, "reason": None, "snapshot": snap}