前言

vn.py 那套我熟:EventEngine 一转,on_tickon_baron_order 各自注册,CtaTemplate 里写逻辑,挺有「正规军」的感觉。第一次用天勤时,我下意识又建了一个 EventEngine,把天勤的 quote 往里面塞,结果双引擎并行——tick 进 vn、也进天勤,下单有时走 MainEngine、有时又在天勤 循环里 insert_order,模拟盘一天下了双倍单,风控当场叫停。

后来才明白:天勤自己已经是引擎,while True: api.wait_update() 就是主事件泵,你要做的是把原来的 on_xxx 改成「在这一帧里,如果 is_changing 了就调用」。不是天勤缺功能,是调度权只能有一个老大

下面是我带同事迁 vn 时的对照表和 class 模板,算法(均线、通道)可以原样搬,BarGenerator 的思想也能留,但数据源和循环必须换天勤的

一、结构对照:别找一一等价,找职责等价

vn.py 里你熟悉的 天勤里建议
EventEngine while True: api.wait_update()
on_tick if api.is_changing(quote): ...
on_bar if api.is_changing(klines.iloc[-1], "datetime"): ...
MainEngine.send_order insert_order / TargetPosTask
CtaTemplate 自写 class + on_update()

vn 的「事件类型字符串」在天勤里没有对应物——不必硬造,用 is_changing 的字段参数就能达到「只在价格变时算」「只在新 K 线时算」的效果。

二、把 CtaTemplate 收成 class(我用的模板)

class MyStrategy:
    def __init__(self, api):
        self.api = api
        self.quote = api.get_quote("SHFE.rb2510")
        self.klines = api.get_kline_serial("SHFE.rb2510", 60)

    def on_update(self):
        api = self.api
        if api.is_changing(self.klines.iloc[-1], "datetime"):
            self.on_bar_close()
        if api.is_changing(self.quote, "last_price"):
            self.on_tick()

    def on_bar_close(self):
        pass

    def on_tick(self):
        pass

api = TqApi(TqSim(), auth=TqAuth("账户", "密码"))
s = MyStrategy(api)
while True:
    api.wait_update()
    s.on_update()

多策略就多个 instance,禁止多个策略共用一个全局 target_pos。vn 里你可能习惯每个 Strategy 独立,天勤也一样,只是共用一个 wait_update

三、数据容器:BarGenerator 可以留,引擎别留

vn.py 的 BarGenerator、ArrayManager 继续服务你的指标计算没问题,但 K 线来源改成 get_kline_serial 的 DataFrame。我踩过的坑是:仍在 vn 里合成 bar,天勤也订了 kline,两套 bar 差一根,信号差一分钟,能纠结一整天。

不要在 vn 的 MainEngine 里嵌 TqApi,选一条主循环。研究阶段可以在 Jupyter 里用 vn 算因子、天勤只负责执行,但生产环境尽量一条线,否则出问题不知道信谁。

四、迁移顺序(我要求新人按周走)

  1. 第一周:只迁行情和指标,模拟盘对价格、对 K 线收盘时间,不下单。
  2. 第二周:迁 TargetPosTaskinsert_order,1 手来回,对持仓和 order 日志。
  3. 第三周:迁风控、多品种、夜盘时段过滤。

跳步的人往往在第三周才暴露「bar 差一根」这种基础问题,返工更痛。

五、常见坑

  • vn 线程 + 天勤 单线程:二选一。
  • 全局变量在多个策略间共享:状态进 class。
  • 回调里下单、主循环里也下单:统一从一个 on_bar_close 出口下单。

总结

vn.py 迁天勤,我花最多时间的不是学 API,是克制再包一层 EventEngine 的冲动。天勤的 wait_update 已经帮你阻塞到「有更新」了,is_changing 帮你过滤「谁更新」,这和 vn 的 emit 本质是同一件事。你把 CtaTemplate 改成 class + on_update,算法留、调度换,通常两三周能平稳过渡。文档 advanced/for_vnpy_user.rst 建议团队一起读,有争议时以文档为准,别以「我以前 vn 是这么写的」为准——两个框架的脾气不一样。

FAQ

1)能否长期两套并存?

不建议,维护成本和幽灵 bug 都会上去。

2)回测怎么迁?

TqBacktest 替换 vn 回测模块,策略类尽量复用。

3)多策略怎么写?

多 class,一个 wait_update,各自 is_changing 早返回。

4)性能会变差吗?

看你是不是 tick 级全算;vn 也一样怕这个。

5)官方迁移说明在哪?

advanced/for_vnpy_user.rst

风险提示

本文用于期货量化技术实践讨论,不构成投资建议。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