如何编码实现策略平均盈利/亏损交易回撤统计及仪表盘展示?
实现交易回撤统计与仪表盘展示
核心逻辑拆解
先明确交易回撤的计算规则:
- 做多交易:回撤 = (入场价 - 持仓期间最低价) / 入场价 × 100%(取正值,代表价格向相反方向的最大波动幅度)
- 做空交易:回撤 = (持仓期间最高价 - 入场价) / 入场价 × 100%(同样取正值)
- 区分盈利交易(平仓后净利润>0)和亏损交易(平仓后净利润≤0),分别计算两类交易的回撤平均值。
代码实现步骤
1. 定义回撤计算函数
假设交易记录包含entry_price(入场价)、position_side(持仓方向)、high_in_trade(持仓最高价)、low_in_trade(持仓最低价)等字段,先写单条交易的回撤计算函数:
def calculate_trade_drawdown(trade): if trade['position_side'] == 'long': # 做多场景:计算入场价到持仓最低价的下跌幅度 drawdown_pct = (trade['entry_price'] - trade['low_in_trade']) / trade['entry_price'] * 100 elif trade['position_side'] == 'short': # 做空场景:计算入场价到持仓最高价的上涨幅度 drawdown_pct = (trade['high_in_trade'] - trade['entry_price']) / trade['entry_price'] * 100 else: raise ValueError("持仓方向仅支持'long'或'short'") # 极端情况(价格无反向波动)下回撤为0,确保结果非负 return max(drawdown_pct, 0.0)
2. 批量统计盈利/亏损交易的平均回撤
遍历所有交易数据,分类收集回撤值并计算平均值:
# 示例交易数据,可替换为你的真实交易记录 trades = [ {'entry_price': 100, 'exit_price': 108, 'position_side': 'long', 'pnl_pct': 8, 'high_in_trade': 108, 'low_in_trade': 98}, {'entry_price': 100, 'exit_price': 99, 'position_side': 'long', 'pnl_pct': -1, 'high_in_trade': 100, 'low_in_trade': 98}, {'entry_price': 100, 'exit_price': 98, 'position_side': 'long', 'pnl_pct': -2, 'high_in_trade': 100, 'low_in_trade': 98}, {'entry_price': 100, 'exit_price': 92, 'position_side': 'short', 'pnl_pct': 8, 'high_in_trade': 102, 'low_in_trade': 92}, {'entry_price': 100, 'exit_price': 101, 'position_side': 'short', 'pnl_pct': -1, 'high_in_trade': 102, 'low_in_trade': 100}, ] # 初始化分类容器 winning_drawdowns = [] losing_drawdowns = [] for trade in trades: drawdown = calculate_trade_drawdown(trade) if trade['pnl_pct'] > 0: winning_drawdowns.append(drawdown) else: losing_drawdowns.append(drawdown) # 计算平均值(避免空列表报错) avg_winning_drawdown = sum(winning_drawdowns) / len(winning_drawdowns) if winning_drawdowns else 0.0 avg_losing_drawdown = sum(losing_drawdowns) / len(losing_drawdowns) if losing_drawdowns else 0.0 print(f"平均盈利交易回撤: {avg_winning_drawdown:.2f}%") print(f"平均亏损交易回撤: {avg_losing_drawdown:.2f}%")
3. 仪表盘可视化
用Plotly实现交互式双仪表盘,直观展示统计结果:
import plotly.graph_objects as go # 创建仪表盘布局 fig = go.Figure() # 添加平均盈利回撤仪表盘 fig.add_trace(go.Indicator( mode = "gauge+number", value = avg_winning_drawdown, title = {'text': "平均盈利交易回撤(%)"}, gauge = { 'axis': {'range': [0, max(avg_winning_drawdown * 1.5, 10)]}, 'bar': {'color': "green"}, 'steps': [{'range': [0, avg_winning_drawdown], 'color': "rgba(0,255,0,0.3)"}] }, domain = {'row': 0, 'column': 0} )) # 添加平均亏损回撤仪表盘 fig.add_trace(go.Indicator( mode = "gauge+number", value = avg_losing_drawdown, title = {'text': "平均亏损交易回撤(%)"}, gauge = { 'axis': {'range': [0, max(avg_losing_drawdown * 1.5, 10)]}, 'bar': {'color': "red"}, 'steps': [{'range': [0, avg_losing_drawdown], 'color': "rgba(255,0,0,0.3)"}] }, domain = {'row': 0, 'column': 1} )) # 调整整体布局 fig.update_layout( grid = {'rows': 1, 'columns': 2, 'pattern': "independent"}, title = "策略绩效回撤统计" ) fig.show()
注意事项
- 若使用量化框架(如Backtrader、VectorBT),需从框架中提取持仓时段的高低价数据,部分框架需手动记录价格极值。
- 如需静态仪表盘,可改用Matplotlib的
mpl_toolkits扩展实现。
内容的提问来源于stack exchange,提问作者Muhammed Tahreem Alam
相关产品推荐
相关产品推荐

