回测系统概述
做量化交易这些年,我越来越觉得回测系统是整个策略生命线的起点。说白了,没有靠谱的回测,你的策略就像在黑暗中开车——你根本不知道前方是坦途还是悬崖。
今天咱们聊聊回测系统的核心概念。我会结合自己踩过的坑,帮你把这块地基打扎实。
什么是事件驱动回测
先讲个故事。我刚开始做回测时,用的是最简单的向量化方法。就是把历史价格数据拉下来,算算收益率,觉得策略不错就上线了。结果呢?实盘第一天就亏了3%。
为什么会这样?因为真实市场不是按「收盘价买入,收盘价卖出」这种理想方式运行的。市场是一笔一笔交易组成的,每一笔都有时间戳、有价格、有成交量。
事件驱动回测,就是模拟这种真实的市场行为。它把市场活动拆解成一个个事件:
- 新的K线数据到达
- 订单被成交
- 收到成交回报
- 定时任务触发
每个事件都会触发相应的处理逻辑。你的策略就像在真实市场中一样,收到数据、做出决策、发送订单、等待成交。
核心区别:向量化回测是「事后诸葛亮」,事件驱动回测是「实时模拟」。
回测在量化交易中的重要性
我见过太多人,策略回测跑出年化50%就兴奋得睡不着觉。结果实盘一个月就亏回去了。为什么?因为回测本身就有很多坑。
回测的重要性体现在三个层面:
- 验证策略逻辑:你的策略在历史上是否真的有效?还是只是运气好?
- 发现潜在问题:比如滑点、手续费、流动性不足等,回测能帮你提前暴露这些问题。
- 优化参数:但这里要小心,过度优化是回测最大的敌人。
我曾经犯过一个低级错误:回测时没考虑手续费,结果实盘被手续费吃掉了大部分利润。从那以后,我每条回测记录都会标注「是否包含手续费」。
事件驱动架构 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()
这段代码虽然简单,但已经包含了事件驱动回测的核心思想:事件循环、事件类型、事件处理。你想想看,真实市场不就是这样的吗?数据来了,你决策,下单,等成交,再处理结果。
关键点:事件驱动回测的核心不是代码有多复杂,而是它模拟了「决策-执行-反馈」这个闭环。这才是真实交易的本质。
我的建议
如果你刚开始做回测,我的建议是:
- 先用向量化回测:快速验证策略逻辑是否合理
- 发现问题后转事件驱动:特别是当策略涉及限价单、滑点敏感时
- 不要过度追求精度:回测本身就是对真实市场的近似,精度够用就行
记住,回测的目的是帮你发现策略的弱点,而不是证明策略有多牛。我见过太多人把回测做成「数据挖掘」,最后实盘一败涂地。
好了,这一章就到这里。回测系统的地基已经打好了,下一章咱们开始搭建真正的事件驱动框架。