问题描述
在回测时,我使用 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 的历史成分股数据库中显然没有未来的数据,因此返回了空数组。此外,获取历史成分股同样需要提前在【数据管理】中下载好对应的历史成分股数据。
解决办法:
- 确保传入的时间戳是有效的历史时间(且在您下载的数据时间范围内)。
- 在回测中,通常我们不需要手动硬编码写死时间戳,而是应该动态获取当前 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)
总结建议
- 检查时间戳:使用在线工具检查您硬编码的时间戳是否正确,避免填入未来时间。
- 补充数据:QMT 的
get_sector强依赖本地数据。无论是最新成分股还是历史成分股,测试前务必在【数据管理】中将对应指数的历史成分股数据补充完整。 - 动态获取:回测时务必结合
ContextInfo.get_bar_timetag(index)动态获取时间戳,以保证策略逻辑的严谨性。