期货量化主力换月程序怎么移仓:天勤 underlying_symbol 与任务切换
2026/6/10 0:16:43 网站建设 项目流程

前言

国内期货是按月挂牌交易的:螺纹钢同时有 2505、2510、2511 等多个具体合约,其中成交量最大的那个月份叫主力合约。每隔一段时间,市场注意力会从近月移到远月,主力就会换月。对做程序化的人来说,换月那几天特别容易出事:研究时用的是主连曲线,实盘却要下在具体月份上;旧月份里还有持仓没平掉,程序已经对着新月份set_target_volume(3),结果新旧两月同时持仓,保证金和风险度一起飙升。

天勤量化(TqSdk)是国内常用的 Python 期货量化框架。它的核心对象是TqApi:你创建一次TqApi,在里面订阅行情、查持仓、下单,整个程序靠反复调用wait_update()推进。主连合约在代码里常写作KQ.m@SHFE.rb,它的行情对象上有一个字段underlying_symbol,表示当前主力对应的具体可交易合约。换月程序化的关键,就是盯住这个字段何时变化,并据此完成移仓,而不是假装合约永远不变。

一、先弄清几个名词

名称是什么为什么会出现换月问题
具体月份合约SHFE.rb2510,交易所真实可交易标的到期、流动性转移,主力会换到别的月份
主连KQ.m@把历史上各阶段主力拼接成连续 K 线,方便看长期趋势研究好用,但不能直接当作单一合约的真实成交价
TqApi天勤主连接,变量常写作api订阅、交易、查询都通过它,需api.close()释放
get_quote(代码)取得某合约实时行情快照主连 quote 上有underlying_symbol
underlying_symbol主连当前指向的具体合约代码换月时这个字符串会变,程序若不处理就会对错合约
wait_update()阻塞等待一批业务数据更新不调用它,内存里的行情和持仓都是旧的
get_kline_serial订阅 K 线表,表里有datetime信号若在具体月上算,换月后要改订阅的 symbol
TargetPosTask天勤调仓工具,把净持仓调到目标手数每个具体合约通常只能有一个 task 实例
set_target_volume(n)设置目标净仓为 n 手,真正发单在后续wait_update换月要对旧月 set 0、对新月 set 目标
get_position查柜台认可的持仓移仓是否完成以pos.pos为准
pos.pos净持仓,正为多、负为空旧月不为 0 就不能算移仓完成

二、换月时程序里实际会发生什么

现象原因若不管会怎样
underlying_symbol从 rb2505 变成 rb2510交易所主力切换仍对旧月下单,流动性差、滑点大或拒单
主连 K 线连续、具体月 K 线有断档不同合约历史长度不同信号 bar 与执行合约对不上
旧月pos.pos仍大于 0移仓未完成新旧两月叠仓,保证金占用翻倍

主连价格是拼接出来的研究序列,不能默认它等于某一个具体合约从上市到退市的全部真实成交路径。实盘执行必须跟踪具体合约,换月就是执行层重新对齐的过程。

三、underlying_symbol 怎么读、为何刚订阅可能为空

fromtqsdkimportTqApi,TqAuth,TqSimfromtqsdk.libimportTargetPosTask api=TqApi(TqSim(),auth=TqAuth("快期账户","密码"))cont="KQ.m@SHFE.rb"q_cont=api.get_quote(cont)whileTrue:api.wait_update()trade_sym=q_cont.underlying_symboliftrade_sym:break

说明:

  • KQ.m@SHFE.rbSHFE是上期所,rb是螺纹钢品种;KQ.m@表示主力连续。
  • get_quote后各字段可能还是空的,必须wait_update()收到行情包才有值,这是天勤文档明确提醒过的。
  • trade_sym形如SHFE.rb2510,才是你应用TargetPosTaskget_position的执行合约。

策略里应维护变量current_trade_sym,每个交易日开盘或每次主循环检查trade_sym != current_trade_sym;若变化,进入移仓流程,不能静默改代码里的字符串却不平旧仓。

四、移仓流程:先平后开还是分批

两种常见写法,团队选一种写进策略说明书:

  1. 先平后开:在旧 symbol 上set_target_volume(0),循环wait_update直到get_position(旧).pos == 0,再对新 symbol 创建TargetPosTaskset_target_volume(目标)
  2. 分批换月:在数个交易日内逐步把仓位从旧月迁到新月,降低单日冲击成本。

注意天勤约束:同一具体合约只能有一个TargetPosTask(单例)。换月后对新trade_sym建 task;旧月 task 在平仓完成后不再设置新目标。若对同一 symbol 用不同的priceoffset_priority重复创建 task,会直接抛异常。

defon_roll(old_sym,new_sym,target,tasks):ifold_symintasks:tasks[old_sym].set_target_volume(0)# 此处应循环 wait_update,直到 get_position(old_sym).pos == 0ifnew_symnotintasks:tasks[new_sym]=TargetPosTask(api,new_sym,price="ACTIVE")tasks[new_sym].set_target_volume(target)

price="ACTIVE"表示对价下单(买用卖一、卖用买一),换月求成交时常用;若改用PASSIVE排队,在换月流动性混乱时可能久不成交。

五、K 线订阅要不要跟着切

  • 信号来自主连 K 线、执行用underlying_symbol:主连序列换月时内部标的会变,通常不必重订主连get_kline_serial;但要盯执行合约是否切换。
  • 信号来自具体月 K 线:换月后应改get_kline_serial(new_sym, 周期秒数, data_length=...),并重新做指标就绪判断——新月份历史 K 线变短,均线可能出现 nan,在 nan 上不能交易。

日志建议记录:换月日期、旧 sym、新 sym、移仓前后pos.pos、耗时,便于与期货公司账单核对。

六、模拟与回测注意

TqSim(天勤内置模拟账户)、TqKq(快期模拟)换月行为依赖行情服务,换月周应在模拟盘完整跑一遍移仓。回测若用主连,换月附近成交假设与具体月实盘会有偏差,样本外应用具体月再验证。

总结

主力换月那几天,程序要把underlying_symbol的变化当成和「信号触发」同级的重要事件:先发现切换,再平旧月、对新主力恢复目标仓,而不是继续对过期主力下单。天勤用主连做研究、用具体月做执行是常见分工,TqApiwait_update驱动一切更新,TargetPosTask负责把净仓推到目标。把移仓顺序、超时与日志写进配置并在模拟盘演练一遍,换月周就不容易变成持仓翻倍或流动性踩坑的突发事故。

FAQ

1)underlying_symbol 长时间为空?

继续wait_update;检查是否休市、网络是否正常、主连代码是否写对。勿在空字符串上下单。

2)换月当天信号和旧仓方向相反?

先处理旧仓风险(风控优先),再跟新信号,避免两头加仓。

3)能否同时持有新旧两月做价差?

那是套利策略,不是移仓;两腿各自TargetPosTask,比例单独管理。

4)个人投资者第一次写换月逻辑?

先用TqSim模拟,打印每次underlying_symbol变化,人工对照行情软件主力是否一致。

风险提示

以上内容用于移仓流程参考,不构成投资建议。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询