问题描述
get_market_data跟get_market_data_ex返回数据的周期不一样吗?
get_market_data_ex没有按照设定的时间段一天一天的推送,get_market_data可以
大家也是这样情况吗?
fields = ['index', 'open', 'high', 'low', 'close', 'volume', 'amount'] periods= 5 start_time = '20240219' end_time = '20240315' for idx, stock_code in enumerate(stock_codes): print(f"处理股票代码:{stock_code}")
'''
param_df = ContextInfo.get_market_data(
fields=fields[1:],
stock_code=[stock_code],
count=int(periods)+1,
dividend_type='front'
)
print(param_df)
'''
param_df = ContextInfo.get_market_data_ex(
fields=fields[1:],
stock_code=[stock_code],
count=int(periods)+1,
dividend_type='front' # 前复权
)
print(param_df)
注释掉的get_market_data能在我设定的起始时间段内回测能一根一根K线的推数据。而get_market_data_ex都是推了今天最新的数据,而且全是一样的。
param_df = ContextInfo.get_market_data_ex(
fields=fields[1:],
stock_code=['603660.SH'],
period='follow',
start_time='',
end_time='',
count=int(5)+1,
dividend_type='follow',
fill_data=True,
subscribe=True
)
print(param_df)
这样,根据手册所有参数都写上,也不行啊,加测时都不是设定日期内的数据,而是全推今天最新的数据啊,怎么回事??
总的时间顺序如:第一周期20240213、20240214、20240215、20240216、20240219;第二周期20240214、20240215、20240216、20240219、20240220;……;最后一个周期20240311、20240312、20240313、20240314、20240315。在运行回测时get_market_data可以做到上而的效果,而get_market_data_ex全是一样的数据。
我昨晚弄了7个小时,没找到原因在哪…………
解决方案
在 QMT 平台的回测模式下,get_market_data 和 get_market_data_ex 的运行逻辑确实存在差异,主要体现在对时间基准的默认处理方式上。
为什么会出现这种情况?
-
get_market_data的逻辑:
在回测模式下,当您使用get_market_data并指定count参数(且不指定具体的start_time和end_time)时,系统会自动以当前回测进度所在的 K 线(即当前 Bar)作为基准时间,向前推算获取指定数量的 K 线数据。因此,它能实现随着回测进度“一天一天推送”的效果。 -
get_market_data_ex的逻辑:
get_market_data_ex是一个更底层、更通用的接口。根据官方文档,当start_time和end_time为空时,它默认end_time为最新时间(即本地数据的最新日期,通常是今天)。它不会自动跟随回测的当前进度。因此,在回测的每一个周期里,它都去取了本地最新的数据,导致您看到“全是一样的数据”。
如何解决?
要让 get_market_data_ex 在回测中实现和 get_market_data 一样的效果(跟随回测进度逐根 K 线获取),您需要动态地将当前回测 K 线的时间作为 end_time 传入。
您可以通过 ContextInfo.get_bar_timetag(ContextInfo.barpos) 获取当前 K 线的时间戳,将其转换为字符串格式后传给 end_time。
正确的代码示例
#coding:gbk
import time
def init(ContextInfo):
ContextInfo.set_universe(['603660.SH'])
def handlebar(ContextInfo):
# 获取当前回测进度所在的 K 线索引
bar_index = ContextInfo.barpos
# 获取当前 K 线的时间戳(毫秒)
timetag = ContextInfo.get_bar_timetag(bar_index)
# 将时间戳转换为 get_market_data_ex 需要的字符串格式 (YYYYMMDD)
# 注意:timetag_to_datetime 是 QMT 内置函数
current_date_str = timetag_to_datetime(timetag, '%Y%m%d')
fields = ['open', 'high', 'low', 'close', 'volume', 'amount']
periods = 5
stock_code = '603660.SH'
# 使用 get_market_data_ex,并动态传入 end_time
param_df = ContextInfo.get_market_data_ex(
fields=fields,
stock_code=[stock_code],
period='1d', # 明确指定周期
start_time='', # start_time 留空,由 count 决定向前取多少根
end_time=current_date_str, # 动态传入当前回测 K 线的时间
count=int(periods) + 1,
dividend_type='front',
fill_data=True,
subscribe=True
)
print(f"当前回测日期: {current_date_str}")
if stock_code in param_df:
print(param_df[stock_code])
总结
get_market_data在回测时具有“上下文感知”能力,会自动以当前 Bar 为截止时间。get_market_data_ex是绝对时间查询,如果不传end_time,永远返回最新数据。在回测中使用时,必须手动传入当前 Bar 的时间作为end_time。