🚀 AI 一键生成 qmt 策略代码

QMT回测中 get_market_data 与 get_market_data_ex 运行逻辑有何不同?

qmt | 发布时间: 2026/5/21
以下内容由 EasyQuant 生成。

问题描述

【done】请教:回测时get_market_data跟get_market_data_ex运行逻辑不一样吗

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_dataget_market_data_ex 的运行逻辑确实存在差异,主要体现在对时间基准的默认处理方式上。

为什么会出现这种情况?

  1. get_market_data 的逻辑
    在回测模式下,当您使用 get_market_data 并指定 count 参数(且不指定具体的 start_timeend_time)时,系统会自动以当前回测进度所在的 K 线(即当前 Bar)作为基准时间,向前推算获取指定数量的 K 线数据。因此,它能实现随着回测进度“一天一天推送”的效果。

  2. get_market_data_ex 的逻辑
    get_market_data_ex 是一个更底层、更通用的接口。根据官方文档,当 start_timeend_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