第2章:回测系统架构设计

做量化交易这几年,我最大的感悟就是:回测系统的架构设计,直接决定了你策略研究的效率天花板。很多新手一上来就写个循环跑数据,结果数据量一上来就崩,或者策略逻辑稍微复杂点就改不动代码。嗯,这其实都是架构没想清楚。

今天我们就来聊聊,一个能支撑高频策略研发的回测系统,到底该怎么搭。

2.1 系统分层架构

我个人习惯把回测系统拆成四层。你想想看,如果所有代码都揉在一起,改个数据源都要动策略逻辑,那得多痛苦?

层级 名称 核心职责
L1 数据层 行情数据接入、清洗、存储、缓存
L2 引擎层 事件驱动、撮合逻辑、时间管理
L3 策略层 信号生成、订单管理、风控
L4 分析层 绩效归因、风险指标、可视化

说白了,每一层只管自己的事。数据层不用管策略怎么算,策略层也不用关心数据是从CSV读的还是从数据库拉的。我在项目中遇到过最坑的事,就是有人把数据清洗逻辑写在策略类里,结果换了个数据源,整个策略都得重写。

核心原则: 层与层之间通过接口通信,不要跨层调用内部方法。

2.2 模块划分

每一层内部,我建议再拆成更细的模块。这样后期维护、多人协作都方便。

数据层模块

  • 数据源适配器:支持CSV、数据库、API等多种来源
  • 数据清洗器:处理缺失值、异常值、复权计算
  • 缓存管理器:内存缓存+磁盘缓存,避免重复IO
  • 时间对齐器:不同频率数据的时间戳对齐

引擎层模块

  • 事件调度器:管理Tick、Bar、定时器等事件
  • 撮合引擎:模拟订单簿、成交逻辑
  • 时间控制器:支持回放、快进、暂停

策略层模块

  • 信号生成器:指标计算、模式识别
  • 订单管理器:下单、撤单、订单状态跟踪
  • 风控模块:资金管理、仓位限制、最大回撤控制

分析层模块

  • 绩效计算器:夏普比率、最大回撤、胜率等
  • 归因分析器:收益来源拆解
  • 报告生成器:HTML/PDF报告输出
避坑指南: 我曾经把风控逻辑写在策略里,结果策略一改,风控忘了同步,回测结果虚高。后来我把风控独立成一个模块,策略只能通过接口查询风控状态,再也没出过问题。

2.3 数据流设计

数据怎么在系统里流转?这是架构设计的灵魂。我画了一张图,你看完就明白了。

数据层 行情数据接入 清洗·缓存·对齐 引擎层 事件驱动·撮合 时间管理 策略层 信号生成·订单管理 风控 分析层 绩效归因·风险指标 可视化 行情数据 事件推送 订单指令 成交记录 数据流说明: ① 数据层推送行情 → 引擎层生成事件 → 策略层接收事件并计算信号 ② 策略层发出订单指令 → 引擎层撮合 → 成交结果返回策略层 ③ 策略层将成交记录 → 分析层进行绩效计算

数据流其实就三条主线:

  1. 行情数据流:数据层 → 引擎层 → 策略层。这是正向的,引擎层把数据包装成事件,策略层监听事件做计算。
  2. 订单指令流:策略层 → 引擎层。策略发出买卖指令,引擎层负责撮合。
  3. 成交结果流:引擎层 → 策略层 → 分析层。成交后,策略更新持仓,同时把记录发给分析层。
注意: 数据流必须是单向的,不要出现循环依赖。我曾经见过一个系统,策略层直接去数据层读数据,结果引擎层的时间控制完全失效,回测结果一塌糊涂。

2.4 性能目标设定

高频策略的回测,性能是硬指标。你想想看,如果回测一天的数据要跑10分钟,那你还怎么调参?

我一般会设定这几个性能目标:

指标 目标值 说明
单Tick处理耗时 < 1μs 包括事件分发、策略计算、订单检查
撮合延迟 < 100ns 订单簿匹配速度
内存占用 < 4GB 支持1年全市场Tick数据
回放速度 ≥ 100x 即1天数据在15分钟内跑完
我的经验: 性能优化要「先测量,后优化」。别一上来就搞什么内存池、无锁队列。先用profiler跑一遍,看看瓶颈到底在哪。我遇到过最离谱的事,优化了半天撮合引擎,结果发现瓶颈是日志打印——IO操作占了60%的时间。

具体怎么优化?几个方向:

  • 数据结构选型:用数组代替链表,用连续内存减少缓存miss
  • 避免内存分配:预分配对象池,不要在回测循环里new对象
  • 并行化:多只股票的回测可以并行跑,但要注意共享状态的同步
  • 减少IO:日志异步写入,数据尽量加载到内存

嗯,架构设计这块,说白了就是「高内聚、低耦合」这六个字。但真正落地的时候,细节特别多。上面这些是我踩过坑之后总结出来的,希望能帮你少走弯路。