问题描述
解决方案
在 QMT 量化交易平台中,算法单(如拆单、智能算法交易)被系统视为“任务”(Task)。要暂停或恢复一个正在执行的算法单,需要使用 pause_task 和 resume_task 函数。
这两个操作的核心前提是必须先获取到该算法单对应的 任务编号(taskId)。
以下是具体的实现步骤和代码示例。
核心函数说明
- 获取任务信息:
get_trade_detail_data(accountID, accountType, 'task')- 用于获取当前账号下的所有任务对象,从中提取
m_nTaskId(任务ID)和m_eStatus(任务状态)。
- 用于获取当前账号下的所有任务对象,从中提取
- 暂停任务:
pause_task(taskId, accountId, accountType, ContextInfo)- 将指定 ID 的运行中任务挂起。
- 恢复任务:
resume_task(taskId, accountId, accountType, ContextInfo)- 将指定 ID 的已暂停任务重新启动。
完整代码示例
以下策略代码展示了如何遍历当前账号下的所有任务,找到正在运行的任务进行暂停,或找到已暂停的任务进行恢复。
# -*- coding: gbk -*-
def init(ContextInfo):
# 设置资金账号
ContextInfo.accid = '6000000248'
# 设置账号类型:'STOCK'股票, 'FUTURE'期货, 'CREDIT'信用
ContextInfo.accType = 'STOCK'
# 绑定账号(接收回报必须)
ContextInfo.set_account(ContextInfo.accid)
print("策略初始化完成,准备管理算法任务...")
def handlebar(ContextInfo):
# 获取当前账号下的所有任务列表
# 第三个参数 'task' 表示获取任务数据
task_list = get_trade_detail_data(ContextInfo.accid, ContextInfo.accType, 'task')
if not task_list:
print("当前没有查询到任何算法任务。")
return
for task_obj in task_list:
# 获取任务ID
task_id = task_obj.m_nTaskId
# 获取任务状态
# 状态枚举参考:TASK_STATUS_RUNNING(执行中), TASK_STATUS_PAUSE(暂停)
# 注意:这里直接打印状态数值或描述,具体枚举值需参考文档附录
task_status = task_obj.m_eStatus
print(f"发现任务 -> ID: {task_id}, 状态: {task_status}, 说明: {task_obj.m_strMsg}")
# --- 示例逻辑:暂停所有正在运行的任务 ---
# 假设 TASK_STATUS_RUNNING 对应的状态码通常表示运行中(具体需结合实际返回值判断)
# 这里演示如何调用暂停函数
# 实际使用时,建议根据 task_id 或 task_obj.m_strMsg 来筛选特定任务
# 演示:暂停指定任务
# pause_task(task_id, ContextInfo.accid, ContextInfo.accType, ContextInfo)
# print(f"已发送暂停指令: 任务ID {task_id}")
# --- 示例逻辑:恢复所有已暂停的任务 ---
# 演示:恢复指定任务
# resume_task(task_id, ContextInfo.accid, ContextInfo.accType, ContextInfo)
# print(f"已发送恢复指令: 任务ID {task_id}")
# 为了防止在回测或实盘中频繁触发,这里仅作演示,实际逻辑请配合条件判断使用
return
# 封装一个自定义函数,方便在策略其他地方直接调用暂停
def my_pause_specific_task(ContextInfo, target_task_id):
"""
根据任务ID暂停特定任务
"""
pause_task(target_task_id, ContextInfo.accid, ContextInfo.accType, ContextInfo)
print(f"调用暂停函数: {target_task_id}")
# 封装一个自定义函数,方便在策略其他地方直接调用恢复
def my_resume_specific_task(ContextInfo, target_task_id):
"""
根据任务ID恢复特定任务
"""
resume_task(target_task_id, ContextInfo.accid, ContextInfo.accType, ContextInfo)
print(f"调用恢复函数: {target_task_id}")
注意事项
- taskId 的获取:
taskId是系统生成的唯一标识字符串或数字。必须通过get_trade_detail_data获取对象后读取m_nTaskId属性。 - 批量操作:如果
pause_task或resume_task的taskId参数传为空字符串或特定空值(视具体版本实现而定,通常建议传具体ID),可能会影响该账号下所有可操作的任务,请谨慎使用。建议始终传入具体的taskId。 - 状态确认:发出暂停或恢复指令后,任务状态不会立即改变(涉及网络交互)。建议在下一轮
handlebar或通过get_trade_detail_data再次查询确认状态是否已更新。 - 区别于撤单:
pause_task:暂停算法,未成交的委托可能保留或撤销(取决于算法具体逻辑),任务本身还在,可以恢复。cancel_task:撤销任务,任务彻底结束,不可恢复。
Q&A
Q: pause_task 和 cancel_task 有什么区别?
A: pause_task 是暂时停止算法的执行,后续可以通过 resume_task 继续运行,进度通常会保留;而 cancel_task 是彻底终止任务,相当于删除了这个算法单,无法恢复,如果需要继续交易必须重新下单。
Q: 如何判断任务当前是“运行中”还是“已暂停”?
A: 通过 get_trade_detail_data 获取任务对象后,检查 m_eStatus 属性。通常在 QMT 的枚举定义中,TASK_STATUS_RUNNING 代表执行中,TASK_STATUS_PAUSE 代表暂停。
Q: 为什么调用了 resume_task 后任务没有立即恢复?
A: 这是一个异步操作。指令发送给服务器后需要处理时间。此外,如果账户资金不足、持仓不足或触发了风控限制,即使调用了恢复函数,任务也可能无法实际继续执行,建议检查日志输出或 orderError_callback 回调。