问题描述
解决方案
在 QMT 中,要在融券卖出前检查是否有券(即查询融券卖出的最大可下单量),需要使用 query_credit_opvolume 函数配合回调函数 credit_opvolume_callback 来实现。
这是一个异步操作:你发送查询请求,服务器处理后,通过回调函数将结果推送回来。
核心步骤
- 发起查询:在
handlebar或其他逻辑中调用query_credit_opvolume。- opType 参数需设置为 28(代表融券卖出)。
- 接收结果:在策略中定义
credit_opvolume_callback函数,系统会自动调用该函数并传入查询结果。- 如果返回的
result大于 0,说明有券且账户资金充足,可以下单。
- 如果返回的
策略代码示例
# -*- coding: gbk -*-
import time
def init(ContextInfo):
# 1. 设置您的信用资金账号
# 请将 '您的信用账号ID' 替换为实际的账号
ContextInfo.accid = '6000000248'
ContextInfo.set_account(ContextInfo.accid)
# 定义一个全局变量用于控制查询频率,避免每个tick都查
ContextInfo.last_query_time = 0
def handlebar(ContextInfo):
# 仅在最后一根K线(实时行情)运行
if not ContextInfo.is_last_bar():
return
# 示例:每隔10秒查询一次 600000.SH 的融券可用量
if time.time() - ContextInfo.last_query_time > 10:
stock_code = '600000.SH'
# 获取当前最新价作为参考价格
# 注意:get_market_data_ex 返回的是字典,需解析
last_data = ContextInfo.get_market_data_ex(['close'], [stock_code], period='1d', count=1)
if stock_code in last_data and not last_data[stock_code].empty:
current_price = last_data[stock_code].iloc[-1]['close']
else:
current_price = 10.0 # 获取失败时的默认值,实际使用请做好容错
# --- 核心查询逻辑 ---
# opType = 28 : 融券卖出
# prType = 11 : 限价 (也可以用 5 最新价等,需与下单类型一致)
# seq : 序列号,建议使用时间戳或唯一ID,以便在回调中区分是哪次查询
seq = int(time.time())
print(f"[{time.strftime('%H:%M:%S')}] 发起查询: {stock_code} 价格:{current_price} 融券可卖量...")
# 调用异步查询接口
query_credit_opvolume(ContextInfo.accid, stock_code, 28, 11, current_price, seq, ContextInfo)
ContextInfo.last_query_time = time.time()
def credit_opvolume_callback(ContextInfo, accid, seq, ret, result):
"""
查询两融最大可下单量的回调函数
系统会自动调用此函数返回 query_credit_opvolume 的结果
"""
# ret: 查询结果状态。1:正常返回, -1:正在查询中, <0: 报错
if ret == 1:
print(f"==> 回调收到 (seq={seq}): 账号 {accid} 融券卖出最大可下单量为: {result}")
if result > 0:
print(" -> 状态:有券可融。")
# 在此处可以添加下单逻辑,例如:
# passorder(28, 1101, accid, '600000.SH', 11, price, 100, ContextInfo)
else:
print(" -> 状态:无券 或 保证金不足 或 价格超出涨跌停限制。")
elif ret == -1:
print(f"==> 回调收到 (seq={seq}): 查询正在进行中...")
else:
print(f"==> 回调收到 (seq={seq}): 查询出错,错误代码: {ret}")
关键参数说明
-
query_credit_opvolume参数详解:accountId: 信用资金账号。stockCode: 股票代码(如'600000.SH')。opType: 28。这是融券卖出的操作代码。prType: 报价类型。通常填 11 (限价) 或 5 (最新价)。这会影响系统计算最大可买量时的资金预估。price: 委托价格。如果是限价单,填具体的数值;如果是市价单,此值可能被忽略,但建议填入当前价以获得准确估算。seq: 查询序列号(整数)。用于在回调函数中对应是哪一次查询。
-
注意事项:
- 频率限制: 该函数是从服务器/柜台查询数据,建议平均查询时间间隔 30秒 一次,不可在每个 tick 中频繁调用,否则可能导致查询阻塞或被柜台限制。
- 结果含义: 返回的
result是综合了券池余量和账户可用保证金后的最大可下单数量。如果返回 0,可能是券池没券,也可能是账户没钱(保证金),或者价格不在涨跌停范围内。 - 异步特性: 代码执行完
query_credit_opvolume后不会立即得到结果,必须在credit_opvolume_callback中处理后续逻辑(如下单)。
Q&A
Q: get_enable_short_contract 这个函数有什么用?
A: get_enable_short_contract(accId) 用于获取信用账户当前可融券的标的明细列表。它返回的是一个列表,告诉你哪些股票允许融券(即在标的池内),但它通常不包含具体的“当前可用数量”。如果你只是想筛选出哪些股票是融券标的,可以用这个函数;如果你需要知道具体能卖多少股(有没有券源),必须用 query_credit_opvolume。
Q: 为什么我查询到的结果是 0,但我看软件上显示有券?
A: query_credit_opvolume 返回的是最大可下单量。
- 检查您的信用账户是否有足够的可用保证金。如果没钱,即使有券,可下单量也是 0。
- 检查传入的
price是否在当日涨跌停范围内。 - 检查
opType是否填对(28 为融券卖出)。
Q: 回测模式下这个函数有效吗?
A: 在回测模式下,QMT 通常不连接真实的柜台券池,因此该函数可能无法返回真实的券源数据,或者返回模拟的无限量/固定量。该功能主要用于实盘交易中规避废单。