经常有人问同一件事:信号明明发出去了,QMT 那边却没下单,或者下了没成交,是不是桥把单丢了?
先说结论。大多数情况不是丢单,而是三条刻意设计的边界。它们是为了「绝不重复下单」做的取舍,不是 bug。分清这三条,能省掉一大半无效排查。这篇是工程记录,不构成投资建议,也不代操盘。
一、边界一:一个 Token 只挂一台 QMT
同一个 Token 如果在两台机器上同时拉信号,两台会抢到同一批信号。因为「拉取即出队」是在服务端完成的,谁先请求谁先拿走,而两台机器的网络与时钟并不同步,实际会出现同一批被两边各领走一部分、甚至同一笔被两边都领到的情况。
所以记住一条:一台机器一个 Token。要跑两台,就建两个 Token。
二、边界二:拉到即出队,等于「至多一次」
这是最容易被误判成丢单的一条。
信号被 QMT 端拉走的那一刻就出队了,不等下单回执。好处是不会重复领取,也不会有两笔同时消费同一条。代价是:如果领取之后、真正下单之前进程崩了,这条信号不会自动重放。
这是故意的。反过来设计——等回执才出队——会带来超时重试,进而重复下单。在交易场景里,重复下单比漏一单危险得多。
所以看到「服务器上已标记消费、本机却没有委托」,先确认那段时间执行器有没有重启或异常退出,不要一上来就怀疑链路。
三、边界三:执行器进程重启后,本地仓记账清空
为了让下单路径不再每次都打 get_trade_detail_data(这是早期「每笔卡好几秒」的主因之一),清仓逻辑走的是本进程内的记账。
进程一重启,这份记账就没了。结果是:已经有真实持仓、但本进程并不知道的清仓信号,可能被直接跳过。
目前对这条的处理方式是——实盘自己接受这个取舍,或者重启后先核对一次真实持仓,再让信号继续跑。
四、还有一种,不是边界
成交本身仍取决于券商、行情、资金和 passorder 的规则。信号桥只保证「指令按时按序送到本机执行器」,不保证成交。
下单返回 True 只表示请求被接受,不等于成交。废单、部成、拒单都走委托状态,对账写法在这里:https://www.kimiquant.cn/problems/qmt-order-callback
五、自查顺序(照着走,别乱猜)
- 先看服务器上这条
signal_id 的状态。还没被领取,说明本机根本没在拉,查 Token、进程、网络;已领取但没有回执,大概率崩在了中间那一段。
- 翻本机执行器日志,看有没有重启记录。
- 如果重启过,先对一次真实持仓,再判断清仓为什么被跳过。
- 最后才怀疑链路本身。
三条边界连同实测数字的完整说明,我整理在这页:https://www.kimiquant.cn/notes/jq-signal-latency
(整理这类接口笔记时我常用 WorkBuddy 辅助,贴报错、对着 API 排错比翻手册快一些:https://workbuddy.ai/invite?code=66L9RNCT ) |