Alphalens · 分位收益与多空价差
Alphalens 分位收益:分组收益怎么读,累计收益口径为什么总对不上
把因子值从低到高切成 N 组,逐组算持有收益——这是因子研究里最直观的一张图。Alphalens 用 mean_return_by_quantile 出分位均值收益,用 compute_mean_returns_spread 出最高与最低分位的价差;但累计收益这条线长期有口径争议,真实 issue 里争论了好几年。
Alphalens 的分位收益怎么变成结论
performance.py 的分位收益函数整理(非官方图);分位编号方向以源码实现为准。Alphalens 的四个分位收益函数分别输出什么
分位收益相关的函数输出的东西形状不同:有的是一张表,有的是一个带标准误的二元组,有的是一个时序。下表按源码签名整理。
| 函数 | 输出 | 回答的问题 | 怎么读 | 适用场景 | 注意点 |
|---|---|---|---|---|---|
mean_return_by_quantile | 分位均值收益(配一个标准误对象) | 每组平均收益是多少 | 看条形是否单调:从最低分位到最高分位应该是阶梯状 | 因子方向与强度的第一张图 | 参数 by_date、by_group 会改变聚合维度 |
compute_mean_returns_spread | 最高与最低分位的收益差(以及标准误) | 多空组合的收益幅度 | 看价差是否显著大于 0(结合标准误) | 判断因子的极端分位是否真的有区分度 | 价差受极端分位样本量影响,分组越细越不稳 |
factor_returns | 按期加权的因子收益时序 | 因子本身作为一个组合的收益路径 | 看累计曲线的斜率与回撤段 | 与 pyfolio 衔接、或自己算组合绩效 | equal_weight、group_adjust、demeaned 三个开关会显著改变结果 |
factor_cumulative_returns | 因子模拟组合的累计收益 | 长期累计表现 | 看曲线,但要注意口径争议 | 写研究报告时展示累计路径 | issue #374 / #357 / #386 / #380 都在讨论这条线的口径 |
cumulative_returns / rate_of_return | 把简单收益换算成累计收益与单位周期收益率 | 多周期收益怎么换算 | 这是底层换算工具,直接用它说明你在自定义口径 | 需要与非默认口径对齐时 | 换算假设(复利/单利、周期长度)必须写清 |
Alphalens 分位收益的四种形态分别意味着什么
Alphalens 的分位图不是只看「最高一组赚得多」这一点,形态本身是信息。下面四种形态对应完全不同的后续动作。
| 形态 | 看起来是什么样 | 含义 | 典型成因 | 下一步动作 | 注意点 |
|---|---|---|---|---|---|
| 单调阶梯 | 各分位收益从低到高逐级上升 | 因子排序信息贯穿全样本 | 因子与未来收益的关系近似单调 | 可以再看 IC 与换手率来决定调仓频率 | 先确认分位编号方向,否则会把反向阶梯读成正向 |
| 两端翘起 | 中间分位平、两端分位一中一负 | 信息主要来自极端值 | 因子在阈值附近才有效(事件类、分位类因子常见) | 用多空价差而不是均值 IC 来描述这个因子 | 极端分位样本天然更少,收益更不稳定 |
| 平坦或无规律 | 各分位收益差别在噪声范围内 | 在当前频率与样本期下没有区分度 | 持有期不匹配、行业暴露掩盖、或因子本身无效 | 先做行业中性化与持有期敏感性检查,再决定是否放弃 | 别靠调整分位数量「凑」出好看的结果 |
| U 型反号 | 两端都比中间差(或两端收益都为负) | 因子可能是反向的,或极值区有数据问题 | 因子定义方向反了;或极值未被处理 | 检查因子定义方向与 filter_zscore 设置 | 反号不等于可以用反向交易:交易成本会吃掉价差 |
Alphalens 累计收益口径为什么对不上:一条争了五年的曲线
真实 issue 里关于累计收益的讨论一直没有结论。这一节把争议原文、影响面和处理建议摆出来,方便你在报告中写清口径。
| Issue | 提出的问题 | 时间与状态 | 对上图时会看到什么 | 建议做法 |
|---|---|---|---|---|
| #374 | 质疑 factor_cumulative_returns 的数值不正确(讨论 16 条) | 2020-05-01 开,至今 open | 自己手工复算的累计收益与图上的曲线对不上 | 在报告里注明所用口径,并保存当时的库版本 |
| #357 | 请求简化 cumulative_returns 的定义(讨论 8 条) | 2020-01-31 开,open | 多周期(5/10 日)曲线的读法不直观 | 只把累计收益图当相对比较用,不作为绝对收益结论 |
| #386 | 累计收益在 periods > 1 时是否还做周期调整 | 2020-09-09 开,open | 1 日与 5 日曲线混在一张图里难以比较 | 一次只看一个持有期,别把不同期数叠在一起 |
| #380 | 持有期大于 1 日时分位累计收益图不显示 | 2020-05-27 开,open | 图是空的或只有一条线 | 换用 plot_cumulative_returns_by_quantile 直接对分位收益画图 |
| #369 / #370 | tear sheet 图不可读 / 偶发空白图 | 2020-04 开,open | 图能出来但看不清,或重跑一次才出现 | 别依赖 tear sheet 一次性出图,关键图用 plotting 单独画 |
| #313(已修) | 均值收益应先按日期聚合再按分位聚合 | 2018-08-06,已合并 | — | 说明这类口径问题历史上确实修过,但也说明不同版本结果可能不同 |
Alphalens 的 long_short 与 group_neutral 四种组合怎么选
Alphalens 的这两个开关决定「多空组合怎么构造」,是分位收益口径里最容易含糊的地方。下面四步给出选择顺序与预期输出。
先跑默认组合:long_short=True、group_neutral=False
代码:
mean_return_by_quantile(factor_data),或直接create_returns_tear_sheet(factor_data)。预期:得到全样本口径下的分位均值收益与多空价差,这是最接近「因子原始信息」的一版。打开 demeaned / group_adjust 看行业影响
在因子收益相关函数里把
demeaned或group_adjust打开。预期:数值会变,通常变小;如果变化很大,说明原结论里有相当部分来自行业间收益差。需要「行业内多空」就打开 group_neutral
create_returns_tear_sheet(factor_data, long_short=True, group_neutral=True)。预期:每个行业内分别做多高因子、做空低因子,输出的是行业内价差;适合做行业中性因子研究。记录口径并固定版本
把 long_short / group_neutral / equal_weight 三个开关的取值与库版本写进研究记录。预期:任何人拿同一份数据与同一组开关都能复现同一张图——这是这套参数唯一的意义。
Alphalens 的 IC 与分位收益结论打架时怎么办
Alphalens 的这两种指标准确描述同一件事的不同侧面,偶尔会给出相反印象。下表按最常见的四种冲突给出排查顺序。
| 现象 | 可能原因 | 先查什么 | 处置 |
|---|---|---|---|
| IC 均值不低,但分位收益平坦 | IC 由中间分位的排序贡献,极端分位没有区分度 | 分位收益表中的两端分组 | 改用多空价差描述因子,并在报告里写明「中间分位有效」 |
| 分位收益单调好看,IC 却很弱 | 收益被少数极端标的带动(秩相关对极端值不敏感) | filter_zscore 设置与实际丢弃比例 | 收紧极值过滤后重跑,确认结论是否仍成立 |
| 两者都好看,但换手极高 | 因子短期噪声大、排序频繁变化 | 换手率与 rank 自相关(见下一页) | 把持有期拉长或降低调仓频率后再评估 |
| 不同 periods 结论相反 | 信号半衰期恰好卡在你选的期数之间 | 各期的 IC 与分位收益对照 | 选定与调仓计划一致的期数,只报这一期结论 |
分几组、怎么分组:5 组还是 10 组,行业分组怎么用
分位数量与分组方式直接改变分位收益的形状。中文资料常只写「分成五组」,但不解释换组数会发生什么。
| 选择 | 典型用法 | 好处 | 代价 | 注意点 |
|---|---|---|---|---|
| 5 组(默认) | 最常用的初筛 | 每组样本充足,图形稳定 | 看不到极端分位的细节 | 多空价差只用两端,中间组的形态会被忽略 |
| 10 组 | 想观察单调性细节 | 更接近连续关系的形状 | 每组样本变少,噪声变大 | 股票池小的时候容易整组只剩几只标的 |
自定义 bins | 分布严重偏斜的因子 | 不等宽分箱更贴合业务含义 | 边界需要自己论证 | quantiles 与 bins 只能给一个 |
| 行业内分组 | 行业间差异大的因子 | 剥掉行业间收益差 | 小行业分位失真 | 需要提供 groupby,并打开 binning_by_group |
| 股票池分组 | 分板块/分市值层看 | 能看出因子在哪个子池更有效 | 分组越多、每组结论越不稳 | 分组结论需给出各组样本量 |
| 单调性检验 | 判断排序信息是否贯穿 | 比「两端价差」更完整 | 需要额外计算 | 常用做法:分组收益的秩相关或相邻组差值的符号一致性 |
多空组合怎么才做得出:涨跌停、成本与容量
分位收益是从数据里算出来的,不是从市场上交易出来的。下面把「报告里的多空价差」与「实际可实现的收益」之间常见的四道损耗列清楚。
| 现实约束 | 报告里的处理 | 实际影响 | 怎么自查 | 注意点 |
|---|---|---|---|---|
| 涨跌停无法成交 | 通常不处理:只要当天有价格就算成交 | 涨停买入、跌停卖出的交易根本不会发生,价差被高估 | 把涨跌停日的标的从对应分位里剔除后重算 | 一字板与触板后打开要区别处理 |
| 停牌 | 价格缺失时由清洗阶段丢弃 | 复牌跳空会集中体现在某一期 | 统计复牌日收益的分布 | 长期停牌标的会整段消失 |
| 成分变动 | 每期按新分位重建组合 | 换手率上升,交易成本随之上升 | 用 quantile_turnover 量化替换比例 | 换手不是缺陷,但不扣成本就等于高估收益 |
| 交易成本 | 默认完全不扣 | 高频调仓时成本可能吃掉全部价差 | 见「换手与自相关」页的示例假设换算 | 费率必须换成你自己的 |
| 容量与冲击 | 默认不限制 | 资金规模越大,实际成交价越差 | 按标的成交额约束单只持仓上限 | 小市值股尤其明显 |
| 最小交易单位 | 默认可买任意股数 | 高价股与小额资金下无法精确配权 | 按 100 股整数倍模拟 | 组合标的越多,影响越小 |
Alphalens 分位收益常见问题
分位收益与累计收益的口径以 performance.py 实现为准;存在争议的部分已在上一节逐条标注 issue 编号。
Alphalens 的分位收益为什么会出现「第 5 组最好、第 4 组反而最差」这种乱序?
常见原因有三:该期样本内某一组只包含少数标的;因子在该区间没有单调性;或者零值/极值把某一组的构成污染了。先看每组的样本数量,再看 zero_aware 与 filter_zscore 的设置,最后才考虑换因子。
多空价差为负说明什么?
说明按当前因子方向,高因子组的收益反而低于低因子组。这可能是因子方向定义反了,也可能是这段样本期内因子确实失效。无论哪种,都不要直接把「反向交易」当解决方案:价差里没有扣交易成本,也没有考虑可交易性。
累计收益能直接当作策略收益吗?
不能。它是因子模拟组合的累计口径展示,存在长期争议(#374 / #357 / #386 / #380),且不含交易成本、容量与风控约束。要评估策略收益请用完整的回测框架,并且不要在任何页面上把它说成可实现收益。
equal_weight 开关改的是什么?
改的是组合内标的的加权方式:等权 or 按因子值加权。factor_weights 就是算权重的那一层。等权更稳健,加权更贴近「因子强度决定仓位」的想法,但也会放大极端值的影响。
by_date 是什么意思?
它决定均值收益是「先按日期聚合再按分位聚合」还是反过来。这个顺序在历史上修过(issue #313),不同版本结果可能不同。口径以你所用版本的实现为准,写报告时把库版本一起记下来。
能不能只看多空价差,不看分位图?
可以,但会丢信息:价差只描述两端,分位图能看出中间分位的形态(例如 U 型)。建议两张一起看,并在报告中说明你用的是哪一种口径。
这些结论和免部署技能有关吗?
没有已证实集成。分位收益与多空口径必须在装了 Alphalens 的 Python 环境里计算;本机技能可以提供取数与出图,但不实现这套因子绩效口径。
本站的分位收益图是真的吗?
不是真实行情。本站没有接任何行情数据源,所有示例与运行记录均基于合成数据,并在每处标注。真实结论请用自己的数据重跑。