第 7 课 · 回测是什么,以及五个作弊漏洞
第 7 课 · 回测是什么,以及五个作弊漏洞
【这课你会明白什么】
- 回测的本质:让规则在历史上”重演一遍”的考场
- 五个最常见的放水漏洞,每个都配”不堵会怎样”
- 一个真实演示:−$23,744 的解剖报告
正文
回测=把一条写死的交易规则放回历史数据里重演一遍,算出”如果当时真这么做,结果如何”。它是想法工厂的考场。考场最大的风险不是考不出来,而是不知不觉给考生放水——回测几乎总是比实盘好看,差距就藏在漏洞里。下面五个漏洞,是我们的回测引擎逐条堵死的:
| 漏洞 | 例子 | 堵法 | 不堵会怎样 |
|---|---|---|---|
| ① 未来函数:用了当时不可能知道的信息 | “收盘价站上均线(最近 N 根 K 线收盘价的平均)就按这根收盘价买入”——收盘价收盘后才知道 | 第 i 根 K 线收盘算信号,第 i+1 根开盘才成交 | 回测虚高,实盘立刻打回原形 |
| ② 零摩擦幻觉 | 不算佣金、滑点 | 每次成交按 1 tick 不利价差+佣金记账(第 4 课口径) | 高频亏钱策略在纸面上变赚钱 |
| ③ K 线内部顺序不可知(第 5 课) | 同一根 K 线里,止损价和止盈价(预设的”赚够就落袋”离场价)都碰到了,先算哪个? | 一律按止损算(对自己最不利的假设) | 挑对自己有利的顺序=系统性放水 |
| ④ 跳空(开盘价直接越过一段价位)穿过止损 | 隔夜开盘直接开在止损价更坏的一侧 | 按更差的实际开盘价成交,不按止损价 | 真实的隔夜大亏被”削”成小亏 |
| ⑤ 限价单触价即成 | 实盘限价单要排队(第 3 课) | 必须穿价才算成交 | 一堆实盘轮不到你的成交混进统计 |
还有第六条:持仓不许穿越数据块边界(第 5 课的空洞),块末强制平仓——不让物理上不可能的持仓路径混进统计。
引擎本身用的是”笨办法”:逐根 K 线往前推,不用任何花哨的批量算法。原因:带止损的交易是”路径依赖”的——这一根发生什么取决于之前的持仓状态,聪明写法极易出错且错了看不出来;笨办法的每笔成交都能手工验算。我们先手算好 7 个场景的标准答案,再让引擎去对——分毫不差。8 万根 K 线跑 2 秒,够用。
解剖演示。我们故意跑了一个教科书式的反面教材:30 分钟均线上穿 120 分钟均线就买、下穿就卖,止损 10 个 tick,当天强平。十个月真实数据,5,610 笔,净亏 −$23,744。拆开看:
| 成分 | 金额 | 每笔平均 |
|---|---|---|
| 策略本身(无摩擦毛利) | ≈ −$1,865 | −$0.33 ≈ 抛硬币 |
| 滑点 | −$14,025 | −$2.50 |
| 佣金 | −$7,854 | −$1.40 |
| 净结果 | −$23,744 | −$4.23 |
三个教训:“有信号”不等于”有优势”(毛利几乎为零);92% 的亏损是摩擦——零期望+高频率=定期向收费站捐款(第 4 课的活标本,5,610 笔里 4,755 笔死在那个 10 tick 的窄止损上,每次止损重付一遍过路费);这个坏消息回测 2 秒就给出,挂模拟盘要等三个月——回测系统真正卖的商品,是廉价而诚实的坏消息。
【与我们项目的连接】
上面每条规则都实现在项目的回测引擎里(backtest.py),7 个手算场景是它的永久考卷。−$23,744 的完整解剖在《初学者手册》第 17 节。往后你在任何报告里看到”净期望”三个字,背后都默认这六条规则全部生效。
【三个自测问题】
- “收盘价突破就按收盘价买入”错在哪里?
- 同一根 K 线里止损和止盈都触发了,为什么必须按止损算?
- 演示策略的最大死因是什么——策略烂,还是别的?
(答案:1. 收盘价在收盘那一刻才确定,拿它当买入价等于用了未来信息;必须下一根开盘才成交。2. K 线不记录内部先后顺序,无法证明止盈在前;选择对自己不利的假设是唯一不放水的做法。3. 别的:策略本身近似抛硬币(−$0.33/笔),真正的死因是 5,610 次交易的摩擦——92% 的亏损是成本。)