跳到主要内容

端到端流水线:因子 → 选股 → 风险加权 → 回测

直觉

这一节把上一节的假设一次性跑通:从原始价格出发,构造复合因子得分、每月选前 10、用反波动率加权、月度再平衡,最后与等权基准对比净值与指标。一条流水线、一份代码、一个结论——这就是 Capstone 的核心。注意每一步都严格防前视:月末 tt 用截至 tt 的信息算因子/权重,赚取的是 tt+1t\to t+1 的下月收益

流水线数学

复合得分(截面排名等权):

Scoret,i=rankt(qualityi)+rankt(mom12t,i)\text{Score}_{t,i}=\text{rank}_t(\text{quality}_i)+\text{rank}_t(\text{mom12}_{t,i})

反波动率权重(仅对入选的 10 只,σ^i\hat\sigma_i 为其年化波动):

wi=1/σ^ij1/σ^jw_i=\frac{1/\hat\sigma_i}{\sum_j 1/\hat\sigma_j}

组合下月收益 RtP=itop10wiRi,tt+1R^{P}_{t}=\sum_{i\in\text{top10}} w_i\,R_{i,\,t\to t+1},基准为 50 只等权。

「人话」解释:为什么用「排名复合」和「反波动率加权」?

排名复合:质量和动量量纲不同(一个无量纲、一个是百分比),直接相加会被量纲大的主导。先各自转成截面排名再相加,等于「在质量和动量两个维度上都靠前的股票」得分最高——简单、稳健、无量纲问题。 反波动率加权:风险平价要求各资产风险贡献相等,其轻量近似就是「波动越大、权重越小」(w1/σw\propto1/\sigma)。它让组合不被一两只高波动股绑架,天然控制回撤——比等权更「风险均衡」,又比完整风险平价优化简单得多,适合教学级流水线。

可运行案例:完整流水线一键跑通

import quant
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

prices = pd.read_csv('/data/sp500_universe_daily.csv', parse_dates=['date']).set_index('date')
meta = pd.read_csv('/data/sp500_metadata.csv').set_index('ticker').loc[prices.columns]
dret = np.log(prices / prices.shift(1))
monthly = prices.resample('ME').last(); mret = monthly.pct_change()

# 1) 因子: 质量(持久) + 12月动量, 截面排名等权复合
quality = pd.DataFrame(np.tile(meta['quality'].values, (len(monthly), 1)),
                     index=monthly.index, columns=monthly.columns)
mom12 = np.log(monthly / monthly.shift(12))
score = quality.rank(axis=1) + mom12.rank(axis=1)            # 复合得分

# 2) 反波动率权重(过去3月年化波动)
vol3 = (dret.rolling(63).std() * np.sqrt(252)).resample('ME').last()
fwd = mret.shift(-1)                                          # 下月收益(标签)

# 3) 月度选股 top10 + 反波动率加权 + 回测
dec = monthly.index[12:-1]                                     # 动量需12月预热, 末月无下月收益
port, bench = [], []
for t in dec:
  picks = score.loc[t].nlargest(10).index
  invv = 1 / vol3.loc[t, picks].clip(lower=0.05); w = invv / invv.sum()
  f = fwd.loc[t]
  port.append((f[picks] * w).sum()); bench.append(f.mean())
port = pd.Series(port, index=dec); bench = pd.Series(bench, index=dec)
pe, be = (1 + port).cumprod(), (1 + bench).cumprod()

print(f"{'':8} {'年化':>7} {'夏普':>6} {'最大回撤':>8}")
for n, eq, r in [('策略', pe, port), ('等权基准', be, bench)]:
  s = quant.performance_summary(eq, r, freq=12)
  print(f"{n:8} {s['年化收益']:+6.2%} {s['夏普']:6.2f} {s['最大回撤']:7.2%}")
print(f"\n主动年化 = {(pe.iloc[-1]**(12/len(port))-1)-(be.iloc[-1]**(12/len(bench))-1):+.2%}")

plt.figure(figsize=(9, 3.6))
plt.plot(pe, color='darkgreen', lw=1.6, label='策略(质量+动量,反波动率)')
plt.plot(be, color='gray', ls='--', lw=1.2, label='等权基准')
plt.title('Capstone 端到端流水线净值'); plt.ylabel('净值'); plt.legend(fontsize=9)
plt.tight_layout(); plt.show()

小结

  • 一条流水线:复合因子得分 → 选 top10 → 反波动率加权 → 月度再平衡 → 对比基准
  • 全程防前视:月末 tt 的因子/权重只对应 tt+1t\to t+1 的下月收益;
  • 反波动率加权是风险平价的轻量近似,能在不引入优化的前提下控制回撤。