第 7 章 · 04 Alphalens 信号评估 本节摘要:本节讲因子评估的标准化工具——Alphalens。上一节我们用线性模型预测股票收益,得到一组预测值。但这些预测值作为「因子」到底有没有用?Alphalens 是 Quantopian 开源的因子分析套件,输入因子值和价格,一键输出 tear sheet:把股票按因子值分 5 组(quantile),看各组的前向收益是否单调;算信息系数 IC(因子值与前向收益的相关性);算换手率(因子排名的稳定性)。本节讲三件事:Alphalens 的输入契约( )、tear sheet 的核心指标(分组收益、IC、换手率),以及如何用它对比 LinearRegression/Ridge/Lasso 三个模型的信号质量,选出最优模型和最优 α。
本节摘要:本节讲因子评估的标准化工具——Alphalens。上一节我们用线性模型预测股票收益,得到一组预测值。但这些预测值作为「因子」到底有没有用?Alphalens 是 Quantopian 开源的因子分析套件,输入因子值和价格,一键输出 tear sheet:把股票按因子值分 5 组(quantile),看各组的前向收益是否单调;算信息系数 IC(因子值与前向收益的相关性);算换手率(因子排名的稳定性)。本节讲三件事:Alphalens 的输入契约(
get_clean_factor_and_forward_returns)、tear sheet 的核心指标(分组收益、IC、换手率),以及如何用它对比 LinearRegression/Ridge/Lasso 三个模型的信号质量,选出最优模型和最优 α。
内容来源:原项目
ch07/06_evaluating_signals_using_alphalens.ipynb,汉化并套用体系化模板。
⚠️ 风险提示:Alphalens 评估的是「因子在历史上有无统计预测力」,不等于「交易能赚钱」。优秀因子加上交易成本、容量、市场冲击后可能不可盈利。
阅读完本节,你应当能够:
get_clean_factor_and_forward_returns 准备 Alphalens 输入。第 3 节我们用 MultipleTimeSeriesCV 算了每日 IC,知道模型「平均预测力」。但这只回答了一半问题:
Alphalens 把这些维度一次性可视化,是因子研究的标准化工具。
Alphalens 的核心函数是 get_clean_factor_and_forward_returns,它要两个输入:
from alphalens.utils import get_clean_factor_and_forward_returns from alphalens.tears import create_summary_tear_sheet # 因子值:从模型预测转成 MultiIndex Series lr_factor = (lr_predictions.predicted.swaplevel() .unstack('symbol').dropna(how='all').stack() .tz_localize('UTC', level='date').sort_index()) # 价格:用次日开盘价(避免用收盘价造成前视) trade_prices = (pd.read_hdf(DATA_STORE, 'quandl/wiki/prices') .swaplevel().sort_index() .loc[idx[tickers, '2014':'2017'], 'adj_open'] .unstack('symbol').sort_index().shift(-1).tz_localize('UTC')) # 清洗 + 计算多期限前向收益 factor_data = get_clean_factor_and_forward_returns( factor=lr_factor, prices=trade_prices, quantiles=5, periods=(1, 5, 10, 21))
⚠️ 价格选择:必须用「能成交的价格」。如果用 t 日收盘价算因子、又用 t 日收盘价算收益,等于「收盘看到信号、收盘成交」——前视。实务用
shift(-1)取次日开盘价,模拟「收盘决策、次日开盘成交」。
quantiles=5 把每日股票按因子值分成 5 组(0~4),periods=(1,5,10,21) 计算这些前向期限的收益。
create_summary_tear_sheet(factor_data) 输出三组关键信息:
把股票按因子值分 5 组,看每组在不同前向期限的平均收益。理想因子的分组收益应该单调:
| quantile | 1d 收益 | 5d 收益 | 21d 收益 |
|---|---|---|---|
| 1(最低) | -0.05% | -0.20% | -0.80% |
| 2 | -0.01% | -0.05% | -0.20% |
| 3(中) | 0.00% | 0.00% | 0.00% |
| 4 | 0.02% | 0.08% | 0.30% |
| 5(最高) | 0.06% | 0.25% | 1.00% |
如果最高组收益远高于最低组,且中间单调,说明因子有强横截面区分力。多空组合 = 「买 quintile 5 + 卖 quintile 1」。
| 期限 | IC 均值 | IC 标准差 | ICIR |
|---|---|---|---|
| 1d | 0.030 | 0.08 | 0.38 |
| 5d | 0.045 | 0.10 | 0.45 |
| 21d | 0.060 | 0.12 | 0.50 |
换手率衡量因子排名的稳定性——每天有多少股票从一组换到另一组。高换手率意味着高交易成本:
| quantile | 换手率 |
|---|---|
| 1 | 0.15 |
| 5 | 0.18 |
换手率 0.15 表示每天该组有 15% 的股票被换掉。换手率 >0.3 的因子即使 IC 高,在扣成本后也难盈利。
06 notebook 的核心价值是横向对比三个模型在最优 α 下的信号质量:
# 选每个模型 CV 上 IC 最高的 α def get_best_alpha(scores): return scores.groupby('alpha').ic.mean().idxmax() best_ridge_alpha = get_best_alpha(ridge_scores) ridge_predictions = ridge_predictions[ridge_predictions.alpha == best_ridge_alpha] # 对每个模型做 Alphalens for name, preds in [('Linear', lr_factor), ('Ridge', ridge_factor), ('Lasso', lasso_factor)]: fd = get_clean_factor_and_forward_returns(factor=preds, prices=trade_prices, quantiles=5, periods=(1, 5, 10, 21)) print(f'=== {name} ===') create_summary_tear_sheet(fd)
对比维度:
典型发现:Lasso 因稀疏性通常换手率较低(只看少数稳定因子),Ridge 的 IC 略高但换手率也高,纯 LinearRegression 不稳。综合三者选最优模型 + 最优 α。
第 3 节我们手写 Spearman IC,Alphalens 做的更全:
| 维度 | 第 3 节手写 IC | Alphalens |
|---|---|---|
| IC 计算 | ✓ | ✓ |
| 分组收益单调性 | ✗ | ✓ |
| 多期限对比(1/5/10/21d) | 需分别跑 | 一次全出 |
| 换手率 | ✗ | ✓ |
| 可视化 | 自己画 | 内置 tear sheet |
Alphalens 是手写 IC 的「全功能升级版」,因子研究阶段强烈推荐。
get_clean_factor_and_forward_returns(factor, prices, quantiles=5, periods=...),价格要用 shift(-1) 次日开盘防前视。下一节,我们用逻辑回归处理宏观变量的离散状态预测——从回归转到分类,预测市场涨跌或经济衰退。