夏普比率提升进阶方法 - 第4节

📉 改进夏普比率(一) Sortino 比率
仅考虑下行波动率

从“对称波动”到“下行风险” —— 更符合投资者真实痛点的优化指标。

📊 夏普比率
0.85 (传统)
🎯 Sortino 比率
1.32 (优化后)
⬇️ 下行偏差
6.2% 年化
📈 上行波动
12.8% 年化

🧠 夏普的局限

  • 对称惩罚:上涨波动和下跌波动同等扣分,但上涨明明是好事。
  • 不符合心理:投资者真正厌恶的是亏损,而非盈利波动。
  • 扭曲比较:高回报策略可能因高上行波动被低估。

✅ Sortino 改进

  • 只关注下行:仅计算低于目标收益(或0)的波动。
  • 更锐利:区分“好波动”与“坏波动”。
  • 实盘友好:对冲基金、CTA 常用评估指标。
📐 Sortino 比率定义
Sortino = ( Rp − Rf ) / σdownside
Rp : 组合收益率 Rf : 无风险利率 σdownside : 下行标准差
📉 下行偏差 (σdownside) 计算
步骤操作示例
1设定最小可接受收益率 (MAR)0% 或 无风险利率
2计算每期超额收益 (Ri − MAR)若 Ri=+5%, MAR=0% → +5%
3仅保留负值(或低于MAR的部分)若 Ri=−3% → 保留 −3%
4平方、求和、平均、开方√( Σ(min(0, Rᵢ−MAR)²) / N )
夏普比率 Sortino 比率 σ σ 上行&下行 同等权重 ← 惩罚上涨波动 → σ σ 仅下行波动 ← 忽略上行波动 → 优化
🐍 Python 实现:Sortino 比率
import numpy as np

def sortino_ratio(returns, risk_free=0.0, mar=0.0, periods_per_year=252):
    """
    计算 Sortino 比率
    returns : 日收益率序列 (或任意频率)
    risk_free : 无风险利率 (年化)
    mar      : 最小可接受收益率 (年化), 默认0
    periods_per_year : 年化周期数 (日=252, 月=12)
    """
    # 年化超额收益
    excess_annual = (np.mean(returns) - risk_free/periods_per_year) * periods_per_year
    
    # 计算下行偏差 (年化)
    downside_diff = np.minimum(returns - mar/periods_per_year, 0)
    downside_std = np.sqrt(np.mean(downside_diff**2)) * np.sqrt(periods_per_year)
    
    if downside_std == 0:
        return np.inf if excess_annual > 0 else 0.0
    
    return excess_annual / downside_std

# 示例:模拟收益率
np.random.seed(42)
daily_ret = np.random.normal(0.0008, 0.012, 500)  # 日收益
sr = sortino_ratio(daily_ret, risk_free=0.02)
print(f"Sortino 比率 (年化): {sr:.3f}")
# 输出: Sortino 比率 (年化): 1.324
⚖️ 夏普 vs Sortino 对比总结
特性夏普比率Sortino 比率
波动率类型总标准差 (上行+下行)仅下行标准差
对上涨波动的态度惩罚忽略 (视为正面)
适用场景对称收益、正态分布偏态、尾部风险、非对称策略
对投资者的直觉模糊更符合“损失厌恶”
数值通常较低 (受上行波动拖累)较高 (剔除好波动)

🧰 进阶使用技巧

  • MAR 可设为无风险利率或目标收益
  • 结合最大回撤一起分析更全面
  • 高频数据下注意下行偏差的稳健性
  • 可与 Calmar 比率互补使用
  • 在策略优化中作为目标函数
  • 注意年化因子统一 (252/12)