# ETF 量化轮动策略 V2 · 完整规则
> 部署日期: 2026-05-14
> 实盘版本: B 策略 + 5 相位 Ensemble + Filter B + DD-6.5% + PV-7.5%/5d

## 资产宇宙 (3 个 ETF)

| 代码 | 名称 | 用途 |
|---|---|---|
| 513300.SH | 华夏纳指 100 ETF | 海外科技敞口 |
| 159985.SZ | 华夏豆粕 ETF | 商品 / 低相关分散 |
| 159915.SZ | 易方达创业板 ETF | A 股成长 |

辅助信号:
- **000001.SH 上证综指**: 仅用于 Filter B (假牛检测), 不参与持仓

## 核心参数

```
lookback = 20        # 信号回看窗 (交易日)
rebalance = 5        # 调仓周期 (交易日)
PHASES = 5           # 5 相位 Ensemble
fee = 0.005%         # 单边手续费 (万 0.5)
slippage = 0.05%     # 单边滑点 (5bp)
cash_rate = 2.0%/年  # 现金收益率
DD_threshold = -6.5%   # 倒 V 防御阈值
PV_du_threshold = +7.5% # 正 V 反弹阈值
PV_min_days = 5         # 正 V 反弹持续最少天数
annual_days = 252
vol_floor = 1e-12
```

## 信号计算流程 (每个交易日 14:50 执行 1 个相位)

对每个资产 s ∈ {纳指, 豆粕, 创业板}, 用最近 lookback+1 个交易日的收盘价:

### Step 1 - 基础动量与波动率
```
R = close[t] / close[t-lookback] - 1       # 20 日总收益
daily_returns = close.pct_change().iloc[1:]
σ_annual = std(daily_returns, ddof=0) × sqrt(252)
score = R / σ_annual                       # 风险调整动量
```

### Step 2 - Filter B 假牛防御 (上证综指 vs 创业板)
```
shang_R = shang_close[t] / shang_close[t-20] - 1
cyb_R = R[创业板]
if shang_R >= cyb_R:
    score[创业板] = 0   # 屏蔽创业板
```

### Step 3 - DD-6.5% 倒 V 防御
```
if score[s] > 0:
    peak = running_max(close[t-20:t+1])
    drawdown = min(close / peak - 1)         # 20日内 peak-to-trough 最大回撤
    if drawdown <= -0.065:
        score[s] = 0   # 已经在跌, 不接刀
```

### Step 4 - PV-7.5%/5d 正 V 进攻
```
if score[s] <= 0 AND σ_annual > vol_floor:
    trough_idx = argmin(close[t-20:t+1])
    drawup = close[t] / close[trough_idx] - 1
    days_since_trough = t - trough_idx
    if drawup >= 0.075 AND days_since_trough >= 5:
        score[s] = drawup / σ_annual   # 注入反弹 score
```

### Step 5 - 反波动率加权
```
positives = {s : score[s] > 0 AND σ[s] > vol_floor}
if positives 非空:
    inv_vol = {s: 1/σ[s] for s in positives}
    weight[s] = inv_vol[s] / sum(inv_vol) × 100   # 整数百分比
```

### Step 6 - 5 相位 Ensemble
```
5 个虚拟子账户, 每个 1/5 总资金
相位 p ∈ {0,1,2,3,4} 在 pos mod 5 == p 的交易日按 Step 1-5 重新调仓
其他相位维持上次调仓权重不变
总目标权重 = 5 个子账户权重的等权平均
```

## 调仓执行

- 每个交易日 14:50 BJT 执行 (5 相位中的 1 个)
- 实际操作: 计算总目标股数 vs 当前持仓, 差额 ≥ 100 股则下单
- 股数向下取整到整百
- 不下单当日 < 100 股的微调 (避免高频)

## 关键回测数据 (2014-01 ~ 2026-05, 用 Codex 合成豆粕扩展至 2014)

| 指标 | V0 基线 (无 DD/PV) | V2 (DD+PV) | 改善 |
|---|---|---|---|
| Full Sharpe | 1.503 | 1.584 | +0.08 |
| OOS Sharpe (2023-2026) | 1.590 | **1.860** | +0.27 |
| OOS 95% Bootstrap CI | — | **[+0.055, +0.525]** | 唯一显著候选 |
| Full MaxDD | -19.1% | -18.2% | +0.9pp |
| OOS MaxDD | -16.4% | **-13.1%** | +3.3pp |
| 2026 YTD 累计 | +18.99% | **+22.42%** | +3.43pp |
| 2026 YTD MaxDD | -10.84% | **-7.50%** | +3.34pp |
| 平均换手率 | 0.100 | 0.098 | 持平 |

PBO (DD-only 子集): 0.109 (低过拟合区)
PBO (DD+PV 组合): 0.598 (警示但 Spearman=0)
PV 触发后 20d 命中率: 67.6% (n=34, OOS 2023-2026)

## 验证规模

- 总候选评估: ~200 (Batch 1-5 + 用户提案 V1/V2 + 综合 Bootstrap)
- 文献参考: 17 篇 (Daniel-Moskowitz 2016 momentum crash, Barroso-Santa-Clara 2015, Da-Gurun-Warachka 2014 FIP, Hurst-Ooi-Pedersen 2017 等)
- 回测数据: 2949 交易日 × 5 相位 × 3 资产
- Bootstrap: 1000 次块 bootstrap × 多组比较
- Walk-forward OOS: 4 个独立时间窗 (3/4 胜出)

## 已被数据否决的方案 (不要再推)

- ❌ A1 加速度切半 (前/后半段 sign 对比) - 实证不触发
- ❌ A3 OLS 斜率 - PBO 0.528 严重过拟合
- ❌ M1 Frog-in-the-Pan ID (Da-Gurun-Warachka) - PBO 0.448 + Spearman -0.45
- ❌ M5 正天比率 (Grinblatt-Moskowitz) - hard cut OOS 暴跌
- ❌ M8 52w 高点接近度 (George-Hwang) - 仅微超 V0
- ❌ B7 TS-Momentum t-stat (Moskowitz) - 全候选塌方
- ❌ B8 MACD - 无 alpha
- ❌ B9 横截面 Top-1 - 集中度过高
- ❌ Filter B buffer > 0 - 单调劣化
- ❌ PHASES ≠ 5 / rb ≠ 5 - 都不优
- ❌ V0 替换 benchmark (沪深300/上证50) - 改进 ≤ 0.02 Sharpe

## 退出机制 (上线后监控)

如果 6 个月内 (到 2026-11):
- PV 触发 ≥ 3 次且 20d 命中率 < 60% → 关闭 PV, 退回 DD-6.5 only
- PV 触发 ≥ 3 次且 20d 命中率 ≥ 60% → 维持 DD+PV
- PV 触发 0-2 次 → 继续观察

DD-6.5 only 永远是 fallback (PBO 0.109 最稳, OOS Sharpe 1.832).

## 实盘资金 (2026-05-14 起)
本金: ¥641,459 (卖出 513500 标普 + 原 513300 减仓后)
首次建仓: 按 5 相位 Ensemble 当日权重一次性买入
后续: 每个交易日 14:50 调 1 个相位 (约 1/5 子账户)
