打印交易明细

This commit is contained in:
2025-11-02 19:32:36 +08:00
parent 1157a9650c
commit f474b31f57
2 changed files with 210 additions and 2 deletions

View File

@ -54,7 +54,7 @@ def get_processed_data():
# 限制为最近一年数据
end_date = smic_data.index.max()
start_date = end_date - pd.Timedelta(days=360*3)
start_date = end_date - pd.Timedelta(days=360)
print(f"\n限制回测时间范围: {start_date}{end_date}")

View File

@ -175,6 +175,209 @@ def print_statistics(strategy_data, portfolio):
print(f"做空信号次数: {short_count}")
print(f"总信号次数: {total_signals}")
def print_trade_orders(strategy_data, stock_portfolio):
"""打印所有交易订单信息"""
if stock_portfolio is None:
return
print("\n" + "="*60)
print("=== 详细交易订单信息 ===")
print("="*60)
try:
# 获取订单记录
orders_df = stock_portfolio.orders.records_readable
if len(orders_df) > 0:
print(f"\n总订单数量: {len(orders_df)}")
# 按时间排序
time_column = None
possible_time_columns = ['Timestamp', 'Date', 'Time']
for col in possible_time_columns:
if col in orders_df.columns:
time_column = col
break
if time_column:
orders_sorted = orders_df.sort_values(time_column)
else:
orders_sorted = orders_df
# 显示所有订单(按时间排序)
pd.set_option('display.max_rows', None)
pd.set_option('display.width', None)
print("\n【所有交易订单(按时间排序)】")
print(orders_sorted.to_string(index=False))
# 按股票分组统计
print(f"\n【按股票统计】")
for column in ['SMIC', 'HHIC']:
column_orders = orders_sorted[orders_sorted['Column'] == column]
if len(column_orders) > 0:
buy_orders = column_orders[column_orders['Side'] == 'Buy']
sell_orders = column_orders[column_orders['Side'] == 'Sell']
print(f"\n{column} 订单统计:")
print(f" 总订单数: {len(column_orders)}")
print(f" 买入订单: {len(buy_orders)}")
print(f" 卖出订单: {len(sell_orders)}")
print(f" 总交易金额: {column_orders['Size'].abs().sum():.2f}")
print(f" 总手续费: {column_orders['Fees'].sum():.2f}")
# 按日期分组统计
if time_column:
print(f"\n【按日期统计】")
daily_orders = orders_sorted.groupby(time_column).agg({
'Column': 'count',
'Size': 'sum',
'Fees': 'sum'
}).rename(columns={'Column': '订单数'})
print(daily_orders.to_string())
else:
print(f"\n【按日期统计】- 未找到时间列")
# 重置pandas显示选项
pd.reset_option('display.max_rows')
pd.reset_option('display.width')
else:
print("没有找到交易订单")
except Exception as e:
print(f"打印订单信息时出错: {e}")
import traceback
traceback.print_exc()
def print_detailed_trade_analysis(strategy_data, stock_portfolio):
"""打印详细的交易分析"""
if stock_portfolio is None:
return
print("\n" + "="*60)
print("=== 详细交易分析 ===")
print("="*60)
try:
# 获取交易记录
trades_df = stock_portfolio.trades.records_readable
if len(trades_df) > 0:
print(f"\n总交易次数: {len(trades_df)}")
# 按开仓时间排序
trades_sorted = trades_df.sort_values('Entry Timestamp')
# 显示所有交易(按时间排序)
pd.set_option('display.max_rows', None)
pd.set_option('display.width', None)
print("\n【所有交易记录(按开仓时间排序)】")
print(trades_sorted.to_string(index=False))
# 按股票分组分析
print(f"\n【按股票交易分析】")
for column in ['SMIC', 'HHIC']:
column_trades = trades_sorted[trades_sorted['Column'] == column]
if len(column_trades) > 0:
winning_trades = column_trades[column_trades['PnL'] > 0]
losing_trades = column_trades[column_trades['PnL'] < 0]
print(f"\n{column} 交易分析:")
print(f" 总交易次数: {len(column_trades)}")
print(f" 盈利交易: {len(winning_trades)}")
print(f" 亏损交易: {len(losing_trades)}")
print(f" 胜率: {len(winning_trades)/len(column_trades)*100:.1f}%")
print(f" 总盈亏: {column_trades['PnL'].sum():.2f}")
print(f" 平均每笔盈亏: {column_trades['PnL'].mean():.2f}")
print(f" 最大盈利: {column_trades['PnL'].max():.2f}")
print(f" 最大亏损: {column_trades['PnL'].min():.2f}")
if len(winning_trades) > 0:
print(f" 平均盈利: {winning_trades['PnL'].mean():.2f}")
if len(losing_trades) > 0:
print(f" 平均亏损: {losing_trades['PnL'].mean():.2f}")
# 正确的配对交易分析
print(f"\n【配对交易分析(修正)】")
# 按开仓时间分组找出同一天开仓的SMIC和HHIC交易
entry_groups = trades_sorted.groupby('Entry Timestamp').agg({
'Column': list,
'PnL': list,
'Size': list,
'Direction': list,
'Exit Timestamp': list
})
pair_trades = []
for entry_date, group_data in entry_groups.iterrows():
columns = group_data['Column']
pnls = group_data['PnL']
directions = group_data['Direction']
exit_times = group_data['Exit Timestamp']
# 检查是否同时有SMIC和HHIC的交易
if 'SMIC' in columns and 'HHIC' in columns:
smic_idx = columns.index('SMIC')
hhic_idx = columns.index('HHIC')
# 检查交易方向是否配对(一个做多,一个做空)
if directions[smic_idx] != directions[hhic_idx]:
pair_pnl = pnls[smic_idx] + pnls[hhic_idx]
pair_trades.append({
'entry_date': entry_date,
'exit_date_smic': exit_times[smic_idx],
'exit_date_hhic': exit_times[hhic_idx],
'smic_pnl': pnls[smic_idx],
'hhic_pnl': pnls[hhic_idx],
'total_pnl': pair_pnl,
'smic_direction': directions[smic_idx],
'hhic_direction': directions[hhic_idx]
})
if pair_trades:
# 按开仓时间排序配对交易
pair_trades_sorted = sorted(pair_trades, key=lambda x: x['entry_date'])
print(f"配对交易次数: {len(pair_trades_sorted)}")
total_pair_pnl = sum(trade['total_pnl'] for trade in pair_trades_sorted)
avg_pair_pnl = total_pair_pnl / len(pair_trades_sorted)
winning_pairs = [t for t in pair_trades_sorted if t['total_pnl'] > 0]
losing_pairs = [t for t in pair_trades_sorted if t['total_pnl'] < 0]
print(f"配对交易总盈亏: {total_pair_pnl:.2f}")
print(f"平均每对盈亏: {avg_pair_pnl:.2f}")
print(f"盈利配对: {len(winning_pairs)}")
print(f"亏损配对: {len(losing_pairs)}")
print(f"配对胜率: {len(winning_pairs)/len(pair_trades_sorted)*100:.1f}%")
# 显示每对交易的详细信息(按时间排序)
print(f"\n【各配对交易详情(按开仓时间排序)】")
for i, trade in enumerate(pair_trades_sorted, 1):
status = "盈利" if trade['total_pnl'] > 0 else "亏损"
print(f"{i}对 - 开仓: {trade['entry_date']}")
print(f" SMIC({trade['smic_direction']}): {trade['smic_pnl']:.2f} (平仓: {trade['exit_date_smic']})")
print(f" HHIC({trade['hhic_direction']}): {trade['hhic_pnl']:.2f} (平仓: {trade['exit_date_hhic']})")
print(f" 总盈亏: {trade['total_pnl']:.2f} [{status}]")
print()
else:
print("没有找到配对交易")
# 重置pandas显示选项
pd.reset_option('display.max_rows')
pd.reset_option('display.width')
else:
print("没有找到交易记录")
except Exception as e:
print(f"打印交易分析时出错: {e}")
import traceback
traceback.print_exc()
def main():
"""主函数"""
@ -197,8 +400,13 @@ def main():
# 绘制基于比率的结果
plot_results(strategy_data, ratio_portfolio)
# 打印详细交易订单信息
print_trade_orders(strategy_data, stock_portfolio)
# 打印详细交易分析
print_detailed_trade_analysis(strategy_data, stock_portfolio)
print("程序执行完成!")
if __name__ == "__main__":
main()