问题描述
miniQMT 界面可以显示完整原因,query_stock_orders 返回的 XtOrder.status_msg 只能显示前 20 个字符。
请问如何判断废单原因?
解决方案
在 miniQMT (xtquant) 中,query_stock_orders 返回的 XtOrder 对象底层是通过 C++ 结构体映射过来的。由于底层结构体对状态信息字段(如 status_msg)的字符数组长度有限制,导致在 Python 端获取时经常会被截断(例如只显示前 20 个字符),从而无法看全完整的废单原因。
要解决这个问题并获取完整的废单原因,可以采用以下几种替代方案:
方法一:使用交易回调函数(推荐)
不要仅依赖主动查询(query_stock_orders),而是通过订阅交易主推回调来获取完整的错误信息。在回调函数中,通常会返回更详细的错误描述。
1. 在 miniQMT (xtquant) 中:
实现 XtTradedataCallback 接口中的 on_order_error 或 on_stock_order 回调。当订单发生错误时,底层推送的错误信息通常比查询接口返回的字段更完整。
2. 在 QMT 内置 Python API 中:
根据 QMT API 文档,可以使用 orderError_callback 主推函数来捕获异常下单的完整信息:
def orderError_callback(ContextInfo, orderArgs, errMsg):
print('下单异常参数:', orderArgs)
print('完整废单原因:', errMsg) # 这里可以获取完整的错误信息
方法二:查看 QMT 内置 API 的 m_strCancelInfo 字段
如果您是在 QMT 客户端内部编写策略,可以通过 get_trade_detail_data 或 get_value_by_order_id 获取原生的 order 委托对象。该对象包含一个专门记录废单原因的字段 m_strCancelInfo,它通常不会像状态信息那样被严重截断。
def handlebar(ContextInfo):
# 获取最新的委托号
orderid = get_last_order_id(ContextInfo.accid, 'stock', 'order')
if orderid != '-1':
# 获取委托对象
order_obj = get_value_by_order_id(orderid, ContextInfo.accid, 'stock', 'order')
if order_obj:
# m_strCancelInfo 专门用于记录废单原因
print('废单原因:', order_obj.m_strCancelInfo)
方法三:排查本地日志文件
如果代码层面暂时无法绕过截断问题,且急需排查某笔废单的原因,可以直接查看 QMT/miniQMT 客户端的本地日志文件。客户端界面上能显示完整原因,说明底层数据是完整的,只是在 Python 接口封装时被截断了。
- 日志路径:通常位于 QMT 安装目录下的
\userdata_mini\logs或\userdata\logs文件夹中。 - 排查方法:打开当天的日志文件(如
xttrader.log或类似名称),搜索对应的委托编号(order_id)或股票代码,即可看到柜台返回的原始、未截断的 JSON/文本格式的废单报错信息。
总结:对于自动化策略,建议**结合主推回调函数(Callback)**来捕获和处理废单逻辑,这比轮询 query_stock_orders 更加高效且信息更完整。