QMT“回调函数”新手指南

QUANT 2025-11-27 14:45:11 92 举报

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 - 账号持仓状态变化主推
   用于监控持仓、计算盈亏、执行风险控制
"""

最后我们来看看结果:




尊重知识,尊重市场 1

著作权归文章作者所有。

最新回复 ( 0 )
发新帖
0
DEPRECATED: addslashes(): Passing null to parameter #1 ($string) of type string is deprecated (/data/user/htdocs/xiunophp/xiunophp.min.php:48)