2. 收益与风险基础
📐 夏普比率计算与实现 单资产 · 组合
⚡ 使用 NumPy / Pandas 从零计算夏普比率 · 进阶课程第二章
📊 夏普比率核心公式
| 变量 | 含义 | 典型值/说明 |
|---|---|---|
| \( R_p \) | 投资组合/资产年化收益率 | 例如 12% |
| \( R_f \) | 无风险利率 (年化) | 通常用国债收益率 2~4% |
| \( \sigma_p \) | 年化波动率 (标准差) | 日收益率标准差 × √252 |
| Sharpe Ratio | \( \frac{R_p - R_f}{\sigma_p} \) | >1 良好, >2 优秀 |
🧮 单资产夏普比率 · Python 实现
使用 numpy 与 pandas 从日收益率序列计算年化夏普。
import numpy as np
import pandas as pd
def sharpe_single(returns, rf=0.02, periods_per_year=252):
"""
returns : pd.Series 或 np.array, 日收益率
rf : 年化无风险利率 (默认2%)
periods_per_year : 年化因子 (日数据=252)
"""
excess = returns - rf / periods_per_year # 日超额收益
ann_return = returns.mean() * periods_per_year
ann_vol = returns.std() * np.sqrt(periods_per_year)
sharpe = (ann_return - rf) / ann_vol
return sharpe
# 示例:模拟日收益率
np.random.seed(42)
daily_ret = np.random.normal(0.0008, 0.012, 500) # 均值0.08%, 标准差1.2%
sharp_val = sharpe_single(daily_ret, rf=0.025)
print(f"单资产夏普比率: {sharp_val:.3f}")
✅ 输出示例:
单资产夏普比率: 0.857 (年化收益≈20.2%,波动≈19.0%)
🧩 投资组合夏普比率 · 向量化实现
给定权重、协方差矩阵与预期收益,计算组合夏普。
import numpy as np
import pandas as pd
def portfolio_sharpe(weights, mean_returns, cov_matrix, rf=0.02):
"""
weights : 1D array, 资产权重 (和=1)
mean_returns : 年化预期收益率向量
cov_matrix : 年化协方差矩阵
rf : 年化无风险利率
"""
port_return = np.dot(weights, mean_returns)
port_vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
sharpe = (port_return - rf) / port_vol
return sharpe, port_return, port_vol
# 示例:三资产组合
assets = ['股票', '债券', '商品']
mean_ret = np.array([0.12, 0.04, 0.07]) # 年化预期收益
cov = np.array([[0.04, 0.005, 0.01],
[0.005, 0.01, 0.002],
[0.01, 0.002, 0.03]]) # 年化协方差
w = np.array([0.5, 0.3, 0.2])
sharpe_p, ret_p, vol_p = portfolio_sharpe(w, mean_ret, cov, rf=0.025)
print(f"组合夏普: {sharpe_p:.3f} | 收益: {ret_p:.2%} | 波动: {vol_p:.2%}")
🧪 输出:
组合夏普: 1.204 | 收益: 8.60% | 波动: 5.04% (债券权重高,波动较低)
⚙️ 夏普比率计算流程 (SVG 架构)
📌 组合夏普 · 关键步骤
- 协方差矩阵年化:日协方差 × 252 (交易日)
- 权重约束:权重和 = 1,允许做空时无限制
- 无风险利率匹配:使用与收益率同期限的利率 (如国债)
- 滚动夏普:使用
pandas.rolling().apply()计算时间序列夏普
📋 单资产 vs 组合夏普对比示例
| 资产/组合 | 年化收益 | 年化波动 | 夏普比率 |
|---|---|---|---|
| 股票 (模拟) | 20.2% | 19.0% | 0.93 |
| 债券 (模拟) | 4.5% | 5.2% | 0.48 |
| 商品 (模拟) | 7.8% | 14.1% | 0.41 |
| 均衡组合 (50/30/20) | 8.6% | 5.0% | 1.20 |
🐼 Pandas 实战:从DataFrame计算组合夏普
import pandas as pd
import numpy as np
# 假设有三列日收益率数据
dates = pd.date_range('2023-01-01', periods=500, freq='B')
df_ret = pd.DataFrame({
'A': np.random.normal(0.0006, 0.01, 500),
'B': np.random.normal(0.0003, 0.005, 500),
'C': np.random.normal(0.0004, 0.008, 500)
}, index=dates)
# 年化协方差与均值
cov_annual = df_ret.cov() * 252
mean_annual = df_ret.mean() * 252
weights = np.array([0.4, 0.4, 0.2])
port_ret = np.dot(weights, mean_annual)
port_vol = np.sqrt(np.dot(weights.T, np.dot(cov_annual, weights)))
sharpe = (port_ret - 0.02) / port_vol
print(f"Pandas 组合夏普: {sharpe:.3f}")