🚀 AI 一键生成 qmt 策略代码

QMT 平台 get_market_data_ex 获取不到期货数据(返回空 DataFrame)的原因及排查指南

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

问题描述

为什获取不到期货数据

his_price = ContextInfo.get_market_data_ex(fields=[], stock_code=['c2409.DF'], period='1m', count=10,fill_data=True)

print(his_price['c2409.DF'])
为什么这样始终获取不到期货的数据,返回的Dataframe是空,在模拟交易、回测都是空,回测的历史数据已经下载好了。

解决方案

在 QMT 平台中使用 ContextInfo.get_market_data_ex 获取期货数据时返回空的 DataFrame,通常是由以下几个原因导致的。请按照以下步骤逐一排查:

1. 合约已过期(最常见原因)

你请求的合约是 c2409.DF(大商所玉米24年9月合约)。

  • 在模拟交易/实盘中:如果当前时间已经超过了 2024 年 9 月,该合约已经退市。QMT 的实时行情接口无法获取已退市合约的最新数据,因此会返回空。
  • 在回测中:如果你的回测时间区间(在策略编辑器的“回测参数”中设置的开始时间和结束时间)不在该合约的存续期内(例如你设置的回测时间是 2024年10月),同样会获取不到数据。

解决办法

  • 如果是模拟交易,请更换为当前的主力合约(例如 c2501.DFc2505.DF)。
  • 你可以使用 ContextInfo.get_main_contract('c.DF') 动态获取当前的主力合约代码。

2. 数据周期未正确补充

你提到“历史数据已经下载好了”,但请确认你下载的是否是 1分钟线(1m) 数据。

  • QMT 的数据管理中,日线(1d)和分钟线(1m, 5m等)是分开下载的。
  • 如果你只下载了日线数据,但代码中请求的是 period='1m',本地数据库中没有分钟线数据,就会返回空。

解决办法
进入 QMT 终端的 数据管理 -> 补充数据,选择大商所(DF),勾选“1分钟线”,并确保时间范围覆盖了你的回测区间。

3. 回测时间与 count 参数的配合

在回测模式下,get_market_data_ex 默认会以当前 K 线(ContextInfo.barpos 对应的时间)为基准往前取 count 根 K 线。

  • 如果你的主图品种是股票,而你在代码里取期货数据,且主图的时间轴与期货的交易时间不完全重合,可能会导致取数异常。
  • 确保你的策略运行的主图品种也是期货,或者主图的时间轴包含了期货的交易时间。

4. 调试排查代码

你可以将以下代码放入你的策略中运行,通过日志输出来定位问题:

#coding:gbk

def init(ContextInfo):
    # 动态获取当前玉米的主力合约
    main_contract = ContextInfo.get_main_contract('c.DF')
    print(f"当前玉米主力合约为: {main_contract}")
    # 将主力合约存入全局变量
    ContextInfo.my_contract = main_contract

def handlebar(ContextInfo):
    # 确保只在最后一根K线或特定条件下打印,避免日志过多
    if not ContextInfo.is_last_bar():
        return
        
    contract = ContextInfo.my_contract
    
    # 尝试获取数据
    his_price = ContextInfo.get_market_data_ex(
        fields=['open', 'high', 'low', 'close', 'volume'], 
        stock_code=[contract], 
        period='1m', 
        count=10,
        subscribe=True # 确保订阅开关打开
    )
    
    if contract in his_price and not his_price[contract].empty:
        print(f"成功获取到 {contract} 的数据:")
        print(his_price[contract])
    else:
        print(f"警告:获取 {contract} 数据为空!请检查合约是否退市或数据是否下载。")

总结

对于 c2409.DF 这种特定交割月的合约,99% 的概率是因为在当前时间点它已经退市。在编写期货策略时,强烈建议使用 ContextInfo.get_main_contract() 动态获取主力合约进行交易和数据获取,而不是将合约代码写死。