Capstone 选题:多因子选股 + 风险加权 + 风控
直觉
学了十二个模块,是时候把它们串成一个完整项目。Capstone 不是再学新知识,而是把数据 → 因子 → 组合 → 回测 → 归因 → 风控走成一条流水线,并像真实研究那样先立假设、再用数据验证、最后写报告。我们的选题:用「质量 + 动量」复合因子做横截面选股,用反波动率加权做风险控制,目标是跑赢等权基准、且回撤更小。这一节先立清假设、定好口径与成功标准,再动手——好的研究从清晰的假设开始。
项目假设与设计
- 假设:高质量、近期强势的股票,未来一个月大概率继续跑赢低质量、弱势股;
- 因子:
quality(持久横截面特征)+ 12 月动量,截面排名等权复合成得分; - 选股:每月取复合得分最高的 10 只;
- 加权:反波动率加权(波动大的股权重小)——风险平价的轻量近似;
- 基准:50 只股票等权月度组合;
- 成功标准:策略夏普高于基准、年化跑赢、最大回撤不显著放大。
「人话」解释:为什么要先立假设、定基准、再动手?
没有预先假设就开始翻数据,几乎必然过拟合——你总会「发现」某个在过去表现极佳、但纯属巧合的规律。科学做法是:先写下「我相信什么、为什么」,再让数据来反驳。同时必须定基准(等权/市值加权),因为没有基准的「年化 10%」毫无意义——基准若也有 9%,你的策略其实没贡献什么。最后定成功标准(夏普更高、回撤更小),让我们在动手前就知道「怎样算成功」,避免事后改标准来迁就结果。
可运行案例:先验证假设、再建流水线
动手前先用数据检验两个前提:(1) 质量因子有没有截面预测力(IC);(2) 等权基准长什么样(这是要打败的对手)。
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]
monthly = prices.resample('ME').last(); mret = monthly.pct_change()
quality = meta['quality']
# (1) 质量因子月度截面 IC
ic = []
for t in mret.index[1:-1]:
y = mret.shift(-1).loc[t]
ic.append(quality.rank().corr(y.rank()))
ic = np.array(ic)
print(f"质量因子: 月均IC={ic.mean():+.3f} ICIR={ic.mean()/ic.std():.2f}")
# (2) 等权基准(要打败的对手)
bench = mret.mean(axis=1).dropna()
be = (1 + bench).cumprod()
s = quant.performance_summary(be, bench, freq=12)
print(f"等权基准: 年化={s['年化收益']:+.2%} 夏普={s['夏普']:.2f} 最大回撤={s['最大回撤']:.2%}")
plt.figure(figsize=(9, 3.3))
plt.bar(range(len(ic)), ic, color=['seagreen' if v > 0 else 'indianred' for v in ic], width=1.0)
plt.title('质量因子月度 IC:整体偏正 → 假设有据'); plt.xlabel('月'); plt.ylabel('IC')
plt.tight_layout(); plt.show()
print("\n→ IC 为正、基准已标定; 下一节正式搭建端到端流水线。")
小结
- Capstone 把所学串成数据→因子→组合→回测→归因→风控的完整流水线;
- 先立假设、定基准、定成功标准,再动手——这是防过拟合的第一道闸;
- 本项目:质量+动量选前 10、反波动率加权,目标是跑赢等权基准且回撤可控。