问题描述
解决方案
在 QMT 中,查询信用账户(两融账户)的最大可买或可卖数量,不能通过简单的数学计算(如可用资金除以价格)来准确获得,因为涉及到保证金比例、授信额度、折算率等复杂因素。
QMT 提供了专门的异步查询接口 query_credit_opvolume 配合回调函数 credit_opvolume_callback 来实现这一功能。
核心步骤
- 发起查询:在
handlebar或其他逻辑中调用query_credit_opvolume发送查询请求。 - 接收结果:必须在策略中定义
credit_opvolume_callback函数,平台会在查询结果返回时自动调用该函数,并将最大可下单量传入。
代码实现
以下是一个完整的策略示例,展示了如何查询“融资买入”和“融券卖出”的最大可下单量。
# -*- coding: gbk -*-
import time
def init(ContextInfo):
# 1. 设置资金账号(必须是信用账号)
# 请将下面的账号替换为您的真实信用账号
ContextInfo.accid = '88000001'
ContextInfo.set_account(ContextInfo.accid)
# 定义一个全局变量用于控制查询频率,避免频繁调用
ContextInfo.last_query_time = 0
def handlebar(ContextInfo):
# 避免在每根K线或每个Tick都查询,这里限制为每30秒查询一次
# 官方文档建议平均查询时间间隔30s一次,不可频繁调用
if time.time() - ContextInfo.last_query_time < 30:
return
# 获取当前时间戳作为唯一的序列号(seq),用于在回调中区分是哪次查询
seq = int(time.time())
# 标的代码
stock_code = '600000.SH'
# 假设下单价格为 10.0 元
order_price = 10.0
# 报价类型:11 代表限价 (同 passorder 的 prType)
pr_type = 11
# --- 查询 1: 融资买入 (opType = 27) ---
op_type_buy = 27
print(f"发起查询: 融资买入 {stock_code} 价格 {order_price}")
query_credit_opvolume(ContextInfo.accid, stock_code, op_type_buy, pr_type, order_price, seq, ContextInfo)
# --- 查询 2: 融券卖出 (opType = 28) ---
# 为了区分不同的查询,这里 seq + 1
op_type_sell = 28
print(f"发起查询: 融券卖出 {stock_code} 价格 {order_price}")
query_credit_opvolume(ContextInfo.accid, stock_code, op_type_sell, pr_type, order_price, seq + 1, ContextInfo)
# 更新查询时间
ContextInfo.last_query_time = time.time()
# --- 回调函数:接收查询结果 ---
def credit_opvolume_callback(ContextInfo, accid, seq, ret, result):
"""
ContextInfo: 策略全局对象
accid: 账号
seq: 发起查询时传入的序列号
ret: 查询状态 (1: 正常返回, -1: 查询中, -2: 账号非法, -3: 参数非法, -4: 超时/报错)
result: 查询到的最大可下单量
"""
if ret == 1:
print(f"【回调收到】账号:{accid}, 序列号:{seq}, 最大可下单量: {result}")
# 在这里可以将 result 存储到全局变量中,供 handlebar 下单使用
# 例如: ContextInfo.max_buy_volume = result
else:
print(f"【查询失败】账号:{accid}, 序列号:{seq}, 错误代码: {ret}")
关键参数说明
1. query_credit_opvolume 函数
用法:query_credit_opvolume(accountId, stockCode, opType, prType, price, seq, ContextInfo)
- accountId: 您的信用资金账号。
- stockCode: 股票代码(如
'600000.SH'),也可以是代码列表。 - opType: 操作类型,决定了您查询的是哪种业务的最大量。常用值如下:
27: 融资买入28: 融券卖出33: 担保品买入(使用自有资金买入)34: 担保品卖出(卖出持仓)
- prType: 报价类型,通常填
11(限价)。 - price: 委托价格。因为最大可买数量取决于价格(资金/价格),所以必须传入预期的下单价格。
- seq: 查询序列号(整数)。建议使用时间戳或自增ID,以便在回调函数中知道返回的数据对应哪一次查询。
2. credit_opvolume_callback 函数
用法:credit_opvolume_callback(ContextInfo, accid, seq, ret, result)
这是系统回调,不需要您手动调用,只需在代码中定义即可。当服务器返回数据时,系统会自动执行此函数。
- result: 这就是您需要的最大可下单数量。
注意事项
- 异步机制:该查询不是立即返回结果的。代码执行完
query_credit_opvolume后会继续往下执行,直到服务器响应后才会触发credit_opvolume_callback。因此,不要在调用查询函数的下一行直接使用结果下单。 - 调用频率:该函数需要向柜台/服务器发送请求,官方建议平均查询间隔 30秒一次,切勿在
handlebar中无限制地频繁调用,否则可能导致接口被限流或报错。 - 价格影响:传入的
price会直接影响计算出的最大数量(数量 ≈ 可用资金 / 价格 / 保证金比例),请务必传入合理的预期成交价。
Q&A
Q: 为什么不能直接用可用资金除以价格来计算融资买入量?
A: 信用交易涉及保证金比例(不同标的比例不同)、授信额度上限以及折算率等风控指标。简单的除法无法涵盖这些柜台端的风控逻辑,因此必须通过专用接口向柜台查询。
Q: opType 填 23 (普通买入) 可以吗?
A: 不可以。对于信用账户,必须明确指定是“担保品买入”(33) 还是 “融资买入”(27)。23 通常用于普通股票账户。
Q: 如果 ret 返回 -4 是什么意思?
A: 通常表示查询超时或服务器返回报错。这可能是网络问题,或者是查询过于频繁导致的,建议增加查询的时间间隔。