QMT交易靠”回调函数”实时更新账户、委托、成交状态。
那么什么是回调函数?
如,当一笔新的成交回报推送到客户端时,QMT会自动调用我们预设的deal_callback函数,并将成交详情作为参数传递给它。简单来说 :回调就是QMT在事件触发时自动替你执行预先写好的函数。
为什么在QMT中使用回调函数?
在量化交易中,交易信号的产生和执行、账户资金的变动、持仓的更新等都是异步发生的事件。如果使用传统的轮询方式(即每隔一段时间就去查询一次状态),不仅效率低下,还会增加延迟,甚至可能错过关键的交易时机。而回调函数完美地解决了这个问题,它提供了一种事件驱动的模式,使得策略能够实时响应市场和交易系统的变化,从而实现更高效、更精准的执行交易。
回调函数如何工作?
1.定义函数:我们需要在我们的策略代码中,按照QMT规定的函数名和参数格式,定义一个或多个回调函数。
在策略初始化阶段(init函数中),我们一般通过ContextInfo.set_account() 来指定要监控的资金账户。
2.事件触发:当交易过程中有相关事件发生时(如资金变动、委托状态更新、新成交等),QMT的客户端会接收到这些信息。QMT客户端会自动调用我们已经定义好的、与该事件对应的回调函数,并将事件的详细信息作为参数传入。
通过这套机制,我们的策略就能像一个时刻待命的机器人,对交易过程中的每一个关键事件做出即时反应。
核心回调函数详解:
接下来,我们将深入探讨几个最常用、也是最重要的回调函数。掌握了它们,你就能够实时监控和处理交易过程中的核心事件。
2.1 account_callback: 资金账户状态变化
此函数在你的资金账户状态发生任何变化时被触发,例如资金的存入、取出,或者当日盈亏的变化等。
释义:当资金账号状态有变化时,QMT客户端会调用此函数。
用法:account_callback(ContextInfo, accountInfo)
2.2 order_callback: 委托状态变化
每当你提交一笔委托,或者这笔委托的状态发生改变(如从未成交到部分成交,或完全成交,或被撤销),order_callback就会被调用。
释义:当账号的委托状态有变化时,QMT客户端会调用此函数。
用法:order_callback(ContextInfo, orderInfo)
2.3 deal_callback: 成交状态变化
当你的任何一笔委托产生了实际的成交,deal_callback就会被触发。这通常是策略逻辑中最核心的部分,因为成交意味着你的交易意图得到了市场的响应。
释义:当账号有新的成交记录时,QMT客户端会调用此函数。
用法:deal_callback(ContextInfo, dealInfo)
2.4 position_callback: 持仓状态变化
任何导致你账户持仓发生变动的行为(主要是买入或卖出成交),都会触发position_callback。这个函数对于实时计算持仓盈亏、管理仓位风险至关重要。
释义:当账号的持仓状态有变化时,QMT客户端会调用此函数。
用法:position_callback(ContextInfo, positionInfo)
3. 错误处理
在真实的交易环境中,下单操作并非总能成功。可能会因为资金不足、涨跌停限制、非交易时间等原因导致下单失败。及时捕获并处理这些异常情况,是保证策略稳定运行的重要环节。
3.1 orderError_callback: 异常下单处理
当任何一笔下单请求未能通过柜台或交易所的校验,被拒绝执行时,orderError_callback就会被触发,并返回详细的错误信息。
释义:当账号下单异常时,QMT客户端会调用此函数。
用法:orderError_callback(ContextInfo, orderArgs, errMsg) 通过这个回调,你可以知道哪一笔下单失败了,以及失败的原因,从而进行相应的处理
下面是一段完整的示例代码:供学习参考
# coding:gbk
"""
QMT主推回调函数框架案例
基于以下五个核心回调函数构建的完整策略模板:
1. account_callback - 资金账户状态变化主推
2. task_callback - 账号任务状态变化主推
3. order_callback - 账号委托状态变化主推
4. deal_callback - 账号成交状态变化主推
5. position_callback - 账号持仓状态变化主推
"""
# ============ 全局配置 ============
# 账户配置
ACCOUNT_ID = "你的账户"
# 交易配置
STOCK_CODE = "000001.SZ" # 交易股票代码(例如平安银行)
ORDER_PRICE = 15.0 # 下单价格
ORDER_VOLUME = 100 # 下单数量
# 策略状态
strategy_status = {
"initialized": False, # 是否初始化完成
"started": False, # 是否启动完成
"total_orders": 0, # 总委托数
"total_deals": 0, # 总成交数
"current_position": 0, # 当前持仓
"total_asset": 0, # 总资产
"available_cash": 0, # 可用资金
}
# 订单追踪
orders_tracking = {} # 用于追踪订单状态
deals_tracking = {} # 用于追踪成交记录
# ============ 辅助函数 ============
def show_data(data):
"""
将QMT对象转换为字典,便于查看所有属性
参数:
data: QMT对象
返回:
包含所有属性的字典
"""
tdata = {}
for ar in dir(data):
if ar[:2] != 'm_':
continue
try:
tdata[ar] = getattr(data, ar)
except:
tdata[ar] = '<无法转换>'
return tdata
def print_header(title):
"""打印标题"""
print("\n" + "="*60)
print(f" {title}")
print("="*60)
def print_section(title):
"""打印小标题"""
print(f"\n{'-'*60}")
print(f" {title}")
print(f"{'-'*60}")
def log_message(level, message):
"""
统一的日志输出函数
参数:
level: 日志级别 (INFO, WARN, ERROR, SUCCESS)
message: 日志消息
"""
level_map = { #可以在这里添加标志我就随便添加了一些
"INFO": "?? ",
"WARN": "?? ",
"ERROR": "?",
"SUCCESS": "?"
}
prefix = level_map.get(level, "")
print(f"{prefix} {message}")
def init(ContextInfo):
"""
策略初始化函数
在策略启动时被调用一次
职责:
初始化全局变量
设置策略参数
准备数据结构
"""
print_header("策略初始化 - init()")
try:
# 标记初始化开始
strategy_status["initialized"] = False
log_message("INFO", f"账户号: {ACCOUNT_ID}")
log_message("INFO", f"交易股票: {STOCK_CODE}")
log_message("INFO", f"下单价格: {ORDER_PRICE}元")
log_message("INFO", f"下单数量: {ORDER_VOLUME}股")
# 初始化订单和成交追踪字典
orders_tracking.clear()
deals_tracking.clear()
# 标记初始化完成
strategy_status["initialized"] = True
log_message("SUCCESS", "策略初始化完成,等待after_init执行...")
except Exception as e:
log_message("ERROR", f"初始化失败: {e}")
def after_init(ContextInfo):
"""
策略启动后执行的函数
在init()之后立即执行一次
职责:
发送初始委托
启动交易逻辑
初始化监控
【如何在此函数中下单】
使用 passorder 函数发送委托指令,格式如下(具体可参考前面的文章):
passorder(
23, # 订单类型:23=普通委托
1101, # 业务类型:1101=A股买卖
account, # 账户对象(由QMT系统提供)
"000001.SZ", # 合约代码
15.0, # 委托价格
100, # 委托数量
11, # 价格类型:11=限价单
"买入", # 订单备注
ContextInfo # 上下文对象
)
"""
print_header("策略启动 - after_init()")
try:
strategy_status["started"] = False
log_message("INFO", "策略启动,准备发送委托...")
# ===== 发送第一笔正常委托 =====
print_section("发送第一笔委托 - 正常买入")
print(f" 股票代码: {STOCK_CODE}")
print(f" 买入价格: {ORDER_PRICE}元")
print(f" 买入数量: {ORDER_VOLUME}股")
print(f" 下单类型: 限价买入")
try:
# 在这里调用 passorder 函数
# 注意:account 是由QMT系统自动传入的全局变量
# 你可以直接使用 account,不需要任何前缀
# 取消注释下面这行来实际发送委托
# passorder(23, 1101, account, STOCK_CODE, ORDER_PRICE, ORDER_VOLUME, 11, "正常买入", ContextInfo)
log_message("SUCCESS", "第一笔委托已发送")
strategy_status["total_orders"] += 1
except Exception as e:
log_message("ERROR", f"发送第一笔委托失败: {e}")
# ===== 发送第二笔异常委托(一般用于测试错误处理)=====
# ===== 发送第二笔异常委托(一般用于测试错误处理)=====
print_section("发送第二笔委托 - 异常委托(测试错误处理)")
print(f" 股票代码: XXXXXX.SZ (不存在的合约)")
print(f" 买入价格: 10.0元")
print(f" 买入数量: 100股")
print(f" 说明: 此委托会失败,用于测试orderError_callback")
try:
# 取消注释下面这行来实际发送异常委托
# passorder(23, 1101, account, "XXXXXX.SZ", 10.0, 100, 11, "异常测试", ContextInfo)
log_message("INFO", "异常委托已发送(用于测试错误处理)")
except Exception as e:
log_message("ERROR", f"发送第二笔委托失败: {e}")
# 标记启动完成
strategy_status["started"] = True
log_message("SUCCESS", "策略启动完成,等待回调信息...")
except Exception as e:
log_message("ERROR", f"启动失败: {e}")
# ============ 五大主推回调函数 ============
def account_callback(ContextInfo, accountInfo):
"""
主推函数1--资金账户状态变化主推
当账户的资金状态发生变化时被调用
包括:资金变动、持仓市值变化、盈亏变化等
参数:
ContextInfo: QMT全局上下文
accountInfo: 账户对象,包含账户的详细信息
关键属性:
m_dTotalAsset: 总资产
m_dAvailable: 可用资金
m_dMarketValue: 持仓市值
m_dDynamicProfit: 今日盈亏
m_dStaticProfit: 总盈亏
用途:
- 实时监控账户资金状态
- 计算账户盈亏
- 控制仓位大小
- 风险管理
"""
try:
print_section("【account_callback】资金账户状态变化")
account_data = show_data(accountInfo)
# 获取关键财务数据
total_asset = account_data.get('m_dTotalAsset', 0)
available = account_data.get('m_dAvailable', 0)
market_value = account_data.get('m_dMarketValue', 0)
dynamic_profit = account_data.get('m_dDynamicProfit', 0)
static_profit = account_data.get('m_dStaticProfit', 0)
# 更新全局状态
strategy_status["total_asset"] = total_asset
strategy_status["available_cash"] = available
# 打印账户信息
print(f" 账户号: {account_data.get('m_strAccountID', 'N/A')}")
print(f" 总资产: {total_asset:.2f}元")
print(f" 可用资金: {available:.2f}元")
print(f" 持仓市值: {market_value:.2f}元")
print(f" 今日盈亏: {dynamic_profit:.2f}元")
print(f" 总盈亏: {static_profit:.2f}元")
# 风险提示
if available < ORDER_PRICE * ORDER_VOLUME:
log_message("WARN", "可用资金不足,可能无法完成下单")
# ===== 你的账户处理逻辑 =====
# 在这里可以添加
# 例如:根据资金状态调整仓位、执行止损等
except Exception as e:
log_message("ERROR", f"account_callback异常: {e}")
def task_callback(ContextInfo, taskInfo):
"""
主推函数2--账号任务状态变化主推
当账户有异步任务状态变化时被调用
包括:查询任务、批量操作等
参数:
ContextInfo: QMT全局上下文
taskInfo: 任务对象,包含任务的详细信息
关键属性:
m_nTaskStatus: 任务状态
m_strTaskID: 任务ID
用途:
- 监控异步任务进度
- 处理任务完成事件
- 管理后台操作
"""
try:
print_section("【task_callback】账号任务状态变化")
task_data = show_data(taskInfo)
# 获取任务信息
task_status = task_data.get('m_nTaskStatus', 'N/A')
task_id = task_data.get('m_strTaskID', 'N/A')
print(f" 任务ID: {task_id}")
print(f" 任务状态: {task_status}")
#
# 在这里添加例如:根据任务状态执行相应操作
except Exception as e:
log_message("ERROR", f"task_callback异常: {e}")
def order_callback(ContextInfo, orderInfo):
"""
主推函数3--账号委托状态变化主推
当账户的委托状态发生变化时被调用
包括:新委托、委托被拒、部分成交、全部成交、已撤等
参数:
ContextInfo: QMT全局上下文
orderInfo: 委托对象,包含委托的详细信息
关键属性:
m_strInstrumentID: 合约代码
m_nOrderStatus: 委托状态 (0=未报, 1=已报, 2=已成, 3=部成, 4=已撤, 5=待撤, 6=拒单)
m_dLimitPrice: 委托价格
m_nVolumeTotalOriginal: 委托总数量
m_nVolumeTraded: 已成交数量
m_strOrderSysID: 委托编号
用途:
- 跟踪委托进度
- 管理订单状态
- 执行止损/止盈
- 记录交易日志
"""
try:
print_section("【order_callback】账号委托状态变化")
order_data = show_data(orderInfo)
# 获取委托信息
instrument_id = order_data.get('m_strInstrumentID', 'N/A')
order_status = order_data.get('m_nOrderStatus', 'N/A')
limit_price = order_data.get('m_dLimitPrice', 0)
volume_total = order_data.get('m_nVolumeTotalOriginal', 0)
volume_traded = order_data.get('m_nVolumeTraded', 0)
order_sys_id = order_data.get('m_strOrderSysID', 'N/A')
direction = order_data.get('m_nDirection', 0)
# 打印委托信息
print(f" 合约代码: {instrument_id}")
print(f" 交易方向: {'买入' if direction == 0 else '卖出'}")
print(f" 委托价格: {limit_price}元")
print(f" 委托数量: {volume_total}股")
print(f" 已成数量: {volume_traded}股")
print(f" 委托状态: {order_status}")
print(f" 委托编号: {order_sys_id}")
# 状态解释
status_map = {
0: "未报",
1: "已报",
2: "已成",
3: "部成",
4: "已撤",
5: "待撤",
6: "拒单"
}
status_text = status_map.get(order_status, "未知")
print(f" 状态说明: {status_text}")
# 追踪订单
orders_tracking[order_sys_id] = {
"instrument": instrument_id,
"status": order_status,
"price": limit_price,
"volume": volume_total,
"traded": volume_traded
}
# 根据委托状态执行相应操作
if order_status == 2: # 已成
log_message("SUCCESS", f"委托 {order_sys_id} 已全部成交")
elif order_status == 3: # 部成
log_message("INFO", f"委托 {order_sys_id} 部分成交,已成 {volume_traded}/{volume_total}")
elif order_status == 6: # 拒单
log_message("WARN", f"委托 {order_sys_id} 被拒单")
# 在这里可以添加
# 例如:根据委托状态执行止损、止盈等操作
except Exception as e:
log_message("ERROR", f"order_callback异常: {e}")
def deal_callback(ContextInfo, dealInfo):
"""
主推函数4--账号成交状态变化主推
当账户有新的成交时被调用
每次成交都会触发此回调
参数:
ContextInfo: QMT全局上下文
dealInfo: 成交对象,包含成交的详细信息
关键属性:
m_strInstrumentID: 合约代码
m_nDirection: 交易方向 (0=买入, 1=卖出)
m_dTradePrice: 成交价格
m_nVolume: 成交数量
m_strTradeTime: 成交时间
m_dTradeAmount: 成交金额
用途:
- 处理成交事件
- 更新持仓成本
- 记录交易日志
- 执行后续操作(如设置止盈止损)
"""
try:
print_section("【deal_callback】账号成交状态变化")
deal_data = show_data(dealInfo)
# 获取成交信息
instrument_id = deal_data.get('m_strInstrumentID', 'N/A')
direction = deal_data.get('m_nDirection', 0)
trade_price = deal_data.get('m_dTradePrice', 0)
volume = deal_data.get('m_nVolume', 0)
trade_time = deal_data.get('m_strTradeTime', 'N/A')
trade_amount = deal_data.get('m_dTradeAmount', 0)
# 更新全局状态
strategy_status["total_deals"] += 1
# 打印成交信息
print(f" 成交合约: {instrument_id}")
print(f" 交易方向: {'买入' if direction == 0 else '卖出'}")
print(f" 成交价格: {trade_price}元")
print(f" 成交数量: {volume}股")
print(f" 成交金额: {trade_amount:.2f}元")
print(f" 成交时间: {trade_time}")
# 追踪成交
deal_id = deal_data.get('m_strDealID', 'N/A')
deals_tracking[deal_id] = {
"instrument": instrument_id,
"direction": direction,
"price": trade_price,
"volume": volume,
"amount": trade_amount,
"time": trade_time
}
log_message("SUCCESS", f"新成交: {instrument_id} {volume}股 @ {trade_price}元")
# 在这里添加如:
# 1. 更新持仓成本
# 2. 设置止盈止损
# 3. 发送通知
# 4. 记录交易日志
except Exception as e:
log_message("ERROR", f"deal_callback异常: {e}")
def position_callback(ContextInfo, positionInfo):
"""
主推函数5--账号持仓状态变化主推
当账户的持仓发生变化时被调用
主要是买入或卖出成交后
参数:
ContextInfo: QMT全局上下文
positionInfo: 持仓对象,包含持仓的详细信息
关键属性:
m_strInstrumentID: 合约代码
m_nVolume: 持仓数量
m_dOpenPrice: 开仓成本(平均成本价)
m_dMarketValue: 持仓市值
m_dPositionProfit: 持仓盈亏
m_dPositionProfitRate: 持仓盈亏比例
用途:
- 监控持仓变化
- 计算持仓盈亏
- 管理仓位风险
- 执行风险控制
"""
try:
print_section("【position_callback】账号持仓状态变化")
pos_data = show_data(positionInfo)
# 获取持仓信息
instrument_id = pos_data.get('m_strInstrumentID', 'N/A')
volume = pos_data.get('m_nVolume', 0)
open_price = pos_data.get('m_dOpenPrice', 0)
market_value = pos_data.get('m_dMarketValue', 0)
position_profit = pos_data.get('m_dPositionProfit', 0)
position_profit_rate = pos_data.get('m_dPositionProfitRate', 0)
# 更新全局状态
strategy_status["current_position"] = volume
# 打印持仓信息
print(f" 持仓合约: {instrument_id}")
print(f" 持仓数量: {volume}股")
print(f" 开仓成本: {open_price:.2f}元/股")
print(f" 持仓市值: {market_value:.2f}元")
print(f" 持仓盈亏: {position_profit:.2f}元")
print(f" 盈亏比例: {position_profit_rate:.2f}%")
# 盈亏提示
if position_profit > 0:
log_message("SUCCESS", f"持仓盈利: {position_profit:.2f}元")
elif position_profit < 0:
log_message("WARN", f"持仓亏损: {position_profit:.2f}元")
else:
log_message("INFO", "持仓平价")
# 在这里可以添加如:
# 1. 根据盈亏执行止盈止损
# 2. 动态调整仓位
# 3. 风险预警
except Exception as e:
log_message("ERROR", f"position_callback异常: {e}")
def orderError_callback(ContextInfo, orderArgs, errMsg):
"""
异常下单回调
当下单请求被拒绝或发生错误时被调用
参数:
ContextInfo: QMT全局上下文
orderArgs: 下单参数对象
errMsg: 错误信息字符串
用途:
- 捕获下单错误
- 记录错误日志
- 发送错误通知
- 调整策略参数
"""
try:
print_section("【orderError_callback】下单异常")
order_params = show_data(orderArgs)
# 获取下单参数
instrument_id = order_params.get('m_strInstrumentID', 'N/A')
limit_price = order_params.get('m_dLimitPrice', 0)
volume = order_params.get('m_nVolume', 0)
# 打印错误信息
print(f" 异常合约: {instrument_id}")
print(f" 异常价格: {limit_price}元")
print(f" 异常数量: {volume}股")
print(f" 错误原因: {errMsg}")
log_message("ERROR", f"下单失败: {errMsg}")
# 在这里可以添加如:
# 1. 记录错误到文件
# 2. 发送错误通知
# 3. 调整策略参数后重试
except Exception as e:
log_message("ERROR", f"orderError_callback异常: {e}")
# ============ 策略状态查询函数 ============
def print_strategy_status():
"""打印策略当前状态"""
print_header("策略状态汇总")
print(f" 初始化状态: {'? 已完成' if strategy_status['initialized'] else '? 未完成'}")
print(f" 启动状态: {'? 已启动' if strategy_status['started'] else '? 未启动'}")
print(f" 总委托数: {strategy_status['total_orders']}")
print(f" 总成交数: {strategy_status['total_deals']}")
print(f" 当前持仓: {strategy_status['current_position']}股")
print(f" 总资产: {strategy_status['total_asset']:.2f}元")
print(f" 可用资金: {strategy_status['available_cash']:.2f}元")
def print_orders_status():
"""打印所有订单状态"""
print_header("订单追踪信息")
if not orders_tracking:
print(" 暂无订单信息")
return
for order_id, order_info in orders_tracking.items():
print(f"\n 订单ID: {order_id}")
print(f" 合约: {order_info['instrument']}")
print(f" 状态: {order_info['status']}")
print(f" 价格: {order_info['price']}元")
print(f" 数量: {order_info['volume']}股")
print(f" 已成: {order_info['traded']}股")
def print_deals_status():
"""打印所有成交记录"""
print_header("成交追踪信息")
if not deals_tracking:
print(" 暂无成交信息")
return
for deal_id, deal_info in deals_tracking.items():
print(f"\n 成交ID: {deal_id}")
print(f" 合约: {deal_info['instrument']}")
print(f" 方向: {'买入' if deal_info['direction'] == 0 else '卖出'}")
print(f" 价格: {deal_info['price']}元")
print(f" 数量: {deal_info['volume']}股")
print(f" 金额: {deal_info['amount']:.2f}元")
print(f" 时间: {deal_info['time']}")
# ============ 使用说明 ============
"""
框架简易介绍
这是一个基于QMT五大主推回调函数的示例框架:
1. account_callback - 资金账户状态变化主推
用于监控账户资金、计算盈亏、控制仓位
2. task_callback - 账号任务状态变化主推
用于监控异步任务、处理后台操作
3. order_callback - 账号委托状态变化主推
用于跟踪委托进度、管理订单、执行止损止盈
4. deal_callback - 账号成交状态变化主推
用于处理成交事件、更新持仓、记录交易
5. position_callback - 账号持仓状态变化主推
用于监控持仓、计算盈亏、执行风险控制
"""最后我们来看看结果:
著作权归文章作者所有。