回测系统概述

做量化交易这些年,我越来越觉得回测系统是整个策略生命线的起点。说白了,没有靠谱的回测,你的策略就像在黑暗中开车——你根本不知道前方是坦途还是悬崖。

今天咱们聊聊回测系统的核心概念。我会结合自己踩过的坑,帮你把这块地基打扎实。

什么是事件驱动回测

先讲个故事。我刚开始做回测时,用的是最简单的向量化方法。就是把历史价格数据拉下来,算算收益率,觉得策略不错就上线了。结果呢?实盘第一天就亏了3%。

为什么会这样?因为真实市场不是按「收盘价买入,收盘价卖出」这种理想方式运行的。市场是一笔一笔交易组成的,每一笔都有时间戳、有价格、有成交量。

事件驱动回测,就是模拟这种真实的市场行为。它把市场活动拆解成一个个事件:

  • 新的K线数据到达
  • 订单被成交
  • 收到成交回报
  • 定时任务触发

每个事件都会触发相应的处理逻辑。你的策略就像在真实市场中一样,收到数据、做出决策、发送订单、等待成交。

核心区别:向量化回测是「事后诸葛亮」,事件驱动回测是「实时模拟」。

回测在量化交易中的重要性

我见过太多人,策略回测跑出年化50%就兴奋得睡不着觉。结果实盘一个月就亏回去了。为什么?因为回测本身就有很多坑。

回测的重要性体现在三个层面:

  1. 验证策略逻辑:你的策略在历史上是否真的有效?还是只是运气好?
  2. 发现潜在问题:比如滑点、手续费、流动性不足等,回测能帮你提前暴露这些问题。
  3. 优化参数:但这里要小心,过度优化是回测最大的敌人。

我曾经犯过一个低级错误:回测时没考虑手续费,结果实盘被手续费吃掉了大部分利润。从那以后,我每条回测记录都会标注「是否包含手续费」。

事件驱动架构 vs 向量化回测

这两种方法,说白了就是「模拟」和「计算」的区别。我画了张图,帮你直观理解:

回测架构对比 向量化回测 输入:全部历史数据 处理:一次性计算 输出:策略收益曲线 优点:速度快,适合初步筛选 缺点:忽略市场微观结构 事件驱动回测 输入:逐笔事件流 处理:事件循环 + 回调 输出:模拟实盘全过程 优点:贴近真实市场 缺点:速度较慢,实现复杂

你看,向量化回测就像用Excel算账,一次性搞定。事件驱动回测则像模拟经营游戏,每一步都要等事件触发。

两种架构的详细对比

对比维度 向量化回测 事件驱动回测
处理方式 批量计算,一次性处理所有数据 逐事件处理,模拟真实市场节奏
时间精度 通常以日线为单位 可以精确到毫秒级
订单模拟 假设立即成交,忽略滑点 模拟订单簿,考虑成交概率
实现难度 低,几十行代码就能跑 高,需要事件循环和状态管理
适用场景 策略初步筛选、因子研究 高频策略、实盘前验证

我个人习惯:先用向量化回测快速筛选策略,再用事件驱动回测做精细验证。这样既保证了效率,又不会漏掉关键细节。

什么时候该用事件驱动回测

你想想看,如果你的策略涉及以下任何一点,向量化回测基本就靠不住了:

  • 限价单:你的订单可能成交,也可能不成交
  • 滑点敏感:比如高频策略,每笔交易差一个tick就是盈亏之分
  • 多资产联动:不同资产的成交时间不同步
  • 复杂风控:比如日内止损、仓位限制等

嗯,这里要注意。很多人觉得事件驱动回测太麻烦,就用向量化回测凑合。结果实盘时发现,策略在回测中赚的钱,有一半是「假设成交」带来的幻觉。

我曾经帮一个朋友调试策略,他的回测年化收益40%,实盘只有5%。最后发现,他的策略在回测中每次都以最优价成交,但实盘中根本抢不到那个价格。这就是典型的「回测幻觉」。

一个简单的事件驱动回测框架

说了这么多理论,咱们看看代码长什么样。这是一个极简的事件驱动回测框架核心:

class EventDrivenBacktest:
    def __init__(self, strategy, data_feed):
        self.strategy = strategy
        self.data_feed = data_feed
        self.events = []
        self.portfolio = Portfolio()
    
    def run(self):
        # 事件循环
        for event in self.data_feed:
            # 处理市场数据事件
            if event.type == 'MARKET_DATA':
                # 生成信号
                signal = self.strategy.on_data(event.data)
                if signal:
                    # 创建订单事件
                    order_event = OrderEvent(signal)
                    self.events.append(order_event)
            
            # 处理订单事件
            elif event.type == 'ORDER':
                # 模拟成交
                fill = self.simulate_fill(event)
                if fill:
                    # 更新投资组合
                    self.portfolio.update(fill)
            
            # 处理成交回报事件
            elif event.type == 'FILL':
                self.strategy.on_fill(event)
        
        return self.portfolio.get_performance()

这段代码虽然简单,但已经包含了事件驱动回测的核心思想:事件循环、事件类型、事件处理。你想想看,真实市场不就是这样的吗?数据来了,你决策,下单,等成交,再处理结果。

关键点:事件驱动回测的核心不是代码有多复杂,而是它模拟了「决策-执行-反馈」这个闭环。这才是真实交易的本质。

我的建议

如果你刚开始做回测,我的建议是:

  1. 先用向量化回测:快速验证策略逻辑是否合理
  2. 发现问题后转事件驱动:特别是当策略涉及限价单、滑点敏感时
  3. 不要过度追求精度:回测本身就是对真实市场的近似,精度够用就行

记住,回测的目的是帮你发现策略的弱点,而不是证明策略有多牛。我见过太多人把回测做成「数据挖掘」,最后实盘一败涂地。

好了,这一章就到这里。回测系统的地基已经打好了,下一章咱们开始搭建真正的事件驱动框架。

专注资料整理