Skip to content

夏普比率与风险收益

为什么需要夏普比率

假设有两个策略:

  • 策略A:年化收益率20%,年化波动率30%
  • 策略B:年化收益率15%,年化波动率10%

哪个策略更好?如果只看收益率,A更好。但如果考虑到风险,B明显更优——B用少得多的波动换取了可观的收益。

这就是夏普比率要解决的问题:如何衡量策略的"性价比"——每承担一单位风险,能获得多少收益补偿?

在投资领域,收益和风险永远是硬币的两面。任何收益都伴随着风险,问题在于这个风险是否"值得"。夏普比率正是量化这个"值不值得"的工具。

夏普比率的定义与公式

夏普比率(Sharpe Ratio)由诺贝尔经济学奖得主威廉·夏普(William F. Sharpe)于1966年提出,是衡量风险调整后收益的最广泛使用的指标。

公式

夏普比率 = (Rp - Rf) / σp

其中:

  • Rp(Return of Portfolio):策略的年化收益率
  • Rf(Risk-Free Rate):无风险利率
  • σp(Standard Deviation of Portfolio):策略年化收益率的标准差(即年化波动率)
  • Rp - Rf:超额收益(Excess Return),即策略收益中超过无风险收益的部分

分子(超额收益)衡量的是策略比"无风险投资"多赚了多少,分母(波动率)衡量的是赚这些超额收益承受了多少波动。两者相除,就得到了"每单位风险对应的超额收益"。

直观理解

你可以把夏普比率类比为生活中的"性价比":

  • 买手机:花3000元买到的功能 vs 花费的钱 → 性价比
  • 投资:承担的风险换来的超额收益 → 夏普比率

夏普比率高,意味着策略的"风险性价比"好——用较少的风险波动换取了较多的超额收益。

无风险利率的选择

在计算夏普比率时,需要确定无风险利率的值。不同场景下的选择:

  • A股回测:通常使用一年期国债收益率,约2%左右;或使用银行间7天质押式回购利率(DR007)
  • 美国市场:通常使用3个月国债收益率
  • 简化计算:有时直接取0,这样夏普比率简化为 Rp / σp
python
# 计算夏普比率
import numpy as np

def sharpe_ratio(daily_values, risk_free_rate=0.02, trading_days_per_year=252):
    """
    计算夏普比率

    Parameters:
        daily_values: 每日净值序列
        risk_free_rate: 年化无风险利率(默认2%)
        trading_days_per_year: 每年交易日数(默认252)

    Returns:
        夏普比率
    """
    # 计算每日收益率
    daily_returns = np.diff(daily_values) / daily_values[:-1]

    # 日化无风险利率
    daily_rf = (1 + risk_free_rate) ** (1 / trading_days_per_year) - 1

    # 每日超额收益率
    excess_returns = daily_returns - daily_rf

    # 夏普比率 = 平均超额收益 / 超额收益标准差 × sqrt(252)
    if excess_returns.std() == 0:
        return 0.0

    sharpe = excess_returns.mean() / excess_returns.std() * np.sqrt(trading_days_per_year)

    return sharpe

上面代码中的关键点是最后的年化处理。为什么需要乘以 sqrt(252)

这是因为:如果我们用日频数据计算,得到的是日夏普比率。年化夏普比率的推导如下:

年化超额收益 = 日均超额收益 × 252
年化波动率 = 日波动率 × sqrt(252)

年化夏普比率 = 年化超额收益 / 年化波动率
            = (日均超额收益 × 252) / (日波动率 × sqrt(252))
            = (日均超额收益 / 日波动率) × sqrt(252)
            = 日夏普比率 × sqrt(252)

所以从日频数据计算年化夏普比率时,只需要将日夏普比率乘以 sqrt(252) 即可。

夏普比率的参考标准

以下是业界普遍接受的夏普比率评价标准:

夏普比率评价说明
< 0策略收益不及无风险利率,不如把钱存银行
0 ~ 0.5较差风险补偿不足,承担的风险没有得到足够回报
0.5 ~ 1.0一般可接受但不算好,很多公募基金在这个范围
1.0 ~ 2.0不错优秀的策略,大多数顶尖量化基金的目标
2.0 ~ 3.0优秀非常出色的风险调整收益
> 3.0卓越极其优秀,但需要仔细验证是否存在过拟合

