问题描述
解决方案
on_order_response 与 on_trade_response 的区别及用法
在 PTrade 量化交易系统中,on_order_response(委托主推)和 on_trade_response(成交主推)都是用于接收实时交易状态更新的回调函数,但它们的触发时机和包含的数据侧重点完全不同。
1. 核心区别
| 特性 | on_order_response (委托主推) | on_trade_response (成交主推) |
|---|---|---|
| 触发时机 | 委托状态发生任何变化时触发。包括:已报、废单、部成、已成、已撤等。 | 仅在发生实际成交时触发。包括:部分成交、全部成交。 |
| 关注对象 | 订单 (Order) 的生命周期。关注的是这张单子当前处于什么状态(是排队中、撤单了还是完成了)。 | 成交 (Trade) 的具体细节。关注的是刚刚那一笔撮合发生了什么(成交了多少股、成交价是多少)。 |
| 数据内容 | 包含委托编号、委托状态(status)、累计成交量、剩余撤销信息等。 | 包含成交编号、成交价格、本次成交数量、成交金额等。 |
| 典型用途 | 监控订单是否报送成功、判断是否已全部完成、确认撤单是否成功。 | 计算实时的成交均价、统计刚刚买入/卖出的具体数量、做高频对冲逻辑。 |
2. 我应该用哪个来确认单子成交了?
如果你只是想确认**“我的单子有没有产生交易(成交)”**,最直接且推荐使用的是 on_trade_response。
- 推荐理由:该函数只有在撮合成功(买卖成交)时才会触发。只要收到了这个回调,就意味着资金和股票发生了交换。
- 补充说明:如果你需要确认**“单子是否全部执行完毕(不再有剩余挂单)”**,则需要结合
on_order_response中的status字段(状态为 '8' 代表已成)来判断。
3. 详细场景解析
场景 A:你需要知道刚刚那一笔成交了多少钱,用于计算成本
使用 on_trade_response。
因为它返回的 trade_list 中包含 business_price(成交均价)和 business_amount(本次成交量),这是计算实时成本最准确的数据。
场景 B:你需要知道订单是否被废单,或者是否撤单成功
使用 on_order_response。
on_trade_response 不会推送废单或撤单信息。你需要监听 on_order_response 中的 status:
status == '9': 废单status == '6': 已撤status == '8': 已成(全部成交)
4. 代码示例
以下代码展示了如何同时使用这两个函数来监控交易状态:
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
# 必须在 initialize 中开启接收主推消息的参数(部分券商环境默认开启,显式设置更稳妥)
# receive_other_response: 是否接收非本策略产生的订单主推
set_parameters(receive_other_response="1")
def handle_data(context, data):
# 示例:下单买入 1000 股
order(g.security, 1000)
# 【委托主推】:用于监控订单状态变化(报单、撤单、全部完成)
def on_order_response(context, order_list):
for order_info in order_list:
# 获取订单状态
status = order_info.get('status')
entrust_no = order_info.get('entrust_no')
if status == '8':
log.info("订单 %s 已全部成交(Order Finished)" % entrust_no)
elif status == '9':
log.error("订单 %s 是废单,请检查资金或参数(Order Rejected)" % entrust_no)
elif status == '6':
log.info("订单 %s 已撤单(Order Canceled)" % entrust_no)
elif status == '2':
log.info("订单 %s 已报送至柜台(Order Submitted)" % entrust_no)
# 【成交主推】:用于确认具体的成交动作(最适合确认“成交了”)
def on_trade_response(context, trade_list):
for trade_info in trade_list:
stock_code = trade_info.get('stock_code')
price = trade_info.get('business_price')
amount = trade_info.get('business_amount')
entrust_no = trade_info.get('entrust_no')
# 只要进到这里,说明肯定发生了成交
log.info(">>> 确认成交!股票: %s, 委托号: %s, 本笔成交价: %f, 本笔成交量: %f" % (
stock_code, entrust_no, price, amount
))
Q&A 常见问题解答
Q: 如果一个大单分成了 5 笔成交,这两个函数会触发几次?
on_trade_response: 会触发 5次。每一笔撮合成功都会推送一次,告诉你这一笔成交了多少。on_order_response: 可能会触发 5次或更多。每次成交后,订单的“累计成交量”发生变化,状态可能从“已报”变为“部成”(部分成交),最后变为“已成”。它反映的是订单状态的更新。
Q: on_order_response 里的 amount 和 on_trade_response 里的 business_amount 有什么区别?
on_order_response中的amount通常指委托总数量(或者是该订单当前的累计成交数量,视具体字段定义而定,通常需结合business_amount字段看累计值)。on_trade_response中的business_amount指的是当前这一笔的成交数量(增量)。
Q: 回测模式下这两个函数有用吗?
- 有用。PTrade 的回测引擎会模拟撮合过程。虽然回测通常是基于分钟或日线数据,但在回测中这两个函数依然会被调用,逻辑与实盘一致,非常适合用来验证策略的信号处理逻辑。