3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 QMT 平台中,默认的策略运行机制是基于“主图驱动”的,即策略挂载在哪个标的上,就由该标的的行情(Tick 或 Bar)来驱动 handlebar 函数的执行。
如果需要在策略中同时监控和交易多个标的(例如多因子选股、配对交易或篮子交易),仅依赖主图驱动可能会导致非主图标的的信号延迟。此时,我们需要使用 ContextInfo.subscribe_quote 接口来进行独立的数据订阅,并通过回调函数来处理实时推送的数据。
以下是关于如何在 QMT 策略中管理多个行情数据订阅的详细说明和代码示例。
ContextInfo.subscribe_quote(stock_code, period, dividend_type, callback)
handlebar。datas 参数,包含当前更新的数据。也可以结合 ContextInfo.get_market_data_ex 获取更详细的历史数据。以下代码展示了如何订阅一个股票列表,并在数据更新时实时打印最新价格。
# -*- coding: gbk -*-
def init(ContextInfo):
"""
初始化函数
"""
# 1. 定义需要订阅的股票池
ContextInfo.stock_list = ['600000.SH', '000001.SZ', '000300.SH']
# 2. 定义订阅的周期 (例如 'tick', '1m', '1d')
# 注意:实盘中通常订阅 'tick' 以获得最快响应
period = 'tick'
# 3. 遍历股票池进行订阅
print("开始订阅行情...")
for stock in ContextInfo.stock_list:
# subscribe_quote 返回订阅号,如果需要反订阅可以使用该返回值
# 参数说明: 代码, 周期, 复权方式('follow'跟随主图), 回调函数
ContextInfo.subscribe_quote(stock, period, 'follow', on_quote_callback)
print(f"已订阅: {stock}")
def on_quote_callback(datas):
"""
行情推送回调函数
当订阅的股票有新行情时,此函数会被触发
datas 格式: {code: dataframe}
"""
# 遍历推送过来的数据(通常一次推送可能包含一个或多个标的)
for stock_code, df in datas.items():
# 获取最新的一行数据
if not df.empty:
last_price = df.iloc[-1]['close']
# 获取当前时间 (毫秒时间戳转字符串,需自行实现或使用简单打印)
# 这里直接打印演示
print(f">>> 行情推送 [{stock_code}]: 最新价 {last_price}")
# 在此处编写您的交易逻辑
# 例如:如果价格突破某条线,则下单
# check_signal_and_order(stock_code, last_price)
def handlebar(ContextInfo):
"""
主图驱动函数
"""
# 如果策略完全依赖 subscribe_quote 的回调驱动,handlebar 可以留空
# 或者在这里处理一些定时任务、收盘后的逻辑
if ContextInfo.is_new_bar():
print(f"主图 {ContextInfo.stockcode} K线更新")
# 辅助函数示例:简单的交易逻辑封装
def check_signal_and_order(stock_code, price):
# 示例逻辑:仅作演示
pass
回调函数的定义 (on_quote_callback):
datas)。datas 是一个字典,Key 是合约代码,Value 是包含该合约最新数据的 pandas.DataFrame。订阅与主图的关系:
subscribe_quote 后,策略就变成了多源驱动。handlebar 依然会随主图(策略界面上选择的那个标的)更新而运行。on_quote_callback 会随订阅列表中的任意标的更新而运行。反订阅 (unsubscribe_quote):
ContextInfo.unsubscribe_quote(subId)。subId 是 subscribe_quote 调用时的返回值。数据获取建议:
datas 参数带有了最新的行情,但如果需要计算复杂的指标(如 MA, MACD),建议在回调函数内部调用 ContextInfo.get_market_data_ex 来获取指定长度的历史数据窗口。Q: subscribe_quote 在回测模式下有效吗?
A: 在回测模式下,QMT 主要依赖 handlebar 逐根 K 线驱动。虽然接口在回测中不会报错,但回测的核心逻辑通常是基于 handlebar 遍历历史时间轴。subscribe_quote 的主要应用场景是实盘和模拟交易中的实时行情监控。
Q: 订阅的股票数量有限制吗?
A: QMT 平台本身对订阅数量有一定的内部限制,且订阅过多标的(例如几千只)会消耗大量内存和 CPU 资源,导致策略响应变慢。建议根据硬件配置合理控制订阅数量,通常几十到几百只是可以接受的。
Q: 为什么我在 on_quote_callback 里下单没有反应?
A: 请检查是否正确设置了交易账号 (ContextInfo.set_account)。此外,确保回调函数内部的逻辑没有报错(可以使用 try...except 捕获异常并打印日志),因为回调函数是在后台线程运行的,有时错误信息不如主线程明显。
Q: 如何获取 Level-2 数据(如买一卖一队列)?
A: 如果您开通了 Level-2 权限,可以在 subscribe_quote 的周期参数中使用 'l2quoteaux' (快照指标) 或 'tick' (分笔) 并配合 get_market_data_ex 获取更深度的盘口数据。