现实中的夏普比率

为了让你对夏普比率有更直观的感受,以下是一些现实中的参考:

  • 沪深300指数:长期夏普比率大约在0.3-0.6之间(取决于计算时段)
  • 优秀公募基金:长期夏普比率大约在0.5-1.0之间
  • 顶尖量化私募:长期夏普比率大约在1.0-2.0之间
  • 文艺复兴大奖章基金(Medallion Fund):据说长期夏普比率超过2.0

需要注意的是,上面提到的顶尖基金的夏普比率是长期实盘业绩。在回测中,如果你得到超过3.0的夏普比率,首先应该怀疑是否存在过拟合或其他问题,而不是沾沾自喜。

夏普比率的计算示例

下面通过一个完整的例子演示夏普比率的计算。

python
import numpy as np
import pandas as pd

# 模拟一个策略的每日净值(252个交易日,约1年)
np.random.seed(42)
initial_value = 1.0
daily_returns = np.random.normal(0.0008, 0.015, 252)  # 日均收益0.08%,日波动率1.5%
daily_values = initial_value * np.cumprod(1 + daily_returns)

# 计算各项参数
ann_return = (daily_values[-1] / daily_values[0]) ** (252 / len(daily_values)) - 1
ann_volatility = daily_returns.std() * np.sqrt(252)
risk_free_rate = 0.02

sharpe = (ann_return - risk_free_rate) / ann_volatility

print(f"年化收益率: {ann_return:.2%}")
print(f"年化波动率: {ann_volatility:.2%}")
print(f"无风险利率: {risk_free_rate:.2%}")
print(f"夏普比率:   {sharpe:.2f}")

输出示例:

年化收益率: 18.25%
年化波动率: 23.81%
无风险利率: 2.00%
夏普比率:   0.68

这个策略的夏普比率为0.68,处于"一般"水平——虽然跑赢了无风险收益,但考虑到23.81%的年化波动率,风险补偿不算充分。

影响夏普比率的因素

理解哪些因素会影响夏普比率,有助于你有针对性地改进策略。

因素一:提高超额收益(分子)

提高策略的平均收益率可以直接提高夏普比率。常见方法:

  • 优化入场和出场时机,提高策略的胜率和盈亏比
  • 加入更有效的因子或信号
  • 提高资金使用效率(避免长期空仓)

因素二:降低波动率(分母)

降低收益率的波动同样可以提高夏普比率,甚至效果更明显:

  • 分散投资:持有多个不相关或低相关的资产,可以有效降低组合波动率
  • 仓位管理:控制单次交易的仓位大小,避免过度集中
  • 动态调仓:在市场波动加大时适当降低仓位

一个简单但有效的方法是将多个相关性低的策略组合在一起:

python
# 两个策略组合后的波动率变化
strategy_a_vol = 0.20  # 策略A年化波动率20%
strategy_b_vol = 0.20  # 策略B年化波动率20%
correlation = 0.3       # 两策略收益相关性

# 组合波动率(等权重)
portfolio_vol = np.sqrt(
    0.5**2 * strategy_a_vol**2 +
    0.5**2 * strategy_b_vol**2 +
    2 * 0.5 * 0.5 * correlation * strategy_a_vol * strategy_b_vol
)
# portfolio_vol ≈ 0.162,低于单个策略的0.20

# 如果两策略的年化收益都是15%
portfolio_return = 0.15
sharpe_a = (0.15 - 0.02) / 0.20  # = 0.65
sharpe_portfolio = (0.15 - 0.02) / 0.162  # = 0.80

print(f"单个策略夏普: {sharpe_a:.2f}")
print(f"组合后夏普:   {sharpe_portfolio:.2f}")

通过组合两个低相关策略,夏普比率从0.65提升到0.80。这就是分散投资的力量。

因素三:时间尺度

