多套AI策略夏普比率,最大回撤批量计算程序,自动横向排名。
多策略夏普比率与最大回撤批量计算及横向排名工具定位策略研发阶段的「多策略横向对比与筛选」工具适用课程实验、策略竞赛、多因子模型对比语言Python 3.8一、实际应用场景描述在《智能证券投资》课程或实际量化研究中一个常见场景是我有 10 套策略到底哪套最好具体来说研究者可能需要1. 同时维护多套策略不同因子组合、不同参数、不同模型2. 每套策略都有回测结果日收益率序列3. 需要从 风险调整后收益 的角度进行横向对比4. 最终选出 综合表现最优 的 1~3 套策略如果手动逐个算夏普比率、最大回撤再人工排序既低效又容易出错。二、引入痛点 痛点 1指标口径不一致问题 后果有的算算术夏普有的算对数夏普 不可比有的年化用 252有的用 365 结果偏差有的用无风险利率有的不用 口径混乱 不同策略的好没有统一标准 痛点 2批量计算重复劳动- 10 套策略 10 次手动计算- 每次改因子或参数全部重算- 没有自动化脚本 研究效率极低 痛点 3排名维度单一- 只看收益率 → 忽略风险- 只看夏普 → 忽略回撤- 没有综合评分 最好的定义模糊三、核心逻辑讲解✅ 夏普比率Sharpe Ratio衡量 每承受一单位风险获得多少超额收益SR (策略日均收益 - 无风险利率) / 策略收益波动率 × √交易日数夏普值 解读 0 跑输无风险利率0 ~ 1 一般1 ~ 2 较好 2 优秀需警惕过拟合✅ 最大回撤Maximum Drawdown衡量 从历史最高点到最低点的最大跌幅回撤_t (净值_t - 历史最高净值) / 历史最高净值最大回撤 min(回撤_t)最大回撤 解读 5% 非常稳健5% ~ 15% 正常15% ~ 25% 偏高 25% 高风险✅ 综合排名机制采用 百分位打分法Percentile Ranking综合得分 w1 × 夏普百分位排名 w2 × 回撤百分位排名夏普越高越好回撤越低越好两者加权得到综合排名。四、代码模块化实现 项目结构strategy_comparison/│├── config.py # 参数配置├── data_loader.py # 数据加载├── metrics.py # 指标计算夏普、回撤├── ranker.py # 横向排名与综合评分├── reporter.py # 报告生成与可视化├── main.py # 程序入口└── README.mdconfig.py# config.pyfrom pathlib import Pathfrom datetime import date# 数据目录DATA_DIR Path(__file__).parent / data# 回测参数START_DATE date(2020, 1, 1)END_DATE date(2024, 12, 31)RISK_FREE_RATE 0.0 # 无风险利率日化设为 0 表示计算超额收益版ANNUALIZE_FACTOR 252 # 年化因子A 股交易日约 252 天# 综合排名权重SHARPE_WEIGHT 0.5 # 夏普比率权重DRAWDOWN_WEIGHT 0.5 # 最大回撤权重绝对值越大越差# 策略文件命名规则# data/returns/strategy_{name}.csv# 字段date, returndata_loader.py# data_loader.pyimport pandas as pdfrom pathlib import Pathfrom config import DATA_DIR, START_DATE, END_DATEdef load_strategy_returns(strategy_name: str) - pd.Series:加载单套策略的日收益率序列Args:strategy_name: 策略名称对应文件名 strategy_{name}.csvReturns:以 date 为索引的 return 序列file_path DATA_DIR / returns / fstrategy_{strategy_name}.csvif not file_path.exists():raise FileNotFoundError(f策略文件不存在: {file_path})df pd.read_csv(file_path, parse_dates[date])df df.set_index(date)[return]# 按日期范围过滤mask (df.index START_DATE) (df.index END_DATE)df df[mask]return df.sort_index()def load_all_strategies(strategy_names: list[str]) - dict[str, pd.Series]:批量加载多套策略的收益率数据Returns:{策略名: 日收益率 Series}results {}for name in strategy_names:try:results[name] load_strategy_returns(name)print(f ✓ 已加载策略: {name} ({len(results[name])} 个交易日))except FileNotFoundError as e:print(f ✗ 跳过策略: {name}文件不存在)print(f\n[数据加载] 共加载 {len(results)} 套策略\n)return resultsmetrics.py# metrics.pyimport numpy as npimport pandas as pdfrom config import RISK_FREE_RATE, ANNUALIZE_FACTORdef calc_sharpe_ratio(returns: pd.Series) - float:计算年化夏普比率公式: SR (E[R] - Rf) / σ(R) × √Tif len(returns) 2:return np.nanexcess_returns returns - RISK_FREE_RATEmean_excess excess_returns.mean()std_excess excess_returns.std()if std_excess 0:return np.nandaily_sharpe mean_excess / std_excessannualized_sharpe daily_sharpe * np.sqrt(ANNUALIZE_FACTOR)return float(annualized_sharpe)def calc_max_drawdown(returns: pd.Series) - float:计算最大回撤负值如 -0.15 表示 15%公式: MDD min((净值_t - 历史最高净值) / 历史最高净值)if len(returns) 2:return np.nannav (1 returns).cumprod() # 累积净值running_max nav.cummax() # 历史最高净值drawdown (nav - running_max) / running_max # 回撤序列return float(drawdown.min())def calc_total_return(returns: pd.Series) - float:计算总收益if len(returns) 1:return np.nanreturn float((1 returns).prod() - 1)def calc_win_rate(returns: pd.Series) - float:计算胜率if len(returns) 1:return np.nanreturn float((returns 0).mean())def calc_annualized_return(returns: pd.Series) - float:计算年化收益if len(returns) 2:return np.nantotal_return (1 returns).prod() - 1n_days len(returns)annualized (1 total_return) ** (ANNUALIZE_FACTOR / n_days) - 1return float(annualized)def evaluate_strategy(returns: pd.Series, strategy_name: str) - dict:对单套策略计算全部绩效指标return {strategy: strategy_name,trading_days: len(returns),total_return: calc_total_return(returns),annualized_return: calc_annualized_return(returns),sharpe_ratio: calc_sharpe_ratio(returns),max_drawdown: calc_max_drawdown(returns),win_rate: calc_win_rate(returns),}ranker.py# ranker.pyimport numpy as npimport pandas as pdfrom config import SHARPE_WEIGHT, DRAWDOWN_WEIGHTdef rank_strategies(metrics_df: pd.DataFrame) - pd.DataFrame:对多套策略进行横向排名排名规则- 夏普比率降序排列越高越好- 最大回撤升序排列越小越好即越接近 0 越好- 综合得分加权平均df metrics_df.copy()# 1. 夏普比率排名降序 → 排名越小越好df[sharpe_rank] df[sharpe_ratio].rank(ascendingFalse, methodaverage)# 2. 最大回撤排名升序 → 回撤越小排名越靠前# 注意max_drawdown 是负数所以升序 绝对值越小越靠前df[drawdown_rank] df[max_drawdown].rank(ascendingTrue, methodaverage)# 3. 综合得分百分制# 将排名转换为百分位得分n len(df)df[sharpe_score] (n - df[sharpe_rank] 1) / n * 100df[drawdown_score] (n - df[drawdown_rank] 1) / n * 100# 4. 综合得分df[composite_score] (SHARPE_WEIGHT * df[sharpe_score] DRAWDOWN_WEIGHT * df[drawdown_score])# 5. 最终排名df[final_rank] df[composite_score].rank(ascendingFalse, methodmin)# 排序df df.sort_values(final_rank).reset_index(dropTrue)return dfdef format_metrics_df(df: pd.DataFrame) - pd.DataFrame:格式化输出formatted df[[final_rank, strategy, total_return, annualized_return,sharpe_ratio, max_drawdown, win_rate,sharpe_rank, drawdown_rank, composite_score]].copy()# 重命名列formatted.columns [综合排名, 策略名称, 总收益, 年化收益,夏普比率, 最大回撤, 胜率,夏普排名, 回撤排名, 综合得分]# 格式化数值formatted[总收益] formatted[总收益].apply(lambda x: f{x:.2%})formatted[年化收益] formatted[年化收益].apply(lambda x: f{x:.2%})formatted[夏普比率] formatted[夏普比率].apply(lambda x: f{x:.4f})formatted[最大回撤] formatted[最大回撤].apply(lambda x: f{x:.2%})formatted[胜率] formatted[胜率].apply(lambda x: f{x:.2%})formatted[综合得分] formatted[综合得分].apply(lambda x: f{x:.1f})return formattedreporter.py# reporter.pyimport pandas as pdimport numpy as npdef print_rankings(formatted_df: pd.DataFrame):打印排名表格print(\n * 90)print( 多策略夏普比率 最大回撤 横向排名)print( * 90)print(formatted_df.to_string(indexFalse))print( * 90)def print_summary(ranked_df: pd.DataFrame):打印摘要统计print(\n--- 摘要统计 ---)best_overall ranked_df.loc[ranked_df[final_rank].idxmin()]best_sharpe ranked_df.loc[ranked_df[sharpe_ratio].idxmax()]best_drawdown ranked_df.loc[ranked_df[max_drawdown].idxmax()]print(f综合最优策略: {best_overall[strategy]})print(f 夏普最优策略: {best_sharpe[strategy]} (SR{best_sharpe[sharpe_ratio]:.4f}))print(f 回撤最小策略: {best_drawdown[strategy]} (MDD{best_drawdown[max_drawdown]:.2%}))# 夏普分布sharpe_values ranked_df[sharpe_ratio].dropna()print(f\n夏普比率分布:)print(f 最高: {sharpe_values.max():.4f})print(f 最低: {sharpe_values.min():.4f})print(f 均值: {sharpe_values.mean():.4f})print(f 标准差: {sharpe_values.std():.4f})def export_to_csv(ranked_df: pd.DataFrame, filepath: str strategy_rankings.csv):导出完整结果到 CSVexport_df ranked_df.copy()export_df.to_csv(filepath, indexFalse, encodingutf-8-sig)print(f\n[导出] 完整结果已保存至: {filepath})main.py# main.pyimport pandas as pdfrom data_loader import load_all_strategiesfrom metrics import evaluate_strategyfrom ranker import rank_strategies, format_metrics_dffrom reporter import print_rankings, print_summary, export_to_csvdef main():# 配置区 # 策略名称列表对应 data/returns/strategy_{name}.csvSTRATEGY_NAMES [value_factor,momentum_factor,quality_factor,low_volatility,growth_factor,multi_factor_v1,multi_factor_v2,ml_lgbm,ml_xgboost,hybrid_smart,]# print( * 60)print( 多策略夏普比率 最大回撤 批量计算)print( * 60)# 1. 批量加载策略数据print(\n[第一步] 加载策略收益率数据...)strategies load_all_strategies(STRATEGY_NAMES)if len(strategies) 0:print(\n❌ 未加载到任何策略数据请检查 data/returns/ 目录)return# 2. 逐策略计算绩效指标print([第二步] 计算各策略绩效指标...)metrics_list []for name, returns in strategies.items():metrics evaluate_strategy(returns, name)metrics_list.append(metrics)metrics_df pd.DataFrame(metrics_list)# 3. 横向排名print([第三步] 执行横向排名...)ranked_df rank_strategies(metrics_df)# 4. 格式化输出formatted format_metrics_df(ranked_df)# 5. 打印报告print_rankings(formatted)print_summary(ranked_df)# 6. 导出export_to_csv(ranked_df)print(\n✅ 全部完成)if __name__ __main__:main()五、README 文件# 多策略夏普比率 最大回撤批量计算与横向排名工具## 功能- 批量计算多套策略的夏普比率和最大回撤- 自动横向排名支持加权综合评分- 输出标准化排名表格和摘要统计## 快速开始### 1. 准备数据在 data/returns/ 目录下放置各策略的日收益率文件strategy_value_factor.csv:date,return2020-01-02,0.01202020-01-03,-0.0050### 2. 配置策略列表编辑 main.py 中的 STRATEGY_NAMES 列表STRATEGY_NAMES [value_factor,momentum_factor,...]### 3. 运行pip install pandas numpypython main.py## 输出示例多策略夏普比率 最大回撤 横向排名综合排名 策略名称 总收益 年化收益 夏普比率 最大回撤 胜率1 hybrid_smart 45.20% 8.50% 1.5230 -12.30% 56.80%2 multi_factor_v2 38.60% 7.20% 1.4120 -14.10% 54.30%3 ml_lgbm 32.10% 6.10% 1.2800 -15.80% 52.90%...## 排名规则| 指标 | 方向 | 说明 ||---|---|---|| 夏普比率 | 越高越好 | 风险调整后收益 || 最大回撤 | 越低越好 | 下行风险控制 || 综合得分 | 加权平均 | 可配置权重 |默认权重夏普 50% 回撤 50%可通过 config.py 调整 SHARPE_WEIGHT 和 DRAWDOWN_WEIGHT六、核心知识点卡片【知识点卡片策略横向对比与排名】1️⃣ 夏普比率Sharpe Ratio- 衡量单位风险的超额收益- 年化公式SR_daily × √252- 局限性假设收益正态分布对肥尾不敏感2️⃣ 最大回撤Maximum Drawdown- 衡量极端下行风险- 比波动率更直观投资者更敏感- 局限性对回测起止时间敏感3️⃣ 百分位排名法- 将不同量纲的指标统一到同一尺度- 避免某单一指标主导排名- 加权方案可根据研究目标调整4️⃣ 多策略对比的注意事项- 确保所有策略使用相同的时间区间- 统一年化因子和交易日数- 注意幸存者偏差淘汰的策略是否被纳入对比- 样本外验证结果应单独标注七、免责声明与风险提示⚠️ 免责声明- 本程序仅供 学术研究与课程实验 使用- 不构成任何投资建议或投资依据- 排名结果仅反映历史回测表现⚠️ 风险提示- 历史夏普比率高 ≠ 未来表现好- 回测最大回撤可能被低估未考虑极端行情- 多策略排名可能受时间区间选择影响- 权重设置具有主观性不同权重可能导致不同排名- 建议结合样本外验证、滚动窗口分析综合判断八、总结本文构建了一个 多策略绩效指标批量计算与横向排名工具核心要点1. 批量计算一套代码覆盖所有策略避免重复劳动2. 统一口径年化因子、无风险利率、排名方法全部标准化3. 多维排名同时考虑夏普比率和最大回撤避免单一指标误导4. 可扩展可轻松加入 Sortino、Calmar、信息比率等指标核心原则选策略不是选回测最好看的而是选 风险调整后最稳健的。本文代码仅供学习与技术交流不构成任何投资建议股市有风险入市需谨慎利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