🚀 AI 一键生成 qmt 策略代码

QMT/miniQMT 卖出股票后 query_stock_asset 资金未更新怎么办?

qmt | 发布时间: 2026/5/21
以下内容由 EasyQuant 生成。

问题描述

miniqmt,国金,卖完成交了,query_stock_asset的cash还没变,你们遇到过么

国金证券,我是监听一个组合,先卖后买,卖完之后,没隔 0.3 秒查询余额然后买入,循环 8 秒,结果 cash 一直没有增加...

是我代码的问题么?还是国金客户端哪里设置的错了缓存之类的?

解决方案

这是一个在 QMT/miniQMT 实盘交易中非常常见的问题,不是你的代码写错了,也不是客户端设置错误,而是由底层接口的缓存机制和券商柜台的同步延迟造成的。

为什么会出现资金未及时更新的情况?

  1. 客户端缓存机制:QMT 客户端为了降低对券商柜台的查询压力,对资产查询(如 query_stock_assetget_trade_detail_data 查询 account)是有缓存机制的。你每隔 0.3 秒去高频轮询,极大概率命中的都是本地缓存的旧数据,而不是实时去柜台拉取的最新数据。
  2. 柜台结算延迟:即使订单在交易所已经撮合成交,券商柜台进行资金解冻、清算并更新到你的可用资金账户中,也需要一定的毫秒级到秒级的时间。0.3秒的轮询频率远快于柜台资金状态同步的频率。
  3. 字段查看错误:请确保你查询的是可用资金(Available)而不是可取资金(FetchBalance)。A股是T+1交收,卖出后的钱当天只能买股票(可用),不能提现(可取)。

推荐的解决方案

在量化交易中,极其不推荐使用高频轮询(While + Sleep)的方式来等待资金更新。正确的做法是采用事件驱动(回调函数)本地资金影子账户的方式。

方案一:使用成交回报回调(推荐)

利用 QMT 提供的 deal_callback(成交主推函数)。当卖出订单真实成交时,系统会主动推送成交信息。你可以在收到卖出成交的回报后,再触发买入逻辑。

def init(ContextInfo):
    ContextInfo.set_account('你的资金账号')
    ContextInfo.buy_flag = False # 控制是否已经触发买入

def deal_callback(ContextInfo, dealInfo):
    # 当收到成交回报时触发
    print('收到成交回报,成交代码:', dealInfo.m_strInstrumentID)
    
    # 判断如果是你刚才卖出的股票成交了
    if dealInfo.m_nDirection == 49: # 49代表卖出
        print(f'卖出成交数量: {dealInfo.m_nVolume}, 成交金额: {dealInfo.m_dTradeAmount}')
        
        # 此时说明钱已经回来了(或者即将回来),可以执行买入逻辑
        if not ContextInfo.buy_flag:
            # 执行买入操作
            # passorder(23, 1101, ContextInfo.accID, '买入代码', 5, -1, 买入数量, ContextInfo)
            ContextInfo.buy_flag = True

方案二:维护本地“影子资金”

如果你必须连续执行“卖出 -> 买入”的换仓操作,最稳妥的方法是在代码中自己计算可用资金,而不是依赖接口返回。

  1. 策略初始化时,查询一次初始可用资金 local_cash = get_trade_detail_data(acc, 'stock', 'account')[0].m_dAvailable
  2. 当你下达卖出指令并确认成交后,在代码里手动加上这笔钱:local_cash += (卖出成交价 * 卖出数量 - 预估手续费)
  3. 下买入单时,直接使用你本地维护的 local_cash 作为资金上限进行下单。

方案三:降低轮询频率并强制刷新

如果你一定要用轮询的方式,请将 sleep(0.3) 改为 sleep(1)sleep(2)。过高的频率不仅查不到最新资金,还可能触发券商柜台的流控限制(Rate Limit),导致账号被临时限制查询。

总结:放弃 0.3 秒的高频轮询,改用 deal_callback 监听卖出成交事件,或者在本地自行计算卖出释放的资金,是解决此类换仓资金衔接问题的最佳实践。