夏普比率的计算结果与数据频率有关。使用日频数据、周频数据或月频数据计算出的夏普比率可能略有差异。一般来说:

  • 日频数据最常用,计算结果也最稳定
  • 月频数据受个别异常月影响较大
  • 年频数据样本量太少,统计意义不大

夏普比率的局限性

夏普比率虽然是最广泛使用的风险调整收益指标,但它有几个重要的局限性,使用者必须了解。

局限性一:假设收益服从正态分布

夏普比率用标准差来衡量风险,这隐含了一个假设——收益率服从正态分布(钟形曲线)。但实际市场中:

  • 收益率分布存在尖峰厚尾(Fat Tails):极端亏损和极端盈利出现的频率比正态分布预测的要高
  • 收益率分布可能是偏斜的(Skewed):某些策略(如卖出期权策略)的收益分布严重左偏

这意味着夏普比率可能会低估极端风险。一个策略的夏普比率看起来不错,但可能在极端行情下遭受远超预期的大亏损。

python
# 举例:卖出看涨期权策略的收益特征
# 大部分时间:稳定赚取期权费 → 高夏普比率
# 极端情况:偶尔巨额亏损 → 标准差无法充分反映风险
# 这类策略的夏普比率可能虚高

局限性二:对上行波动和下行波动一视同仁

夏普比率的分母是总波动率,它把上涨的波动和下跌的波动同等对待。但从投资者的角度来看,上涨的波动是"好"的(赚钱了),下跌的波动才是"坏"的(亏钱了)。

一个策略如果有大量大幅上涨和小幅下跌,其波动率可能很高,导致夏普比率偏低——但这显然不是一个差策略。夏普比率无法区分"好的波动"和"坏的波动"。

局限性三:对短期数据敏感

如果回测时间很短(比如只有3个月),夏普比率的估计会非常不稳定。短时间内的市场行情可能比较特殊(比如碰上一波大牛市),导致夏普比率虚高或虚低。

一般来说,至少需要2-3年的数据,夏普比率才有一定的统计参考价值。

局限性四:不适用于非线性策略

对于包含期权等非线性衍生品的策略,或者有复杂仓位管理的策略,收益分布远非正态。此时夏普比率可能严重失真。

Sortino比率——夏普比率的改进

为了解决夏普比率"对上行和下行波动一视同仁"的问题,Sortino比率应运而生。

定义

Sortino比率(Sortino Ratio)由 Frank Sortino 提出,它只考虑下行波动(Downside Deviation)作为风险的度量。

公式

Sortino比率 = (Rp - Rf) / σd

其中:

  • Rp:策略的年化收益率
  • Rf:无风险利率(或称为最低可接受回报 MAR, Minimum Acceptable Return)
  • σd:下行波动率,只计算低于目标收益率的部分

下行波动率的计算

python
def downside_deviation(returns, target_return=0):
    """
    计算下行波动率

    Parameters:
        returns: 收益率序列
        target_return: 目标收益率(低于此值的才计入下行波动)

    Returns:
        下行波动率
    """
    # 只取低于目标收益率的值,其余设为0
    downside = np.minimum(returns - target_return, 0)
    return np.sqrt(np.mean(downside ** 2))

def sortino_ratio(daily_values, risk_free_rate=0.02, trading_days_per_year=252):
    """计算Sortino比率"""
    daily_returns = np.diff(daily_values) / daily_values[:-1]

    # 日化无风险利率
    daily_rf = (1 + risk_free_rate) ** (1 / trading_days_per_year) - 1

    # 年化超额收益
    excess_return = (daily_values[-1] / daily_values[0]) ** (trading_days_per_year / len(daily_values)) - 1 - risk_free_rate

    # 下行波动率(年化)
    dd = downside_deviation(daily_returns, daily_rf)
    annualized_dd = dd * np.sqrt(trading_days_per_year)

    if annualized_dd == 0:
        return float('inf')

    return excess_return / annualized_dd

Sortino比率与夏普比率的对比

python
# 对比两种策略
np.random.seed(42)

# 策略A:收益对称分布
returns_a = np.random.normal(0.001, 0.02, 252)
values_a = np.cumprod(1 + returns_a)

