← 返回教程库

回测里你每根 K 线看一眼盘,实盘里你每几秒看一眼

最后更新 2026-08-19
📚 量化与 AI 投研 📖 回测与实盘为什么对不上 ⏱ 约 21 分钟 R2 · 注意风险
你将学到
  • 说得出判断频率的差异具体会造成哪四类行为差异,而不是笼统地说「回测粒度粗」
  • 理解一份回测报告里的成交明细,有一部分是系统「替你猜出来的路径」,并知道这个猜测被写在哪里
  • 会用「持仓时长除以 K 线长度」这把粗尺子,判断一份报告受这条影响是轻还是重

有人把两份成绩单摆在你面前。左边是回测:这一年做了四十来笔交易,离场原因那一栏,「止损」占了大半。右边是他真金白银跑了一个月的对账单:一个月就做了六十多笔,离场原因五花八门,止损反倒不多。

他挠头说,我一个字都没改啊。

他说的是实话,代码确实一个字没改。但这两份成绩单本来就不该长得一样——因为它们回答的根本不是同一个问题。左边那份回答的是「假如我一小时抬一次头看盘,会做出什么动作」,右边那份回答的是「假如我几秒钟抬一次头,会做出什么动作」。

这件事在 回测好看实盘亏,差的到底是哪三件事 里已经点过名,那篇给的是全局地图,三处差异各占一格。这一篇只干一件事:把「判断频率」这一格拆开,看看它到底会长出哪几类具体的行为差异。至于费率档位那一格,归 回测按贵宾价算账,实盘按你的真实价算账;指标启动期那一格,归 指标的启动期。这篇一概不碰,免得三条搅在一起,你哪条都没记住。

先把立场说清楚:下面写到的所有系统行为,都来自我对本地源码与文档快照的阅读,不是我跑通了程序拿到的实测结果。我要给你的是「这个概念在真实系统里长什么样」,以及你作为一个要掏钱的人该怎么想它。

差异不是「粗一点」,是四类不同的动作

很多人对这件事的理解停在「回测粒度粗,所以不够精确」。这个理解太温和了,它让你以为差异是一个可以忽略的小数点。

实际情况是:判断频率一变,规则做出的动作类别就变了。不是同一件事做得糙一点,是有些事根本没做、有些事做了很多遍、有些事做的时机完全不同。下面四类,我一类一类拆。

第一类:一根 K 线里价格来回穿,回测只能判一次

先打个比方

假设你家门口装了个监控。但这个监控很特别,它不存录像,一小时只存四张照片:这一小时刚开始的样子、这一小时里画面最亮的一瞬间、最暗的一瞬间、这一小时结束的样子。

现在有人问你:这一小时里,快递员是先来的还是收废品的先来的?

你答不上来。你手上只有四张照片,没有顺序。你只能猜——而且你猜的那个顺序,会直接决定你接下来的判断。

K 线就是这四张照片。一根小时线,记的是这一小时的开盘价、最高价、最低价、收盘价,四个数。它不记录顺序。 价格是先跌到最低再涨到最高,还是先冲到最高再砸到最低,这根柱子里没有这个信息。

这对你的判断意味着什么

你的规则里但凡有两条以上会在同一根 K 线里被触发,回测就必须替你决定「谁先发生」。而这个决定,直接改写你的成交记录。

举个不需要代码就能想明白的场景。你手上有一笔仓位,你设了一条止损线在下方,也设了一条止盈线在上方(止盈就是赚到一定幅度主动了结)。这一小时里,价格既碰到了下面的止损线,也碰到了上面的止盈线——最低价穿过了止损,最高价穿过了止盈。

这一笔到底是赚的还是亏的? 完全取决于价格先碰哪一条。而 K 线不告诉你先碰哪一条。

实盘里没有这个问题:价格一秒一秒地走,先碰到哪条就是哪条,事实只有一个。回测里必须有个规矩,否则程序跑不下去。于是系统就定了一条规矩——而这条规矩,就是你那份成绩单里一部分数字的真正来源。

请把这句话记牢:一份回测报告的成交明细里,有一部分不是历史事实,是系统按一条预先写好的规矩推演出来的。

它在系统里长什么样

