vnpy EventEngine 事件引擎 · event-driven engine
新手写策略最直觉的写法是 while True: get_price(); sleep(1)——这是轮询。它有两个致命问题:延迟最高 1 秒,且 99% 的循环都在白跑。
事件驱动反过来:行情主动找你。交易所推一个 tick,框架包成 Event(EVENT_TICK, tick),丢进队列。引擎从队列取出,看类型是 EVENT_TICK,分发给所有订阅了 tick 的处理器——你的策略、风控、日志、UI 各自收到,各自干活。延迟是毫秒级,CPU 不空转。
vnpy 的 EventEngine 就是干这个的。它不是什么高深东西——一个队列 + 一个分发线程 + 一张"事件类型→处理器列表"的注册表。但它把整个框架解耦了:行情源、策略、风控、订单、UI 互不认识,只通过事件通信。这就是为什么 vnpy 能同时跑 CTP、币安、回测,互不干扰。
下面模拟 vnpy 的 EventEngine。左边是事件源(点一下生成一个事件),中间是事件队列,右边是注册的处理器。点"自动跑"看事件被取出、分发、各处理器响应的全过程。
事件驱动的核心是一张注册表:Dict[EventType, List[Handler]]。处理器启动时调用 engine.register(type, handler) 把自己挂到对应类型下。引擎取出事件后,handlers = registry[event.type],挨个调用。
关键设计:一个事件类型可以有多个处理器。一个 tick 进来,策略算指标、风控查仓位、UI 刷新 K 线——全靠这一份事件,互不阻塞。这就是 vnpy 能"行情来了同时干三件事"的底层。
另一个细节:处理器在同一线程顺序执行(vnpy 默认)。好处是无需加锁、逻辑简单;坏处是一个处理器卡住会拖慢所有事件。所以处理器要快——重活扔到策略自己的工作线程,引擎线程只做分发。