3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 QMT(迅投/国信量化平台)中进行两融(融资融券)交易时,为了避免直接下单时因超出授信额度或可用资金而导致废单,通常需要先查询当前账号的最大可下单量。由于该查询需要向柜台服务器发送请求,QMT 采用了异步查询 + 回调机制,即通过 query_credit_opvolume 发起查询,并在 credit_opvolume_callback 中接收和处理返回结果。
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: 策略全局上下文环境对象。注意事项:
- 本函数一次最多支持查询 200 只股票。
- 同时只能有一个查询任务在进行,若上一次查询未完成再次调用,后续查询会提前返回。
- 由于从服务器实时拉取数据,建议平均查询间隔在 30 秒以上,切勿频繁调用。
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.SH 和 000001.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}")
seq):由于回调是异步触发的,建议使用时间戳或自增计数器作为 seq,并在 ContextInfo 中维护一个字典(例如 ContextInfo.pending_requests[seq] = ...),以便回调触发时准确关联触发查询时的逻辑上下文。time.time() 进行频率控制,避免因请求过于频繁导致服务器拒拒绝或账号被限制。result 里的最大可下单量后,结合实际策略拟调仓数量取小值,再调用 passorder 进行安全下单。