BOCPD 灵敏度优化:诊断先行方案
BOCPD 灵敏度优化:诊断先行方案
版本:v1.0 | 日期:2026-03-12
适用:Hyperliquid 量化交易系统(Adaptive Bollinger Z-Score 配对策略)
关联:docs/开仓动量过滤器设计方案_v5.1.md
1. 问题定义
1.1 现象
BOCPD(Layer 0)在价格冲高回落场景中过度拦截,阻止了合理的反转开仓信号。
实际案例:PURR/USDC:USDC,5 分钟 K 线
- 价格经历一波快速上涨后已明显见顶回落
- 此时触发 short 信号(Z-Score 偏离),方向与回落一致
- Layer 0 拦截:
P(trending)=0.945 > 0.75 - 问题:趋势已经结束、价格正在回归,P(trending) 仍然很高
1.2 期望行为
| 场景 | 期望决策 | 原因 |
|---|---|---|
| 冲高回落中做空 | 放行 | 趋势已反转,均值回归假设重新成立 |
| 连续多根快速波动 + K 线极长 + 无衰减迹象 | 拦截 | 真正的极端行情,风险极高 |
核心矛盾:当前 BOCPD 只看 P(trending) 幅度,不区分「趋势进行中」vs「趋势已见顶回落」。
1.3 原 BOCPD 参数(修改前)
hazard_rate = 0.05 # 期望 run length ≈ 20 bars
drift_threshold = 0.0005 # |drift| 超过此值视为趋势
max_run = 60 # 截断窗口
bocpd_trend_thresh = 0.90 - 0.15*s = 0.75 # P(trending) 阈值(strength=0.5 时)
2. 方案探索与取舍
2.1 方案 A:反转检测逻辑(已否决)
思路:在 _check_regime 中加入 _detect_reversal() 方法,基于加权漂移均值 + 变点概率判断趋势方向是否已反转,若反转则将硬拦截降级为软拦截(交由 Layer 3 仲裁)。
实现代价:~65 行新增代码,引入 regime_is_soft 标记。
否决原因:
- 过度工程化:为解决一个阈值问题引入了复杂的反转检测子系统
- 参数增多:反转判定本身需要额外阈值(漂移方向、变点概率门限),同样缺乏经验依据
- 违背 KISS 原则:更简单的方案应该优先考虑
2.2 方案 B:参数校准(已采纳,先行调整)
思路:提高 bocpd_trend_thresh(0.75→0.92)和 drift_threshold(0.0005→0.001),使 BOCPD 只在真正极端的持续暴涨暴跌中拦截。
调参依据:
- PURR 案例 P(trending)=0.945,原阈值 0.75 明显过低,大量中等波动场景被误杀
drift_threshold从 0.0005 提高到 0.001(5min K 线 0.1%),过滤掉微弱漂移的噪声判定- 阈值提高到 0.92 后,仅真正极端行情(P(trending)>0.92)才触发拦截
风险与应对:
- 缺乏大量历史样本验证 0.92 是否为最优值 → 配合方案 C 诊断日志持续监测
- 可能放行部分本应拦截的场景 → 通过后续数据分析进一步微调
2.3 方案 C:诊断日志,数据驱动后续校准(已采纳,同步实施)
思路:增加诊断日志字段,收集真实市场环境下 BOCPD 拦截/放行事件的详细数据,为后续参数精调提供统计依据。
优势:
- 与参数调整互补:调参先解决最明显的误杀,诊断数据支撑后续精细化
- 数据驱动:避免反复盲调
- 可扩展:如诊断字段不足,随时可增加
3. 实施内容
3.1 参数调整
修改 MomentumFilter.__init__ 中两个关键参数(momentum_filter.py:561-597):
bocpd_trend_thresh(strength 联动阈值):
| 公式 | s=0 | s=0.5 | s=1 | |
|---|---|---|---|---|
| 修改前 | 0.90 - 0.15*s |
0.90 | 0.75 | 0.75 |
| 修改后 | 0.97 - 0.10*s |
0.97 | 0.92 | 0.87 |
设计意图:整体上移阈值区间,仅在 P(trending) 极高时拦截。s=1 最严格时仍保留 0.87 的较高门槛。
bocpd_drift_thresh(算法常量):
| 值 | 含义 | |
|---|---|---|
| 修改前 | 0.0005 | 5min K 线 0.05% 漂移即判定趋势 |
| 修改后 | 0.001 | 5min K 线 0.1% 漂移才判定趋势 |
设计意图:提高最小有意义漂移门槛,过滤掉正常波动产生的微弱漂移信号。
3.2 新增诊断属性
在 _BOCPD 类中添加 diagnostics 属性(momentum_filter.py:315-330):
@property
def diagnostics(self) -> tuple[float, int, float]:
"""诊断信息:(加权漂移均值, MAP run length, 变点概率 P(r=0))。"""
drift_mean = 0.0
map_r = 0
map_logp = float('-inf')
for i in range(len(self._log_probs)):
prob = math.exp(self._log_probs[i])
drift_mean += prob * self._suff[i][0]
if self._log_probs[i] > map_logp:
map_logp = self._log_probs[i]
map_r = i
cp_prob = math.exp(self._log_probs[0]) if self._log_probs else 0.0
return drift_mean, map_r, cp_prob
三个诊断字段:
| 字段 | 含义 | 校准用途 |
|---|---|---|
drift_mean |
后验加权漂移均值 | 正=上涨趋势 负=下跌趋势;反转时符号与 direction 一致则说明趋势方向已对齐 |
MAP_r |
最大后验概率对应的 run length | 小值(<5)= 新机制刚开始;大值 = 机制已持续较久 |
P(cp) |
变点概率 P(r=0) | 高值意味着刚发生机制切换,可能是反转信号 |
3.3 拦截日志增强
修改 _check_regime 方法(momentum_filter.py:899-905):
if trend_prob > self._bocpd_trend_thresh:
drift_mean, map_r, cp_prob = bocpd.diagnostics
return False, (
f"Layer0-BOCPD趋势机制: P(trending)={trend_prob:.3f}"
f">{self._bocpd_trend_thresh}"
f" | drift={drift_mean:+.6f} MAP_r={map_r} P(cp)={cp_prob:.3f}"
)
日志示例:
Layer0-BOCPD趋势机制: P(trending)=0.960>0.92 | drift=-0.002341 MAP_r=3 P(cp)=0.412
上例可解读为:虽然 P(trending) 高,但 drift 已转负(价格在跌),MAP_r=3(新机制仅 3 bars),P(cp)=0.412(刚发生变点)—— 典型的反转场景。
4. 数据收集与分析计划
4.1 收集阶段
运行系统收集至少 3-7 天的拦截日志,覆盖:
- 不同 symbol(高波动 alt 如 PURR, FARTCOIN vs 低波动 alt)
- 不同市场状态(趋势行情 vs 震荡行情)
- 不同时段(亚洲/欧洲/美洲交易时段)
4.2 分析维度
收集到足够样本后,按以下维度分析:
| 分析项 | 方法 | 目标 |
|---|---|---|
| P(trending) 分布 | 直方图 + 分位数 | 确定合理阈值区间 |
| drift 符号 vs direction 对齐率 | 交叉表 | 量化「趋势已反转」的占比 |
| MAP_r 分布 | 按拦截 vs 应放行分组对比 | 找到区分新旧机制的 run length 阈值 |
| P(cp) 与反转的相关性 | ROC 分析 | 评估变点概率作为反转信号的预测力 |
4.3 校准路径
根据数据分析结果,选择最简方案:
路径 1(最优):仅调 bocpd_trend_thresh
条件:数据显示 P(trending) 在应放行 vs 应拦截之间有清晰分界
路径 2:drift 方向感知
条件:drift 符号与 direction 对齐时,几乎都应放行
实现:drift 方向与交易方向一致时,提高阈值(等效放宽)
路径 3:P(cp) 辅助判定
条件:P(cp) 高的拦截事件中,大部分应放行
实现:P(cp) > 阈值时将硬拦截降级为软拦截
5. P1 路线评估
在诊断数据收集期间,评估了三个既有 P1 优化项:
| 项目 | 结论 | 原因 |
|---|---|---|
| 元参数降维 | 已完成 | strength 元参数已驱动 7 个关键阈值,无需额外降维 |
| OFI 微结构集成 | 暂缓 | 当前瓶颈不在微结构层面,且 OFI 数据获取需额外基础设施 |
| BOCPD 自适应参数 | 等数据 | 需先有诊断数据才能判断自适应的方向和范围 |
6. 改动文件清单
| 文件 | 改动 | 行号 |
|---|---|---|
src/trading/momentum_filter.py |
bocpd_trend_thresh 公式:0.90-0.15*s → 0.97-0.10*s |
564-565 |
src/trading/momentum_filter.py |
bocpd_drift_thresh:0.0005 → 0.001 |
597 |
src/trading/momentum_filter.py |
新增 _BOCPD.diagnostics 属性 |
315-330 |
src/trading/momentum_filter.py |
_check_regime 拦截日志增加诊断字段 |
899-905 |
影响范围:
- 参数调整:BOCPD 拦截阈值提高,减少中等波动场景的误杀
- 诊断日志:不影响过滤逻辑,仅增加拦截时的日志输出
7. 后续步骤
- 提交当前改动(参数调整 + 诊断日志,已完成)
- 运行 3-7 天,观察新阈值下的拦截/放行表现,同时收集诊断数据
- 导出并分析拦截日志中的
P(trending) / drift / MAP_r / P(cp)分布 - 根据数据选择校准路径(见 §4.3)
- 实施并验证校准方案,输出 v5.2 设计文档