问题描述
2026-05-14 17:12:54 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 准备完成: ['231974.SH'] 1m 数据下载 (miniqmt_market.py:602)
2026-05-14 17:12:54 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 已完成: 231974.SH [1m] (1/8) 数据下载 (miniqmt_market.py:609)
2026-05-14 17:12:54 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 已完成: 231974.SH [1m] (2/8) 数据下载 (miniqmt_market.py:609)
2026-05-14 17:12:54 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 已完成: 231974.SH [1m] (3/8) 数据下载 (miniqmt_market.py:609)
2026-05-14 17:12:54 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 已完成: 231974.SH [1m] (4/8) 数据下载 (miniqmt_market.py:609)
2026-05-14 17:12:54 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 已完成: 231974.SH [1m] (5/8) 数据下载 (miniqmt_market.py:609)
2026-05-14 17:12:54 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 已完成: 231974.SH [1m] (6/8) 数据下载 (miniqmt_market.py:609)
2026-05-14 17:12:55 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 已完成: 231974.SH [1m] (7/8) 数据下载 (miniqmt_market.py:609)
2026-05-14 17:12:55 [ INFO] src.market.feed.vendors.miniqmt.miniqmt_market: 已完成: 231974.SH [1m] (8/8) 数据下载 (miniqmt_market.py:609)
两支股票分成 16 次下载
{'finished': 1, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
{'finished': 2, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
{'finished': 3, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
{'finished': 4, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
{'finished': 5, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
{'finished': 6, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
{'finished': 7, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
{'finished': 8, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
{'finished': 9, 'total': 16, 'stockcode': '', 'message': '600111.SH'}
{'finished': 10, 'total': 16, 'stockcode': '', 'message': '600111.SH'}
{'finished': 11, 'total': 16, 'stockcode': '', 'message': '600111.SH'}
{'finished': 12, 'total': 16, 'stockcode': '', 'message': '600111.SH'}
{'finished': 13, 'total': 16, 'stockcode': '', 'message': '600111.SH'}
{'finished': 14, 'total': 16, 'stockcode': '', 'message': '600111.SH'}
{'finished': 15, 'total': 16, 'stockcode': '', 'message': '600111.SH'}
{'finished': 16, 'total': 16, 'stockcode': '', 'message': '600111.SH'}
现在 message 里只有股票代码,而 stockcode 里反而为空了?是逻辑错误,还是?
按正常的逻辑,分批下载也可以,但是有没有一个返回值告诉分批下载完成的提示。
解决方案
在使用 QMT 平台的 xtdata.download_history_data2 接口下载历史数据时,遇到分批下载和回调参数异常的情况,这其实是 QMT 底层数据处理机制的一部分。以下是详细的解析和处理建议:
1. 为什么会分批下载?
QMT 底层在处理大量历史数据(特别是分钟级数据,如 1m 数据)时,为了避免单次请求数据量过大导致内存溢出或网络超时,会将数据按时间段切分成多个批次进行下载。例如,一年的 1m 数据可能会被切分成 8 个批次。当请求多只股票时,总批次数会相应增加(如两只股票各 8 批次,总计 16 批次)。
2. 回调参数 message 和 stockcode 的问题
在回调函数返回的字典中:
{'finished': 1, 'total': 16, 'stockcode': '', 'message': '600031.SH'}
message包含股票代码,而stockcode为空:这通常是 QMT 底层 C++ 接口在封装回调数据时的一个已知特性(或可以说是历史遗留的命名不规范)。在某些版本的 QMT 中,message字段被用来传递当前正在处理的股票代码或状态信息,而stockcode字段可能未被正确赋值。建议在编写回调处理逻辑时,直接从message字段提取股票代码。
3. 如何判断分批下载完成?
要判断整个下载任务是否完成,可以通过比较回调字典中的 finished 和 total 字段。当 finished == total 时,表示所有批次的数据均已下载完毕。
示例代码:
from xtquant import xtdata
import time
# 定义回调函数
def on_download_progress(data):
finished = data.get('finished', 0)
total = data.get('total', 0)
message = data.get('message', '')
print(f"下载进度: {finished}/{total}, 当前处理: {message}")
if finished == total and total > 0:
print("所有数据下载完成!")
# 在这里可以触发后续的数据处理逻辑
# 股票列表
stock_list = ['600031.SH', '600111.SH']
# 开始下载
print("开始下载历史数据...")
xtdata.download_history_data2(
stock_list=stock_list,
period='1m',
start_time='20230101',
end_time='20231231',
callback=on_download_progress
)
# 保持主线程运行,等待异步下载完成
while True:
time.sleep(1)
总结
- 分批下载是正常逻辑,用于处理大数据量。
message包含股票代码是已知特性,请直接从中提取信息。- 通过
finished == total判断下载完成,并在回调中触发后续逻辑。