程序员量化交易实战 12:回测不能只看最终收益
原创 · 约 8 分钟阅读 · 阅读 --
Last updated on

程序员量化交易实战 12:回测不能只看最终收益

作者: Alex Xiang


程序员量化交易实战 12:回测不能只看最终收益

古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。这个专栏会把一个 A 股量化平台从 0 到 1 拆开写:数据、策略、回测、模拟盘、提醒和生产化,尽量用真实代码和真实运行结果说话。更完整的更新也会同步到微信公众号「字与码」。

第 11 篇有了多标的组合回测。现在如果只看 final_equity,很容易误判策略。

最终收益高,可能是中间回撤很深;胜率高,可能是小赚大亏;交易次数太少,可能只是偶然命中。第 12 篇要把这些指标统一成一组可复用的回测评价语言。

程序员量化交易实战第十二篇封面

指标是策略验收语言

回测指标不是装饰图表。

当两个策略结果不一样时,我们要知道差异来自哪里:收益、波动、回撤、交易频率、胜率还是盈亏比。

回测指标面板

新增指标对象

第 12 章新增 app/performance_metrics.py

@dataclass(frozen=True)
class PerformanceMetrics:
    total_return: float
    annualized_return: float
    annualized_volatility: float
    sharpe_like: float | None
    max_drawdown: float
    win_rate: float | None
    profit_loss_ratio: float | None
    trade_count: int
    turnover: float

这里叫 sharpe_like,不是严格金融教科书里的 Sharpe。因为当前还没有无风险利率输入,只是用年化收益除以年化波动,作为早期工程比较指标。

从权益曲线计算收益率

权益曲线先转成逐日收益:

def equity_returns(equity_curve: Iterable[dict[str, object]]) -> list[float]:
    values = [float(row["equity"]) for row in equity_curve]
    out: list[float] = []
    for previous, current in zip(values, values[1:], strict=False):
        if previous:
            out.append(round(current / previous - 1, 8))
    return out

有了逐日收益,年化波动就是样本标准差乘以 sqrt(252)

variance = sum((value - mean) ** 2 for value in returns) / (len(returns) - 1)
return round(math.sqrt(variance * 252), 6)

胜率要从成对交易算

单笔买入不产生盈亏,只有买入和卖出配对后才有交易盈亏。

def trade_pnls(trades: Iterable[MiniBacktestTrade]) -> list[float]:
    pnls: list[float] = []
    open_cost: float | None = None
    for trade in trades:
        if trade.side == "buy":
            open_cost = trade.amount + trade.fee
        elif trade.side == "sell" and open_cost is not None:
            pnls.append(round(trade.amount - trade.fee - open_cost, 2))
            open_cost = None
    return pnls

这一步能避免把未平仓持仓误算成已实现胜率。

本章更新与代码仓库

本章更新内容:

  • 新增 app/performance_metrics.py
  • 实现总收益、年化收益、年化波动、类 Sharpe、胜率、盈亏比、换手率和交易次数。
  • 新增 tests/test_performance_metrics.py,覆盖空曲线、交易配对和指标汇总。

代码仓库:

https://github.com/ax2/zi-quant-platform

本章代码:

git clone https://github.com/ax2/zi-quant-platform.git
cd zi-quant-platform
git checkout chapter-12
uv sync --extra dev
uv run pytest tests/test_performance_metrics.py

第 12 章全量测试通过:176 passed,仍只有既有 FastAPI deprecation warning。

本篇小结

最终收益只是策略结果的一部分。

第 12 篇把回测评价指标变成可复用代码。后面做参数搜索和策略晋升时,不再靠“看起来收益更高”,而是用统一指标做比较。