回测系统核心架构:四大模块的职责划分

做高频交易回测,说白了就是模拟真实市场环境,验证你的策略到底能不能赚钱。我见过太多人一上来就写策略代码,结果回测数据对不上、执行延迟算错、分析结果全是坑。嗯,这其实都是架构没想清楚。

今天我就带你拆解一下回测系统的核心架构。我个人习惯把系统分成四层:数据层、策略层、执行层、分析层。每一层各司其职,层与层之间通过标准接口通信。你想想看,这样设计的好处是什么?——任何一个层出了问题,你只需要替换那一层,不用动其他代码。

核心原则:层与层之间只通过数据对象通信,不共享内存状态。这是避免「牵一发而动全身」的关键。
高频交易回测系统 — 四层架构图 数据层 行情数据 · 订单簿 · 交易记录 · 数据清洗与对齐 策略层 信号生成 · 订单决策 · 参数管理 · 风险控制 执行层 订单路由 · 撮合模拟 · 滑点模型 · 延迟模拟 分析层 绩效指标 · 归因分析 · 风险度量 · 可视化报告 数据流方向:数据层 → 策略层 → 执行层 → 分析层 每层通过标准接口通信,支持模块化替换与扩展

1. 数据层:回测的基石

数据层是整个系统的地基。地基不稳,上面盖什么都白搭。我在项目中遇到过最头疼的事,就是回测跑出来收益惊人,结果发现是数据里混了未来信息——tick 数据的时间戳对错了时区。

数据层要干三件事:

  • 数据获取与存储:从交易所、数据供应商拉取行情数据。高频交易通常需要 Level 2 甚至 Level 3 的 tick 级数据。
  • 数据清洗与对齐:去掉异常 tick、处理缺失值、对齐不同品种的时间轴。这一步最容易被忽视,但坑最多。
  • 数据接口封装:对外提供统一的查询接口,比如 get_ticks(symbol, start, end)。策略层不需要关心数据是从 CSV 读的还是从数据库拉的。
我的建议:数据层一定要做「时间对齐」。不同交易所的 tick 到达时间不一样,如果你直接按时间戳拼接,很容易引入前视偏差。我曾经因为这个 bug 白忙了两个月。

2. 策略层:你的交易大脑

策略层是大家最熟悉的部分。说白了,就是写你的交易逻辑。但很多人把策略层搞得太重,什么数据清洗、订单管理全塞进来,最后代码乱成一锅粥。

策略层只负责两件事:

  1. 信号生成:根据数据层提供的行情,计算买卖信号。比如均线金叉、波动率突破、订单簿不平衡等。
  2. 订单决策:信号来了,要不要下单?下多少?要不要加风控检查?

举个例子,一个简单的做市策略:

class MarketMakingStrategy:
    def on_tick(self, tick):
        # 计算最优买卖价
        bid_price = tick.mid_price - self.spread / 2
        ask_price = tick.mid_price + self.spread / 2
        
        # 检查库存风险
        if self.position > self.max_position:
            return  # 不再买入
        
        # 生成订单
        self.send_order(side='buy', price=bid_price, qty=100)
        self.send_order(side='sell', price=ask_price, qty=100)
注意:策略层不要直接操作订单簿或账户信息。它只负责「决策」,不负责「执行」。把执行细节交给下一层。

3. 执行层:模拟真实交易环境

执行层是回测系统里最容易出偏差的地方。你想想看,策略说「我要以 10.00 元买入 1000 股」,但真实市场里可能根本没人卖给你,或者成交价滑到了 10.02 元。执行层就是模拟这个过程。

执行层核心模块:

模块 职责 常见坑点
订单路由 将策略订单发送到模拟撮合引擎 订单类型支持不全(如冰山订单)
撮合模拟 根据订单簿数据模拟成交 未考虑盘口深度,导致成交价过于理想
滑点模型 模拟市场冲击和延迟造成的价格偏差 滑点参数设置过于随意
延迟模拟 模拟网络延迟、交易所处理延迟 忽略延迟会导致策略「预知未来」

我记得有一次帮朋友调试回测,他的策略年化收益 300%,我一查执行层——好家伙,撮合用的是「最优价成交」,完全没考虑盘口深度。真实市场里,大单进去价格早被打飞了。

核心原则:执行层要「悲观」一点。宁可低估收益,也不要高估。回测里赚 10%,实盘可能亏 5%。把滑点和延迟往大了设,跑出来的结果才可信。

4. 分析层:回测的照妖镜

分析层是最后一步,也是很多人草草了事的一步。跑完回测看一眼收益率就完事了?太天真了。分析层要回答三个问题:

  • 赚了多少?——总收益率、年化收益率、夏普比率、最大回撤。
  • 怎么赚的?——归因分析:是方向性交易赚的,还是做市赚的?是高频信号贡献大,还是低频信号贡献大?
  • 风险有多大?——VaR、CVaR、持仓集中度、换手率。

我个人习惯在分析层加一个「压力测试」模块。把历史极端行情(比如 2010 年闪电崩盘、2020 年 3 月流动性枯竭)喂进去,看看策略会不会爆仓。这个步骤能帮你筛掉 80% 的伪策略。

一个小技巧:分析层不要只看最终结果。把每天的收益、持仓、成交明细都存下来。这样出了问题可以回溯到具体哪一天、哪一笔交易出了问题。我曾经靠这个习惯,半小时就定位到了一个订单簿数据错位的 bug。

各层之间的协作流程

四层不是各自为政的。它们通过事件驱动的方式协作:

  1. 数据层推送新的 tick 数据
  2. 策略层收到 tick,计算信号,生成订单指令
  3. 执行层收到订单指令,模拟撮合,返回成交结果
  4. 分析层记录每一笔成交,更新绩效指标

这个流程每来一个 tick 就循环一次。高频回测里,一天可能有几百万个 tick,所以性能优化也很关键。嗯,这个我们后面章节再细聊。

总结一下:数据层管「有什么」,策略层管「做什么」,执行层管「怎么做」,分析层管「做得怎么样」。各层职责清晰,系统才能稳定、可扩展、可调试。

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