功能

交易分析

通过 MAE、MFE、优势比率、盈利因子和图表分析交易与持仓

哪些交易赚了钱,退出做得好吗?VBT 将每笔交易保留为包含入场、退出、利润和价格偏移的记录,让 Python 交易分析能够为单次或数千次回测计算胜率、盈利因子、期望收益、MAE、MFE 和优势比率。

Check whether a 5% stop would have cut the winners
data = vbt.YFData.pull(["BTC-USD", "ETH-USD"], start="2018-01-01", end="2025-01-01")
fast = data.close.rolling(20).mean()
slow = data.close.rolling(50).mean()
pf = vbt.PF.from_signals(
    data,
    fast.vbt.crossed_above(slow),
    fast.vbt.crossed_below(slow),
    fees=0.001,
)
trades = pf.trades.status_closed  
metrics = ["total_records", "win_rate", "profit_factor", "expectancy", "sqn"]
trades.stats(metrics, agg_func=None)
         Total Records  Win Rate [%]  Profit Factor  Expectancy       SQN
symbol
BTC-USD             26     30.769231       1.632437   13.422132  0.669763
ETH-USD             23     52.173913       1.867036   33.244891  0.803366
mae = trades.mae_returns.values  
returns = trades.returns.values
pnl = trades.pnl.values
cut = (returns > 0) & (mae < -0.05)
pd.Series({
    "winners": (returns > 0).sum(),
    "winners that first fell over 5%": cut.sum(),
    "their profit": pnl[cut].sum().round(2),
    "profit of all winners": pnl[returns > 0].sum().round(2),
})
winners                              20.00
winners that first fell over 5%       9.00
their profit                       1306.13
profit of all winners              2547.29
dtype: float64
trades.plot_mae_returns(column="BTC-USD").show()
比特币均线交叉交易的最大不利偏移与最终收益率散点图 图表数据(JSON)

20 笔盈利交易中,有 9 笔曾先跌至低于入场价 5% 以上,而它们贡献了总盈利的一半。5% 止损会使它们亏损平仓。散点图为每笔比特币交易展示同样的信息:相对于最终结果,它曾逆着持仓方向走了多远。

交易与持仓

同样的订单可以按三种方式分组为交易,每种方式回答不同问题:

记录每条记录对应用途
pf.entry_trades建仓或加仓的订单评估入场
pf.exit_trades(pf.trades)减仓或平仓的订单评估退出
pf.positions从建仓到完全平仓的持仓评估完整持仓

只有一次入场和退出时,三者相同。分批建仓或平仓时则不同:

Split two buys and two sells into trades and positions
index = pd.date_range("2026-01-01", periods=4)
close = pd.Series([10.0, 11.0, 12.0, 13.0], index=index)
pf = vbt.PF.from_orders(close, size=[1, 1, -1, -1])
cols = ["Entry Index", "Exit Index", "Size", "PnL"]

pf.entry_trades.readable[cols]
  Entry Index Exit Index  Size  PnL
0  2026-01-01 2026-01-04   1.0  2.5
1  2026-01-02 2026-01-04   1.0  1.5
pf.exit_trades.readable[cols]
  Entry Index Exit Index  Size  PnL
0  2026-01-01 2026-01-03   1.0  1.5
1  2026-01-01 2026-01-04   1.0  2.5
pf.positions.readable[cols]
  Entry Index Exit Index  Size  PnL
0  2026-01-01 2026-01-04   2.0  4.0

入场交易使用平均退出价衡量每次入场,退出交易则使用平均入场价衡量每次退出。记录带有输入的列标签,因此参数网格的交易可按参数分组,direction_long 或 direction_short 可选择多头或空头。pf.trade_history 将订单与三种视图连接起来,如下方交易历史功能介绍所示。每个订单占一行,各行携带该订单的入场交易或退出交易利润,因此在上述例子中,PnL 列加总为 8,是实际利润的两倍。请改用三种记录类型中的一种计算统计。

交易指标

trades.stats() 报告胜率、最佳和最差交易、平均盈利和亏损、连续盈利与亏损次数、盈利因子、期望收益及系统质量指数(SQN)。每项指标也都可作为属性访问,例如 trades.profit_factor。

交易收益率是利润相对于入场投入资金的比例,而非相对于账户价值。100 美元持仓赚取 5 美元,无论账户多大,收益率都是 5%。盈利因子、期望收益和 SQN 默认根据利润计算,设置 use_returns=True 则改为根据收益率计算,从而消除仓位规模的影响。

盈利因子是盈利交易总利润除以亏损交易总亏损。数值为 2 表示盈利交易赚到的金额是亏损交易损失的两倍。期望收益是以账户币种计的每笔交易平均利润,因此期望收益为 10,表示选定记录中每笔交易平均赚取 10。结合胜率阅读这些指标,了解盈利交易的规模能否弥补亏损。

