问题描述
请问两种下单的区别是什么? 分别适用于什么样的场景?
还有 order_stock_async 为什么不能回调成交主推 on_stock_trade
解决方案
首先需要说明的是,order_stock 和 order_stock_async 通常是 Ptrade 量化平台的 API 函数。在 QMT 平台中,对应的核心下单函数是 passorder 或 order_lots 等。不过,同步下单与异步下单的逻辑在量化交易中是通用的。以下为您详细解答这两种模式的区别、适用场景,以及 QMT 中的对应实现方案。\n\n### 一、 同步下单与异步下单的区别\n\n1. 同步下单 (类似 order_stock)\n* 执行机制:程序在调用下单函数后会阻塞(等待),直到交易柜台返回下单结果(如委托成功、委托失败、返回委托编号等),程序才会继续执行下一行代码。\n* 优点:逻辑清晰,能够立即获取委托编号(order_id),方便后续逻辑直接依赖该委托结果。\n* 缺点:如果网络延迟或柜台响应慢,会导致策略卡顿,影响后续行情的处理或其他股票的下单。\n\n2. 异步下单 (类似 order_stock_async)\n* 执行机制:程序调用下单函数后立即返回,不等待柜台的响应结果,直接执行下一行代码。下单请求会被放入后台队列异步发送。\n* 优点:执行速度极快,不会阻塞策略主线程,非常适合需要同时对多只股票进行批量下单的场景。\n* 缺点:无法立即获取委托编号,必须依赖回调函数(Callback)来接收委托和成交结果,逻辑编写相对复杂。\n\n### 二、 适用场景\n\n* 同步下单适用场景:单只股票交易、对下单顺序有严格要求的策略(例如:必须确认卖出成功后,才执行买入操作的网格交易或调仓逻辑)、低频交易。\n* 异步下单适用场景:高频交易、多只股票的批量调仓(如一篮子股票买卖)、对时间极度敏感的抢单策略。\n\n### 三、 为什么异步下单不能回调成交主推?\n\n在某些平台(如 Ptrade)中,order_stock_async 无法触发 on_stock_trade 回调,通常有以下几个原因:\n1. 底层机制隔离:异步下单通常由独立的后台线程或进程池处理,其上下文环境可能与主策略的事件循环隔离,导致底层 C++ 核心在收到成交回报时,无法正确路由到 Python 层的回调函数中。\n2. 委托编号未及时映射:异步下单时,策略尚未在本地记录该笔订单的上下文。当极速成交回报返回时,系统可能找不到对应的本地订单记录,从而丢弃了回调。\n3. API 设计限制:部分平台的异步接口设计为“发后不理”(Fire-and-Forget),仅用于极致速度的盲发,故意阉割了状态追踪和回调机制以减少性能开销。\n\n### 四、 QMT 平台中的替代方案\n\n在 QMT 平台中,下单机制默认是基于事件驱动的,核心下单函数 passorder 配合 quickTrade 参数可以实现极速下单。QMT 提供了完善的实时主推回调函数,无论下单速度多快,都能稳定接收回调:\n\n1. QMT 下单示例\npython\ndef handlebar(ContextInfo):\n # 使用 passorder 下单,quickTrade=1 表示立即触发下单\n passorder(23, 1101, ContextInfo.accid, '000001.SZ', 5, -1, 100, 'MyStrategy', 1, 'UserOrder001', ContextInfo)\n\n\n2. QMT 接收成交与委托回调\nQMT 中必须在 init 中绑定账号,才能正常接收回调:\npython\ndef init(ContextInfo):\n # 绑定资金账号,用于接收交易主推\n ContextInfo.set_account('6000000058')\n\n# 委托状态变化主推\ndef order_callback(ContextInfo, orderInfo):\n print('收到委托回报,委托号:', orderInfo.m_strOrderSysID)\n\n# 成交状态变化主推(相当于 on_stock_trade)\ndef deal_callback(ContextInfo, dealInfo):\n print('收到成交回报,成交代码:', dealInfo.m_strInstrumentID, '成交量:', dealInfo.m_nVolume)\n\n\n总结:如果您在追求极速下单的同时又需要稳定的成交回调,建议在 QMT 中使用 passorder 结合 deal_callback 机制,这套机制在底层 C++ 的支持下既能保证非阻塞的高效执行,又能完美追踪每一笔订单的成交状态。