# 策略B:正偏分布(大涨小跌)
positive_returns = np.random.exponential(0.01, 252)
negative_returns = -np.random.exponential(0.005, 252)
mask = np.random.random(252) > 0.4
returns_b = np.where(mask, positive_returns, negative_returns)
values_b = np.cumprod(1 + returns_b)

# 计算夏普和Sortino
sharpe_a = sharpe_ratio(values_a)
sharpe_b = sharpe_ratio(values_b)
sortino_a = sortino_ratio(values_a)
sortino_b = sortino_ratio(values_b)

print(f"策略A - 夏普: {sharpe_a:.2f}, Sortino: {sortino_a:.2f}")
print(f"策略B - 夏普: {sharpe_b:.2f}, Sortino: {sortino_b:.2f}")

Sortino比率通常高于夏普比率,因为它只惩罚下行波动。如果一个策略的Sortino比率显著高于夏普比率,说明该策略的上行波动占比更大——这是个好信号。

何时使用Sortino比率

  • 当策略的收益分布明显偏斜时(不对称)
  • 当你更关心下行风险而非总体波动时
  • 当评估趋势跟踪策略时(通常正偏分布)

其他风险调整收益指标

除了夏普比率和Sortino比率,还有几个值得关注的风险调整指标。

信息比率(Information Ratio)

信息比率 = (策略收益率 - 基准收益率) / 跟踪误差

信息比率衡量的是策略相对于基准的超额收益的稳定性。跟踪误差(Tracking Error)是策略收益与基准收益之间差异的标准差。

Omega比率

Omega比率考虑了收益分布的全部信息(而非只考虑均值和标准差),通过计算正收益区域的"面积"与负收益区域的"面积"之比来衡量策略质量。

卡玛比率(Calmar Ratio)

上一章已经介绍过,卡玛比率 = 年化收益率 / 最大回撤。它用最大回撤而非波动率来衡量风险,更加直观。

实战建议

如何正确使用夏普比率

  1. 作为筛选工具:用夏普比率初步筛选策略。低于0.5的策略可以排除,节省深入研究的时间。
  2. 横向比较:用夏普比率比较不同策略的风险收益效率,而非孤立地看某个策略的绝对值。
  3. 结合其他指标:夏普比率不应单独使用。始终结合最大回撤、胜率、盈亏比等指标综合判断。
  4. 关注稳定性:看夏普比率在不同时段是否稳定。如果滚动1年的夏普比率波动很大,说明策略不够稳健。

滚动夏普比率

滚动夏普比率(Rolling Sharpe Ratio)可以帮助你了解夏普比率随时间的变化情况:

python
def rolling_sharpe(daily_values, window=252, risk_free_rate=0.02):
    """计算滚动夏普比率"""
    daily_returns = np.diff(daily_values) / daily_values[:-1]
    daily_rf = (1 + risk_free_rate) ** (1 / 252) - 1
    excess_returns = daily_returns - daily_rf

    rolling_sharpe_values = []
    for i in range(window, len(excess_returns)):
        window_excess = excess_returns[i - window:i]
        if window_excess.std() == 0:
            rolling_sharpe_values.append(0)
        else:
            rs = window_excess.mean() / window_excess.std() * np.sqrt(252)
            rolling_sharpe_values.append(rs)

    return rolling_sharpe_values

如果滚动夏普比率一直稳定在1.0以上,说明策略持续有效。如果某个时段突然大幅下降甚至转负,需要警惕策略可能在该市场环境下失效。

总结

夏普比率是衡量策略风险调整收益的核心工具,但不是万能的。正确的做法是:

  1. 理解夏普比率的计算方法和含义
  2. 知道它的局限性(正态分布假设、上下行波动不区分等)
  3. 结合Sortino比率、最大回撤、Calmar比率等指标综合评价
  4. 使用滚动指标观察策略表现的稳定性
  5. 始终将回测指标与实盘表现进行对比验证

记住:任何单一指标都无法全面评价一个策略。好的策略评价应该是多维度、多指标的。

仅供学习交流,不构成任何投资建议