前言
组合里同时交易螺纹、铁矿、豆粕时,最怕共用一个target_pos变量,或 A 合约还在调仓 B 合约已改信号。目标持仓应按合约维度拆表,执行层一 symbol 一条线。
天勤TargetPosTask对同一账户同一合约保证单例(源码用account_key#symbol作 key)。下面讲数据结构、更新顺序和常见冲突。
一、per-symbol 状态表
fromtqsdk.libimportTargetPosTask symbols=["SHFE.rb2510","DCE.i2509"]tasks={s:TargetPosTask(api,s)forsinsymbols}targets={s:0forsinsymbols}klines={s:api.get_kline_serial(s,300,data_length=200)forsinsymbols}信号函数返回{symbol: target_volume},禁止用全局 int 表示“做多做空”。
二、单例与构造参数
重复TargetPosTask(api, s, price="ACTIVE")参数一致则返回同一实例;offset_priority或price不一致会抛错。多品种若平今规则不同,应为不同 symbol 建不同 task(每个 symbol 本来就要独立实例)。
文档强调:set_target_volume不立刻下单,在后续wait_update执行;多合约循环里 set 多个 symbol 后,必须继续wait_update,不要在中途 sleep。
三、更新节奏
whileTrue:api.wait_update()forsinsymbols:kl=klines[s]ifnotapi.is_changing(kl.iloc[-1],"datetime"):continuet=calc_target(kl)# 仅算该合约iftisNone:continuetargets[s]=t tasks[s].set_target_volume(t)信号层只写targets[s],不在calc_target里insert_order。
四、价差腿成对更新
双腿价差:同一帧内算好两条腿目标,再依次set_target_volume,缩短单腿裸露时间。组合合约(SP)则按一个 symbol 一个 task,勿与双腿混规则。
五、禁止混用 insert_order
同一合约上TargetPosTask与insert_order并用会冲突(官方明确禁止)。多合约若部分手写报单,按 symbol 划清边界。
六、收盘核对
每个 symbol 打印:target、pos.pos、在途ALIVE委托数(status 以文档为准)。偏差先查部分成交与 set 后未 wait_update。
总结
多合约目标持仓:字典维护 targets 与 tasks,K 线 datetime 按合约分别触发,成对价差同帧更新。利用 TargetPosTask 单例,构造参数一次定终身,调仓只改 set_target_volume。
不与 insert_order 混用;按 symbol 日志与 position 核对。
FAQ
1)十个合约会很慢吗?
合约越多,每帧潜在 work 越大,可只订阅必要品种。
2)一个 task 管多合约?
不能,一 task 一 symbol。
3)targets 与 position 不一致?
以 get_position 为准,查成交与 wait_update 是否跟上。
4)多账户?
task 构造传 account=,各账户独立字典。
风险提示
本文讨论仓位管理技术,不构成投资建议。