行为
CR-013 下行波动率与Sortino分母公式修正为严格半方差¶
| 字段 | 内容 |
|---|---|
| CR ID | CR-013 |
| 标题 | 下行波动率与Sortino分母计算由“截断序列标准差”修正为“严格半方差开方” |
| 发起人 | 架构顾问 (数学公式严密性审查) |
| 日期 | 2026-04-17 |
| 状态 | ✅ Approved |
| 影响范围 |
0001-特征字典基线文档.txt B/E类公式定义、feature_engineering.py 底层算子实现、test_feature_engineering.py 期望值断言 |
1. 变更描述¶
原基线公式约束:
-
downside_vol_26w:rolling_std(min(weekly_return, 0), 26) -
rolling_sortino_26w分母:rolling_std(min(weekly_ret, 0), 26)
变更为:
-
downside_vol_26w: $\sqrt{Mean(\min(weekly_return, 0)^2)}$ (即负收益平方的均方根 RMS) -
rolling_sortino_26w分母: $\sqrt{Mean(\min(weekly_ret - rf, 0)^2)}$ (即超额收益为负部分的半方差开方,目标收益率切换为无风险利率)
2. 变更原因(根因追溯)¶
在代码实施前的数学推演审查中发现,原基线公式存在严重的数学定义谬误:
-
零值污染导致方差缩水:原公式
rolling_std(min(ret, 0))实际计算的是“包含大量人为零值的截断序列的标准差”。将正收益强行置为 0 后,这些 0 会拉低序列均值 $\bar{X}$,导致原本真正的负收益偏离度 $(X - \bar{X})^2$ 被严重缩小,算出的值远小于真实下行风险。 - 违背“半方差”本意:业界标准的下行波动率(半方差开方)衡量的是“低于目标收益率部分的偏离度的平方根”,数学上是直接对偏离值求平方平均再开方(不减去均值,因为目标就是 0)。原公式错用了一般标准差的计算逻辑。
- 破坏树模型分裂点:对于 LightGBM,原公式会在原本没有 0 值的连续负收益分布中,强行注入大量绝对 0 值,制造出虚假的“数据密集区”,直接干扰决策树寻找最优信息增益分裂点。
3. 影响分析¶
| 受影响模块 | 影响说明 | 应对措施 |
|---|---|---|
0001-特征字典基线文档.txt |
B类与E类的公式描述必须重写,彻底消除 rolling_std(min(...)) 字眼 |
发起基线文档修订,锁定严格半方差公式 |
feature_engineering.py |
底层算子无法直接复用 Polars 的 .rolling_std(),需改为 (pl.col("down_ret")**2).rolling(N).mean().sqrt()
|
重构波动矩阵计算逻辑,确保向量化且无零值污染 |
test_feature_engineering.py |
针对 downside_vol 和 sortino 的手工计算期望值需按新公式重新推导 |
更新单测中的 pytest.approx 期望值 |
由 Huarui Lin 更新于 6 个月 之前 · 1 修订