问题描述
委托主推回调为什么速度更快
解决方案
在 PTrade 量化交易平台中,on_order_response(委托主推回调)的执行速度显著快于使用 get_order() 或 get_orders() 进行普通查询。这种速度优势主要源于底层数据交互机制的根本差异。
以下是导致 on_order_response 速度更快的核心原因解析:
1. 事件驱动(Push) vs 主动查询(Pull)
- 委托主推(Push 机制):
on_order_response是基于事件驱动的。当券商柜台的订单状态发生任何变化(如已报、部成、已成、废单等)时,底层交易网关会第一时间主动将这些状态变化推送(Push)给策略引擎,并立即触发on_order_response回调函数。这种方式几乎没有延迟。 - 普通查询(Pull 机制):
get_order()等查询函数是策略**主动向引擎或柜台发起请求(Pull)**来获取状态。策略通常需要在handle_data或run_interval中定时轮询,这不可避免地会产生时间间隔(例如每秒查一次,那么状态更新最多可能有 1 秒的延迟)。
2. 绕过引擎状态同步的中间环节
根据 PTrade 官方 API 文档说明,on_order_response “比引擎、get_order()和get_orders()函数更新Order状态的速度更快”。
- 当柜台状态返回时,主推回调是直接将底层原始数据(字典格式)传递给策略。
- 而引擎内部维护的
Order对象状态,需要等待底层数据到达后,再进行解析、状态机更新和对象封装。get_order()查询的往往是引擎同步后的状态,这中间存在微小的处理时延。
3. 减少网络与系统开销
主动查询需要经历“发起请求 -> 引擎处理 -> (可能)请求柜台 -> 柜台响应 -> 引擎解析 -> 返回策略”的完整往返过程(Round Trip)。而主推回调是单向的底层直接通知,极大地减少了系统 I/O 和网络通信的开销。
适用场景与使用建议
由于其极高的响应速度,on_order_response 非常适合对速度要求极高的策略(如 Tick 级交易、高频做市、抢单策略或需要极速撤单重报的场景)。
⚠️ 使用注意事项:
- 避免无限循环:如果在
on_order_response内部直接调用order()等下单接口,新下的单又会触发主推回调,极易造成无限迭代循环。必须通过状态标志(如全局变量g.flag)进行严格的逻辑控制。 - 处理外部订单:如果接收到非本策略(如手动在终端下单)产生的主推,由于引擎中没有对应的 Order 对象,主推信息中的
order_id字段会为空字符串"",策略代码中需要对此做好异常处理。 - 废单状态差异:如果是废单(如下单价格超过价格笼子),
order()函数依然会返回order_id,在委托回调里的status可能是2(已报),但在随后的成交回调(on_trade_response)或最终状态中status会变为9(废单)。
代码示例:
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
g.order_placed = False
def on_order_response(context, order_list):
# 极速响应订单状态变化
for order_info in order_list:
log.info(f"收到委托主推,订单号: {order_info.get('order_id')}, 状态: {order_info.get('status')}")
# 示例:如果订单已成 (status == '8'),执行后续极速逻辑
if order_info.get('status') == '8':
log.info("订单已完全成交!")
def handle_data(context, data):
if not g.order_placed:
order(g.security, 100)
g.order_placed = True
总结来说,利用 on_order_response 可以让你的 PTrade 策略从“被动等待”升级为“主动响应”,是提升量化交易执行效率的关键技巧。