← 文档库
📄 文档learn/截面选基-理解手册/09-市场状态平滑过渡:因子权重连续化与标签滞后.md
🌱 创建于2026-08-13 23:28
✏️ 修改于2026-08-13 23:28
👁️ 浏览量—
🔗 短链接/~learn/s/c7274c9f
🔐 可见性

09 - 市场状态平滑过渡:因子权重连续化与标签滞后

> 复盘日期:2026-08-13 > 触发:本周"新进 Top10 原因解释"里,香港证券等 ETF 的「稳定性」因子分数单周 +36pp,持仓 Top10 一组变一组,观感异常。 > 结论:不是数据 bug,是市场状态(regime)离散硬切换 → 因子权重/仓位/大类偏好阶跃导致的系统性"过渡太直接"问题。

---

1. 问题现象

截面选基页(ETF 策略持仓)「新进 Top10」子表里,某只 ETF 的解释出现:

📌 主要变化:稳定性走强
🟢 📊稳定性↑+36pp

用户直觉是"稳定性评分怎么瞬间加 36 个百分点,是不是市场风格切换 / bug"。

2. 归因(分两层,别混在一起)

2.1 表层:稳定性分数 +36pp 是「因子分数」,不是「权重」

+36pp 里的 稳定性 对应 DB 字段 factor_vol_stability,它存的是经过 rank 百分位归一化的稳定性因子分数(Factor.normalize(series, method='rank')),与 regime 权重无关。

> 注意:rank 百分位会放大"截面密集区"的小变化。这是稳定性因子分数单周跳几十 pp 的放大器,但本身不是错误。

2.2 深层(真正要修的):离散 regime 硬切换导致权重阶跃

RegimeDetector.detect() 用硬阈值把市场切成 6 个离散状态(BULL/MILD_BULL/RANGING/HIGH_VOL/BEAR/SEVERE_BEAR),AdaptiveWeightEngine / get_exposure_cap / 大类偏好都按离散状态查表:

状态 momentum overbought_avoid vol_stability
-------------------------------------------------
MILD_BULL 0.30 0.20 0.22
RANGING 0.20 0.27 0.25
HIGH_VOL 0.10 0.33 0.30

只要 price_vs_ma_200 或 vol_ratio 在阈值附近轻轻一穿,标签一翻,5 个因子权重整体跳变,综合评分重排 → Top10 换一组。这就是用户说的"今天温和牛、明天震荡,持仓直接换一批"。

3. 前沿研究依据(为何这样修)

4. 修复方案(v2 平滑过渡)

核心思路:权重、仓位、大类偏好全部连续化,离散标签仅作展示语义并加滞后。

4.1 新增连续 regime_score ∈ [0,1](factor/regime.py)

由三个特征连续映射:

trend = clip(price_vs_ma / 0.05, -1, 1) * 0.5      # 趋势轴
vol_penalty = max(0, vol_ratio - 1.0) * 0.5         # 波动惩罚
trend_bonus = clip(trend_strength, 0, 1) * 0.10     # 趋势强度微调
score = clip(0.5 + trend - vol_penalty + trend_bonus, 0, 1)

score 越高越进攻,越低越防守,无阈值跳变。

4.2 因子权重连续插值(factor/weight_engine.py)

AdaptiveWeightEngine._continuous_base(score) 用 np.interp 在 5 个锚点(0=SEVERE_BEAR, 0.2=BEAR, 0.5=RANGING, 0.8=MILD_BULL, 1.0=BULL)之间对 5 因子权重线性插值,锚点数值与原离散表完全一致。

校准后权重随 score 平滑过渡:

score momentum overbought_avoid vol_stability
--------------------------------------------------
0.00 (SEVERE_BEAR) 0.080 0.350 0.320
0.22 (HIGH_VOL) 0.107 0.326 0.315
0.52 (RANGING) 0.207 0.265 0.248
0.72 (MILD_BULL) 0.273 0.219 0.228
0.97 (BULL) 0.343 0.158 0.203

4.3 仓位上限连续化(RegimeDetector.get_exposure_cap)

exposure_cap 不再按离散标签查表,改用 np.interp(score, [0,0.2,0.5,0.8,1], [0.15,0.35,0.6,0.9,1.0]),再叠加原有 vol 惩罚。

4.4 大类资产偏好连续化(selector/multi_factor_selector.py)

债券 / 贵金属 / REITs 的防御加成原来按 is_defensive_regime / is_bull_regime 二值切换(如债券 1.10 ↔ 0.95),现按 regime_score 做 np.interp 平滑过渡(中性=1.0)。

4.5 离散标签滞后(RegimeDetector._apply_hysteresis)

标签切换需 score 越过「当前状态锚点 ↔ 目标状态锚点」的中点 + 0.06 缓冲带,避免边界抖动。标签只用于展示,不再影响权重/仓位。

> 回测前会 reset_hysteresis()(engine._compute_weekly_backtest_drawdown 入口),避免复用实盘状态污染历史回测。

5. 关键改动文件

文件 改动
------------
adata/aohan/quant/selection/factor/regime.py 新增 regime_score、_risk_score、_apply_hysteresis、连续 exposure_cap
adata/aohan/quant/selection/factor/weight_engine.py 新增 _continuous_base(score),compute() 优先用连续插值
adata/aohan/quant/selection/selector/multi_factor_selector.py 债券/贵金属/REITs 大类偏好连续化
adata/aohan/quant/selection/engine.py 回测入口 reset_hysteresis()
unified_server.py 修复市场状态 hint 点击外部不隐藏的 UI 问题

6. UI 顺手修复

市场状态标识(.regime-badge)的 hint 弹窗:点击标识能开,但点击其他区域不关闭。修复为全局 document.addEventListener('click'),点击 .regime-badge 之外时移除所有 tip-open。

7. 验证结果

8. 后续可优化方向(暂未做,记录备查)

▶ 📜 变更历史(1 次提交)

828431a2026-08-13 23:28feat: 市场状态平滑过渡 - 因子权重连续化+标签滞后,避免状态切换致持仓剧烈重排
🍃quant 知识库
by 伊甸园和枫

🔊 播放设置

勾选音源后调节配比,总和自动归一化
已选 0 个 · 合计:0%
合成中...
00:00/00:00
1.0x

分享图片

生成中...