第 2 章 · 03 回测如何工作 本节摘要:回测(backtest)不是预测器,而是历史模拟器——它的价值是让你在投入真实资金前,先看清一套规则在历史数据里经历过什么:赚了多少、最大亏了多少、交易频率多高、是否被手续费吃掉、是否只在某一年有效。本节先给回测入口命令,让你能亲手跑一次;然后讲本章的重头戏——为什么不同市场必须走不同引擎:A 股要处理 T+1、涨跌停、一手 100 股、佣金、印花税;加密 7×24、T+0;期货有保证金和交割。最后点破一个残酷现实:「信号准不准」和「落到真实规则后能否赚钱」是两回事,很多看起来漂亮的短线策略,一加入滑点和费用就失效。 内容来源:原项目中文入门教程(第 5 章「回测如何工作」)与英文文档 合并改写。
本节摘要:回测(backtest)不是预测器,而是历史模拟器——它的价值是让你在投入真实资金前,先看清一套规则在历史数据里经历过什么:赚了多少、最大亏了多少、交易频率多高、是否被手续费吃掉、是否只在某一年有效。本节先给回测入口命令,让你能亲手跑一次;然后讲本章的重头戏——为什么不同市场必须走不同引擎:A 股要处理 T+1、涨跌停、一手 100 股、佣金、印花税;加密 7×24、T+0;期货有保证金和交割。最后点破一个残酷现实:「信号准不准」和「落到真实规则后能否赚钱」是两回事,很多看起来漂亮的短线策略,一加入滑点和费用就失效。
内容来源:原项目中文入门教程(第 5 章「回测如何工作」)与英文文档
core-concepts/backtesting合并改写。
阅读完本节,你应当能够:
backtest 工具的流程。很多人对回测有一个误解——以为回测好的策略未来就能赚钱。这是错的。
回测的本质:回测不是预测器,而是历史模拟器。它的价值是让你在投入真实资金前,先看清一套规则在历史数据里经历过什么:赚了多少、最大亏了多少、交易频率多高、是否只是某一年有效、是否被手续费吃掉。它只能证明历史表现,不能证明未来收益。
为什么历史好不代表未来好?至少有三个原因:
所以回测的正确用法是证伪而非证实——它帮你淘汰「在历史里就不行」的策略,但不能保证「在历史里行」的策略未来一定行。
⚠️ 所有回测结果均不构成投资建议。历史表现不代表未来收益。
最直接的回测入口是 CLI:
vibe-trading run -p "Backtest a momentum strategy on a broad equity universe from 2020 to 2025. Include benchmark comparison, drawdown, turnover, and a short explanation."
这条提示背后发生的事:
关键步骤:
config.json 和 code/signal_engine.py(详见第 2 章 02)。backtest 工具:这个工具会先校验 config.json 和 signal_engine.py 的合法性(字段齐不齐、代码能不能跑),再运行。agent/backtest/runner.py,根据 config.engine 选择对应的市场引擎。💡 为什么先校验再运行:
config.json字段缺失或signal_engine.py有语法错误,会让回测跑到一半失败。先校验能在早期暴露问题,节省时间。
这是本节的核心。很多人以为「回测就是按信号买卖,所有市场都一样」,这是大错。
不同市场有完全不同的交易规则。 项目为此维护了多个引擎,每个引擎封装了对应市场的规则:
agent/backtest/engines/ china_a.py # A 股 global_equity.py # 全球股票 crypto.py # 加密 china_futures.py # 中国期货 global_futures.py # 全球期货 forex.py # 外汇 composite.py # 组合市场 options_portfolio.py # 期权组合
以 A 股(china_a)和全球股票(global_equity)为例,规则差异极大:
| 规则 | A 股(china_a) | 全球股票(global_equity) |
|---|---|---|
| 交收制度 | T+1(今天买,明天才能卖) | 可能 T+0 |
| 涨跌停 | 有(主板 ±10%,创业板/科创板 ±20%) | 通常无 |
| 一手股数 | 100 股(买入须是 100 的整数倍) | 可买 1 股甚至小数股 |
| 做空 | 受限(融券) | 通常支持 |
| 佣金 | 有,可协商 | 有 |
| 印花税 | 卖出单边征收 | 部分市场有 |
| 交易时间 | 固定时段 | 各市场不同 |
加密(crypto)又是另一套:7×24 交易、T+0、可加杠杆、无涨跌停、手续费率因交易所而异。期货(china_futures / global_futures)还要处理保证金、每日盯市、交割月。期权(options_portfolio)要处理行权、Greeks、组合保证金。
如果引擎选错,回测结果会和真实交易差距巨大,甚至完全不可信。举几个典型错配:
global_equity 跑 A 股:不会处理 T+1,你以为今天买今天就能卖,实盘根本做不到;不处理涨跌停,你以为能买到涨停板的股票,实际买不到;不扣印花税,成本被低估。china_a 跑加密:加密 7×24 交易,A 股引擎按固定时段处理会丢掉大量数据;加密没有「一手 100 股」概念,强制整数化会很奇怪。composite 让不同市场由不同子引擎协作。💡 引擎选择原则:引擎必须和你的标的市場匹配。A 股用
china_a,美股/港股用global_equity,加密用crypto,跨市场用composite。config.json的engine字段就是干这个的。
除了引擎,config.json 的 bar 字段(回测的 K 线周期)也会显著影响结果。项目支持的周期包括:1m、5m、15m、30m、1H、4H、1D(是否可用取决于数据源)。
1D):适合中长线策略,数据量小,回测快。1m/5m/15m):适合短线、日内策略,数据量大,回测慢,但对成交细节刻画更精细。⚠️ 分钟级回测的陷阱:分钟级数据更精细,但也会放大「过拟合」风险——你能在更细的粒度上找到「恰好适配历史」的参数,但这些参数往往在样本外失效。除非你的策略本身就是分钟级,否则建议从日级开始。
理解了引擎和成本,你就能看破一个常见幻觉:「我的信号很准,所以策略一定赚钱」。未必。
「信号准」只代表你判断对了方向(比如预测某只股票会涨,它确实涨了)。但从「判断对方向」到「实际赚到钱」,中间还有几道关:
你的判断(信号): 某股会涨 ✓(信号准) │ ▼ 实际交易: - 能买到吗?(涨停/停牌) - 成本多少?(佣金/滑点/印花税) - 仓位合理吗?(集中度) - 能及时退出吗?(T+1/流动性) │ ▼ 最终盈亏:可能赚、可能亏、可能只是打平
💡 残酷现实:很多看起来漂亮的短线策略,一加入滑点和费用就失效。这是因为它们的「超额收益」本来就薄,被成本一吃就没了。这也是为什么回测必须按真实市场规则跑——用对的引擎、扣对的成本。
把本节内容串起来,看一条覆盖多资产的回测命令:
vibe-trading run -p "Backtest an equal-weight SPY and BTC-USDT momentum rotation strategy for 2024 with benchmark comparison"
这条命令会:
composite,让股票部分走 global_equity、加密部分走 crypto。⚠️ 即使回测结果很好看,也不构成投资建议。SPY 和 BTC-USDT 都是真实标的,任何实盘交易前必须经过你自己的判断、券商确认、模拟盘验证。
vibe-trading run -p "...",agent 生成 run dir → 调用 backtest 工具 → 校验 → 运行 runner.py → 选引擎 → 产出。⚠️ 本节所有回测命令与结果均不构成投资建议。历史表现不代表未来收益。
下一节,我们将讲验证工具与回测陷阱——基准对比、蒙特卡洛、Bootstrap、Walk-Forward、run card 的作用与局限,以及 lookahead(偷看未来)与违反 PIT(点在时间)这两类回测常见错误的识别与规避。