"""出场结构的唯一来源。**只用标准库**,这是硬约束。 为什么单独一个模块、且不许引第三方库:执行器要跑在只装了 `aiohttp` 的生产机 上。这几个数原先从 `research/step43_fill_aware_budget.py` 读,那个模块顶层 `import pandas`,于是生产机为了两个 float 得装 pandas + pyarrow(实测 `assert_decomposable()` 一调就把 numpy/pandas/pyarrow 全拖进来)。 方向也要注意:**生产拥有这个契约,研究侧反过来读它。** 反过来写成生产 import 研究侧,就等于把回测的依赖树绑到实盘进程上。 ⚠️ 研究侧还散着 6 处同样的字面量(step44/47/48/49/52 与 exit_model 的默认 参数),本次没有统一。改这里的值**不会**自动改到那些脚本,对表要手工。 统一它们要重跑那批脚本确认结果不变,属于独立的一次改动。 """ from __future__ import annotations # 以 ATR 为单位的出场结构。来源:research/step43_fill_aware_budget.py 的 # 参数扫描结论(1m 主线)。含义见 live_exec.py 顶部注释 SL = 2.0 # 止损:入场价的 2 ATR SCALE_AT = 3.0 # 减半点:3 ATR 处平掉一半 RUNNER = 8.0 # 剩余半仓的目标:8 ATR RUNNER_STOP = 2.0 # 剩余半仓的止损,**不移动**,仍在入场价的 2 ATR MAXB = 48 # 超时:48 根(1m 上即 48 分钟) # 两个半仓共用同一个不动止损,这是「一次入场拆两腿」能等价于回测的前提。 # RUNNER_STOP != SL 时该等价性失效,`live_exec.assert_decomposable()` 会硬挡 DECOMPOSABLE = RUNNER_STOP == SL