对于 R 倍数等需要记录之外信息的指标,只需在记录基础上添加几行代码。止损距离为两个 ATR 时,交易利润除以初始风险即可得到 R 倍数:

Express trade results as multiples of the initial risk
stop_dist = 2 * data.run("atr", window=14).atr
pf = vbt.PF.from_signals(
    data,
    fast.vbt.crossed_above(slow),
    fast.vbt.crossed_below(slow),
    sl_stop=stop_dist,
    delta_format="absolute",
    fees=0.001,
)
trades = pf.trades.status_closed
entry_risk = stop_dist.values[trades.entry_idx.values, trades.col.values]
risk = entry_risk * trades.size.values
pd.Series(trades.pnl.values / risk).describe().round(2)
count    50.00
mean      3.19
std      14.88
min      -1.05
25%      -1.02
50%      -1.01
75%       1.05
max      77.89
dtype: float64

大多数亏损交易在约一个风险单位处止损,少数盈利交易则获得其数倍回报,这是趋势跟随系统的典型特征。

比较多头与空头交易

您可以对交易子集运行相同分析,无需重新运行回测。这里四笔交易使多头和空头具有相同胜率,但结果截然不同:

Compare both sides of a strategy from one simulation
side_close = pd.Series([100.0, 120.0, 100.0, 105.0, 100.0, 95.0, 100.0, 98.0], index=pd.date_range("2026-01-01", periods=8))
side_pf = vbt.PF.from_orders(side_close, size=[1, -1, -1, 1, 1, -1, -1, 1], init_cash=1000)
side_trades = side_pf.trades.status_closed
side_metrics = ["total_records", "win_rate", "profit_factor", "expectancy"]
pd.DataFrame({
    "Long": side_trades.direction_long.stats(side_metrics),
    "Short": side_trades.direction_short.stats(side_metrics),
}).round(2)
               Long Short
Total Records     2     2
Win Rate [%]   50.0  50.0
Profit Factor   4.0   0.4
Expectancy      7.5  -1.5

多头交易赚取 20、亏损 5,空头交易则亏损 5、赚取 2。分开观察两侧可以看清利润来源。筛选后的记录仍支持相同交易图表和偏移分析。其他筛选和分组方式,请参阅记录与映射数组。

价格偏移

最大不利偏移(MAE)是交易达到的最差位置,最大有利偏移(MFE)则是最佳位置。两者都有价格单位和收益率形式,并记录发生时的 K 线。与最终结果比较,可以了解止损是否过紧、退出是否错失利润。扩展版本从入场开始逐 K 线跟踪两者,如下方扩展交易指标功能介绍所示;MAE 与 MFE功能介绍则比较使用和不使用止损的投资组合。

利用这些结果选择待测试的止损或目标水平,再通过止损与止盈模拟这些退出。比较新的交易分布和投资组合结果,了解修改对盈利和亏损交易分别产生的影响。

入场质量

优势比率是经波动率调整后的平均 MFE 除以经波动率调整后的平均 MAE。高于 1 表示入场后有利方向的移动通常大于不利方向。运行优势比率对每种持有期进行计算,让您看到入场需要多少根 K 线才能展现优势,并与随机入场比较,如优势比率功能介绍所示。

交易图表

trades.plot() 绘制每笔交易从入场到退出的过程,并按盈亏着色。pf.plot_trade_signals() 分别标记多头、空头的入场和退出,plot_pnl、plot_returns、plot_mae 和 plot_mfe 则以散点图展示交易层面的结果。这些图是标准 Plotly 图形,因此悬停标签可携带任意额外信息,例如入场时的指标值。

扩展交易指标

✅ 常规 MAE 和 MFE 等指标仅代表每笔交易的最终结果。但如果想了解它们在交易过程中的变化呢?现在可以将扩展交易指标作为 DataFrame 分析!

Visualize the expanding MFE using projections
data = vbt.YFData.pull("BTC-USD")
pf = vbt.PF.from_random_signals(data, n=50, tp_stop=0.5, seed=42)
pf.trades.plot_expanding_mfe_returns().show()
BTC-USD 交易的扩展最大有利偏移收益率投影 图表数据(JSON)

交易信号

✅ 新的交易绘图方法将入场和退出交易细分为多头入场、多头退出、空头入场和空头退出,并支持不同持仓样式。

