问题描述
解决方案
在 QMT 的 Python API 中,下单函数(如 passorder、order_lots 等)本身不直接返回委托 ID。
要获取刚下的那笔委托的 ID,需要在下单后立即调用 get_last_order_id() 函数。
为了确保获取到的 ID 确实是你刚刚下的那一单(而不是其他策略或人工下的单),强烈建议在下单时指定 strategyName(策略名),并在获取 ID 时传入相同的 strategyName。
以下是具体的实现步骤和代码示例:
核心步骤
- 下单时:在
passorder或其他交易函数中,传入strategyName参数。 - 下单后:立即调用
get_last_order_id(accountID, accountType, 'order', strategyName)。
代码示例
# -*- coding: gbk -*-
def init(ContextInfo):
# 设置资金账号
ContextInfo.accid = '6000000248'
# 设置账号类型:'STOCK'股票, 'FUTURE'期货
ContextInfo.accountType = 'STOCK'
# 绑定账号,用于接收回报
ContextInfo.set_account(ContextInfo.accid)
def handlebar(ContextInfo):
# 仅在最后一根K线运行,避免历史回测重复下单
if not ContextInfo.is_last_bar():
return
# 定义一个唯一的策略名称,用于区分委托
my_strategy_name = "my_strategy_001"
# 下单示例:以最新价买入 100 股 600000.SH
# 注意:这里必须传入 strategyName 参数
passorder(23, 1101, ContextInfo.accid, '600000.SH', 5, -1, 100, my_strategy_name, 1, "remark", ContextInfo)
# 下单后立即获取该策略名下的最新委托ID
# 参数说明:账号ID, 账号类型, 数据类型('order'), 策略名
order_id = get_last_order_id(ContextInfo.accid, ContextInfo.accountType, 'order', my_strategy_name)
if order_id != '-1':
print("下单成功,委托ID为: " + str(order_id))
# 可以进一步通过 ID 获取委托详细信息
order_obj = get_value_by_order_id(order_id, ContextInfo.accid, ContextInfo.accountType, 'order')
if order_obj:
print("委托合约: " + order_obj.m_strInstrumentID)
print("委托状态: " + str(order_obj.m_nOrderStatus))
else:
print("未获取到委托ID,可能下单失败或未生成委托")
注意事项
- strategyName 的重要性:如果不使用
strategyName,get_last_order_id返回的是该账号下全市场的最新一笔委托。如果此时有其他策略或人工在同一账号下单,可能会获取到错误的 ID。指定strategyName可以隔离出本策略的委托。 - 返回值检查:如果未找到对应的委托(例如下单参数错误导致未生成委托),
get_last_order_id会返回字符串'-1'。 - 交易函数封装:如果你使用的是
order_lots、order_value等封装函数,它们同样支持传入ContextInfo和账号信息,但对strategyName的支持可能不如passorder直接(取决于具体封装实现)。为了最精确的控制,建议在需要获取 ID 的场景下使用passorder。
Q&A
Q: 为什么下单函数不直接返回 Order ID?
A: QMT 的底层交易接口设计是异步的。Python 层的下单函数主要负责发送指令,指令发送后,柜台或交易网关生成 Order ID 是一个独立的过程。通过 get_last_order_id 查询是获取该生成结果的标准方式。
Q: get_last_order_id 能获取到成交 ID 吗?
A: 可以。将第三个参数从 'order' 改为 'deal',即 get_last_order_id(..., 'deal', ...),即可获取最新一笔成交的 ID。但请注意,委托发出后不一定立即成交,所以通常先获取委托 ID。
Q: 如果我不传 strategyName 会怎样?
A: 如果不传 strategyName,函数将返回该资金账号下最新产生的一笔委托 ID。在单策略、无人工干预的理想环境下通常没问题,但在多策略并发或有人工操作的环境下,极易获取到错误的 ID,导致逻辑混乱。