本节摘要:这一节把一个 Strategy API V2 策略从"注册在平台上"推进到"产出一份配置正确的回测报告"。先讲清回测在 QuantDinger 流水线里的位置——策略产出 intents,backtest_engine 消费 intents,同一条代码路径既跑回测也跑实盘;再逐项配置四个要素:区间、费用、滑点、初始资金,每一项给出它扭曲结果的方向;然后拆解输出报告的四个区块,说明各回答什么问题、先看哪个;最后给出 CLI 与界面两条启动路径,并用一张表收拢五个最常见的配置坑。本节的目标不是"跑出数字",而是让数字在方法论上站得住。
QuantDinger 的策略不直接调用下单函数。按官方文档口径,Strategy API V2 让策略声明四类东西:intents(交易意图)、sizing(头寸规模)、risk(风控约束)、运行时钩子(生命周期回调)。回测引擎与实盘执行器消费的是同一份声明:
同一策略,两条消费路径 ┌── backtest_engine ── 历史行情逐段回放 ── 模拟撮合 ── 报告 │ 策略(Strategy API V2) intents/sizing/risk/钩子 │ └── trading-worker ── 实时行情 ── Jev 决策门(第 09 章) ── 真实/虚拟订单
这个设计的含义很直接:你在第 05 章写的策略,回测时怎么算,实盘时就怎么算(撮合与延迟另计)。如果回测和实盘是两套代码,回测结论从一开始就没有参考价值。回测报告可信的工程前提,就是这条共享路径真实存在且没有被你在钩子里绕开。
另一个工程事实:回测任务是异步的。按第 02 章《v5架构总览》的六进程分工,任务由 celery-worker 执行,backend 只负责提交与展示——所以"提交后界面上转圈"是正常现象,报告完成后会出现在任务列表里。
一份典型的回测配置如下(示意结构,字段名与默认值以官方文档为准):
# backtest_breakout.yaml —— 回测任务配置(示意结构,字段以官方文档为准) strategy: breakout_v2 # 已注册的策略标识(第 05 章产物) symbol: BTC/USDT timeframe: 1h range: start: "2023-01-01" # 回测起点(含) end: "2025-12-31" # 回测终点(含) capital: initial: 10000 # 初始资金,按计价货币计(示意值) currency: USDT max_position_pct: 0.30 # 单标的最大仓位占比(示意值) costs: fee_taker: 0.001 # 吃单费率 0.1%(示意值,按你账户实际档位改) fee_maker: 0.0002 # 挂单费率(示意值) slippage_bps: 5 # 每笔按 5 个基点回补滑点(示意值) data: source: local # 使用第 03 章搭好的本地数据层 fill_gap: forward # 缺口处理方式
四个要素对结果的影响方向各不相同,配置前先心里有数:
| 要素 | 影响什么 | 配错的典型后果 |
|---|---|---|
| 区间 | 样本量与市场状态覆盖 | 只覆盖单边行情,策略被区间"养大" |
| 费用 | 每笔来回的真实成本 | 用零费率跑高频策略,交易越多越失真 |
| 滑点 | 成交价与信号价的差距 | 小流动性标的按零滑点成交,回测虚增利润空间 |
| 初始资金 | 仓位约束与复利路径 | 资金太小触发最小下单量限制,资金太大掩盖集中度 |
两点经验。第一,费率档位要按你真实账户填:同一交易所对不同用户、不同月交易量的费率不同,抄别人的配置等于测别人的账户。第二,滑点建议从保守值起步(比如按费率的若干倍取,示意做法),6.3 节会专门做敏感性扫描,这里先求不失真。
回测完成后,报告(结构以官方文档为准)大体分四个区块。阅读顺序建议从下往上——先确认样本可信,再看曲线:
| 区块 | 内容 | 回答的问题 | 先看什么 |
|---|---|---|---|
| 交易明细 | 每笔信号、成交价、数量、费用 | 成交假设是否贴近现实 | 成交价与信号价的偏离 |
| 绩效指标 | 夏普、最大回撤、胜率、盈亏比、交易笔数 | 结果是否显著 | 交易笔数是否足够(样本量) |
| 持仓与现金轨迹 | 仓位、现金随时间变化 | 资金路径是否健康 | 是否长期满仓或长期空仓 |
| 净值与回撤曲线 | 逐段净值与回撤深度 | 何时赚何时亏 | 回撤段对应的市场状态 |
交易笔数值得单独强调。一个两年区间只有二十几笔交易的策略,其胜率与夏普的估计误差极大,任何指标都谈不上显著。经验上先看笔数再看比率(经验做法,非硬门槛),笔数不够时优先拉长区间或换更短周期,而不是急着解读比率。
界面路径:平台 Web 界面进入策略页,选择回测,填四要素后提交(菜单命名以官方文档为准)。CLI 路径适合写进脚本做批量实验:
# run_bt.sh —— 提交一个回测任务并等待完成(命令形态为示意,以官方文档为准) export PATH="/usr/bin:$PATH" qd backtest run --config backtest_breakout.yaml qd backtest status --watch # 轮询任务状态直到完成 qd backtest report --out report_breakout.json
把"提交—等待—取报告"固化成脚本有两个好处:一是四要素随配置文件进版本管理,半年后你还知道自己当时测了什么;二是 6.2 节的四件套要反复跑不同区间与参数组合,手工点界面不可持续。
注意脚本里不要写死绝对路径与密钥,配置文件里也不要——第 11 章会把这类敏感项统一收进环境变量管理。
| 坑 | 症状 | 修正 |
|---|---|---|
| 零费率零滑点 | 交易越频繁指标越好看 | 按真实账户档位填,滑点保守起步 |
| 区间只覆盖单边行情 | 净值曲线一路向上 | 覆盖至少一段明显回撤期(选区间的责任在你) |
| 数据缺口未处理 | 某些段净值跳变 | 回看第 03 章数据层缺口检查,再选 fill 策略 |
| 初始资金不现实 | 复利路径失真,仓位约束失效 | 按真实可投入资金填 |
| 在钩子里访问未来数据 | 指标好得离谱 | 检查运行时钩子只用当根收盘前可得的数据 |
第五个坑最隐蔽也最致命:任何形式的未来函数(用当根未收盘数据、用次日数据填补当日字段)都会让报告变成自欺工具。引擎会尽量阻止明显的越界访问,但策略层的字段拼装错误仍可能绕过,值得专门用第 05 章的钩子测试清单复查一遍。
单份报告做到配置正确,只解决了"这一测可信"。但一次回测证明不了策略本身可信——你大概率已经试过好几组参数、好几个区间。下一节上四道统计锁:walk-forward、PBO、Deflated Sharpe、Monte Carlo,专门审查"多次尝试之后还剩下的东西"。