freqtrade 是一个公开的自动交易框架。它的回测文档里有整整一节,标题直译过来就是「回测所做的假设」,开头一句话说得很坦白:因为回测缺少 K 线内部发生了什么的细节信息,所以它需要做出一些假设。

这一节里跟顺序有关的几条,我挑三条讲给你听。

第一条:判定止损时,假设「低点先于高点发生」,理由写的是优先保护本金。 也就是说,在止损这件事上,系统故意往悲观的方向猜——先假设你被打到了最低点。这是一条保守的假设,对你有利,因为它不会让你高估策略。

第二条:判定追踪止损时,假设「高点先发生」。 追踪止损是那种止损线会跟着价格往上爬的止损,机制细节在 追踪止损 里讲得更透。在这里,系统先用最高价把止损线往上抬一格,再拿抬过的止损线去对最低价。文档里说这样做是为了让「高低差很大的那种 K 线」被正确回测。

你有没有注意到什么不对劲?同一根 K 线,在判止损的时候被假设成「先跌后涨」,在判追踪止损的时候被假设成「先涨后跌」。 这不是系统写错了,两条假设各有各的合理性,是分别针对两类规则做的取舍。但对你这个看报告的人来说,含义很清楚:你手上那根柱子,在成绩单的不同格子里被当成了不同的走法。 现实里它只有一种走法。

第三条最值钱,因为它是系统主动交代的后果。 文档里写着:在同一根 K 线内,止损的判定排在止盈之前,所以你常常会看到,同一套策略在回测里因「止损」而离场的笔数,比模拟盘和实盘跑出来的多。

停下来体会一下这句话的分量。这不是用户在论坛上的抱怨,是框架作者在官方文档里主动写下的一句「我这里会跟实盘不一样,而且我知道往哪个方向不一样」。它甚至连偏差的方向都告诉你了。

回到开头那两份成绩单:左边回测里止损占大半、右边实盘里止损不多,这不是那个人运气不好,这是一个被写进说明书的已知现象。

文档里还列了一条更直白的规矩:如果同一根 K 线上同时冒出好几种信号,判定的先后顺序是固定的——离场信号排第一,然后是止损,然后是止盈,最后是追踪止损。实盘里没有这个顺序表,实盘的顺序是时间顺序,谁先到谁算数。

第二类:「当前价」这三个字,在两边不是同一个东西

先打个比方

你和朋友约好,「现在气温超过三十度就别出门」。

你出门前伸手到窗外试了试,二十八度,出门了。你朋友打开天气预报,看到「今日最高温 34 度」,认定超了,没出门。

你俩守的是同一条规矩,用的是同一个词——「现在的气温」。但一个人查的是此刻,另一个人查的是今天最热的那一刻。同一个词,两个含义,两个动作。

这对你的判断意味着什么

你的规则里凡是出现「当前价」「此刻的浮盈」「现在赚了多少」这类说法,你都要多问一句:这个「当前」,在回测里指的是哪一个瞬间?

答案可能会让你意外:在某些环节里,回测喂给你规则的「当前价」,是这根 K 线里对你最有利的那个价。

这意味着什么?意味着任何写成「赚到某个幅度就动手」的规则,在回测里,判定条件用的是这根柱子里的最好情况。柱子里的浮盈只要有一瞬间摸到过那个幅度,条件就成立了——哪怕那一瞬间转瞬即逝,哪怕收盘时早就跌回去了。

而在实盘里,这条规则被问了几百遍,每一遍问的都是货真价实的此刻。价格摸高的那一秒,程序不一定正好在那一秒抬头。

它在系统里长什么样

freqtrade 里有一类叫「自定义止损」的功能,说人话就是:让你自己写一段逻辑,每次被问到的时候告诉系统「现在止损应该放在哪」。文档里明确写着,这段逻辑在模拟盘和实盘里,对每一笔未平仓的交易,每一轮循环都会被问一次——而循环大约每几秒转一圈(文档给的是默认值,可以改,以你手上那个版本为准)。回测里,它每根 K 线只被问一次。

关键在下一句。文档说:回测时,传给这段逻辑的「当前价」和「当前浮盈」,用的是这根 K 线的最高价(做空则是最低价);而算出来的那条止损线,是拿这根 K 线的最低价去检验的。

一进一出,用的是这根柱子的两个极端。输入取最有利的那一端,检验取最不利的那一端。

