🚀 AI 一键生成 qmt 策略代码
立即体验

QMT 如何异步查询两融最大可下单量并处理回调结果?

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

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: QMT 两融 API 进阶:query_credit_opvolume 与回调函数异步处理

Question: QMT 如何异步查询两融最大可下单量并处理回调结果?

解决方案

QMT 两融 API 进阶:query_credit_opvolume 与回调函数异步处理

在 QMT(迅投/国信量化平台)中进行两融(融资融券)交易时,为了避免直接下单时因超出授信额度或可用资金而导致废单,通常需要先查询当前账号的最大可下单量。由于该查询需要向柜台服务器发送请求,QMT 采用了异步查询 + 回调机制,即通过 query_credit_opvolume 发起查询,并在 credit_opvolume_callback 中接收和处理返回结果。


一、核心 API 接口说明

1. 发起查询:query_credit_opvolume()

用法:

query_credit_opvolume(accountId, stockCode, opType, prType, price, seq, ContextInfo)

关键参数解析:

  • accountId (str): 查询的两融资金账号。
  • stockCode (str 或 list): 股票代码(如 '600000.SH')或代码列表。
  • opType (int): 操作类型(同 passorder 中的 opType,例如 33 表示信用账号股票买入,27 表示融资买入,28 表示融券卖出)。
  • prType (int): 报单价格类型(同 passorder 中的 prType,如 11 为指定价,5 为最新价)。
  • price (float 或 list): 报价。若 stockCode 为列表,则 price 也需为同等长度的列表。
  • seq (int): 查询序列号(建议传入唯一值如毫秒/秒级时间戳,以便在回调中匹配请求)。
  • ContextInfo: 策略全局上下文环境对象。

注意事项:

  1. 本函数一次最多支持查询 200 只股票。
  2. 同时只能有一个查询任务在进行,若上一次查询未完成再次调用,后续查询会提前返回。
  3. 由于从服务器实时拉取数据,建议平均查询间隔在 30 秒以上,切勿频繁调用。

2. 接收回调:credit_opvolume_callback()

用法:

def credit_opvolume_callback(ContextInfo, accid, seq, ret, result):
    pass

回调参数解析:

  • ContextInfo: 策略模型全局对象。
  • accid (str): 查询对应的资金账号。
  • seq (int): 发起 query_credit_opvolume 时传入的序列号,用于区分是哪一次查询。
  • ret (int): 查询状态码。
    • 1: 正常返回
    • -1: 正在查询中
    • -2: 输入账号非法
    • -3: 输入查询参数非法
    • -4: 超时或服务器返回报错
  • result: 查询到的具体结果(字典或数据结构,包含最大可下单数量等)。

二、代码示例与异步处理实现

下面展示一个完整的 Python 策略结构,说明如何在 handlebar 或定时器中发起两融可下单量查询,并在 credit_opvolume_callback 回调函数中异步接收处理。例如担保品买入 600000.SH000001.SZ

#coding:gbk
import time

def init(ContextInfo):
    # 设置两融账号
    ContextInfo.accid = '6000000248'
    ContextInfo.set_account(ContextInfo.accid)
    
    # 记录最后查询时间,防止频繁请求
    ContextInfo.last_query_time = 0

def handlebar(ContextInfo):
    now = time.time()
    
    # 控制查询间隔,至少间隔 30 秒
    if now - ContextInfo.last_query_time > 30:
        ContextInfo.last_query_time = now
        
        # 生成唯一序列号 (seq)
        seq_id = int(now)
        
        # 示例:批量查询 600000.SH(限价 10 元)与 000001.SZ(限价 20 元)在信用账号下的买入最大数量
        # opType=33 (信用账号股票买入), prType=11 (指定价)
        stocks = ['600000.SH', '000001.SZ']
        prices = [10.0, 20.0]
        
        print(f"发起两融最大可下单量查询, seq: {seq_id}")
        query_credit_opvolume(ContextInfo.accid, stocks, 33, 11, prices, seq_id, ContextInfo)

def credit_opvolume_callback(ContextInfo, accid, seq, ret, result):
    """
    异步回调函数:当柜台返回两融查询结果时自动触发
    """
    if ret == 1:
        print(f"[查询成功] 账号: {accid}, seq: {seq}, 结果: {result}")
        # 在此处可结合策略逻辑进行解析与后续下单操作,如使用 passorder 下单
    else:
        print(f"[查询失败/异常] 账号: {accid}, seq: {seq}, 状态码(ret): {ret}, 错误信息: {result}")

三、实践最佳优化建议

  1. 唯一标识匹配(seq:由于回调是异步触发的,建议使用时间戳或自增计数器作为 seq,并在 ContextInfo 中维护一个字典(例如 ContextInfo.pending_requests[seq] = ...),以便回调触发时准确关联触发查询时的逻辑上下文。
  2. 频率限制:API 明确要求平均查询间隔不宜低于 30s。建议在策略逻辑中加锁或通过 time.time() 进行频率控制,避免因请求过于频繁导致服务器拒拒绝或账号被限制。
  3. 配合风险控制:在回调中获取到 result 里的最大可下单量后,结合实际策略拟调仓数量取小值,再调用 passorder 进行安全下单。