问题描述
如题,使用 subscribe_whole_quote 订阅..再通过 get_market_data_ex 无法获取到数据..但是如果是用
subscribe_quote订阅数据就会自动写入本地,能通过 get_market_data_ex 获得数据...这样是正常的么
解决方案
现象解答
这是完全正常的现象。
在 QMT(迅投/国信)量化平台中,subscribe_whole_quote(全量/全市场订阅)和 subscribe_quote(单票/指定标的订阅)在底层的数据处理机制上有着本质的区别。您所遇到的“全量订阅无法通过 get_market_data_ex 获取,而单票订阅可以”正是由这两种机制的设计初衷决定的。
核心原因解析
1. subscribe_whole_quote(全量订阅)的内存推送机制
全市场订阅通常涉及几千只股票的实时 Tick 数据。如果将这些高频、海量的数据实时写入本地硬盘,会造成极大的磁盘 I/O 瓶颈,导致系统卡顿甚至崩溃。因此,QMT 底层对全量订阅的设计是纯内存回调推送:
- 不写本地:数据到达后直接通过回调函数(Callback)推送到策略内存中,不会自动落盘。
- 无法被
get_market_data_ex读取:因为get_market_data_ex的底层逻辑是优先从本地数据库/缓存中读取数据,既然全量订阅没有落盘,该函数自然无法获取到最新数据。
2. subscribe_quote(指定订阅)的落盘机制
subscribe_quote 主要用于订阅少数指定的合约(如主图合约或特定的股票池)。
- 自动落盘/缓存:由于数据量可控,QMT 底层会自动将这些订阅的数据写入本地缓存或数据库中。
- 支持
get_market_data_ex:当您调用get_market_data_ex时,系统能够从本地读取到刚刚通过subscribe_quote补充进来的最新数据。
解决方案与最佳实践
如果您需要处理全量行情数据,建议采用以下方式:
方案一:直接在回调函数中处理数据(推荐)
对于全量订阅,最标准的做法是直接在回调函数中接收并处理数据,而不是试图去本地读取。您可以将需要的数据存入 Python 的全局变量(如 dict)中供策略使用。
# 全量订阅回调处理示例逻辑
def on_whole_quote(datas):
# datas 通常是一个字典,包含了推送过来的最新行情
for stock_code, data in datas.items():
# 直接在内存中处理或更新您的全局状态
# 例如:ContextInfo.my_market_data[stock_code] = data
pass
方案二:按需使用 subscribe_quote
如果您的策略只需要关注特定的股票池(例如沪深300成分股,或者几十只自选股),强烈建议使用 subscribe_quote 遍历订阅这些股票,而不是使用全量订阅。这样既能保证数据自动落盘,又能完美兼容 get_market_data_ex。
def init(ContextInfo):
# 订阅特定股票池
stock_list = ['000300.SH', '600000.SH', '000001.SZ']
for code in stock_list:
ContextInfo.subscribe_quote(code, period='1d', dividend_type='none', callback=on_quote)
def on_quote(datas):
# 单票订阅的回调
print("收到行情推送:", datas)
def handlebar(ContextInfo):
# 此时可以通过 get_market_data_ex 获取到已订阅落盘的数据
data = ContextInfo.get_market_data_ex(
['close'], ['000300.SH'], period='1d'
)
print(data)
总结
- 全量订阅 (
subscribe_whole_quote) = 内存回调,不落盘,适合高频/全市场扫描,需在回调中自行维护状态。 - 指定订阅 (
subscribe_quote) = 自动落盘,适合特定股票池,完美兼容get_market_data_ex。