第 1 章 · 03 从 run.py 看七步装配与首次运行 本节摘要:本节精读 ——这份仅 87 行的脚本是理解 VeighNa 架构的最佳入口。它演示了一个完整的 VeighNa 交易程序怎么从零搭起来:七步装配(建 QApplication → 建 EventEngine → 建 MainEngine → 装网关 ×N → 装应用 ×N → 建主窗口 → 进 Qt 主循环)。更妙的是,文件里大量注释掉的网关和应用 import 清单,本身就是 VeighNa 插件生态的"菜单"。读完本节,你会理解 MainEngine 这副空壳是怎么被插件一点点填满的,为第 4 章精读 MainEngine 源码打下直觉。 内容来源:原项目源码 ,精读并套用体系化模板。
本节摘要:本节精读
examples/veighna_trader/run.py——这份仅 87 行的脚本是理解 VeighNa 架构的最佳入口。它演示了一个完整的 VeighNa 交易程序怎么从零搭起来:七步装配(建 QApplication → 建 EventEngine → 建 MainEngine → 装网关 ×N → 装应用 ×N → 建主窗口 → 进 Qt 主循环)。更妙的是,文件里大量注释掉的网关和应用 import 清单,本身就是 VeighNa 插件生态的"菜单"。读完本节,你会理解 MainEngine 这副空壳是怎么被插件一点点填满的,为第 4 章精读 MainEngine 源码打下直觉。
内容来源:原项目源码
examples/veighna_trader/run.py,精读并套用体系化模板。
阅读完本节,你应当能够:
run.py 里注释掉的网关/应用清单,认识 VeighNa 的插件生态全貌。run.py 改造成自己的启动脚本(加/减网关应用)。examples/veighna_trader/run.py 全文 87 行,核心的 main() 函数只有 40 多行(run.py:38-86):
38 def main(): 39 """""" 40 qapp = create_qapp() 41 42 event_engine = EventEngine() 43 44 main_engine = MainEngine(event_engine) 45 46 main_engine.add_gateway(CtpGateway) 63 main_engine.add_app(CtaStrategyApp) 64 main_engine.add_app(CtaBacktesterApp) 73 main_engine.add_app(DataManagerApp) 74 79 main_window = MainWindow(main_engine, event_engine) 80 main_window.showMaximized() 81 82 qapp.exec() 83 84 85 if __name__ == "__main__": 86 main()
(中间省略的都是注释掉的其他网关/应用。)这 40 行就是整个 VeighNa GUI 程序的启动逻辑。
run.py:40)40 qapp = create_qapp()
create_qapp() 来自 vnpy.trader.ui,它会创建一个全局的 QApplication 实例,并配置好字体、国际化翻译、HiDPI 缩放等 Qt 环境细节。
💡 核心心法:Qt 是 GUI 框架,任何带界面的 Qt 程序必须先有一个 QApplication。它管理 GUI 程序的控制流和主设置,是所有 Qt 窗口的"根"。VeighNa 的界面基于 PySide6(Qt6 的 Python 绑定),所以这一步不可省。如果你做无界面部署(服务器跑策略),则不需要这一步——见第 12 章的
no_ui/run.py。
run.py:42)42 event_engine = EventEngine()
EventEngine 来自 vnpy.event,是整个框架的通信总线。所有组件(网关、策略、UI)都通过它收发事件:网关收到行情 → put 一个 eTick 事件 → 策略和 UI 各自订阅处理。
注意:这里创建的 event_engine 后面会传给 MainEngine 和 MainWindow 两个地方(run.py:44 和 run.py:79)——所有组件共享同一个事件总线。这是 VeighNa 解耦的关键。
第 2 章会逐行精读
EventEngine的 145 行源码,讲清 Queue+Thread 发布订阅怎么实现。
run.py:44)44 main_engine = MainEngine(event_engine)
MainEngine 来自 vnpy.trader.engine,是整个平台的装配中枢。它本身不实现任何交易逻辑——它只是一个"容器",持有所有网关、应用、子引擎,并提供统一的对外 API(connect/subscribe/send_order 等,实际都委托给具体网关)。
构造时把第 2 步的 event_engine 传进去,MainEngine 内部会:
第 4 章会逐行精读
engine.py的 838 行,讲清装配中枢的"Facade 模式"。
run.py:46)46 main_engine.add_gateway(CtpGateway)
add_gateway 接收一个网关类(这里是 CtpGateway,来自 vnpy_ctp 包),实例化它并注册到 MainEngine 的 gateways 字典。从此 MainEngine 就"认识"了 CTP 这个交易接口,可以 connect/send_order 了。
第 6 行 from vnpy_ctp import CtpGateway 是关键——你必须先 pip install vnpy_ctp 才能 import 它。如果没装,这一行会 ModuleNotFoundError。
run.py:63-73)63 main_engine.add_app(CtaStrategyApp) 64 main_engine.add_app(CtaBacktesterApp) 73 main_engine.add_app(DataManagerApp)
add_app 接收一个应用类(继承 BaseApp),实例化后从中取出 engine_class,再装配成一个子引擎。比如:
CtaStrategyApp → 装配出 CtaEngine(CTA 策略引擎,管理策略实例、加载历史数据、触发 on_bar);CtaBacktesterApp → 装配出回测引擎;DataManagerApp → 装配出数据管理引擎。应用和网关的区别:网关对接交易所(数据/订单通道),应用实现业务逻辑(策略/回测/风控)。
run.py:79-80)79 main_window = MainWindow(main_engine, event_engine) 80 main_window.showMaximized()
MainWindow 来自 vnpy.trader.ui,是 VeighNa Studio 的主界面。它接收 main_engine 和 event_engine,据此构建菜单栏、工具栏、各种监控面板(行情/订单/成交/持仓/账户/日志)。showMaximized() 让窗口最大化显示。
run.py:82)82 qapp.exec()
qapp.exec() 进入 Qt 的事件主循环——从此程序阻塞在这里,处理鼠标键盘事件、定时器、窗口重绘,直到用户关闭窗口。这一行之后的所有逻辑都由 Qt 事件驱动(比如你点"连接"按钮,会触发 connect 流程)。
这就是为什么 GUI 程序的最后一行总是
app.exec()——它把控制权交给 Qt,程序从"顺序执行"模式切换到"事件驱动"模式。
run.py 里注释掉的网关和应用 import,本身就是 VeighNa 生态的"菜单"。把它们整理出来,你能看清整个框架的能力边界。
run.py:7-18)| 包名 | 网关类 | 对接的市场 |
|---|---|---|
vnpy_ctp ✅ |
CtpGateway |
期货(中金所/上期所/大商所/郑商所/广期所) |
vnpy_ctptest |
CtptestGateway |
CTP 测试环境(OpenCTP 模拟) |
vnpy_mini |
MiniGateway |
飞马 Mini(中金所) |
vnpy_femas |
FemasGateway |
中金所 Femas |
vnpy_sopt |
SoptGateway |
股票期权 |
vnpy_esunny |
EsunnyGateway |
鼎信 Esunny |
vnpy_xtp |
XtpGateway |
中泰证券 XTP(A 股) |
vnpy_tora |
ToraStockGateway / ToraOptionGateway |
鑫管家股票/期权 |
vnpy_ib |
IbGateway |
盈透证券(全球股期期权) |
vnpy_tap |
TapGateway |
易盛 Tap |
vnpy_da |
DaGateway |
达钱 DA |
vnpy_rohon |
RohonGateway |
融航 Rohon(期货资管) |
vnpy_tts |
TtsGateway |
TTS(OpenCTP 模拟) |
run.py:20-35)| 包名 | App 类 | 功能 |
|---|---|---|
vnpy_paperaccount |
PaperAccountApp |
模拟成交(无实盘时记录成交) |
vnpy_ctastrategy ✅ |
CtaStrategyApp |
CTA 策略(趋势跟踪) |
vnpy_ctabacktester ✅ |
CtaBacktesterApp |
CTA 策略回测 |
vnpy_spreadtrading |
SpreadTradingApp |
价差交易 |
vnpy_algotrading |
AlgoTradingApp |
算法交易(TWAP/VWAP) |
vnpy_optionmaster |
OptionMasterApp |
期权交易/波动率 |
vnpy_portfoliostrategy |
PortfolioStrategyApp |
组合策略 |
vnpy_scripttrader |
ScriptTraderApp |
脚本交易(交互式) |
vnpy_chartwizard |
ChartWizardApp |
K 线图表向导 |
vnpy_rpcservice |
RpcServiceApp |
RPC 服务(分布式) |
vnpy_excelrtd |
ExcelRtdApp |
Excel 实时数据 |
vnpy_datamanager ✅ |
DataManagerApp |
数据管理(下载/导入/导出) |
vnpy_datarecorder |
DataRecorderApp |
行情录制 |
vnpy_riskmanager |
RiskManagerApp |
风控 |
vnpy_webtrader |
WebTraderApp |
Web 交易 |
vnpy_portfoliomanager |
PortfolioManagerApp |
组合管理 |
(✅ = run.py 默认开启的)
理解了七步装配,改造 run.py 就很直观了。常见场景:
场景一:只做国内期货 CTA(默认配置)
保持现状即可——CTP + CtaStrategy + 回测 + 数据管理。
场景二:加美股期权
解开两行注释:
from vnpy_ib import IbGateway from vnpy_optionmaster import OptionMasterApp # ... main_engine.add_gateway(IbGateway) main_engine.add_app(OptionMasterApp)
场景三:服务器无界面跑 CTA
参考 examples/no_ui/run.py(第 12 章详讲):去掉 create_qapp/MainWindow/qapp.exec(),改成 connect → sleep → init → start → while 循环监听,用父子双进程守护。
场景四:做 AI 量化选股
不需要改 run.py——vnpy.alpha 是内置的,直接在 Jupyter Notebook 里 from vnpy.alpha import AlphaLab, ... 即可(见 examples/alpha_research/ 的 notebook)。
启动 run.py 后,VeighNa Studio 的典型使用流程:
每一步背后都是"事件驱动 + 装配"这套架构在工作。
create_qapp → EventEngine → MainEngine → add_gateway ×N → add_app ×N → MainWindow → qapp.exec()。add_gateway/add_app 装配。第 1 章结束。我们知道了 VeighNa 是什么、为什么这样拆、怎么跑起来。下一章(第 2 章)开始钻进源码——精读框架的心脏:EventEngine 事件引擎,看看 145 行怎么搭起一个发布订阅总线。