Skip to content

第16章 回测频率陷阱:日线回测 vs 分钟线回测——高频策略在低频回测中的失真

做量化的人,十有八九都掉进过这个坑。

我自己就栽过。几年前我写了一个高频策略,逻辑是捕捉盘口挂单的瞬间失衡。回测时图省事,用了日线数据。结果呢?回测曲线漂亮得像教科书,年化收益40%,最大回撤不到5%。我差点以为自己找到了圣杯。

实盘一跑,直接傻眼。一个月亏了12%。

问题出在哪?频率。日线回测根本看不到分钟级别的博弈。说白了,你用日线去验证一个秒级策略,就像用年历来预测明天的天气——颗粒度完全不对。

为什么低频回测会失真?

我们先看一个最简单的例子。

假设你有一个策略:当价格突破前5分钟高点时买入,跌破前5分钟低点时卖出。这个策略在分钟线上逻辑清晰,但如果你用日线回测,会发生什么?

日线只有四个价格:开盘、收盘、最高、最低。你根本不知道价格在一天之内是怎么走的。也许开盘后先冲高再回落,日线显示的是长上影线。你的策略可能在开盘就触发了买入,然后收盘前止损。但日线回测会告诉你:今天最高价没突破昨天最高价,所以没交易。

嗯,这就是失真的根源。

核心问题: 低频数据丢失了高频交易的时间顺序和价格路径信息。回测结果与真实交易之间,隔着一道无法逾越的信息鸿沟。

高频策略在低频回测中的三大失真

我总结了三种最常见的失真情况,你对照一下自己的策略,看看中了几条。

1. 信号延迟失真

高频策略依赖的是实时价格。比如你监控的是1分钟K线,信号在 09:31:15 出现。但日线回测中,这个信号会被"压缩"到当天的一个点上。你无法判断信号是在开盘、盘中还是收盘出现的。

结果就是:回测中信号出现的位置,和实际交易中完全不一样。

我曾经回测一个基于1分钟RSI的策略,日线回测显示胜率68%。换成1分钟数据后,胜率掉到51%。为什么?因为日线把很多盘中假突破的信号"美化"了。

2. 滑点与成交率失真

高频策略对滑点极其敏感。一个策略如果每次交易只赚0.1%,滑点0.05%就吃掉一半利润。但日线回测中,你通常只能设置一个固定滑点,比如0.1%。

实际情况呢?高频交易时,滑点会随着市场波动剧烈变化。行情好的时候滑点小,行情差的时候滑点大。日线回测完全模拟不出这种动态变化。

注意: 很多人在日线回测中设置0.1%滑点就觉得够了。但高频策略的真实滑点可能是0.3%甚至更高。回测中的"稳健"在实盘中不堪一击。

3. 资金容量失真

这个坑更大。高频策略的资金容量通常很小。你用一个日线级别的策略,可能每天只交易1-2次,资金容量几千万没问题。但高频策略可能每天交易几十次甚至上百次,每次只吃几个tick的利润。

日线回测中,你根本看不到成交量的限制。你假设每次都能按理想价格成交。但实盘中,你的订单可能直接把价格打穿,或者根本成交不了。

我见过一个朋友,他的高频策略在日线回测中表现完美。实盘时,他投入了500万。结果第一天就亏了8万。原因很简单:他的策略在某个价位上需要买入100手,但那个价位的挂单只有30手。剩下的70手只能追高,成本直接拉高。

如何规避频率陷阱?

说了这么多问题,总得给点解决方案。我个人习惯用下面这套方法,你可以参考。

方法一:使用匹配频率的数据

这个道理很简单,但很多人就是做不到。如果你的策略是分钟级别的,就用分钟数据回测。如果是秒级的,就用tick数据。

别偷懒。我见过太多人用日线回测分钟策略,然后自我安慰说"差不多"。差很多。

策略类型 推荐回测频率 最低要求
日内高频(持仓<1小时) 1分钟或tick 5分钟
日内中频(持仓1-4小时) 5分钟 15分钟
隔夜策略(持仓1-5天) 30分钟或60分钟 日线
中长线(持仓>5天) 日线 日线

方法二:做频率敏感性测试

这个是我自己摸索出来的。拿到一个策略后,我会用不同频率的数据去跑一遍。

比如一个策略,我用日线跑一次,60分钟跑一次,30分钟跑一次,15分钟跑一次。如果结果差异很大,说明策略对频率敏感,需要谨慎。

如果差异很小,那恭喜你,策略比较稳健。

小技巧: 频率敏感性测试的阈值可以这样设:相邻频率之间的收益差异超过20%,就要警惕了。比如日线收益20%,60分钟收益16%,差异20%,问题不大。但如果日线20%,60分钟只有10%,差异50%,这个策略基本不能用于高频。

方法三:引入微观结构模拟

这是高阶玩法。如果你真的要做高频策略,光靠K线数据是不够的。你需要模拟订单簿的微观结构。

简单说,就是模拟真实交易中,你的订单进入市场后,会对价格产生什么影响。这需要用到Level 2数据,也就是逐笔成交和挂单数据。

代码示例(伪代码):

# 模拟订单簿影响
def simulate_order_impact(order_size, order_book):
    # 获取当前最优买卖价
    best_bid = order_book['bids'][0][0]
    best_ask = order_book['asks'][0][0]

    # 计算订单对价格的影响
    # 假设你的买入订单会吃掉卖一、卖二...
    remaining = order_size
    avg_price = 0
    for level in order_book['asks']:
        price = level[0]
        volume = level[1]
        if remaining <= volume:
            avg_price = (avg_price * (order_size - remaining) + price * remaining) / order_size
            break
        else:
            avg_price = (avg_price * (order_size - remaining) + price * volume) / order_size
            remaining -= volume

    # 返回实际成交均价和理想价格的差异
    slippage = (avg_price - best_ask) / best_ask
    return slippage

这个模拟虽然不完美,但比日线回测里固定滑点的方式强太多了。

一个真实的案例

最后分享一个我自己的教训。

2019年,我开发了一个基于1分钟K线的统计套利策略。回测时用了日线数据,结果年化收益35%,夏普比率2.8。我信心满满地上了实盘。

结果呢?第一个月收益只有4%,而且最大回撤达到了8%。我仔细排查后发现,问题出在信号同步上。日线回测中,两个品种的信号是同时出现的。但实盘中,1分钟级别的信号会有几秒到几十秒的延迟。就是这几秒的延迟,让策略的收益大打折扣。

后来我改用1分钟数据重新回测,年化收益降到了18%,夏普比率1.2。这才是真实水平。

嗯,从那以后,我再也不敢用低频数据回测高频策略了。

总结

回测频率陷阱,说白了就是数据颗粒度不匹配的问题。高频策略用低频数据回测,就像用望远镜看显微镜下的世界——看到的全是假象。

记住三条原则:

  • 策略频率决定回测频率,别偷懒
  • 做频率敏感性测试,看策略是否稳健
  • 高频策略一定要模拟微观结构,别用固定滑点

你想想看,如果你的策略在日线上表现完美,但在分钟线上表现平平,那它到底算不算一个好策略?答案你自己心里清楚。


公众号:蓝海资料掘金营,微信deep3321