AlphaFeed Blog

如何用 Python 计算盈亏痛苦比(Gain-to-Pain Ratio)?用「总收益÷总亏损」衡量持有体验

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

如何用 Python 计算盈亏痛苦比(Gain-to-Pain Ratio)?

一句话回答: 盈亏痛苦比(Gain-to-Pain Ratio, GPR)= 区间所有收益之和 ÷ 所有下跌期亏损的绝对值之和,直观回答「我每承受一单位的亏损痛苦,换来了多少净收益」。它是对冲基金经理 Jack Schwager 推崇的简单稳健指标——用 AlphaFeed 取前复权日线聚合成月收益,一个函数就能算,GPR > 1 说明净赚远大于累计痛苦,越高越好;小于 0 则区间整体是亏的。

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

夏普比率要算均值、标准差、无风险利率,还默认正态分布,解释起来绕。盈亏痛苦比的思路极朴素:把赚的和亏的分开加总,用总净收益除以总亏损。它天然只惩罚「下行」,而且对异常值不敏感(用总和而非平方),特别适合衡量「拿着这东西到底值不值这份煎熬」。常用月度口径(更贴合持有感受,弱化日内噪声)。

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

第 1 步:取前复权日线,聚合成月收益

from alphafeed import AlphaFeed
import pandas as pd

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

df = af.klines.get("600519.SH", period="1d", count=750,
                   adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
df["dt"] = pd.to_datetime(df["trade_date"])
monthly = df.set_index("dt")["close"].resample("ME").last().pct_change().dropna()

前复权是前提;resample("ME") 取每月最后一个交易日收盘,算月收益。

第 2 步:计算盈亏痛苦比

def gain_to_pain(ret):
    pain = -ret[ret < 0].sum()                 # 所有下跌期亏损绝对值之和
    return float(ret.sum() / pain) if pain > 0 else float("inf")

print("月度 GPR =", round(gain_to_pain(monthly), 3))

实测(tools/verify_new_2026-10-07.py,SDK 0.1.4):贵州茅台近 37 个月 月度 GPR = −0.227,日度 GPR = −0.052。GPR 为负,说明这段区间茅台累计是亏的——赚的总和还抵不过亏的总和。GPR 诚实地把「这段不好拿」说清楚了。

第 3 步:多只股票横向对比

syms = ["600519.SH", "000001.SZ", "601318.SH"]
data = af.klines.batch(syms, period="1d", count=750,
                       adjust="forward", to_dataframe=True)
for s, k in data.items():
    k = k.sort_values("trade_date"); k["dt"] = pd.to_datetime(k["trade_date"])
    m = k.set_index("dt")["close"].resample("ME").last().pct_change().dropna()
    print(s, round(gain_to_pain(m), 3))

实测:000001.SZ 0.512、601318.SH 0.428,均为正且明显优于茅台的 −0.227——同期这两只「每单位痛苦换来的净收益」为正,持有体验更好。

参数与字段说明

参数/概念含义备注
adjust="forward"前复权必须,除权缺口会制造假亏损
resample("ME")月末重采样月度口径更贴合持有感受
分子所有收益之和含正负,净收益
分母(pain)下跌期亏损绝对值和只累计负的部分
GPR分子 ÷ 分母>1 优秀,<0 区间整体亏损

关键坑与注意事项

常见问题(FAQ)

Q:盈亏痛苦比和夏普、Omega 什么关系? A:都是风险调整收益。夏普用均值/标准差(惩罚上下行波动);Omega 用阈值上下面积比;GPR 最朴素——总净收益 ÷ 总亏损,只惩罚下行,解释最直观。

Q:Schwager 的 GPR 和这里一样吗? A:核心一致(收益和 ÷ 亏损绝对值和)。有的版本分母只用月度负收益、有的减去无风险基准,口径略有差异,自己对比时统一即可。

Q:需要付费吗? A:单只/几只股票日线在免费额度内即可;若要对全市场批量算 GPR 排序选「体验最好」的票,需要 klines.batch + universes(Starter 及以上),详见官网定价页。

小结

盈亏痛苦比用「总净收益 ÷ 总亏损」把「值不值这份煎熬」说成一个数,比夏普更直观、只惩罚下行。有了 AlphaFeed 的前复权数据,聚合月收益后一个函数就能算,还能一键横向对比——记住统一频率与区间、它可以为负。

相关链接:


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