我不想让你把这个当成「系统在坑你」——恰恰相反,这个组合整体是偏保守的,它在故意压低回测成绩。我想让你看见的是另一件事:在这一格里,「当前价」根本不是一个时刻,它是一根柱子的两个端点。 一个在时间上被摊平的词,被你当成了一个具体的瞬间。

顺着这条线往下想,你就会明白一个常被误解的现象:为什么有些人的策略在回测里止损从来没被真正考验过,实盘里却动不动就被扫。因为那条止损线在回测里是从最有利的价格往下量的,量出来的位置偏高偏远,看着很安全。

第三类:一条「松」的规则,在回测里响一声,在实盘里响几百声

这一类是四类里后果最烈的,也是最容易在真实账户上炸开的。

先打个比方

你家装了两种灯。

一种是床头的闹钟,设了七点,七点响一次,你按掉,完事。 另一种是楼道的感应灯,只要有人在动,它就一直亮着,亮到没人为止。

现在你写了一条规矩:「有人在,就开灯。」这条规矩装在闹钟上,一天开一次。装在感应灯上,一整天都在开。

规矩一个字没变,装在什么频率的东西上,行为天差地别。

这对你的判断意味着什么

交易规则分两种写法,多数人从没意识到这个区别。

一种叫边沿触发:「刚刚跌破某条线的那一下」才算数,穿过去之后就不再算了。 另一种叫电平触发:「只要现在还在线下面」就算数,一直算数。

在按 K 线推进的回测里,这两种写法的差别常常看不出来——因为一根 K 线只判一次,判完就走,电平写法也只响了一声。你看着报告,觉得这条规则挺乖。

到了每几秒转一圈的实盘里,两者就分道扬镳了。电平写法会一遍又一遍地成立,一遍又一遍地触发动作。同一根 K 线的时间里,它可能触发几百次。

这对哪类规则最危险?对所有「再买一点」「再补一手」的规则。加仓、补仓、网格式的分批建仓——它们的共同点是:触发之后,仓位变大了,但触发条件本身没有被消灭。价格还在那儿,指标还在那儿,条件还成立。于是下一轮循环,它再买一次。

它在系统里长什么样

freqtrade 文档里有个用红色危险标记的警告框,标题叫「松散的逻辑」。它讲的例子朴素得可怕:假如你写的是「上一根 K 线的某个指标低于某个数值就加仓」,那么在模拟盘和实盘里,这个函数每隔几秒就会被调用一次,你的机器人会每隔几秒就多加一次仓,直到你的钱花光、或者撞上加仓次数上限、或者等到新的一根 K 线出现、指标不再满足条件为止。文档还提醒,分批离场也会犯同样的毛病。

请注意它给的这个反面例子有多么无辜:「指标低于某个数值就加仓」——这句话在任何一本入门书里都像是一条正常的规则。它在回测里也表现得像一条正常的规则,因为回测每根 K 线只问它一次。

同一份文档在同一个功能的另一个警告框里,把这句话说成了机制层面的结论:回测每根 K 线只能调整一次仓位,而实盘一根 K 线之内可以调整很多次,因此两边结果会有偏离。

我想让你从这一条里带走的不是「加仓很危险」,而是一个更普适的追问角度:看一条规则,别只看它说了什么,还要看它触发之后,触发的理由消失了没有。 理由不消失的规则,在高频判断下会自我循环。这个道理不需要你会写代码,你只需要在别人向你解释策略的时候,多问一句:这条规则触发之后,还会不会继续成立?

第四类:交易笔数对不上,是因为「名额」被占的时间不一样

先打个比方

一家只有一张桌子的小餐馆。

老板 A 的规矩是:客人来了坐下,一个整点算一桌,就算你十分钟就吃完走人,这张桌子也得空到下个整点才接新客。 老板 B 的规矩是:吃完就走,走了立刻接下一位。

同样的客流,同一天下来,老板 B 接的客人数量能是老板 A 的好几倍。桌子还是那一张,规矩还是「一次一桌」,变的只是「桌子什么时候算腾出来」。

这对你的判断意味着什么

大多数策略都有一个同时持仓数量的上限——同一时间最多拿几个品种。这个上限就是餐馆的桌子数。

