别再只盯着收益率了!用Python实战计算夏普比率与最大回撤,手把手教你评估策略好坏

张开发
2026/4/21 15:14:21 15 分钟阅读

分享文章

别再只盯着收益率了!用Python实战计算夏普比率与最大回撤,手把手教你评估策略好坏
别再只盯着收益率了用Python实战计算夏普比率与最大回撤手把手教你评估策略好坏当你兴冲冲地跑出一个年化20%的策略时先别急着开香槟。去年有位朋友在比特币暴涨时开发了一套突破追涨策略回测显示年化收益高达380%结果实盘三个月就亏掉了60%本金——他忽略了一个致命问题策略的最大回撤高达75%。这就像开车只盯着时速表不看油量表收益率只是量化策略的冰山一角。1. 从收益率到风险调整收益量化老手的评估框架新手看收益率曲线老手看风险调整后收益。2018年量化对冲基金行业有个经典案例两只年化收益相近的策略A策略夏普比率1.2B策略0.6三年后A策略管理规模增长5倍B策略却被清盘。这就是风险调整收益的魔力。1.1 收益率计算的三个关键变形简单收益率是最直观的计算方式def simple_return(prices): return prices.pct_change().dropna()但专业机构更青睐对数收益率特别是在多期复合计算时import numpy as np def log_returns(prices): return np.log(prices / prices.shift(1)).dropna()为什么选择对数收益率假设某股票三天价格序列为[100, 105, 99]计算方式第1天收益第2天收益总收益简单收益率5%-5.71%-1.0%对数收益率4.88%-5.89%-1.01%当收益率较小时两者差异不大但在高频交易或极端波动时对数收益率的可加性优势就显现出来了。1.2 年化收益率的陷阱与真相很多量化新手容易犯的错误是简单地将月收益乘以12# 错误示范 monthly_return 0.05 naive_annualized monthly_return * 12 # 得出60%的荒谬结论 # 正确做法 cum_return (1 monthly_return)**12 - 1 # 实际年化79.6%对于日频数据专业机构使用几何年化公式def annualize_returns(daily_returns, periods252): compounded (1 daily_returns).prod() return compounded**(periods/len(daily_returns)) - 1注意中国A股通常按242个交易日计算加密货币市场则按365天。参数选择不当会导致15%以上的计算偏差。2. 风险指标比收益率更重要的维度2.1 波动率——收益的孪生阴影波动率计算看似简单但细节决定成败def volatility(returns, annualizeTrue): std returns.std() return std * np.sqrt(252) if annualize else std常见错误包括使用简单收益率计算波动率导致低估忽略收益率序列的自相关性错误设定年化因子股票/加密货币不同2.2 最大回撤策略的生死线2015年股灾期间很多CTA策略虽然最终年化收益为正但最大回撤超过30%导致被强制平仓。计算最大回撤需要动态跟踪峰值def max_drawdown(prices): peak prices.expanding().max() drawdown (peak - prices)/peak return drawdown.max()一个更高效的向量化实现def max_drawdown_fast(prices): i np.argmax(np.maximum.accumulate(prices) - prices) j np.argmax(prices[:i]) return (prices[j] - prices[i]) / prices[j]3. 夏普比率被误解的圣杯3.1 标准夏普比率的Python实现def sharpe_ratio(returns, risk_free0, periods252): excess returns - risk_free/periods return np.sqrt(periods) * excess.mean() / excess.std()参数选择要点无风险利率可用SHIBOR或国债收益率年化系数日频252周频52样本量至少需要200个交易日数据3.2 夏普比率的五个认知误区越高越好谬误某加密货币策略夏普3.0但回撤50% —— 可能隐藏了极端风险跨品种比较谬误股票与债券策略的夏普不可直接对比频率谬误日频计算的夏普通常比月频高30-50%幸存者偏差回测中的夏普往往比实盘高2-3倍非线性风险期权策略可能呈现虚假的高夏普4. 进阶指标索提诺比率与Calmar比率4.1 索提诺比率专注下行风险def sortino_ratio(returns, target0, periods252): downside returns[returns target] if len(downside) 1: return np.nan downside_risk downside.std() * np.sqrt(periods) return np.sqrt(periods) * (returns.mean() - target)/downside_risk适用场景对比策略类型夏普比率索提诺比率趋势跟踪1.21.5均值回归1.10.9高频做市2.31.84.2 Calmar比率收益回撤比def calmar_ratio(prices, periods252): returns prices.pct_change().dropna() annual_return annualize_returns(returns, periods) max_dd max_drawdown(prices) return annual_return / abs(max_dd)实战经验值参考1淘汰策略1-3普通策略3优秀策略5. 构建完整的策略评估报告5.1 指标综合对比表def evaluate_strategy(prices, risk_free0): returns log_returns(prices) return { Annualized Return: annualize_returns(returns), Volatility: volatility(returns), Sharpe Ratio: sharpe_ratio(returns, risk_free), Sortino Ratio: sortino_ratio(returns), Max Drawdown: max_drawdown(prices), Calmar Ratio: calmar_ratio(prices) }示例输出指标策略A策略B基准年化收益18.7%22.3%9.5%波动率15.2%28.6%12.1%夏普比率(无风险3%)1.230.810.54最大回撤-24%-47%-33%5.2 可视化分析技巧使用matplotlib绘制收益-风险散点图import matplotlib.pyplot as plt def plot_risk_reward(metrics): plt.scatter(metrics[Volatility], metrics[Annualized Return], cmetrics[Sharpe Ratio], cmapviridis) plt.colorbar(labelSharpe Ratio) plt.xlabel(Volatility) plt.ylabel(Annualized Return)在实盘前建议用蒙特卡洛模拟生成1000组随机参数组合观察策略在参数空间中的稳定性。去年有个网格交易策略在最优参数下夏普达2.1但参数敏感性分析显示90%区域的夏普低于0.5——这种策略实盘大概率失效。

更多文章