验证超额收益
用信息比率看策略是否持续跑赢基准、跑赢多少,而不是只看绝对涨幅。信息比率越高,说明单位跟踪风险换来的超额越稳定,越能证明主动管理能力。
衡量「相对基准」的绩效,而非只看绝对收益。
| 指标 | 方法 | 含义 | 适用场景 | 注意点 |
|---|---|---|---|---|
| 信息比率 | qs.stats.information_ratio(returns, benchmark) | 单位跟踪误差的超额收益 | 判断主动管理是否持续跑赢基准 | 基准不匹配时结果失真 |
| R² | qs.stats.r_squared(returns, benchmark) | 与基准的相关程度(0-1) | 看策略是否只是「复制」基准 | 高 R² 说明超额主要来自 beta |
| 滚动 beta | qs.plots.rolling_beta(returns, benchmark) | 相对基准的滚动敏感度 | 看风格暴露随时间变化 | 需足够长的收益序列 |
| 对比 | qs.stats.compare(returns, benchmark) | 策略与基准并列对比 | 快速并排查看两者指标 | 需传基准收益序列 |
| 累计收益对比 | qs.stats.compsum(returns) | 收益序列转为累计净值 | 画策略与基准净值叠加曲线 | compsum 本身不含基准,需分别对两者调用后叠加 |
| 回撤序列 | qs.stats.to_drawdown_series(returns) | 收益序列转为回撤序列 | 对比策略与基准的回撤深度/时长 | 可与 plots.drawdowns_periods 配合看回撤区间 |
1. 导入并取策略收益:import quantstats as qs; stock = qs.utils.download_returns('META') —— 得到策略的日收益序列。
2. 取基准收益:benchmark = qs.utils.download_returns('SPY') —— 得到基准日收益序列,与策略同频。
3. 生成带基准的 HTML 报告:qs.reports.html(stock, benchmark) —— 报告内并排展示策略与基准的净值、回撤、指标。
4. 单独算相对指标:qs.stats.information_ratio(stock, benchmark) —— 返回信息比率数值。
5. 看滚动暴露:qs.plots.rolling_beta(stock, benchmark) —— 画出滚动 beta 曲线,观察风格暴露变化。
基准要与策略的市场、风格匹配,否则相对指标失真。
| 策略类型 | 建议基准 | 为什么这么选 |
|---|---|---|
| 美股多空/选股 | SPY(标普500) | 代表大盘 beta,衡量选股带来的超额 |
| 美股成长/科技 | QQQ(纳斯达克100) | 与科技成长风格更匹配,避免把风格误判为 alpha |
| A股组合 | 沪深300 等宽基指数收益序列 | 覆盖大盘蓝筹,衡量相对 A股市场整体 |
| 加密货币 | BTC 或主流指数收益序列 | BTC 是加密市场主导资产,衡量相对加密大盘 |
| 绝对收益/CTA | 可无基准,或选同类策略指数 | 目标是绝对收益,不追求跑赢单一指数 |
| 港股/中概组合 | 恒生指数或恒生科技指数收益序列 | 标的上市地与行业风格要匹配,用 A股宽基衡量港股组合会同时误判 beta 与 alpha |
| 债券/固收组合 | 对应久期的债券指数收益序列 | 股债驱动因素不同,拿股票指数当基准会把「债市行情」误读成策略超额 |
先分清要看「跑赢多少」还是「赚了多少」。
| 维度 | 绝对绩效 | 相对绩效 |
|---|---|---|
| 关注点 | 赚了/亏了多少 | 跑赢/跑输基准多少 |
| 核心指标 | 夏普比率、最大回撤、CAGR | 信息比率、滚动 beta、超额收益 |
| 适用 | 绝对收益目标(如 CTA) | 相对收益目标(如指数增强、选股) |
| 例子 | 策略年化 15%,最大回撤 10% | 策略年化 15%,跑赢 SPY 5 个百分点 |
| 判断标准 | 是否达到收益/风险目标 | 是否跑赢基准,且超额是否稳定 |
| 数据前提 | 只需自身收益序列 | 需要自身与基准两条同频、同口径的收益序列 |
| 常见误用 | 只看涨幅就宣称策略「稳」 | 基准选得过宽,把市场 beta 当成自身 alpha 汇报 |
用信息比率看策略是否持续跑赢基准、跑赢多少,而不是只看绝对涨幅。信息比率越高,说明单位跟踪风险换来的超额越稳定,越能证明主动管理能力。
用滚动 beta 看策略相对基准的敏感度随时间怎么变,识别策略是否在某段行情悄悄加杠杆或转向,避免把市场 beta 当成自身 alpha 来汇报。
报告里同时展示策略与基准的净值、回撤、相对收益,让读者一眼看清「跑赢还是跑输」,比只报绝对收益更有说服力,也更能对齐投资者预期。
相对指标对「两条序列是否同频同口径」极其敏感,下表是最常见的失真形态与排查顺序。
| 现象 | 常见原因 | 会得出什么错结论 | 怎么排查 |
|---|---|---|---|
| 信息比率高得离谱 | 基准与策略市场错配(用宽基大盘对比行业策略) | 把风格收益当成选股能力 | 换成与策略同市场的基准重算一次对照 |
| 净值明显占优但信息比率很低 | 策略与基准频率不同(日频对月频) | 跟踪误差被放大,超额被稀释 | 先把两条序列统一到同一频率再计算 |
| 滚动 beta 曲线剧烈跳变 | 交易日不齐(停牌、上市时间不同、休市口径不同) | 窗口内样本错位,相关性失真 | 先取两条序列日期索引的交集再滚动计算 |
| 相对指标整列是 NaN | benchmark 传了 Series,但索引与策略不一致 | 误以为库不支持该指标 | 打印两条序列的 index 与长度,对齐后再传 |
| 夏普/索提诺与直觉不符 | 无风险利率参数缺省,口径与预期不同 | 跨策略比较时基准不统一 | 显式传入 rf,并在报告里注明口径 |
| 换个基准结论完全反转 | 基准本身被替换或成分调整(指数调仓、退市) | 两份报告无法互相比较 | 固定基准全称与数据来源,写进报告说明 |
| 基准曲线明显更平滑 | 用了价格指数而非含分红的总收益口径 | 高估策略超额 | 两条序列都用总收益(含分红)口径重算 |
先明确一点:QuantStats 不负责抓行情,它只吃「收益率序列」,数据要你自己准备。
1. 美股/ETF 最省事:qs.utils.download_returns('SPY') —— 内部走 yfinance,需要能访问外网,失败时改用本地 CSV。
2. A股换数据源:用 akshare 或 tushare 取指数/个股收盘价,再 pct_change() 得到日收益序列 —— 拿到的是一列收益率,量纲要与策略一致。
3. 对齐索引:把两条序列 reindex 到同一交易日集合,避免因为停牌/新股上市产生 NaN —— 这一步不做,后面的相对指标就不可信。
4. 喂给 QuantStats:qs.reports.html(stock, bm, title='我的策略 vs 沪深300') —— 生成带基准对比的 HTML 报告。
import pandas as pd, akshare as ak, quantstats as qs;hs300 = ak.stock_zh_index_daily(symbol="sh000300");bm = hs300.set_index("date")["close"].pct_change().dropna();qs.reports.html(bm, bm, title="示例:沪深300 vs 沪深300")。预期输出:当前目录生成一份 HTML tearsheet。数据接口名与可用性随数据源版本变化,以其官方文档为准;无外网时优先用本地 CSV。同一份报告,不同读者的关注点完全不同;先定读者,再定指标。
| 读者/场景 | 先看什么 | 再看什么 | 注意点 |
|---|---|---|---|
| 自己复盘 | 净值曲线与基准的叠加 | 回撤区间、滚动 beta | 样本太短不要下结论 |
| 给投资经理 | 信息比率与超额收益 | 跟踪误差、R² | R² 高说明超额主要来自 beta,不是选股 |
| 给客户 | 累计收益对比 + 最大回撤 | 分年度收益对比 | 必须同时给出基准名称与样本区间 |
| 风控视角 | 跟踪误差、回撤深度与时长 | 滚动波动率 | 关注极端窗口,别只看均值 |
| 策略筛选 | 分年度信息比率是否持续为正 | 换手与成本敏感性 | 单期高信息比率不代表可持续 |
| 写进文档/归档 | 口径与参数(频率、rf、基准来源) | 数据区间与数据处理步骤 | 口径缺失会让结论无法复现 |
基准对比只回答「相对基准跑得怎么样」,其余问题各有归属。
不传基准也能跑,但别把不相干的指数硬塞给绝对收益策略当基准。
| 策略类型 | 合理对照 | 不合理对照 | 说明 |
|---|---|---|---|
| CTA/绝对收益 | 现金收益或无风险利率 | 用宽基股票指数当基准 | 目标不是跑赢股市,硬比会低估自身价值 |
| 市场中性 | 同类市场中性策略指数 | 用沪深300/SPY 这类方向性指数 | 方向暴露已被对冲,比方向指数没有意义 |
| 只做单市场选股 | 该市场宽基指数 | 跨市场指数(用美股比 A股策略) | 跨市场比较会把汇率与制度差异算成 alpha |
| 多资产组合 | 自建加权合成基准 | 只挑一个资产当基准 | 合成基准的权重与再平衡规则必须写进报告 |
| 只看自身风险 | 不设基准,只用单序列指标 | 为了凑格式随便填一个 ticker | 基准填错比不填更糟,会得出错误超额 |
| 以 0 收益为基准 | 明确说明这是「相对现金」口径 | 与夏普比率并列汇报 | 口径接近夏普,重复汇报会让人误读为两条独立证据 |
相对指标的错误大多来自数据,而不是代码;取数这一步值得单独校验。
| 数据来源 | 优点 | 风险 | 怎么校验 |
|---|---|---|---|
| 指数公司官网导出 | 口径权威 | 手工导出容易漏日期、格式不统一 | 抽 3 个交易日核对官方点位与涨跌幅 |
| 本地数据商(tushare 等) | 接口稳定、可批量 | 复权方式与分红处理可能与自己预期不同 | 确认是否含分红、是前复权还是后复权 |
| 免费行情接口(akshare/yfinance) | 零成本、上手快 | 字段名与可用性会变;美股需外网 | 固定一次取数结果并落盘存档,别每次重取 |
| 券商/交易软件导出 | 与自己的成交口径一致 | 可能是点数而非收益率,且含停牌行 | 先转成收益率,再检查索引是否有重复日期 |
| 自建合成基准 | 最贴合策略实际配置 | 权重与再平衡规则不透明就没法复现 | 把成分与权重写进报告,并记录调整频率 |
| 手工整理的 CSV | 完全可控、离线可用 | 易混入非交易日、时区错位、单位错误 | 读入后先打印 head/tail 与行数,再算指标 |
可传基准 ticker(如 'SPY')或 pandas Series,官方 README 示例用 'SPY';传 Series 时需与策略收益同频同口径。具体以官方 README/实现为准。
qs.stats.information_ratio(returns, benchmark) 返回单位跟踪误差的超额收益,衡量主动管理的质量,口径以官方实现为准。
不必。绝对收益类策略(如 CTA)可不设基准;但若要衡量相对绩效、算信息比率/滚动 beta,则必须传基准收益序列。
EasyClaw 的 quant-analyst 技能也能做回测并输出 Sharpe/最大回撤等指标,但 QuantStats 是独立的 Python 库,两者无已证实集成;QuantStats 的 benchmark 参数可精细对比基准相对绩效;选择前以各自能力为准。
不能。相对绩效仅代表历史表现,信息比率/滚动 beta 都基于历史收益序列,不构成收益保证或投资建议。
不能直接对比。样本区间、基准全称、数据来源、频率与无风险利率这五项里只要有一项不同,两组相对指标就属于不同口径,数值高低没有可比性。正确做法是固定一份序列做存档,改口径时两组数据同时重算,并在报告里写明变化前后的口径差异,而不是把新旧数字并排放进同一张表。