在按 K 线推进的回测里,一笔交易占住的名额,往往要等到这根 K 线走完才算腾出来。而实盘里,仓位平掉的那一秒,名额就空出来了,下一个信号立刻可以进来。

后果有两层。第一层是笔数对不上:实盘的交易笔数可能远多于回测。第二层更隐蔽——那些在回测里压根没机会出现的交易,你无从知道它们是赚是亏。 报告没有为它们留下任何痕迹。一份成绩单最危险的地方,从来不是它算错的那些数,而是它根本没写进去的那些事。

还有一个更少人知道的角落:当同一根 K 线上同时冒出的信号数量超过名额时,粗粒度的回测只会评估排在前面的那几个。排在后面的那些信号,直接消失,不留痕迹。

它在系统里长什么样

freqtrade 文档里给了一个刻意做出来的极端例子,用来展示同一段行情在两种判断粒度下的差别。设定是同时只允许持有一笔仓位,几个品种在同一根小时线上同时出现了入场信号。

按小时判断,这段时间总共产生 2 笔交易,每笔持仓一小时。 换成按五分钟判断,同一段时间产生 5 笔交易,持仓时长分别是 5 分钟、10 分钟、15 分钟、50 分钟、55 分钟。

同一份历史数据,同一套规则,一个说 2 笔,一个说 5 笔。文档自己给这个差别的定性是「significant」,也就是显著。它给出的原因正是上面那两条:粗粒度下每根 K 线只评估名额上限之内的那几个信号,而且名额要到 K 线结束才释放。

我要提醒你注意的是:这不是一个 bug 报告,这是官方文档里主动放出来的一个演示。一份成熟的系统说明书会给你看它自己最难看的那一面。 你手上那份向你推销的报告,有没有给你看过任何一个「换个算法参数,结果就大变」的对照?

把四类合起来:为什么高频策略被伤得最重

前面四类分开看都像技术细节。合起来算一笔账,你就能得到一把真正能用的粗尺子。

关键的比值只有一个:你的平均持仓时长,除以一根 K 线的长度。

  • 一个用日线判断、平均持仓半年的策略,这个比值大概是一百多。K 线内部那段「看不见的路径」,只占了整段持仓的百分之一不到。上面四类差异有发生的余地,但摊到整条曲线上,基本淹没在噪音里。
  • 一个用五分钟线判断、平均持仓两三根 K 线的策略,这个比值是个位数。这意味着你这笔交易的大部分命运,都发生在系统看不见、只能靠假设去填的那些区间里。

比值越小,回测里「假设」的成分占比越大。当比值小到接近 1,你那份报告基本上是一份假设的产物,而不是一份历史的记录。

这就是「频率越高的策略受这个影响越大」这句话的具体含义。它不是一句模糊的经验,它可以被你用一个除法估出来。而这个除法你不需要代码,只需要问对方两个数:你的 K 线周期是多少,平均持仓多久。

顺带说一句,判断频率高低本身还牵扯着另外一整套权衡——成本、容量、信号新鲜度,那是 调仓频率 这个词条负责的事,这里只谈失真。

缓解的办法:从「每小时看一眼」改成「每五分钟看一眼」

有没有办法把这四类差异压小?有,但只是压小。

思路简单得几乎粗暴:既然差异来自「看得太稀」,那就让回测看得密一点。freqtrade 提供了一个开关,允许你在按小时线做判断的同时,让那些「可能发生动作」的时段用五分钟数据重新推演一遍。命令行上就是给回测命令追加一个 --timeframe-detail 参数。

它带来的变化是实打实的:那些回调函数会按细粒度被反复调用——按一小时配五分钟算,一根主 K 线内就是十二次,而不是一次。上面那个 2 笔变 5 笔的例子,正是这么跑出来的。

但你要清楚三件事:

一,它有代价。 细粒度数据体积大得多,占内存、拖运行时间,而且这些数据你得先有。

二,它没有消灭问题。 从每小时看一眼改成每五分钟看一眼,只是把「看不见的暗区」从一小时缩到五分钟。实盘是几秒一次,暗区还在那儿,只是变窄了。想把暗区彻底填平,你需要逐笔的成交记录,而那已经是另一个量级的工程了。

三,也是最有用的一条——文档里给了一句可以直接拿来当尺子的提示:把这个开关当作策略开发的最后一步,用来确认你的策略没有在利用回测的那些假设占便宜;在这个模式下表现依然不错的策略,才有比较大的希望在模拟盘和实盘里也表现不错。

