踩坑复盘
止损逻辑失效
回撤止损公式中 max() 参数语义错误,导致净值未跌破初始本金时止损永不触发。#31 /
层级 回测 · 风控 严重度 高 关联 #31 / #34 · risk.py
现象
策略经历了明显回撤,回测里的回撤止损却从未触发。风控规则写了、配了、看起来在跑,实际上一次都没生效。
定位
回撤的计算式写成了:
drawdown = nav / max(nav, 1.0) - 1max(nav, 1.0) 的本意大概是想取历史峰值,结果取成了「净值与 1.0 的较大者」。只要 nav ≥ 1.0(没亏破初始本金),分母就恒等于 nav,drawdown 恒为 0——止损阈值永远够不着。
根因
回撤应当对标历史最高净值(running max),而不是初始本金。一个 max() 的语义写偏,让整条风控规则在数学上失效——而它表面上一直在「运行」,毫无破绽。
修复
改为对历史峰值计算回撤(update_drawdown 维护 running max),并补上自动化测试:构造一段必然触发止损的净值序列,断言止损确实触发。
教训:未经自动化测试验证的风控规则不具备可靠性。风控代码的特殊性在于:正常行情下不触发执行,其有效性只有在极端行情下才暴露。等到真正需要时才发现失效,损失已不可挽回。