🚀 AI 一键生成 qmt 策略代码

QMT回测时 ContextInfo.get_sector() 获取指数成分股为空或包含退市股票怎么办?

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

问题描述

ContextInfo.get_sector()回测时有问题?

在回测时,我使用 ContextInfo.get_sector()去尝试获取中证小市值指数成分股,发现了两个问题。回测设置的起始时间是 2025-10-20。

1 获取得到的结果比现在实际的数据多了 30 条。现在中证小市值(399101.SZ)成分股有 961 个,ContextInfo.get_sector("399101.SZ")返回了 991 个。返回结果包含了中航机电(002013.SZ)这种已经退市的股票。

2 ContextInfo.get_sector()接口,按照文档介绍,是可以支持两个参数,形式是 ContextInfo.get_sector(stock, realtime),其中 realtime 是毫秒时间戳。分别尝试了秒级时间戳和毫秒时间戳,只要填了这个参数,返回的都是空数组。

想咨询一下,这个接口是不是有问题?还是我使用的方式不对?

附代码:

def handlebar(ContextInfo):
# 获取中证小市值成分股
stocks = ContextInfo.get_sector("399101.SZ")
print(stocks)

print("=" * 60)
# 获取2025-10-20 11:00:00时刻的中证小市值成分股,毫秒级时间戳
stocks = ContextInfo.get_sector("399101.SZ", 1760929200000)
print(stocks)

print("=" * 60)
# 获取2025-10-20 11:00:00时刻的中证小市值成分股,秒级时间戳
stocks = ContextInfo.get_sector("399101.SZ", 1760929200)
print(stocks)
def handlebar(ContextInfo):
# 获取中证小市值成分股
stocks = ContextInfo.get_sector("399101.SZ")
print(stocks)

print("=" * 60)
# 获取2025-10-20 11:00:00时刻的中证小市值成分股,毫秒级时间戳
stocks = ContextInfo.get_sector("399101.SZ", 1760929200000)
print(stocks)

print("=" * 60)
# 获取2025-10-20 11:00:00时刻的中证小市值成分股,秒级时间戳
stocks = ContextInfo.get_sector("399101.SZ", 1760929200)
print(stocks)

解决方案

针对您在 QMT 回测中使用 ContextInfo.get_sector() 遇到的两个问题,这通常与本地数据同步状态以及时间戳的有效性有关。以下是详细的排查建议和正确的代码编写方式:

问题一:获取的结果比实际多,且包含已退市股票

原因分析:
当您调用 ContextInfo.get_sector("399101.SZ") 且不传入时间戳时,系统默认获取的是本地最新的成分股列表。如果返回了已经退市的股票(如中航机电 002013.SZ),这通常是因为您 QMT 客户端本地的板块/指数成分股数据未更新,导致读取到了旧的缓存数据。

解决办法:
请前往 QMT 客户端的【数据管理】 -> 【补充数据】,勾选并重新下载最新的“板块数据”和“指数成分股数据”,确保本地数据与交易所最新状态同步。

问题二:传入时间戳后返回空数组

原因分析:
您在代码中传入的毫秒级时间戳 1760929200000 转换成北京时间是 2025-10-20 11:00:00。这是一个未来的时间。QMT 的历史成分股数据库中显然没有未来的数据,因此返回了空数组。此外,获取历史成分股同样需要提前在【数据管理】中下载好对应的历史成分股数据。

解决办法:

  1. 确保传入的时间戳是有效的历史时间(且在您下载的数据时间范围内)。
  2. 在回测中,通常我们不需要手动硬编码写死时间戳,而是应该动态获取当前 K 线的时间戳,这样策略才能在回测的每一天获取当时的真实成分股,避免未来函数。

正确的代码示例

在回测中动态获取当前 K 线对应时刻的指数成分股,标准写法如下:

#coding:gbk

def init(ContextInfo):
    # 设置回测股票池或基准
    ContextInfo.set_universe(['399101.SZ'])

def handlebar(ContextInfo):
    # 1. 获取当前运行到的 K 线索引
    index = ContextInfo.barpos
    
    # 2. 动态获取当前 K 线对应时间的毫秒级时间戳
    realtime = ContextInfo.get_bar_timetag(index)
    
    # 3. 传入动态时间戳,获取该历史时刻的真实成分股
    # 注意:必须提前在数据管理中下载好历史成分股数据
    stocks = ContextInfo.get_sector("399101.SZ", realtime)
    
    # 打印当前时间及成分股数量
    from datetime import datetime
    current_time = datetime.fromtimestamp(realtime / 1000.0).strftime('%Y-%m-%d %H:%M:%S')
    print(f"当前回测时间: {current_time}, 中证小市值成分股数量: {len(stocks)}")
    
    # 如果需要查看具体列表,可以取消下方注释
    # print(stocks)

总结建议

  1. 检查时间戳:使用在线工具检查您硬编码的时间戳是否正确,避免填入未来时间。
  2. 补充数据:QMT 的 get_sector 强依赖本地数据。无论是最新成分股还是历史成分股,测试前务必在【数据管理】中将对应指数的历史成分股数据补充完整。
  3. 动态获取:回测时务必结合 ContextInfo.get_bar_timetag(index) 动态获取时间戳,以保证策略逻辑的严谨性。