import pandas as pd # 加载交易记录 df = pd.read_csv('../result/backtest_trades.csv') # 转换日期格式 df['open_date'] = pd.to_datetime(df['open_date']) df['close_date'] = pd.to_datetime(df['close_date']) # 计算持仓天数 df['holding_days'] = (df['close_date'] - df['open_date']).dt.total_seconds() / (60 * 60 * 24) print("=" * 60) print("📊 按交易对(币种)统计分析") print("=" * 60) # 按币种分组 grouped_by_pair = df.groupby('pair').agg( 总交易次数=('profit_abs', 'size'), 平均收益率=('profit_ratio', 'mean'), 累计收益=('profit_abs', 'sum'), 胜率=('profit_ratio', lambda x: (x > 0).mean()), 平均持仓时间_分钟=('trade_duration', 'mean') ) # 格式化输出 grouped_by_pair['平均收益率'] = grouped_by_pair['平均收益率'].map(lambda x: f"{x:.2%}") grouped_by_pair['胜率'] = grouped_by_pair['胜率'].map(lambda x: f"{x:.2%}") grouped_by_pair['累计收益'] = grouped_by_pair['累计收益'].round(4) grouped_by_pair['平均持仓时间_分钟'] = grouped_by_pair['平均持仓时间_分钟'].round(1) print(grouped_by_pair) print("\n📌 说明:") print(" • 总交易次数:该币种总共完成的交易笔数") print(" • 平均收益率:每笔交易的平均盈利比例(正为赚,负为亏)") print(" • 累计收益:所有交易加总的绝对收益(单位:币本位)") print(" • 胜率:盈利交易占总交易的比例") print(" • 平均持仓时间_分钟:平均每笔交易持有多少分钟") print("\n" + "=" * 60) print("🚪 按退出原因统计分析") print("=" * 60) # 按退出原因分组 grouped_by_exit = df.groupby('exit_reason').agg( 总交易次数=('profit_abs', 'size'), 平均收益率=('profit_ratio', 'mean'), 累计收益=('profit_abs', 'sum'), 胜率=('profit_ratio', lambda x: (x > 0).mean()) ) # 格式化输出 grouped_by_exit['平均收益率'] = grouped_by_exit['平均收益率'].map(lambda x: f"{x:.2%}") grouped_by_exit['胜率'] = grouped_by_exit['胜率'].map(lambda x: f"{x:.2%}") grouped_by_exit['累计收益'] = grouped_by_exit['累计收益'].round(4) print(grouped_by_exit) print("\n📌 说明:") print(" • exit_reason 含义参考:") print(" • roi: 达到 ROI 目标自动止盈") print(" • stop_loss: 触发止损") print(" • trailing_stop_loss: 移动止损出场") print(" • custom_exit: 自定义逻辑卖出(如 dynamic_roi)") print(" • force_exit: 强制平仓(如策略更换、手动干预)") print(" • 分析此表可了解哪种退出方式最有效") print("\n" + "=" * 60) print("📅 按开仓月份统计分析") print("=" * 60) # 处理时区并提取月份 df['open_date_naive'] = df['open_date'].dt.tz_localize(None) df['month'] = df['open_date_naive'].dt.to_period('M') grouped_by_month = df.groupby('month').agg( 总交易次数=('profit_abs', 'size'), 平均收益率=('profit_ratio', 'mean'), 累计收益=('profit_abs', 'sum'), 胜率=('profit_ratio', lambda x: (x > 0).mean()) ) # 格式化输出 grouped_by_month['平均收益率'] = grouped_by_month['平均收益率'].map(lambda x: f"{x:.2%}") grouped_by_month['胜率'] = grouped_by_month['胜率'].map(lambda x: f"{x:.2%}") grouped_by_month['累计收益'] = grouped_by_month['累计收益'].round(4) print(grouped_by_month) print("\n📌 说明:") print(" • 统计每个月的交易表现") print(" • 可用于判断策略在不同市场环境下的稳定性") print(" • 若某月收益骤降,可结合行情进一步分析原因") print("\n" + "=" * 60) print("📈 按单笔交易盈利区间统计") print("=" * 60) # 按盈利区间分组统计 bins = [-float('inf'), -0.05, -0.02, 0, 0.02, 0.05, float('inf')] labels = ['<-5%', '-5%~-2%', '-2%~0%', '0%~2%', '2%~5%', '>5%'] df['profit_group'] = pd.cut(df['profit_ratio'], bins=bins, labels=labels) grouped_by_profit = df.groupby('profit_group', observed=True).agg( 交易次数=('profit_abs', 'size'), 平均收益率=('profit_ratio', 'mean'), 累计收益=('profit_abs', 'sum') ) # 格式化 grouped_by_profit['平均收益率'] = grouped_by_profit['平均收益率'].map(lambda x: f"{x:.2%}") grouped_by_profit['累计收益'] = grouped_by_profit['累计收益'].round(4) print(grouped_by_profit) print("\n📌 说明:") print(" • 展示每笔交易的盈利分布情况") print(" • 理想情况:多数集中在 '0%~2%' 和 '2%~5%' 区间") print(" • 若大量亏损(<-2%),需检查止损机制是否有效") print("\n" + "=" * 60) print("⏳ 按持仓时长分类统计") print("=" * 60) # 分组为短中长线 df['duration_group'] = pd.cut(df['trade_duration'], bins=[0, 60, 360, 1440, 100000], labels=['<1小时', '1~6小时', '6小时~1天', '>1天']) grouped_by_duration = df.groupby('duration_group', observed=True).agg( 交易次数=('profit_abs', 'size'), 平均收益率=('profit_ratio', 'mean'), 胜率=('profit_ratio', lambda x: (x > 0).mean()), 累计收益=('profit_abs', 'sum') ) # 格式化 grouped_by_duration['平均收益率'] = grouped_by_duration['平均收益率'].map(lambda x: f"{x:.2%}") grouped_by_duration['胜率'] = grouped_by_duration['胜率'].map(lambda x: f"{x:.2%}") grouped_by_duration['累计收益'] = grouped_by_duration['累计收益'].round(4) print(grouped_by_duration) print("\n📌 说明:") print(" • 分析不同持仓周期的表现") print(" • 可帮助优化策略的持有时间设定") print(" • 例如:若 '<1小时' 胜率高但收益低,可能适合高频微利策略") print("\n✅ 分析完成")