TqSdk 与 vn.py 差异全解析:从 vn.py 迁移到天勤量化的架构、策略范式与实战对照指南

发布时间:2026/10/13 1:51:18
TqSdk 与 vn.py 差异全解析:从 vn.py 迁移到天勤量化的架构、策略范式与实战对照指南 金融科技【免费下载链接】tqsdk-python天勤量化开发包, 期货量化, 实时行情/历史数据/实盘交易项目地址https://gitcode.com/gh_mirrors/tq/tqsdk-python点击查看免费下载本文面向已有 vn.py 使用经验的量化开发者系统梳理 TqSdk天勤量化开发包与 vn.py 在系统架构、策略组织方式、K 线数据、行情更新模型、图形界面与回测等维度的核心差异。阅读完本文你将理解为什么 TqSdk 把每个策略做成一个独立运行的 Python 文件、wait_update/is_changing驱动的编程范式与 vn.py 事件回调的区别并能在迁移已有策略代码时快速套用对应的 TqSdk 写法。如果你只是想先跑通一套最小程序建议先阅读 quickstart 与 framework本文更适合在迁移已有策略代码时对照阅读。一、系统整体架构all-in-one 与网络协作组件之争vn.py 是一套 all-in-one 的结构在一个 Python 软件包中包含了数据库、行情接收/存储、交易接口、图形界面等功能策略、引擎与接口之间通过进程内的事件循环紧密耦合。TqSdk 则采用基于网络协作的组件设计整个系统由以下几个关键组件构成行情网关Open Md Gateway负责提供实时行情和历史数据官方专门运维行情数据库用户可直接使用不需要自己接收和存储数据交易中继网关Open Trade Gateway负责连接到期货公司交易系统CTP / FEMAS / UFX 等DIFF 协议层上面两个网关统一以 Diff 协议对下方提供服务天勤终端和 TqSdk 都按照 Diff 协议连接到行情网关与交易中继网关实现行情和交易功能。这样的结构给用户带来的直接好处是TqSdk 很小安装方便只要简单pip install tqsdk即可无需自行搭建数据库和消息队列行情数据开箱即用官方运维行情数据库用户直接调用即可无需自己接收和存储数据交易接口被大幅度简化不再需要处理 CTP 接口的复杂回调也不需要发起任何查询请求——账户、持仓、委托等状态会随 Diff 协议自动推送并合并更新。对于需要直连期货公司交易系统的用户TqSdk 也提供了TqCtp模块支持用户直连参见 tqsdk.TqCtp 参考文档 与 企业版直连说明。从仓库源码来看这一薄客户端 网络网关的设计在 tqsdk/api.py 中体现得很明显TqApi对象内部维护与服务器的 WebSocket 通道_send_chan/_recv_chan并通过 tqsdk/diff.py 实现 Diff 协议的增量数据合并用户侧只需要持有各类业务对象的引用并反复调用wait_update即可让数据不断推进。二、每个策略是一个单独运行的 py 文件从被调用方到调用方vn.py 的范式从基类派生由框架调用在 vn.py 中实现一个策略程序通常是从CtaTemplate等基类派生一个子类class DoubleMaStrategy(CtaTemplate): parameters [fast_window, slow_window] variables [fast_ma0, fast_ma1, slow_ma0, slow_ma1] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): ... def on_tick(self, tick: TickData): ... def on_bar(self, bar: BarData): ...这个DoubleMaStrategy类写好以后由 vn.py 的策略管理器Vnpy cta runner负责加载运行。整个程序中vn.py 作为调用方用户代码作为被调用方框架负责接收行情和回单然后调用用户的事件响应函数用户策略调用框架提供的下单函数来发送交易指令。TqSdk 的范式无统一基类函数自由组合而在 TqSdk 中策略程序并没有一个统一的基类。TqSdk 只提供一些行情和交易函数用户可以任意组合它们来实现自己的策略程序。还是以双均线策略为例 双均线策略 from tqsdk import TqApi, TqAuth, TqSim, TargetPosTask from tqsdk.tafunc import ma SHORT 30 LONG 60 SYMBOL SHFE.bu2609 api TqApi(authTqAuth(快期账户, 账户密码)) data_length LONG 2 klines api.get_kline_serial(SYMBOL, duration_seconds60, data_lengthdata_length) target_pos TargetPosTask(api, SYMBOL) while True: api.wait_update() if api.is_changing(klines.iloc[-1], datetime): # 产生新k线:重新计算SMA short_avg ma(klines.close, SHORT) # 短周期 long_avg ma(klines.close, LONG) # 长周期 # 均线下穿做空 if long_avg.iloc[-2] short_avg.iloc[-2] and long_avg.iloc[-1] short_avg.iloc[-1]: target_pos.set_target_volume(-3) print(均线下穿做空) # 均线上穿做多 if short_avg.iloc[-2] long_avg.iloc[-2] and short_avg.iloc[-1] long_avg.iloc[-1]: target_pos.set_target_volume(3) print(均线上穿做多)以上代码文件单独运行即可执行一个双均线交易策略。整个程序结构中用户代码作为调用方TqSdk 库代码作为被调用方每个策略是完全独立的进程。仓库中的双均线示例可参考 tqsdk/demo/tutorial/t50.py。TqSdk 将每个策略作为一个独立进程运行这样可以在运行多策略时充分利用多 CPU 的计算能力每个策略都可以随时启动/停止/调试/修改代码而不影响其它策略程序的运行方便地针对单个策略程序进行调试。在策略程序中用户代码可以随意调用 TqSdk 包中的任意函数这带来了更大的自由度例如在一个策略程序中使用多个合约或周期的 K 线数据、盘口数据和 Tick 数据对某些类型的策略来说很方便对多个合约的交易指令进行精细管理管理复杂的子任务方便策略程序与其它库或框架集成。实战示例多合约套利策略以一个价差回归套利策略为例可见多合约同时跟踪 各自独立调仓在 TqSdk 中如何轻松实现 价差回归 当近月-远月的价差大于200时做空近月做多远月 当价差小于150时平仓 from tqsdk import TqApi, TqAuth, TargetPosTask api TqApi(authTqAuth(快期账户, 账户密码)) quote_near api.get_quote(SHFE.rb2610) quote_deferred api.get_quote(SHFE.rb2701) # 创建 rb2610 的目标持仓 task该 task 负责调整 rb2610 的仓位到指定的目标仓位 target_pos_near TargetPosTask(api, SHFE.rb2610) # 创建 rb2701 的目标持仓 task该 task 负责调整 rb2701 的仓位到指定的目标仓位 target_pos_deferred TargetPosTask(api, SHFE.rb2701) while True: api.wait_update() if api.is_changing(quote_near) or api.is_changing(quote_deferred): spread quote_near.last_price - quote_deferred.last_price print(当前价差:, spread) if spread 250: print(目标持仓: 空近月多远月) # 设置目标持仓为正数表示多头负数表示空头0表示空仓 target_pos_near.set_target_volume(-1) target_pos_deferred.set_target_volume(1) elif spread 200: print(目标持仓: 空仓) target_pos_near.set_target_volume(0) target_pos_deferred.set_target_volume(0)在这个程序中我们同时跟踪两个合约的行情信息并为两个合约各创建一个调仓任务可以方便地实现套利策略。TargetPosTask 的底层行为TargetPosTask是目标持仓风格的调仓任务其核心语义来自 tqsdk/lib/target_pos_task.py值得了解set_target_volume只是设置目标手数正数多头、负数空头、0 空仓并不立即下单或撤单实际的下单/撤单动作在之后的每次wait_update()时执行。因此必须保证set_target_volume后还会继续调用wait_update()每次下单后任务会根据后续行情计算最新价格当价格变化时会先撤回本程序发出的在场委托再按最新价格重新下单请勿在使用 TargetPosTask 的同时使用insert_order()函数否则将导致 TargetPosTask 报错或错误下单参数offset_priority默认今昨,开控制开平仓顺序今昨,开表示先平今仓再平昨仓、等待平仓完成后开仓避免开仓保证金不足今昨开表示所有指令同时发出适合有单向大边的品种昨开禁止平今仓适合股指这类平今手续费较高的品种开只开仓不平仓适合锁仓操作若同时设置min_volume与max_volume则进入大单拆分模式每笔以两者之间的随机手数下单全部成交后再继续处理剩余手数直至剩余手数小于max_volume直接下剩余手数。三、K 线数据与指标计算谁生成 K 线使用 vn.py 时K 线由 vn.py 接收实时行情后在用户电脑上生成并存储于用户电脑上的数据库中。而在 TqSdk 中K 线数据和其它行情数据一样由行情网关生成并推送。这带来了一些差别用户不再需要维护 K 线数据库用户电脑实时行情中断后也不再需要补历史数据行情服务器生成 K 线时采用了按 K 线时间严格补全对齐的算法这与 vn.py 或其它软件有明显区别行情数据只在每次程序运行时通过网络获取不在用户硬盘保存。如果策略研究工作需要大量静态历史数据推荐使用数据下载工具DataDownloader参见 tqsdk/tools/downloader.py 及其示例 tqsdk/demo/tutorial/downloader.py另行下载 csv 文件使用。K 线序列是 pandas.DataFrameTqSdk 中的 K 线序列采用pandas.DataFrame格式由TqApi.get_kline_serial返回参见 tqsdk/api.py 中该函数的文档注释。pandas 提供了非常丰富的数据处理函数可以方便地进行数据处理例如ks api.get_kline_serial(SHFE.cu2607, 60) print(ks.iloc[-1]) # - 最后一根K线 print(ks.close) # - 收盘价序列 ks.high - ks.high.shift(1) # - 每根K线最高价-前一根K线最高价, 形成一个新序列get_kline_serial的关键参数与行为symbol合约代码如SHFE.cu2607格式为交易所代码.合约代码也可以传入合约列表一次性提取多个合约的 K 线并按相同时间向第一个合约主合约对齐副合约字段名带数字后缀如open1、close2datetime/duration为公用字段duration_secondsK 线周期以秒为单位1 分钟线为 601 小时线为 3600日线为 86400周期在日线以内时可以任意填写在日线以上时只能是日线86400的整数倍最大为 28 天86400*28data_length需要获取的序列长度默认 200 根每个序列最大支持请求 10000 个数据adj_type可选复权类型F前复权、B后复权仅对股票和基金类型合约有效暂不支持多合约 K 线复权返回的 DataFrame 包含id、datetimeK 线起点时间自 unix epoch 以来的纳秒数、open、high、low、close、volume、open_oi、close_oi等列注意获取后的 kline 对象请不要修改/重命名原始的 kline 序列否则可能导致后续的 K 线数据不更新。tafunc 指标函数库TqSdk 也通过tqsdk.tafunc模块提供了一批行情分析中常用的计算函数实现在 tqsdk/tafunc.py例如from tqsdk import tafunc ks api.get_kline_serial(SHFE.cu2607, 60) ms tafunc.max(ks.open, ks.close) # - 取每根K线开盘价和收盘价的高者构建一个新序列 median3 tafunc.median(ks.close, 100) # - 求最近100根K线收盘价的中间值 ss tafunc.std(ks.close, 5) # - 每5根K线的收盘价标准差仓库中tafunc还提供了ma简单移动平均、sma扩展指数加权移动平均、crossup/crossdown向上/向下穿越、time_to_datetime纳秒时间转datetime.datetime等常用工具函数均可与 K 线序列直接配合使用更多用法可参考 tqsdk/ta.py 与 tqsdk/demo/ta.py。四、数据接收和更新回调模型 vs wait_update/is_changingvn.py 的事件回调模型vn.py 按照事件回调模型设计使用CtaTemplate的on_xxx回调函数进行行情数据和回单处理class DoubleMaStrategy(CtaTemplate): def on_tick(self, tick: TickData): ... def on_bar(self, bar: BarData): ... def on_order(self, order: OrderData): pass def on_trade(self, trade: TradeData): self.put_event()TqSdk 的 wait_update/is_changing 模型TqSdk 不使用事件回调机制。TqApi.wait_update函数设计用来获取任意数据更新from tqsdk import TqApi, TqAuth api TqApi(authTqAuth(快期账户, 账户密码)) ks api.get_kline_serial(SHFE.cu2607, 60) while True: api.wait_update() # - 这个 wait_update 将尝试更新所有数据. 如果没有任何新信息, 程序会阻塞在这一句. 一旦有任意数据被更新, 程序会继续往下执行 print(ks.close.iloc[-1]) # - 最后一根K线的收盘价一次wait_update可能更新多个实体。在这种情况下TqApi.is_changing被用来判断某个实体或其中某个字段是否有变更from tqsdk import TqApi, TqAuth api TqApi(authTqAuth(快期账户, 账户密码)) q api.get_quote(SHFE.cu2607) ks api.get_kline_serial(SHFE.cu2607, 60) x api.insert_order(SHFE.cu2607, directionBUY, offsetOPEN, volume1, limit_price50000) while True: api.wait_update() # - 这个 wait_update 将尝试更新所有数据. 如果没有任何新信息, 程序会阻塞在这一句. 一旦有任意数据被更新, 程序会继续往下执行 if api.is_changing(q): # - 这个 is_changing 用来判定这次更新是否影响到了q print(q) if api.is_changing(x, status): # - 这个 is_changing 用来判定这次更新是否影响到了报单的status字段 print(x)需要记住的要点TqSdk 针对行情数据和交易信息都采用相同的wait_update/is_changing方案。用户需要记住的要点包括get_quote、get_kline_serial、insert_order等业务函数返回的是引用对象reference而非 value它们的字段会在wait_update返回后刷新用户程序除执行自己的业务逻辑外还需要反复调用wait_update在两次wait_update之间数据不会继续推进用insert_order函数下单后还要继续调用wait_update报单指令才会真正发出用户程序中需要避免阻塞不要直接用sleep暂停主循环如果需要定时控制请参考 定时器文档。从源码层面看tqsdk/api.py 中的wait_update实现每次调用wait_update()会同时完成四件事实际发出待发送的网络请求如行情订阅、下单、撤单等推进正在运行的后台任务如 TargetPosTask 等调仓任务尝试从服务器接收并合并新的业务数据包如果当前没有新数据则继续等待。wait_update还支持deadline参数unix epoch 以来的秒数即time.time()不填则无限等待直到有业务数据更新填写后到达截止时间仍无更新则返回False。is_changing则通过比对本次收到的 Diff 数据包与业务对象的路径/字段_is_obj_changing判断特定对象或字段支持str或list形式是否在本轮更新中发生变化K 线产生新一根时其所有字段都算作有更新此时is_changing(klines.iloc[-1])一定返回 True。关于 wait_update 机制的详细说明请见 framework 文档。仓库中的综合演示可参考 tqsdk/demo/tutorial/t30.py它同时演示了 tick 序列变化、新 K 线产生is_changing(klines.iloc[-1], datetime)与收盘价变化is_changing(klines.iloc[-1], close)三种判断。五、下单 APIinsert_order 的参数全景虽然关联文档以TargetPosTask为主但 TqSdk 也提供精细下单函数insert_ordertqsdk/api.py它会在调用后立即返回委托请求在下一次wait_update时发出。核心参数如下symbol拟下单的合约代码格式为交易所代码.合约代码directionBUY或SELLoffsetOPEN、CLOSE或CLOSETODAY上期所和上期能源分平今/平昨平今用CLOSETODAY平昨用CLOSE其他交易所直接用CLOSE按交易所规则平仓股票交易无需填写volume下单数量期货为手数A 股为股数limit_price可选下单价格。数字类型为限价单None默认为市价单郑商所期货/期权、大商所期货支持BEST为最优一档仅中金所支持FIVELEVEL为最优五档仅中金所支持股票目前仅支持限价单必须指定advanced可选FAK剩余即撤销、FOK全成或全撤郑商所期货品种不支持 FOK股票不支持该参数order_id可选指定下单单号默认由 api 自动生成account多账户模式下指定发送指令的账户实例如TqAccount/TqKq/TqSim。示例from tqsdk import TqApi, TqAuth api TqApi(authTqAuth(快期账户, 账户密码)) order api.insert_order(symbolDCE.m1809, directionBUY, offsetOPEN, volume3) while True: api.wait_update() print(单状态: %s, 已成交: %d 手 % (order.status, order.volume_orign - order.volume_left))六、图形界面web_gui 与自定义图表TqSdk 提供web_guiweb_gui 文档来供有图形化需求的用户使用策略运行时交易记录和持仓记录自动在行情图上标记可以快速定位跳转可以跨周期缩放定位策略回测时提供回测报告、图上标记和对应的回测分析报告策略运行和回测信息自动保存可事后随时查阅显示。TqSdk 配合 web_gui 使用时还支持自定义绘制行情图表。TqApi构造参数web_gui默认为False不启用可以传True每次以随机端口生成网页也可以直接设置本机 IP 和端口web_gui[ip]:portip 可选默认为0.0.0.0。为了图形化界面能够接收到程序传输的数据并刷新程序中需要以循环调用api.wait_update的形式更新和获取数据。自定义绘制示例from tqsdk import TqApi, TqAuth api TqApi(authTqAuth(快期账户,账户密码), web_guiTrue) # 获取 cu2607 和 cu2608 的日线数据 klines api.get_kline_serial(SHFE.cu2607, 86400) klines2 api.get_kline_serial(SHFE.cu2608, 86400) # 算出 cu2608 - cu2607 的价差并以折线型态显示在副图 klines[dif] klines2[close] - klines[close] klines[dif.board] DIF klines[dif.color] 0xFF00FF00 klines[dif.width] 3七、回测无需准备数据的事件驱动回测使用 TqSdk 开发的策略可以回测提供 Tick 及 K 线级别的回测TqSdk 允许在一个策略中使用任意多个数据序列回测框架会正确识别并处理这种情况回测前不需要准备数据——历史行情由行情服务器按需提供。回测的入口是把TqBacktest实例传入TqApi构造函数参见 tqsdk/backtest/backtest.py 与 回测文档。TqBacktest(start_dt, end_dt)的起止时间都应为北京时间可以传date指交易日或datetime具体时间点无时区信息时默认为北京时间。回测模式下 K 线会在刚创建出来时和结束时分别更新一次wait_update每次最多推进一个行情时间回测结束后会抛出BacktestFinished异常。回测模式下 quote 的更新频率由所订阅的 tick 和 K 线周期确定订阅了 tick 则按 tick 频率生成否则按 K 线周期生成既无 tick 也无 K 线或 K 线周期大于分钟线时会自动订阅分钟线来生成 quote。一个完整的回测示例可参考 tqsdk/demo/tutorial/backtest.pyfrom datetime import date from tqsdk import TqApi, TqAuth, TqBacktest, TargetPosTask 如果当前价格大于5分钟K线的MA15则开多仓 如果小于则平仓 回测从 2018-05-01 到 2018-10-01 # 在创建 api 实例时传入 TqBacktest 就会进入回测模式 api TqApi(backtestTqBacktest(start_dtdate(2018, 5, 1), end_dtdate(2018, 10, 1)), authTqAuth(快期账户, 账户密码)) # 获得 m1901 5分钟K线的引用 klines api.get_kline_serial(DCE.m1901, 5 * 60, data_length15) # 创建 m1901 的目标持仓 task该 task 负责调整 m1901 的仓位到指定的目标仓位 target_pos TargetPosTask(api, DCE.m1901) while True: api.wait_update() if api.is_changing(klines): ma sum(klines.close.iloc[-15:]) / 15 print(最新价, klines.close.iloc[-1], MA, ma) if klines.close.iloc[-1] ma: print(最新价大于MA: 目标多头5手) # 设置目标持仓为多头5手 target_pos.set_target_volume(5) elif klines.close.iloc[-1] ma: print(最新价小于MA: 目标空仓) # 设置目标持仓为空仓 target_pos.set_target_volume(0)关于策略回测的详细说明请见 backtest 文档配合 web_gui 时回测还会自动生成含成交统计图表的回测报告。八、vn.py 用户迁移对照速查表维度vn.pyTqSdk整体架构all-in-one数据库、行情、交易、GUI 集成在一个包内网络协作组件行情网关 交易中继网关 Diff 协议客户端轻量策略组织从CtaTemplate等基类派生由策略管理器加载运行框架调用用户代码无统一基类每个策略是一个独立运行的 py 文件用户代码调用 TqSdk 函数多策略运行同一进程内由框架统一调度每策略独立进程可充分利用多 CPU、独立启停与调试K 线数据本地接收行情生成 K 线并存入本地数据库由行情网关生成并推送无需维护 K 线数据库、无需补历史数据K 线格式自有数据结构pandas.DataFrame可用 pandas 与tqsdk.tafunc丰富函数处理数据更新模型事件回调on_tick/on_bar/on_order/on_trade轮询式驱动wait_update()获取任意更新 is_changing(obj, key)判断具体对象/字段下单方式调用框架下单接口框架管理状态insert_order精细下单wait_update后才真正发出或TargetPosTask目标持仓自动调仓图形界面内置 GUIweb_guiTrue启动网页图形化界面支持自定义图表绘制回测依赖本地数据无需准备数据支持 Tick/K 线级别、多数据序列回测九、推荐学习步骤要学习使用 TqSdk推荐从 quickstart 开始然后阅读 framework 理解wait_update驱动模型需要批量导入历史数据做研究时可参考 DataDownloader 文档 与 tqsdk/demo/tutorial/downloader.py需要直连 CTP 等期货公司系统时可进一步阅读 TqCtp 参考 与 企业版说明。迁移已有 vn.py 策略时最核心的思维转变有三点策略从被框架调用的类变成独立运行的脚本数据获取从回调推送变成循环拉取 变化判断K 线从本地维护的数据库变成网关生成、随用随取的 DataFrame 序列。把握住这三点其余函数级的迁移都可以对照 tqsdk/api.py 的文档注释与 tqsdk/demo/tutorial 下的示例快速完成。赞分享金融科技【免费下载链接】tqsdk-python天勤量化开发包, 期货量化, 实时行情/历史数据/实盘交易项目地址https://gitcode.com/gh_mirrors/tq/tqsdk-python点击查看免费下载相关推荐天勤量化TqSdk算法交易实战TWAP与VWAP策略实现指南天勤量化TqSdk是专业的期货量化交易开发包提供实时行情、历史数据和实盘交易功能。本文将详细介绍TqSdk中两种核心算法交易策略TWAP与VWAP的实现方法金融科技天勤量化TqSdk期权交易从基础概念到实战策略完整指南天勤量化TqSdk期权交易从基础概念到实战策略完整指南 天勤量化TqSdk是一款专业的期货量化开发包提供实时行情、历史数据和实盘交易功能尤其在期权交易领域金融科技天勤量化TqSdk实战构建你的第一个自动化交易策略天勤量化TqSdk是一个功能强大的Python量化交易开发包为期货量化交易提供了实时行情、历史数据和实盘交易的全方位支持。无论你是量化交易新手还是经验丰富的开金融科技上一篇Activepieces 异步 Webhook 确认机制剖析为何 ACK 走 Redis 持久化而非 Postgres下一篇如何构建个人数字记忆库WeChatMsg聊天记录备份与深度分析完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考