3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 QMT 量化交易平台中,撤销未成交订单主要通过调用 cancel() 函数来实现。为了成功撤单,通常需要先获取当前的委托列表,找到未成交(或部分成交)的订单编号(Order ID),然后针对该编号执行撤单操作。
以下是具体的实现步骤和代码示例。
cancel(orderId, accountId, accountType, ContextInfo)
orderId:委托编号(字符串),通常通过 get_trade_detail_data 获取到的对象属性 m_strOrderSysID 获得。accountId:资金账号。accountType:账号类型(如 'STOCK', 'FUTURE' 等)。ContextInfo:策略全局对象。can_cancel_order(orderId, accountId, accountType)
True (可撤) 或 False (不可撤)。get_trade_detail_data(accountId, accountType, 'ORDER')
以下代码展示了一个完整的流程:在 handlebar 中遍历当前账号的所有委托,检查每一笔委托是否处于“可撤销”状态,如果是,则执行撤单操作。
# -*- coding: gbk -*-
def init(ContextInfo):
# 1. 设置资金账号和类型
ContextInfo.accID = '6000000248' # 请替换为您真实的资金账号
ContextInfo.accType = 'STOCK' # 账号类型:'STOCK'股票, 'FUTURE'期货, 'CREDIT'信用等
# 2. 绑定账号(接收回报消息必须)
ContextInfo.set_account(ContextInfo.accID)
print("策略初始化完成,账号已绑定")
def handlebar(ContextInfo):
# 仅在最后一根K线(实时行情)执行,避免回测历史数据时重复触发
if not ContextInfo.is_last_bar():
return
# 1. 获取当前账号的所有委托记录
# 第三个参数 'ORDER' 表示获取委托信息
order_list = get_trade_detail_data(ContextInfo.accID, ContextInfo.accType, 'ORDER')
# 2. 遍历委托列表
for order in order_list:
# 获取委托编号
order_id = order.m_strOrderSysID
# 3. 判断该委托是否可以撤销
# 使用平台提供的 can_cancel_order 函数进行判断
if can_cancel_order(order_id, ContextInfo.accID, ContextInfo.accType):
# 4. 执行撤单
print(f"发现可撤销订单,委托号: {order_id},标的: {order.m_strInstrumentID}")
cancel(order_id, ContextInfo.accID, ContextInfo.accType, ContextInfo)
else:
# 仅用于调试,实际策略中可注释掉
# print(f"订单 {order_id} 当前状态不可撤销 (状态码: {order.m_nOrderStatus})")
pass
get_trade_detail_data 获取所有的委托对象。每个对象包含该笔委托的详细信息(如委托号、标的、状态等)。order.m_nOrderStatus 属性手动判断状态(如 50 已报, 55 部成),但直接使用 QMT 提供的 can_cancel_order 函数更加安全和简便。cancel 函数发送撤单指令。if not ContextInfo.is_last_bar(): return,确保撤单逻辑只在最新的实时行情中运行,防止在回测历史数据阶段错误地尝试操作。Q: 如何只撤销特定股票的订单?
A: 在遍历 order_list 时增加判断条件。例如:
if order.m_strInstrumentID == '600000.SH' and can_cancel_order(order_id, ...):
cancel(...)
Q: cancel 函数返回值是什么?
A: cancel 函数返回一个布尔值 (bool)。True 表示撤单指令发送成功(不代表撤单一定成功,需等待交易所确认),False 表示发送失败。
Q: 为什么调用了 cancel 但订单没有撤销?
A: 可能原因包括:
init 中使用 set_account 绑定。Q: 如何撤销所有任务(算法交易任务)?
A: 如果是算法交易产生的任务,需要使用 cancel_task(taskId, accountId, accountType, ContextInfo) 函数,而不是普通的 cancel。如果不指定 taskId,则会撤销该账号下所有可撤的任务。