问题描述
解决方案
在 QMT 中,想要在订单成交后立刻获取通知并打印信息,最推荐的方法是使用 交易回报实时主推函数 中的 deal_callback。
相比于在 handlebar 中轮询查询成交记录,deal_callback 是由交易柜台或模拟撮合系统主动推送的,具有实时性高、延迟低的特点。
实现步骤
- 初始化账号:在
init函数中必须使用ContextInfo.set_account(account_id)绑定资金账号,否则无法接收该账号的回报。 - 定义回调函数:在策略代码中定义
deal_callback(ContextInfo, dealInfo)函数。 - 读取成交信息:通过
dealInfo对象读取成交价格 (m_dPrice) 和成交数量 (m_nVolume)。
完整代码示例
# -*- coding: gbk -*-
def init(ContextInfo):
# 1. 设置资金账号
# 请将 'YOUR_ACCOUNT_ID' 替换为您实际的资金账号
account_id = '600000248'
ContextInfo.set_account(account_id)
print(f"策略初始化完成,已绑定账号: {account_id}")
def handlebar(ContextInfo):
# 这里编写您的交易策略逻辑
# 为了演示,这里留空,实际使用时这里会有下单逻辑
pass
def deal_callback(ContextInfo, dealInfo):
"""
成交回报主推函数
当有订单成交时,系统会自动调用此函数
"""
# 2. 获取成交的关键信息
stock_code = dealInfo.m_strInstrumentID # 证券代码
trade_price = dealInfo.m_dPrice # 成交均价
trade_volume = dealInfo.m_nVolume # 成交数量
direction = dealInfo.m_nDirection # 买卖方向 (48:买入, 49:卖出)
offset_flag = dealInfo.m_nOffsetFlag # 开平标志 (48:开仓, 49:平仓)
trade_time = dealInfo.m_strTradeTime # 成交时间
order_sys_id = dealInfo.m_strOrderSysID # 柜台委托号
remark = dealInfo.m_strRemark # 投资备注
# 转换买卖方向文字描述
dir_str = "买入" if direction == 48 else "卖出"
# 3. 打印信息
print("=" * 30)
print(f"【实时成交回报】 {trade_time}")
print(f"标的: {stock_code}")
print(f"操作: {dir_str}")
print(f"成交价格: {trade_price}")
print(f"成交数量: {trade_volume}")
print(f"委托编号: {order_sys_id}")
print(f"备注: {remark}")
print("=" * 30)
# 如果需要基于成交做进一步逻辑(如止损设置),可以在这里添加代码
关键点说明
-
dealInfo 对象属性:
m_dPrice: 成交均价 (浮点数)。m_nVolume: 成交数量 (整数)。m_strInstrumentID: 证券代码 (字符串)。m_strOrderSysID: 对应的委托编号,可用于关联原始订单。m_strRemark: 投资备注,如果在下单时设置了userOrderId或备注,这里会返回,方便策略追踪是哪一笔逻辑触发的成交。
-
运行模式:
- 此回调函数主要在 “实盘” 或 “模拟交易” (运行模式) 下生效。
- 在纯历史数据 “回测” 模式下,部分旧版本 QMT 可能不支持回调触发,但在最新的 QMT 版本中,回测引擎通常也会模拟触发此回调。
-
注意事项:
- 如果一笔委托分多次成交(部成),
deal_callback会被调用多次,每次对应其中一笔具体的成交明细。
- 如果一笔委托分多次成交(部成),
Q&A
Q: deal_callback 和 get_trade_detail_data 有什么区别?
A: deal_callback 是事件驱动的,只有在成交发生的那一瞬间会被系统主动调用,实时性最强,适合做实时通知或触发后续逻辑。get_trade_detail_data 是主动查询函数,通常在 handlebar 或定时任务中调用,用于获取当前的成交列表快照,适合做定期对账或状态检查。
Q: 为什么我的 deal_callback 没有被触发?
A: 请检查以下几点:
- 是否在
init中正确调用了ContextInfo.set_account()绑定了产生交易的账号。 - 策略是否处于“运行”状态(而非停止)。
- 是否确实发生了成交(委托状态变为“已成”或“部成”)。
Q: 如何区分是买入成交还是卖出成交?
A: 通过 dealInfo.m_nDirection 属性判断。通常 48 代表买入(ENTRUST_BUY),49 代表卖出(ENTRUST_SELL)。具体枚举值可参考 QMT API 文档附录。