问题描述
# 修改前
def _download_history_data(stock_code, period, start_time = '', end_time = ''):
cl = get_client()
cl.supply_history_data(stock_code, period, start_time, end_time)
# return
#修改后
def _download_history_data(stock_code, period, start_time = '', end_time = ''):
cl = get_client()
return cl.supply_history_data(stock_code, period, start_time, end_time)
# return
解决方案
问题背景
在使用 QMT 平台的独立 Python 库 xtquant (特别是 20240205 及之前版本) 进行量化开发时,部分开发者发现在调用 xtdata.py 中的内部函数 _download_history_data 时,无法获取到下载操作的返回结果。这会导致程序无法准确判断历史数据是否已经成功触发下载或下载完成。
Bug 原因分析
在修改前的源码中,_download_history_data 函数实例化了客户端对象 cl,并调用了底层的 cl.supply_history_data 方法来补充历史数据。但是,该函数并没有将底层方法的执行结果 return 出来,导致外部调用者接收到的永远是 None。
修改前源码:
def _download_history_data(stock_code, period, start_time = '', end_time = ''):
cl = get_client()
cl.supply_history_data(stock_code, period, start_time, end_time)
# 缺少 return 语句,默认返回 None
官方修复方案
修复方法非常简单,只需要在调用底层 supply_history_data 方法前加上 return 关键字即可,将底层 C++ 接口的返回值透传给 Python 层的调用者。
修改后源码:
def _download_history_data(stock_code, period, start_time = '', end_time = ''):
cl = get_client()
# 增加 return,返回下载请求的执行结果
return cl.supply_history_data(stock_code, period, start_time, end_time)
QMT 平台历史数据获取最佳实践
虽然上述修复针对的是 xtquant 独立包的底层函数,但在 QMT 平台内置的策略编辑器中,我们通常推荐使用 ContextInfo 对象提供的高级 API 来获取历史数据:
1. 提前补充数据
根据 QMT 官方文档,在运行或回测策略前,必须通过客户端的“数据管理”功能,或者使用代码接口提前补充好所需的历史数据。
2. 使用 get_market_data_ex 获取数据
在策略的 handlebar 中,推荐使用 ContextInfo.get_market_data_ex 来获取历史和实时行情,该接口支持多股、多字段,并返回易于处理的 pandas.DataFrame 格式:
def handlebar(ContextInfo):
if not ContextInfo.is_last_bar():
return
# 获取沪深300的日线数据
data = ContextInfo.get_market_data_ex(
fields=['open', 'high', 'low', 'close'],
stock_code=['000300.SH'],
period='1d',
count=100,
dividend_type='front'
)
print(data['000300.SH'])
总结
及时更新 xtquant 库或手动修复 xtdata.py 中的返回值 Bug,可以帮助您在脱离 QMT 终端运行独立 Python 脚本时,更好地控制数据下载流程,确保量化策略的数据完整性。