前言
国内期货量化,是用 Python 程序根据行情自动决定买卖方向、目标持仓几手。例如 5 分钟 K 线上算均线:收盘价在均线上方,程序认为该做多,输出「目标净持仓 3 手」——这一输出就叫交易信号(常记成target或目标仓)。程序通过天勤量化(TqSdk)的TargetPosTask.set_target_volume(3)把真实账户里的持仓往 3 手推,期货公司柜台才会收到报单。
策略从回测、模拟到实盘,往往会改代码:均线从 20 改成 30、加一条风控,这叫一版新程序。上线前你会担心:新程序算出来的信号,和现在正在实盘跑的老程序是否一致?若直接切实盘,万一新信号差很多,就会真下单、真亏钱。影子模式(shadow)解决的就是这件事:程序照常连行情、照常算指标、照常算出「该买几手」,也写入日志,但故意不调用set_target_volume、不insert_order,不向交易所报单。等影子跑够一段时间,对比日志确认新信号可靠,再切换成真正下单。
天勤没有名叫「影子模式」的菜单项,需要你在代码里用环境变量或分支切断发单路径。下面说明几种接法、日志怎么记、为何不能两个进程同时登录同一实盘资金户。
一、先弄清几个名词
| 名称 | 通俗含义 | 在影子模式里干什么 |
|---|---|---|
| 期货量化策略 | 根据行情规则自动算买卖的 Python 程序 | 影子版与实盘版可以是同一份代码 |
| 交易信号 | 策略输出,如「rb2510 目标净仓 +3 手」 | 影子模式要记下来,但不执行 |
| 目标净仓 / target | 希望账户持有的净多头或净空头手数 | 影子只 log,不set_target_volume |
| 上线 / live | 程序连期货公司实盘账户真下单 | TQ_MODE=live等团队自定 |
| 新版 / 旧版 | 改参数或逻辑后的程序版本 | 新版常先 shadow,旧版可能仍在 live |
TqApi | 天勤主连接对象 | shadow 也要创建,否则没有行情 |
TqAuth | 快期账户认证,用于连行情网关 | 收行情通常都需要 |
TqAccount | 期货公司资金账户,实盘下单用 | live 用;shadow 可不连或连但不 set |
TqSim/TqKq | 天勤模拟、快期模拟账户 | 异进程影子常用,绝对不下实盘单 |
wait_update() | 推进行情与持仓更新 | 影子也必须调,否则 K 线不更新 |
bar_datetime | 触发信号的那根 K 线时间 | 对比新旧版信号是否同一时刻一致 |
| shadow | 团队自定的模式名 | 只记信号不下单 |
二、为何「连了 TqAccount」也不会自动下单
常见误解是:一连实盘账户就会交易。天勤里只有你主动调仓才会报单:主要是TargetPosTask.set_target_volume(n),或手写insert_order。主循环若只算均线、print 结果,账户不会有任何变化。影子模式就是利用这一点:在调用set_target_volume之前return或跳过。
三、同进程影子(常用写法)
同一进程连行情(或连TqAccount只读资金),用环境变量区分模式:
importos MODE=os.environ.get("TQ_MODE","live")# live / shadow / simdefon_signal(symbol,target,kl):bar_dt=str(kl.iloc[-2].datetime)log_signal(symbol=symbol,target=target,bar_datetime=bar_dt,mode=MODE)ifMODE=="shadow":return# 影子:到此为止,不向柜台发单tasks[symbol].set_target_volume(target)说明:
iloc[-2]是已收盘 K 线,避免用未收盘 bar 算信号。- 影子时仍要
api.wait_update(),否则kl和均线不更新。 log_signal建议 JSON 行,字段与 live 一致,便于事后 diff。
四、异进程影子(绝对不下实盘单)
进程 A:TqAccount跑老策略、真下单。进程 B:同一套信号代码,但TqApi(TqSim())或TqKq(),只写日志。优点:物理隔离,不可能误下单;缺点:模拟无真实滑点,只能对比「同一根 K 线上 target 是否相同」,不能对比成交价。
对比时可算:方向一致率、差异 bar 列表、是否覆盖夜盘和换月。
五、何时从 shadow 切到 live
团队书面规则,例如:shadow 至少两周、包含夜盘、方向一致率高于 95%、无未解释差异。切换时建议停机改环境变量TQ_MODE=live,启动后先wait_update读get_position对账,再允许自动交易。勿在交易高峰瞬间切换且无日志。
六、切勿双进程抢同一资金户
两个 Python 进程各TqApi(TqAccount(同一期货公司, 同一资金账号, ...))同时自动报单,会互相撤单、重复开仓。影子若需连实盘账户类型,应在同一进程用MODE=shadow分支,不要第二个进程再登录同一资金户。
七、日志字段建议
shadow 与 live 用同一套字段:ts、symbol、bar_datetime、target、mode、version。live 额外记pos、order_id。日后用脚本按bar_datetime和symbol做 join 对比。
总结
影子模式是期货量化上线前的一道保险:在真实行情节奏下,让新程序完整走一遍「算信号」的链路,把目标持仓记下来,但切断通往天勤调仓接口的路径。天勤里没有单独按钮,只要不调用TargetPosTask和insert_order,用TQ_MODE=shadow或另起TqSim进程即可实现。可以这样理解:信号是「程序想买几手」,下单是「真的去跟期货公司说」;影子只做到前者,确认无误后再做后者。
FAQ
1)shadow 要不要读资金?
可选。读get_account()做风控日志可以,但不要 set 非零目标。
2)shadow 能测滑点吗?
不能,没有真实成交;滑点要用小额 live 或模拟统计。
3)TqBacktest 算影子吗?
回测是用历史数据重放,和「实盘旁路 shadow」不同,可互补。
4)退出程序要做什么?
api.close(),避免连接泄漏。
风险提示
以上内容用于上线验证参考,不构成投资建议。