问题描述
排查步骤:
确认是在“策略交易”模块创建了策略并开始运行。在“策略开发”模块点“运行”是无法产生交易信号的。
确认“运行模式”切换到了“实盘”,在“模拟”模式下只会产生策略信号,但不会往柜台(仿真柜台或生产柜台)发单。
确认“策略交易”模块下的“策略信号”分页,如果有信号产生,确认“委托”分页的信息,注意左上角状态选“全部状态”,来源选“本终端”,如果勾选后仍没看到委托信息,则确认信号里的证券代码是否是“可以在QMT交易”的代码;如果没有信号产生,查看策略代码,判断是否达到触发下单的条件或者时间(参考下述第4项)。
如何判断是否是“可以在QMT交易”的代码:在“交易”模块的下单面板输入代码,有相应的盘口行情,则是可下单代码。另外注意:仿真环境只支持深圳的国债逆回购,上海的不支持。
确认“策略周期”,除设置quickTrade=1或2的情况,策略只会在选定的周期的最后一个tick满足发单逻辑时触发下单指令,如果策略周期选择的是日线,则盘中没有发单。
注意:只有passorder、algo_passorder、smart_algo_passorder这三个下单函数的参数里有quickTrade这一项可以设置。如果客户的策略周期选的时间很长,例如30m、60m、1d这种,建议客户设置quickTrade=1或者2(具体选哪个,按客户的需要)。如果不设置的话,默认quickTrade=0,则只有本周期内最后一个tick满足发单条件才会触发发单语句,其他时候不发单。对于其他周期来说,quickTrade=0增加了发单难度,于是看起来肯可能就是一直都不发单,对于日线来说,quickTrade=0意味着只有15:00的行情满足条件才会发单并且此时发出去只会是废单。上述所列3个函数之外的其他下单函数,例如order_lots、order_value,etc.,都是没有quickTrade这个参数可以设置的,相当于是quickTrade=0的情况。
查看“消息提醒”里有无异常信息,查看位置:“交易”模块,下单面板旁边的分页。如果没有,界面左上角“操作”—“查看”—“操作提示”点击一下就有了,把“消息”列拉开看,可以看到有无异常发单信息。
策略里在发单位置打印当前K线的时间,确认发单信号触发时是最新K线而非历史K线。如果策略逻辑里不需要在历史K线上发委托,则可在策略编辑器右边将快速计算设为1,并且在handlebar里用ContextInfo.is_last_bar()对历史K线做过滤。
解决方案
在QMT(迅投/国信)量化平台上编写并运行策略时,遇到“策略不发单”是开发者常碰到的问题。这通常与运行环境设置、信号触发机制或代码逻辑有关。以下是详细的6步排查指南,帮助您快速定位并解决问题。
1. 确认策略运行模块
首先,请确认您是在**“策略交易”模块中创建了策略并开始运行。如果您仅仅是在“策略开发”模块点击了“运行”或“回测”,系统只会进行历史数据计算或模拟输出,是无法产生真实交易信号和发单**的。
2. 检查运行模式设置
确认策略的“运行模式”是否已切换到**“实盘”**。
- 模拟模式:只会产生策略信号,但不会向柜台(仿真柜台或生产柜台)发送真实的委托单。
- 实盘模式:才会真正触发底层交易接口进行发单。
3. 核对策略信号与交易代码
进入“策略交易”模块下的“策略信号”分页:
- 如果有信号产生:请切换到“委托”分页,将左上角状态选为“全部状态”,来源选为“本终端”。如果仍未看到委托信息,请检查信号中的证券代码是否是**“可以在QMT交易”**的代码。
- 判断方法:在“交易”模块的下单面板手动输入该代码,如果有相应的盘口行情,则是可下单代码。注意:仿真环境通常只支持深圳的国债逆回购,不支持上海。
- 如果没有信号产生:说明策略逻辑未满足触发条件,请检查代码逻辑或参考下文的周期设置。
4. 检查策略周期与 quickTrade 参数(核心)
QMT的机制是:默认情况下,策略只会在选定周期的最后一根K线的最后一个tick满足发单逻辑时,才触发下单指令。如果您的策略周期选择的是“日线(1d)”,那么盘中是不会发单的(只有15:00收盘时才会触发,且此时发出的单通常是废单)。
解决方法:使用 quickTrade 参数
在QMT中,只有 passorder、algo_passorder、smart_algo_passorder 这三个综合下单函数支持 quickTrade 参数设置:
quickTrade = 0(默认):仅在本周期最后一个tick满足条件时发单。quickTrade = 1:非历史bar上执行时(即最新K线),只要策略模型调用到该函数就立即触发下单。quickTrade = 2:不判断bar状态,只要调用到就触发下单(历史bar上也会触发,需谨慎使用)。
注意:像 order_lots、order_value 等快捷下单函数没有 quickTrade 参数,相当于默认 quickTrade=0。如果使用长周期(如30m、60m、1d),强烈建议改用 passorder 并设置 quickTrade=1。
5. 查看消息提醒与异常报错
检查“消息提醒”中是否有异常信息。查看位置:
- 在“交易”模块,下单面板旁边的分页。
- 如果没有显示,点击界面左上角“操作” -> “查看” -> “操作提示”,将“消息”列拉开,查看是否有因资金不足、代码错误或风控拦截导致的异常发单信息。
6. 过滤历史K线,确认发单时机
在策略发单位置打印当前K线的时间,确认发单信号触发时是最新K线而非历史K线。如果您的策略逻辑不需要在历史K线上发委托,建议进行以下优化:
- 在策略编辑器右侧的“基本信息”中,将快速计算设为
1(限制计算范围)。 - 在
handlebar函数中,使用ContextInfo.is_last_bar()对历史K线进行过滤,避免无效计算和历史信号干扰。
代码示例:
def handlebar(ContextInfo):
# 过滤历史K线,只在最新K线上执行交易逻辑
if not ContextInfo.is_last_bar():
return
# 您的交易逻辑...
# 使用 passorder 并设置 quickTrade=1 实现盘中立即发单
passorder(23, 1101, ContextInfo.accID, '000001.SZ', 5, -1, 100, 'MyStrategy', 1, 'Order_01', ContextInfo)
通过以上6个步骤的逐一排查,绝大多数QMT策略不发单的问题都可以迎刃而解。重点关注 quickTrade 参数的设置以及 is_last_bar() 的使用,这是量化实盘中最容易被忽略的细节。