上手 ④:QMT 侧配置及测试教程
把跟单策略装进 QMT、逐项过一遍 27 个参数、确认主泵在跑,并完成上线前的真实验证。
这一篇解决什么
把跟单策略装进你本机的 QMT,让它开始主动去中转站领信号,并且在你的账户里真实下单。
这是整条链路的最后一跳,也是最容易出事的一跳 —— 前面几篇出问题最多是没反应,这一篇配错了是真金白银。
动手前必须已具备:① QMT 客户端已装好、量化权限已开(第 ① 篇);③ 已从工作台下载到跟单包(第 ③ 篇)。
第 0 步:先认识这份跟单包
解压后是这样(以通道名 双均线ETF-实盘 为例):
双均线ETF-实盘_QMT跟单包/
├── 安装说明.txt ← 离线版说明,含逐步操作
├── 双均线ETF-实盘.py ★ QMT 侧策略源码
└── 双均线ETF-实盘.xml ★ 参数面板
包里已经写好了你的中转站地址和通道令牌,不需要手工改任何文件。
⚠ 两个文件名必须完全一致。 QMT 靠「xml 文件名 = 策略名」去匹配参数面板。 改名、或者只放一个、或者两个文件前缀不一致,结果都是「打开策略看不到参数设置」。
为什么包里没有 .rzrk 这种格式? .rzrk 是迅投专有的加密策略包格式,只有 QMT 自己「导出」时才会生成,第三方无法凭空造一个出来。所以包里给的是可读的 .py 源码,由你在 QMT 里新建策略、把源码粘进去。装好之后你可以在 QMT 里右键该策略「导出」,得到属于你自己的 .rzrk 备份。
第 1 步:把策略装进 QMT(最容易被跳过的一步)
⚠ 不要只把
.py丢进 QMT 的python文件夹就当装好了。 QMT 那套「放文件夹就自动出现」的机制认的是.rzrk加密包,不是明文.py。 多数券商版把策略加密存储,明文.py放进去不会被识别,策略列表里根本不会出现它。 这就是「按说明放了文件却找不到策略」的原因。
方法 A(推荐,最稳)
- 打开 QMT → 左侧 「模型研究」(策略列表)。
- 在策略列表空白处右键 → 新建策略 / 新建 Python 策略。
- 先把策略名称改成与包内同名(
双均线ETF-实盘)——
要在放文件之前改:QMT 是按「策略名」登记策略的,名字不对,后面放进去的文件就绑不到这个策略上。
- 再把包内
双均线ETF-实盘.py装进去,两种做法都行:
- 粘贴:清空编辑器里的示例代码,把该文件的全部内容复制粘贴进去;
- 覆盖:把该文件复制到 QMT 安装目录的
python文件夹,
覆盖掉 QMT 刚为这个新策略建出来的同名文件。
- 点 「编译」 保存。
方法 B(手上已有 .rzrk 时)
把 .rzrk 复制到 QMT 安装目录的 python 文件夹,重启 QMT 即可自动出现。
放参数面板
把 双均线ETF-实盘.xml 复制到 QMT 安装目录的:
<QMT安装目录>\python\formulaLayout\
例如:D:\东北证券NET专业版\python\formulaLayout\
找不到
python/formulaLayout目录? 在 QMT 安装目录里搜formulaLayout,搜到谁就是它。
装完列表里看不到策略?
右键空白处看有没有「刷新」,或者重启 QMT 再看一次。仍然没有,回头检查第 1 步是不是漏了「编译」。
第 2 步:参数面板(共 27 项,分 7 组)
进入 「模型交易」→ 选中你的策略 → 打开「参数设置」。
必填(4 项)
| 参数 | 默认 | 说明 |
|---|---|---|
[必填] 中转站地址 | 已填好 | 不要以斜杠结尾 |
[必填] 通道令牌 | 已填好 | 等同于钥匙,不要截图外发 |
[必填] 资金账号 | FILL_YOUR_ACCOUNT_ID | 必须与 QMT 当前登录的账号一致。填错的表现是「策略在跑、信号也在领,但单下不出去」 |
[必填] 账户类型 | STOCK | STOCK 普通账户 / CREDIT 两融账户 |
如果日志里出现
WARNING CHANNEL_TOKEN is still a placeholder,说明「通道令牌」是空的 —— 回工作台重新下载跟单包。
交易(7 项)
| 参数 | 默认 | 说明 |
|---|---|---|
[交易] 默认下单模式 | amount | 信号没指定口径时用:amount 股数 / value 金额 / percent 总资产比例 / target_percent 目标仓位 / position 全部可用 |
[交易] 默认报价方式 | counterparty | counterparty 对手价 / last 最新价 / b1~b5 / s1~s5 / limit 用信号里的限价 |
[交易] 报单价模式 | limit | limit 按上面的报价方式自己算限价(默认)/ counterparty 对手价 / best5 最优五档即时成交 / sell5 买入打穿卖五价 / buy5 卖出打穿买五价。后四种价格传 0 交给系统自动取价 |
[交易] 价格笼子比例 | 0.02 | 最终限价被夹在最新价 ±该比例以内,范围 0.001–0.2 |
[交易] 资金使用比例 | 0.80 | 买入最多动用可用资金的比例,0.01–1.0 |
[交易] 最小价位 | 0.01 | 价格取整用;A 股股票填 0.01 |
[交易] 每手股数 | 100 | 股数向下取整到该倍数;A 股填 100 |
风控(9 项)
| 参数 | 默认 | 说明 |
|---|---|---|
[风控] 单笔金额上限 | 200000 | 超过直接拒单,0 = 不限制(不要填 0) |
[风控] 单笔股数上限 | 100000 | 超过直接拒单,0 = 不限制(不要填 0) |
[风控] 信号时效(秒) | 120 | 信号从生成到执行的最大延迟;防隔夜旧信号被翻出来执行 |
[风控] 仅交易时段下单 | 否 | 出厂默认否 = 不做时段限制,收盘后 / 隔夜信号同样会执行。要严格管控改成「是」(09:30–11:30 / 13:00–15:00) |
[风控] 开启自动撤单 | 否 | 本策略挂出的单超时未成交则撤单 |
[风控] 撤单时间(秒) | 20 | 范围 1–1200 |
[风控] 撤单重挂次数 | 3 | 范围 1–10 |
[风控] 废单重试次数 | 3 | 委托状态 57(废单)时自动重新取价并重下;0 = 不重试 |
[风控] 委托确认等待(秒) | 1.2 | 报单后等这么久,确认委托真的出现在 QMT 委托列表里;超时即判定被柜台拒单并回报【执行失败】。范围 0–10,0 = 不校验(回到旧行为:一律显示「已提交」) |
委托确认等待是很有用的一项。设为 0 时,被柜台做成废单的委托会显示成「已提交」,让你以为下单成功了。
测试(3 项)
| 参数 | 默认 | 说明 |
|---|---|---|
[测试] 空跑模式 | 否 | 否 = 真实报单。想先只验链路不发单,临时改成「是」(只写日志、完全不报单) |
[测试] 测试模式 | 否 | 接受历史信号与非交易时段信号,且每笔固定为下面的股数。注意它仍会真实报单,请用模拟账号 |
[测试] 测试模式股数 | 100 | 测试模式下每笔委托的固定股数 |
⚠⚠ 出厂默认就是「真实报单」。 跟单包 v3.0.4 起,
[测试] 空跑模式与[风控] 仅交易时段下单的出厂默认都改成了「否」 —— 前者意味着会真的下单,后者意味着收盘后也会下单。 这么定是为了方便盘后联调,但代价是「装上就跑起来真下单」。 首次接入请务必先读一遍这两个开关,再点【运行】。
引擎(1 项)
| 参数 | 默认 | 说明 |
|---|---|---|
[引擎] 轮询周期 | 1nSecond | 最小 500nMilliSecond。跑在 QMT 主线程上,不建议调得更频繁 |
通知(3 项)
| 参数 | 默认 | 说明 |
|---|---|---|
[通知] Server酱Key | 空 | 微信推送下单结果,留空不推送 |
[通知] Webhook地址 | 空 | 钉钉 / 企业微信 / 飞书机器人地址,留空不推送 |
[通知] Webhook平台 | dingtalk | dingtalk / wecom / feishu |
建议把通知配上。 策略在你自己的电脑上跑,你不一定盯着屏幕;每一笔真实委托推一条微信,是发现问题最快的方式。
第 3 步:运行,并确认「主泵」真的在跑
- 「模型交易」→ 选中你的策略 → 打开参数设置 → 核对上面四项必填 → 保存。
- 点 【运行】。
⚠ 只点「编译」不够。 编译只做语法检查,不会执行
init(),主泵也就不会启动。这是最常见的失败原因 —— 而且表现是「日志一片安静」,看起来像代码有问题。
- 看 QMT 日志窗口,30 秒内应出现这一行:
[follower] alive ticks=.. served=0 failed=0 errors=0 requeue=0 dry_run=0
没有这一行 = 策略没跑起来(没点运行 / 跑在回测模式),不是代码问题。
ContextInfo.run_time在回测模式下不生效,所以必须进「模型交易」界面、以实盘或模拟模式运行。
- 回到中转站工作台,确认 「QMT 连接」变成「已连接」。
- 点工作台 「发送测试信号」,回显应变绿:「✓ 信号已收到 · 通道可用」。
到这一步,链路就通了。
第 4 步:四种联调方式,分清楚再用
| 联调方式 | 会真实报单吗 | 受限条件 | 用来验什么 |
|---|---|---|---|
| 工作台「发送测试信号」 | 不会 | 无:探针不取价、不报单 | 「中转站 → QMT」这一段,任何时间都可点 |
聚宽研究环境 _jqr_e2e_test() | 不会 | 无 | 完整三跳「聚宽 → 中转站 → QMT」 |
| 工作台「买卖预检」 | 不会 | 无 | 以当前持仓和资金,这一单能不能下 |
| 工作台「实盘下单(100股)」 | 会 | 必须带精确价格;走完整风控 | passorder 那一段到底通不通 |
面板「[测试] 测试模式 = 是」 | 会 | 放开信号时效与交易时段;每笔固定 100 股 | 用模拟账号做压力验证 |
不管你用哪种方式,策略跑起来后工作台「QMT 连接」都应变成已连接,信号状态从 待领取 → 已领取 → 已完成 依次推进。
只想先看链路、不报单? 把面板 [测试] 空跑模式 临时改成「是」即可。
第 5 步:编码铁律(遇到报错先看这一节)
为什么会报 0xb4
QMT 加载策略时按 UTF-8 解码文件,而 QMT 编辑器在中文 Windows 上常按 GBK 保存。 文件里只要有一个汉字,两者就会打架:
SyntaxError: (unicode error) 'utf-8' codec can't decode byte 0xb4 in position 1: invalid start byte
0xB4 正是 GBK 里「大」字的第一个字节(大 = B4 F3)。
对策:跟单包里的策略文件是纯 ASCII 的,一个中文字符都没有。 纯 ASCII 在 GBK / UTF-8 / 任何 ASCII 兼容代码页下字节完全一致,这个故障从物理上不可能发生。
⚠ 不要给策略文件加中文注释,也不要用记事本「另存为 ANSI」。 早期流传的「转码成 GBK」建议是错的 —— 那恰好会制造出上面这个错误。 所有中文说明都在
安装说明.txt里,参数面板.xml是 UTF-8(QMT 按 UTF-8 读它),所以面板上的中文标签是安全的。
报错信息怎么读
QMT 的报错经常挤成一行,拆开就清楚了:
0D:\...\python\双均线ETF-实盘.py_SH00030015SyntaxError... position 1 ... line 25
│└──────────── 文件全路径 ────────────┘└───号──┘└┬┘
│ └ 第 15 次触发时报的
└ 无实义前缀
| 片段 | 含义 |
|---|---|
开头那个 0 | 无实义,忽略 |
| 中间的长路径 | 出错文件的全路径 |
_SH000300 | 主图标的代码(策略跑在哪个标的上) |
15 | 第 15 次触发 |
position 1 | 行内字节序号,从 0 起算 |
line 25 | 第一个含非 ASCII 字符的行号 |
所以看到 line 25,就去第 25 行找汉字 —— 基本一找一个准。
另一种编码报错
invalid character in identifier 说明编码已经修好了,但粘贴时混进了全角标点(中文引号、中文逗号)。用包内原文件全选替换重新粘贴一次。
第 6 步:上线前的真实验证
联调全绿之后,不要直接按正常仓位开跑。按这个顺序收尾:
- 核对档位:确认
[测试] 空跑模式= 否、[风控] 仅交易时段下单是你想要的档位。 - 核对风控:
单笔金额上限/单笔股数上限已按资金量设好,都不是 0。 - 核对账号:确认 QMT 当前登录的正是你要用的那个资金账号。
- 用最小数量真下一笔:工作台「实盘下单(100股)」,或直接用聚宽策略发一条最小量信号。
- 去 QMT 委托列表核对方向 / 价格 / 数量,核对完自行撤单。
- 用模拟账号跑满一个交易日,对账无差异后,再逐步放大资金。
常见问题
Q:日志里没有 alive 行? A:策略没跑起来。检查是否只点了「编译」没点【运行】、是否跑在回测模式。这不是代码问题,别去改代码。
Q:我把 .py 按说明放进 python 文件夹了,策略列表里却没有? A:见第 1 步 —— QMT 的「放文件夹自动出现」机制认 .rzrk 加密包,不认明文 .py。请改用方法 A:模型研究 → 右键新建 Python 策略 → 粘贴源码 → 编译保存。
Q:QMT 报 SyntaxError ... can't decode byte 0xb4? A:文件里混进了汉字。用包内原文件全选替换重新复制一次;不要加中文注释,也不要用记事本另存为 ANSI。
Q:打开策略没有「参数设置」,或者面板是空的? A:.xml 与策略不同名,或 .xml 没放进 python\formulaLayout\。两个文件名要一模一样。
Q:日志说下单成功了,但 QMT 委托列表里没有单? A:三个常见原因,按顺序查: ① [测试] 空跑模式 还开着「是」(只写日志不报单); ② 价格填得出界(低于跌停 / 高于涨停)→ 柜台做成废单,废单不出现在有效委托列表里; ③ 同一个通道跑了两个实例,抢走信号的那个跑在回测 / 模拟模式,给出「已提交」的假象。
Q:信号一直堆积在「待领取」? A:QMT 策略没运行,或通道令牌不一致。看工作台「QMT 连接」是不是红点。
Q:工作台显示「离线」,但 QMT 明明在跑? A:心跳没打出去。检查 [必填] 中转站地址 是否公网可达、令牌对不对;重开 QMT 后看日志里有没有连接失败的行。 另外注意:聚宽的策略跑在聚宽的云服务器上,QMT 策略跑在你自己的电脑上 —— 两者遇到的网络问题不是一回事。这台电脑访问不到中转站(公司网络 / 杀毒软件 / 防火墙拦截出站请求)是最常见的原因。
Q:为什么成交数量比我预期少? A:做了 100 股向下取整。买 150 股会变成 100 股。若 [测试] 测试模式 开着,还会进一步收敛到 [测试] 测试模式股数。
Q:信号回报「无法获取有效价格」? A:标的停牌,或代码格式不常见。也可能是信号本身没带价 —— 服务端强制要求真实下单必须带精确价格。
Q:信号被拒,理由是过期? A:信号生成时间比执行时间早超了 [风控] 信号时效(秒)(默认 120 秒)。最常见的原因是回测信号被误推(回测时间戳是历史日期)。如果你确实在回测,这是预期行为。
Q:能同时跑两个策略吗? A:可以。建两个通道,下载两个跟单包,放在不同目录,各自在 QMT 里建一个策略运行项,分别点【运行】。
⚠ 注意:不要两个策略共用同一个通道令牌。 那会让工作台分不清信号是谁发的,并触发「N 个客户端」告警 —— 多出来的那个会抢走信号。
Q:QMT 中途关掉再开,会丢信号吗? A:不会。中转站有租约机制:领走信号时写租约,到期没回报会自动放回「待领取」。重开后会继续领。
Q:QMT 需要装成 Windows 服务 / 用任务计划程序常驻吗? A:不需要。 QMT 自己就是常驻进程。但有两条硬要求:QMT 客户端必须保持登录状态,电脑不能休眠。
安全红线
- QMT 只发起出站请求,不在本机开任何监听端口 —— 不要为它做公网端口映射。
- 通道令牌在参数面板和策略文件里都是明文 —— 不要截图外发。
- 不要用来路不明的中转站地址。
- 保持「单笔金额上限」「单笔股数上限」为有限值 —— 它们是跟单链路上最后一道闸。
- 别把「空跑模式能跑」当成「实盘能跑」。 上线前必须关掉空跑模式、用最小数量真下一笔,去委托列表核对。
- 令牌泄露立刻处理:工作台「更换 Token」→ 重新下载跟单包 → 两个文件在 QMT 里重新放一次。
本篇检查单
- [ ] 跟单包三个文件都在,
.py与.xml文件名一致 - [ ] 已在 QMT「模型研究」里新建 Python 策略并粘贴源码、编译通过
- [ ]
.xml已放进python\formulaLayout\ - [ ] 参数面板四项必填都已核对(地址、令牌、资金账号、账户类型)
- [ ]
[测试] 空跑模式与[风控] 仅交易时段下单的档位已确认(出厂都是「否」) - [ ] 单笔金额上限 / 单笔股数上限已按资金量设好,都不是 0
- [ ] 通知渠道已配置(可选,但强烈建议)
- [ ] 点【运行】后,日志出现
[follower] alive ... - [ ] 工作台「QMT 连接」显示已连接
- [ ] 工作台「发送测试信号」回显变绿
- [ ] 聚宽
_jqr_e2e_test()三跳全[OK] - [ ] 用最小数量真下过一笔,并在 QMT 委托列表核对无误
- [ ] 已确认 QMT 登录的是你要用的那个资金账号
- [ ] QMT 客户端保持登录、电脑不休眠(部署常驻时)
到这里,①②③④ 四篇全部完成。整条链路是: 聚宽产生意图 → 中转站排队校验 → QMT 主动领取并下单 → 回报回到工作台。 出问题时,先看工作台「最近策略信号」的状态停在哪一步,再按对应篇的常见问题排查 —— 三分之二的问题能靠这一步定位。
