第 5 课 · Backtesting Engine & Rule Strategies
回测
一条规则不会自动变成策略。
还得把它放进时间、成本和风险里,认真跑一遍。
《AI Agent & Skills 驱动的量化交易工作流》
回测
引擎
规则
信号
目标
权重
执行
权重
成本与
换手
结果与
风险
计算直觉 · 同一份数据,两种推进方式
事件驱动逐步推进;向量化批量计算
事件驱动逐条读事件、更新状态每根 bar 都可能触发订单、成交或持仓状态的变化。
bar₁bar₂bar₃bar₄…
→
向量化先对齐整段数据,再批量算将价格与权重排成数组,交给底层算子统一处理。
targetshift× returnΣ…
CPU 大白话:在支持 SIMD 的 CPU 上,底层库会把一排连续数字排到同一条“多工位流水线”(向量寄存器)上,一条指令让各工位同时做加/乘;快在少了反复逐个交给 Python 的往返,不是少做数学。
点按“下一根 bar”:左边逐条推进;右边显示整段价格、目标权重和延迟后的执行权重如何一次对齐。
两种回测写法 · 怎么选
向量化回测和事件驱动回测怎样选择?
| 维度 | 向量化回测 | 事件驱动回测 |
| 计算组织 | 完整时间序列与权重矩阵批量运算 | 按行情、订单、成交事件推进状态 |
| 擅长场景 | 日频/低频、多资产、规则清楚的研究 | 盘中、订单簿、部分成交、复杂订单生命周期 |
| 优势 | 快、简洁,容易做多标的对照 | 交易流程细节刻画更自然 |
| 代价 | 不适合精细模拟逐笔路径 | 状态更多,开发与测试成本更高 |
本课就用:VectorBacktester。重点是目标权重、时间对齐和成本,不是逐笔撮合。
别忘了:两种写法都可能有未来函数;换成事件驱动也不会自动让结果更可靠。
互动问题 · 30 秒独立判断
改成事件驱动,未来函数就自动没有了吗?
判断题 · 会 / 不会
同一份日线数据里,今天收盘后才生成信号。
把向量化回测改成事件驱动,结果会自动可靠吗?请先选“会”或“不会”,再说一句理由。
点击展开答案
答案:不会。未来函数来自时间对齐错误:不能让今天收盘后才知道的信号,赚到今天收盘前的收益。换成事件驱动也不会自动修正。
先把分工说清楚
一条交易规则,怎样才算能拿来回测?
close < MA(10) → 买入,只回答了一个入场条件。
规则策略用当时已知的信息,生成一份目标权重。
→
回测引擎按同一套时间和成本规则,把目标权重算成结果。
这一课先解决:把一个规则和一台回测引擎跑通;多个因子怎样一起管组合,留到第 6 课。
VectorBacktester · 一台统一的计算器
回测引擎到底帮我们算什么?
输入标准行情MultiIndex
(symbol, eob)
→
→
→
执行VectorBacktester延迟、收益、成本
→
| 位置 | 负责什么 | 不负责什么 |
| strategies/ | 具体交易规则与权重生成 | 另一套收益、成本公式 |
| skills.backtest | 执行权重、逐日收益、成本、metrics | 替策略发明信号 |
| scripts/ | 组合调用、演示与报告入口 | 承载可复用引擎逻辑 |
所有规则最后都会变成同一种权重表,才能放在同一套标准下比较。
引擎原理 · 从权重到结果
动手看:回测引擎怎样把计划写成账?
按“下一步”:策略交出目标权重;引擎再对齐执行、记收益与成本,最后输出逐日账与指标。
进来什么,出来什么
给引擎什么,它会算出什么?
输入:date × symbol 目标权重
| eob | ETF A | ETF B | ETF C |
| 01-02 | .50 | .50 | .00 |
| 01-03 | .00 | .50 | .50 |
| 01-04 | .00 | .50 | .00 |
每一行是当天希望持有的组合;行和小于 1 的部分可理解为现金。
输出:metrics 示例
{
"total_return": 0.187,
"ann_return": 0.105,
"sharpe_ratio": 0.74,
"max_drawdown": 0.092,
"avg_daily_turnover": 0.031,
"total_transaction_cost": 0.012
}
示例数值只展示字典形状;读指标前,仍要先核对权重和逐日账。
不要混淆:行情的索引是 (symbol, eob);策略输出的行是日期、列是 symbol。
互动问题 · 30 秒独立判断
策略交给回测引擎的是什么?
单选题 · 选 A / B / C
策略说:“明天 ETF A 持 60%,ETF B 持 40%。”
A. 最终净值 B. 目标权重表 C. 交易成本
点击展开答案
答案:B,目标权重表。策略负责目标权重;引擎再负责执行延迟、收益、成本和指标。
时间对齐 · 先上车,才开始计里程
先有信号,再成交,最后才赚到这段收益
D1 收盘后生成目标只能使用截至 D1 已知的数据。
→
signal_lag = 1D2 close 执行目标后移一根 bar,才变成执行仓位。
→
D2 → D3 close赚这段变化执行日的仓位,记下一根 bar 的价格变化。
signal_lag目标在几根 bar 后才执行?
trade_at执行使用 open 还是 close 价格序列?
forward return执行仓位只赚之后一根 bar 的收益。
执行日 t 这一行赚:price[t+1] / price[t] − 1。收盘才知道的信号,不能倒过来赚当天收盘前的收益。
时间对齐 · 用一条时间线确认
改 lag,收益究竟移到哪里?
先预测 D1 的目标怎样落到执行日,再调整 lag,观察执行权重和收益区间如何一起后移。
逐日账 · 先算收益,成本下一页再扣
先把一行毛收益算清楚
| 资产 | D2 执行权重 | D2 → D3 收益 | 贡献 |
| A | 60% | +2% | +1.2% |
| B | 40% | −1% | −0.4% |
毛收益 = 0.6 × 2% + 0.4 × (−1%)
= 0.8%
这是教学手算示例。最后一根 bar 缺少后续价格,不能凭空产生下一期收益。
交易摩擦 · 每次调仓都要算成本
成本在每次调仓时发生
turnoverₜ = Σ |weightₜ − weightₜ₋₁|
transaction_costₜ = turnoverₜ × (commission + slippage)
net_returnₜ = raw_returnₜ − transaction_costₜ
权重不变成本测试中目标/执行权重应相同
换手不变成本参数不应改变调仓行为
成本改变transaction_cost 应随假设提高
结果改变净收益与回撤可能受到影响
看结果 · 别只盯着曲线
跑完回测,先看哪几样东西?
total_return整段累计赚亏
max_drawdown从高点到低点的最大跌幅
avg_daily_turnover平均每天改多少仓
total_transaction_cost假设下累计扣了多少成本
只复制 total_return,无法证明规则、执行、成本和风险真的彼此对得上。
规则案例 · 先看一次真实回测
低于 MA10 做多,ATR 止损只升不降
规则不同,接口一样
规则不同,为什么可以共用同一引擎?
| 环节 | 横截面均值回归 | MA/ATR 单标的 | 是否统一 |
| 信息处理 | 多标的排序、Top N | 入场/退出状态机 | 否,属于策略 |
| 目标权重 | 多列、多个持仓 | 单列、0 或 1 | 是,date × symbol |
| 执行 | signal_lag 与 trade_at | signal_lag 与 trade_at | 是 |
| 记账 | 收益、换手、成本、指标 | 收益、换手、成本、指标 | 是 |
具体菜谱strategies/ 里定义“什么条件 → 什么目标权重”。
→同一台秤与同一本账skills.backtest 用统一的执行和指标口径比较不同菜谱。
互动问题 · 30 秒独立判断
两套规则,什么可以共用?
单选题 · 选 A / B / C
MA/ATR 单标的规则和多标的 Top N 规则,都要进入同一台回测引擎。
A. 入场条件 B. 目标权重表格式 C. 参数数值
点击展开答案
答案:B,目标权重表格式。信号和参数属于策略;两者都能交出 date × symbol 权重,因此可共用执行、成本和记账。
课后练习 · 指定指数研究
对中证全指自由现金流全收益指数 932365CNY010.CSI,开发规则策略要求策略绩效超过 Buy and Hold
研究任务
从指数走势出发,提出可复现的规则
1统计与分析
先让 AI 做数据统计和分析,再根据统计结果开发策略。
2规则
明确入场、退出、仓位与调仓条件。
3回测
设置 signal_lag、佣金与滑点。
4证据
报告净值、回撤、换手、成本和失效场景。
对应 ETF(均跟踪价格指数 932365):563390 华泰柏瑞 · 159232 南方 · 159233 平安 · 512130 鹏华 · 159235 大成 · 159236 工银瑞信 · 561080 华安 · 561870 华富 · 563760 中银 · 563770 招商 · 563780 方正富邦 · 563830 博时 · 563620 兴业