🚀 AI 一键生成 qmt 策略代码

QMT API 教程:如何通过 `account_callback` 实时监控账户状态变化?

qmt | 发布时间: 2025/12/16
以下内容由 EasyQuant 生成。

问题描述

如何实时监控我交易账户的资金和风险状态变化?

解决方案

在 QMT 平台中,要实现对交易账户资金和风险状态的实时监控,最有效的方法是使用 交易回报实时主推函数 中的 account_callback

相比于在 handlebar 中轮询查询,account_callback事件驱动的。这意味着只有当资金账号状态发生变化(如成交、出入金、持仓市值变化导致净值改变)时,该函数才会被触发。这种方式响应速度最快,且占用资源最少。

实现步骤

  1. 初始化 (init):必须使用 ContextInfo.set_account(account_id) 绑定需要监控的资金账号。如果不绑定,回调函数将不会接收到任何推送。
  2. 定义回调 (account_callback):编写该函数逻辑,当收到推送时,从 accountInfo 对象中提取总资产、可用资金、冻结资金及风险度等关键信息。

策略代码实现

以下是一个完整的 Python 策略示例,专门用于监控并打印账户资金变动:

# -*- coding: gbk -*-

def init(ContextInfo):
    """
    初始化函数
    """
    # 1. 设置需要监控的资金账号
    # 请将 'YOUR_ACCOUNT_ID' 替换为您实际的资金账号,例如 '600000248'
    # 注意:实盘模式下必须设置正确的账号,回测模式下该回调可能不触发或行为不同
    account_id = '600000248' 
    ContextInfo.account_id = account_id
    
    # 2. 绑定账号以接收主推消息
    # 这一步至关重要,没有这一步 account_callback 不会被触发
    ContextInfo.set_account(account_id)
    
    print(f"策略初始化完成,开始监控账号: {account_id}")

def handlebar(ContextInfo):
    """
    行情驱动函数
    """
    # 此策略主要依赖回调监控资金,handlebar 中无需编写轮询逻辑
    pass

def account_callback(ContextInfo, accountInfo):
    """
    资金账号状态变化主推函数
    当资金、权益、风险度发生变化时,系统自动调用此函数
    """
    # 过滤非当前监控账号的推送(如果是多账号策略)
    if accountInfo.m_strAccountID != ContextInfo.account_id:
        return

    print("=" * 40)
    print(f"【资金变动实时监控】 时间: {ContextInfo.get_bar_timetag(ContextInfo.barpos)}")
    print(f"账号ID: {accountInfo.m_strAccountID}")
    
    # --- 核心资金数据 ---
    # 总资产 (动态权益/市值)
    print(f"总资产 (Balance): {accountInfo.m_dBalance:.2f}")
    # 可用资金
    print(f"可用资金 (Available): {accountInfo.m_dAvailable:.2f}")
    # 冻结资金 (保证金 + 手续费等)
    print(f"冻结资金 (Frozen): {accountInfo.m_dFrozenCash:.2f}")
    
    # --- 风险与持仓数据 ---
    # 风险度 (通常用于期货或两融,普通股票通常为0或无效)
    # 计算公式通常为:占用保证金 / 权益
    print(f"风险度 (Risk): {accountInfo.m_dRisk:.2f}")
    
    # 持仓盈亏
    print(f"持仓盈亏 (Position Profit): {accountInfo.m_dPositionProfit:.2f}")
    
    # 净值 (Nav)
    print(f"单位净值 (Nav): {accountInfo.m_dNav:.4f}")
    
    # --- 针对信用/期货账户的额外字段 ---
    # 如果是信用账户,可以监控总负债
    if accountInfo.m_dTotalDebit > 0:
        print(f"总负债 (Total Debit): {accountInfo.m_dTotalDebit:.2f}")
        
    print("=" * 40)

    # 扩展逻辑:可以在这里添加风控报警
    # 例如:如果可用资金低于某个阈值,或者风险度过高,发送通知或停止交易
    # if accountInfo.m_dRisk > 0.8:
    #     print("警告:风险度过高!")

代码关键点解析

  1. ContextInfo.set_account(account_id):

    • 这是开启实时监控的开关。必须在 init 中调用。如果策略需要监控多个账号,可以多次调用该函数传入不同的账号 ID。
  2. accountInfo 对象属性:

    • m_dBalance: 总资产。这是最常用的字段,代表当前的动态权益。
    • m_dAvailable: 可用资金。用于判断当前是否还有资金进行新开仓。
    • m_dFrozenCash: 冻结资金。包含挂单冻结、保证金占用等。
    • m_dRisk: 风险度
      • 对于期货/两融账户,这是一个核心风控指标。
      • 对于普通股票账户,此值可能没有实际意义(通常显示为 0)。
    • m_dPositionProfit: 持仓盈亏。反映当前持仓的浮动盈亏情况。
  3. 运行模式:

    • 此功能必须在实盘(或连接了柜台的模拟盘)模式下运行才有效。
    • 在纯历史回测模式下,account_callback 通常不会模拟资金推送,回测中的资金变化通常在 handlebar 内部通过 ContextInfo.capital 等变量体现。

常见问题 (Q&A)

Q: 为什么我的 account_callback 从来没有被触发?
A: 请检查以下两点:

  1. 是否在 init 函数中正确调用了 ContextInfo.set_account('账号ID')
  2. 策略是否处于“实盘”运行模式。如果是在编辑器的“回测”模式下,该回调不会触发。

Q: 如何监控持仓变化而不是资金变化?
A: QMT 提供了 position_callback(ContextInfo, positionInfo) 函数。用法与 account_callback 类似,当持仓数量或状态发生变化时会触发,用于监控具体的持仓明细。

Q: m_dRisk 风险度是如何计算的?
A: 具体的计算方式依赖于柜台返回的数据。一般而言,在期货中风险度 = 保证金占用 / 客户权益。在股票两融中,通常关注维持担保比例(m_dPerAssurescaleValue,位于信用账号详情中),而不是简单的 m_dRisk 字段。

Q: 我可以在回调函数中直接下单吗?
A: 可以。例如,当检测到 m_dAvailable (可用资金) 大于一定金额时触发买入,或者当 m_dRisk (风险度) 超过警戒线时触发平仓(强平保护)。但要注意避免死循环下单(例如下单导致资金变化,资金变化又触发回调)。