Plot trade signals of a Bollinger Bands strategy
data = vbt.YFData.pull("BTC-USD")
bb = data.run("bbands")
long_entries = data.hlc3.vbt.crossed_above(bb.upper) & (bb.bandwidth < 0.1)
long_exits = data.hlc3.vbt.crossed_below(bb.upper) & (bb.bandwidth > 0.5)
short_entries = data.hlc3.vbt.crossed_below(bb.lower) & (bb.bandwidth < 0.1)
short_exits = data.hlc3.vbt.crossed_above(bb.lower) & (bb.bandwidth > 0.5)
pf = vbt.PF.from_signals(
    data,
    long_entries=long_entries,
    long_exits=long_exits,
    short_entries=short_entries,
    short_exits=short_exits
)
pf.plot_trade_signals().show()
BTC-USD OHLC 与布林带策略的多空交易信号 图表数据(JSON)

优势比率

✅ 优势比率是衡量入场盈利能力的独特指标。与大多数绩效指标不同,优势比率同时考虑未平仓盈亏,帮助您寻找更好的交易退出方式。

Compare the edge ratio of an EMA crossover to a random strategy
data = vbt.YFData.pull("BTC-USD")
fast_ema = data.run("ema", 10, hide_params=True)
slow_ema = data.run("ema", 20, hide_params=True)
entries = fast_ema.real_crossed_above(slow_ema)
exits = fast_ema.real_crossed_below(slow_ema)
pf = vbt.PF.from_signals(data, entries, exits, direction="both")
rand_pf = vbt.PF.from_random_signals(data, n=pf.orders.count() // 2, seed=42)  
fig = pf.trades.plot_running_edge_ratio(
    trace_kwargs=dict(line_color="limegreen", name="Edge Ratio (S)")
)
fig = rand_pf.trades.plot_running_edge_ratio(
    trace_kwargs=dict(line_color="mediumslateblue", name="Edge Ratio (R)"),
    fig=fig
)
fig.show()
EMA 交叉策略与随机 BTC-USD 策略的运行优势比率 图表数据(JSON)

交易历史

✅ 交易历史是列出订单的人类可读 DataFrame,并扩展了入场交易、退出交易和持仓的实用细节。

Get the trade history of a random portfolio with one signal
data = vbt.YFData.pull(["BTC-USD", "ETH-USD"], missing_index="drop")
pf = vbt.PF.from_random_signals(
    data,
    n=1,
    seed=42,
    run_kwargs=dict(hide_params=True),
    tp_stop=0.5,
    sl_stop=0.1
)
pf.trade_history
   Order Id   Column              Signal Index            Creation Index  \
0         0  BTC-USD 2016-02-20 00:00:00+00:00 2016-02-20 00:00:00+00:00
1         1  BTC-USD 2016-02-20 00:00:00+00:00 2016-06-12 00:00:00+00:00
2         0  ETH-USD 2019-05-25 00:00:00+00:00 2019-05-25 00:00:00+00:00
3         1  ETH-USD 2019-05-25 00:00:00+00:00 2019-07-15 00:00:00+00:00

                 Fill Index  Side    Type Stop Type      Size       Price  \
0 2016-02-20 00:00:00+00:00   Buy  Market      None  0.228747  437.164001
1 2016-06-12 00:00:00+00:00  Sell  Market        TP  0.228747  655.746002
2 2019-05-25 00:00:00+00:00   Buy  Market      None  0.397204  251.759872
3 2019-07-15 00:00:00+00:00  Sell  Market        SL  0.397204  226.583885

   Fees   PnL  Return Direction  Status  Entry Trade Id  Exit Trade Id  \
0   0.0  50.0     0.5      Long  Closed               0             -1
1   0.0  50.0     0.5      Long  Closed              -1              0
2   0.0 -10.0    -0.1      Long  Closed               0             -1
3   0.0 -10.0    -0.1      Long  Closed              -1              0

   Position Id
0            0
1            0
2            0
3            0

MAE 与 MFE

✅ 最大不利偏移(MAE)帮助您了解交易期间承受的最大亏损,也称持仓最大回撤。最大有利偏移(MFE)则显示交易期间达到的最高利润。分析 MAE 和 MFE 统计,可以帮助您改进退出策略。

Analyze the MAE of a random portfolio without SL
data = vbt.YFData.pull("BTC-USD")
pf = vbt.PF.from_random_signals(data, n=50, seed=42)
pf.trades.plot_mae_returns().show()
不使用止损的 BTC-USD 交易:最大不利偏移与收益率 图表数据(JSON)
Analyze the MAE of a random portfolio with SL
pf = vbt.PF.from_random_signals(data, n=50, sl_stop=0.1, seed=42)
pf.trades.plot_mae_returns().show()
使用止损的 BTC-USD 交易:最大不利偏移与收益率 图表数据(JSON)

版权所有 © 2021–2026 Oleg Polakow。保留所有权利。

本站内容与文档供使用和评估 VectorBT PRO 以及教育用途。任何其他用途,包括开发或支持竞争产品或服务,均须事先取得书面同意。