这句话给了你一个不需要懂代码就能提出的要求:「你有没有用更细的粒度复核过?两版结果差多少?」 请注意这个问法的精髓——你要的不是「我复核过」这三个字,你要的是两个数的对比。差得少,说明这套策略不靠假设吃饭;差得多,说明它的收益有相当一部分来自回测看不见的那段路。答不上来,说明根本没做。

同样的追问也适用于成交本身能不能成的问题,那属于另一类假设,回测里的成交假设 讲得更细;而每一笔成交价上的那点损耗,在 滑点 里。想看看一个自动交易程序开机之后每一轮到底在忙什么,交易机器人开机之后,它一整天到底在忙什么 把那个循环整个翻译了一遍。

你能问出口的四个问题

不需要你会读代码,只需要你听得懂对方有没有绕开。

第一问:你的 K 线周期是多少?平均一笔持仓多久? 用这两个数做个除法,你就知道这份报告里「假设」的分量有多重。比值是三位数,这条基本可以放过;比值是个位数,后面三问一个都不能省。

第二问:如果一根 K 线里止损和止盈都被碰到,你的回测判谁赢? 这个问题问的不是技术细节,是对方知不知道系统替他做过这个决定。答「不知道」不丢人,答「这不重要」就要警惕了——因为它直接决定了那些交易记在赚的一栏还是亏的一栏。

第三问:你的规则里有没有「只要条件还成立就一直动手」这种写法? 特别针对加仓、补仓、分批建仓类的规则。追问一句:触发之后条件会消失吗?如果不会,实盘里它每隔几秒就会再来一次,而回测里它一根 K 线只来一次。

第四问:有没有用更细的粒度复核过?两版的交易笔数和收益各差多少? 这一问是前三问的总检验。拿不出两个数的对比,前面三问的答案都只是嘴上功夫。

⚠️ 风险提示

本节讲的是回测系统与实盘系统在判断频率上的机制差异,不构成任何投资建议、买卖信号或收益承诺。文中出现的所有回测结果与数量对比,均来自公开文档中用于说明问题的演示例子,回测不等于实盘,任何回测数字都建立在一整套关于成交、成本和价格路径的假设之上,其中一部分假设已经在本文中被点名。把这些假设全部处理干净,也只是让报告不那么失真,它依然不能预测未来。完整风险提示见 免责声明

小结

  • K 线只记四个价,不记顺序。所以回测在判断「一根 K 线里谁先发生」时,必须按一条预先写好的规矩去推演——你成绩单里的一部分数字,来自这个推演,而不是来自历史。
  • 同一根 K 线,在判普通止损时被假设成先跌后涨,在判追踪止损时被假设成先涨后跌。这不是错,但意味着现实里唯一的那条路径,在报告的不同格子里被当成了不同的走法。
  • 「当前价」在回测的某些环节里指的是一根柱子的极端值,不是一个瞬间。任何「赚到某个幅度就动手」的规则,都要警惕这个词在两边的含义漂移。
  • 写成「只要条件还成立就动手」的规则,在回测里一根 K 线响一次,在实盘里每几秒响一次——加仓类规则会因此一路加到钱花光,而这在回测报告里完全看不出来。
  • 名额释放的时机不同,会让实盘的交易笔数远多于回测;更麻烦的是,那些回测里没机会发生的交易,你连它们是赚是亏都无从知道。
  • 一把粗尺子:平均持仓时长 ÷ K 线长度。比值越小,这份报告里假设的成分越重。这解释了为什么高频策略受这条影响最大。
  • 缓解手段是用更细的粒度重跑一遍,但那只是把暗区变窄,不是填平。真正该向对方要的,是两版结果的差值,不是一句「我复核过」。

一句话说完这篇:看盘的间隔一变,同一条规矩就会做出不一样的事——所以别问「回测准不准」,要问「这份报告里,有多少是它亲眼看见的,有多少是它替你猜的」。

内容有错、看不懂、或想看下一篇?告诉我们 →

本文为投资教育整理,不构成任何投资建议;不荐个股/基金、不预测点位、不承诺收益。关键数据与结论请结合权威来源自行验证,并见风险免责声明