问题描述
/
解决方案
在 ptrade 量化交易平台中,使用 cancel_order_ex 函数进行撤单时,如果在 on_trade_response(成交主推)或 on_order_response(委托主推)中发现 order_id 字段为空字符串 "",这通常是由非本策略(非本交易)产生的订单引起的。
以下是详细的原因解析:
1. cancel_order_ex 与全局订单
根据 ptrade API 文档,cancel_order_ex(order_param) 函数专门用于撤销通过 get_all_orders() 函数获取的订单。而 get_all_orders() 获取的是账户当日所有订单,这其中不仅包含当前策略发出的订单,还包含非本交易的订单记录(例如:其他并行运行的策略发出的订单、用户通过终端手动发出的订单等)。
2. 缺少对应的 Order 对象
ptrade 引擎在运行当前策略时,只会在内存中为当前策略调用 order() 系列函数产生的委托生成对应的 Order 对象,并分配一个唯一的 order_id。
对于策略外交易产生的订单,当前策略的运行环境中不存在对应的 Order 对象。
3. 主推机制的底层逻辑
当订单状态发生变化(如撤单成功)触发 on_trade_response 或 on_order_response 主推回调时,系统会尝试将底层柜台的委托信息映射到策略内的 Order 对象。
文档中明确指出:“当接到策略外交易产生的主推时(需券商配置默认不推送),由于没有对应的Order对象,主推信息中order_id字段赋值为""”。
总结与建议
因为您使用 cancel_order_ex 撤销的可能是一笔非当前策略发出的订单,系统在推送撤单成交结果时找不到该订单在当前策略中的 Order 对象,所以 order_id 只能返回空值。
应对建议:
如果您需要追踪这类全局订单的撤单状态,不要依赖 order_id,而应该使用柜台返回的委托编号 entrust_no 来进行唯一性匹配和状态跟踪。例如:
def on_trade_response(context, trade_list):
for trade in trade_list:
if trade.get('order_id') == "":
log.info("收到非本策略订单的成交主推,委托编号为: %s, 状态为: %s" % (trade.get('entrust_no'), trade.get('status')))