问题描述
我先调用了xtdata.download_history_data2(stock_list, '1d', end_time=today, callback=lambda data: print(data),
incrementally=None)
然后再调用xtdata.get_market_data_ex([], stocks, period='1d', count=11)
但是获取的数据却没有最新的数据,这是为什么呢?
或者大家都是怎么获取最新的数据的呢?
解决方案
在 QMT (迅投) 量化平台中,遇到 download_history_data2 表现为异步执行,导致紧接着调用 get_market_data_ex 获取不到最新数据,这是一个非常典型的数据同步问题。以下是详细的原因分析及解决方案:
一、 为什么会变成异步执行?
根本原因在于你传入了 callback 参数。
在 QMT 的底层设计中,数据下载涉及到与服务器的网络通信。为了防止主线程被长时间阻塞(特别是在下载大量数据时导致界面卡死),API 提供了异步回调机制:
- 异步模式(非阻塞):当你传入了
callback参数(如callback=lambda data: print(data)),函数会立即返回,并在后台线程进行数据下载。下载完成或有进度时,会触发你提供的回调函数。因此,紧接着执行的get_market_data_ex会在数据真正下载到本地之前运行,自然获取不到最新数据。 - 同步模式(阻塞):如果你不传入
callback参数(或者将其设为None),函数通常会以同步阻塞的方式运行,直到数据完全下载到本地硬盘后才会执行下一行代码。
二、 如何解决获取不到最新数据的问题?
根据你的需求,有以下几种解决方案:
方法 1:强制同步下载(推荐用于盘前/盘后数据准备)
去掉 callback 参数,让程序阻塞等待下载完成,然后再读取数据。
import xtdata
# 1. 同步下载数据(不传 callback)
xtdata.download_history_data2(stock_list, '1d', end_time=today, incrementally=None)
# 2. 下载完成后,再从本地读取数据
data = xtdata.get_market_data_ex([], stocks, period='1d', count=11)
print(data)
方法 2:在回调函数中获取数据(适用于需要异步不阻塞主线程的场景)
如果你希望保持异步下载,必须将获取数据的逻辑写在回调函数内部,确保在下载完成后才去读取。
import xtdata
def on_download_finish(download_info):
print("下载完成:", download_info)
# 在回调中获取最新数据
data = xtdata.get_market_data_ex([], stocks, period='1d', count=11)
print(data)
# 启动异步下载
xtdata.download_history_data2(stock_list, '1d', end_time=today, callback=on_download_finish, incrementally=None)
三、 大家都是怎么获取最新数据的?(最佳实践)
在实际的量化交易中,获取最新数据的方式取决于你所处的场景(盘中实时 vs 盘后分析):
1. 盘中实时获取最新数据(订阅机制)
在盘中交易时,不建议频繁调用 download_history_data2,因为这会产生大量的网络请求延迟。正确的做法是使用订阅机制。
在 QMT 内置策略中,get_market_data_ex 默认带有 subscribe=True 参数(在 xtdata 中也有类似机制或使用 subscribe_quote)。订阅后,终端会自动在后台维护最新数据,你直接读取即可:
# 订阅实时行情(以 QMT 内置 ContextInfo 为例)
# ContextInfo.subscribe_quote(stock_code, period='1d', callback=on_quote)
# 或者在获取时开启订阅(如果 API 支持)
data = xtdata.get_market_data_ex([], stocks, period='1d', count=11, subscribe=True)
2. 获取最新的全推 Tick 数据
如果你需要的是最新的切片数据(如最新价、买卖五档),直接使用 get_full_tick 接口,它会直接从内存中读取终端接收到的最新快照,速度极快,不需要下载历史 K 线:
# 获取最新分笔快照数据
tick_data = xtdata.get_full_tick(stocks)
print(tick_data)
总结
- 同步变异步的原因:传入了
callback参数。 - 解决办法:移除
callback实现同步阻塞,或在callback内部执行读取逻辑。 - 盘中最佳实践:盘前一次性下载历史数据,盘中通过订阅 (
subscribe) 或 Tick 快照 (get_full_tick) 获取最新动态,避免盘中频繁调用下载接口。