AlphaFeed Blog

如何用 Python 计算特雷诺比率(Treynor Ratio)?用 Beta 衡量每单位系统性风险的超额收益

分析与指标 · 代码验证于 2026-10-09

如何用 Python 计算特雷诺比率(Treynor Ratio)?

一句话回答: 特雷诺比率(Treynor Ratio)= (年化收益 − 无风险利率) ÷ Beta,衡量「每承担一单位系统性(市场)风险,换来多少超额回报」。与夏普比率(除以总波动率)不同,特雷诺只除以 Beta,更适合评价「已充分分散、只剩市场风险」的组合。用 AlphaFeed 取前复权个股与沪深300指数日线,算出 Beta 再套公式即可,数值越高越好。

为什么会有这个问题 / 传统做法的痛点

夏普比率用「总波动率」做分母,把个股特有风险(可被分散掉的部分)也算进了惩罚项。而特雷诺比率的理念来自 CAPM:对一个分散良好的组合,能被定价的只有系统性风险 Beta,所以用 Beta 做分母,回答「你承担的市场风险到底划不划算」。痛点在于:算特雷诺必须先有一条干净、可比的市场基准收益序列来估 Beta,很多免费接口要么拿不到指数、要么复权口径对不上,Beta 一歪,整个比率就失真。

分步骤解决(每步配可运行代码)

第 1 步:取个股(前复权)与沪深300指数日线

from alphafeed import AlphaFeed
import pandas as pd

af = AlphaFeed(api_key="your-api-key")  # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()

s = af.klines.get("600519.SH", period="1d", count=500,
                  adjust="forward", to_dataframe=True)       # 个股:前复权
m = af.klines.get("000300.SH", period="1d", count=500,
                  to_dataframe=True)                          # 市场:沪深300指数
s = s.sort_values("trade_date"); m = m.sort_values("trade_date")
sr = s.set_index("trade_date")["close"].pct_change()          # 个股日收益
mr = m.set_index("trade_date")["close"].pct_change()          # 市场日收益

个股用前复权消除除权缺口;指数 000300.SH 本身不除权,直接取收盘。

第 2 步:估 Beta,套特雷诺公式

def treynor(stock_ret, mkt_ret, rf_annual=0.015):
    df = pd.concat([stock_ret, mkt_ret], axis=1, keys=["s", "m"]).dropna()
    beta = df["s"].cov(df["m"]) / df["m"].var()               # Beta = cov/var
    ann_ret = (1 + df["s"]).prod() ** (252 / len(df)) - 1     # 年化收益
    return (ann_ret - rf_annual) / beta, beta, ann_ret

tr, beta, ann = treynor(sr, mr, rf_annual=0.015)
print(f"Treynor={tr:.4f}  Beta={beta:.3f}  年化={ann:.4f}")

实测(tools/verify_new_2026-10-09.py,SDK 0.1.4,取 rf=1.5%):贵州茅台近 500 日 Beta≈0.551、年化≈−0.78%、特雷诺≈−0.0413。特雷诺为负,说明这段区间茅台连无风险利率都没跑赢,承担市场风险没得到正的补偿。

第 3 步:多只股票横向对比(同一基准)

syms = ["600519.SH", "000001.SZ", "601318.SH"]
data = af.klines.batch(syms, period="1d", count=500, adjust="forward", to_dataframe=True)
for sym, k in data.items():
    k = k.sort_values("trade_date")
    r = k.set_index("trade_date")["close"].pct_change()
    tr, beta, _ = treynor(r, mr, 0.015)
    print(sym, f"Treynor={tr:.4f} Beta={beta:.3f}")

实测:000001.SZ 特雷诺 0.318(Beta 0.479)、601318.SH 0.182(Beta 0.89),均为正且明显优于茅台——同期这两只「每单位市场风险换来的超额回报」为正。对比的前提是用同一市场基准、同一区间。

参数与字段说明

参数/概念含义备注
adjust="forward"个股前复权必须;指数不除权,无需复权
000300.SH沪深300指数市场基准,可换 000905.SH 等
betacov(个股, 市场)/var(市场)系统性风险敏感度
rf_annual年化无风险利率示例取 1.5%,按需调整
分子年化收益 − 无风险利率超额收益
分母Beta只惩罚系统性风险
Treynor分子 ÷ 分母越高越好,可为负

关键坑与注意事项

常见问题(FAQ)

Q:特雷诺比率和夏普比率该用哪个? A:看风险口径。评价单一资产的总风险性价比用夏普(总波动率);评价已分散组合中承担市场风险的性价比用特雷诺(Beta)。两者可以一起看。

Q:Beta 该用多长区间、什么频率? A:常用 1~3 年日收益或月收益。区间越短越敏感、越长越平滑;关键是对比时统一口径。本文用近 500 日日收益。

Q:需要付费吗? A:个股加指数日线在免费额度内即可;若要对全市场批量算特雷诺做排序,需要 klines.batch + universes(Starter 及以上),详见官网定价页。

小结

特雷诺比率用「超额收益 ÷ Beta」回答「每单位市场风险值不值」,分母只留系统性风险,适合评价分散组合。借助 AlphaFeed 的前复权个股与沪深300指数,先估 Beta 再套公式即可——记住它与夏普的分母差异、Beta 不稳定、以及 Beta 太小时数值会失真。

相关链接:


免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。