问题描述
解决方案
在 QMT 策略中,获取某个特定时间点的指数成分股列表,主要使用 ContextInfo.get_sector 函数。
核心函数说明
ContextInfo.get_sector(sector, realtime)
- 功能:获取指定指数在指定时刻的成分股列表。
- 参数:
sector(string): 指数代码,格式为'code.market',例如'000300.SH'(沪深300)、'000905.SH'(中证500)。realtime(string/number): 指定的时间点。通常传入毫秒级时间戳。如果不填,默认获取当前最新时刻的成分股。
- 返回值:
list,包含成分股代码的列表(如['000001.SZ', '600000.SH', ...])。
代码示例
以下代码展示了如何在回测或实盘的 handlebar 周期中,动态获取当前 K 线时间点对应的沪深 300 成分股列表。
# -*- coding: gbk -*-
def init(ContextInfo):
# 可以在初始化中设置一些变量,这里暂时不需要
pass
def handlebar(ContextInfo):
# 1. 获取当前 K 线的索引位置
index = ContextInfo.barpos
# 2. 获取当前 K 线对应的时间戳(毫秒级)
# get_bar_timetag 返回的是毫秒时间戳,可以直接传给 get_sector
realtime = ContextInfo.get_bar_timetag(index)
# 3. 定义指数代码 (例如:沪深300)
index_code = '000300.SH'
# 4. 调用接口获取该时间点的成分股
# 注意:如果是回测模式,传入 realtime 非常重要,否则会取到最新日期的成分股导致未来函数
stock_list = ContextInfo.get_sector(index_code, realtime)
# 5. 打印结果验证
# 将时间戳转换为可读日期格式方便查看
date_str = timetag_to_datetime(realtime, '%Y-%m-%d')
print(f"日期: {date_str}, 指数: {index_code}, 成分股数量: {len(stock_list)}")
# 打印前5只成分股示例
if len(stock_list) > 0:
print(f"前5只成分股: {stock_list[:5]}")
注意事项
- 时间戳格式:
realtime参数至关重要。在回测模式下,必须传入历史时间戳(如上例中的ContextInfo.get_bar_timetag(index)),否则系统会默认返回当前最新的成分股列表,导致策略用到“未来数据”,回测结果失真。 - 板块名称 vs 代码:
- 如果使用指数代码(如
'000300.SH'),请使用ContextInfo.get_sector。 - 如果想使用板块名称(如
'沪深300'、'我的自选'),可以使用ContextInfo.get_stock_list_in_sector(sectorname, realtime)。用法类似,但第一个参数传中文名称。
- 如果使用指数代码(如
- 数据补充:在进行回测前,请确保在 QMT 客户端的【数据管理】中下载了对应指数的历史行情数据,以确保成分股历史变动记录是完整的。
Q&A
Q: ContextInfo.get_sector 和 ContextInfo.get_stock_list_in_sector 有什么区别?
A: get_sector 主要用于通过标准的指数代码(如 000300.SH)获取成分股,通常用于标准指数;get_stock_list_in_sector 通过板块名称(如 沪深300 或用户自定义板块名)获取,支持范围更广(包括行业、概念、自选股),但使用名称可能存在重名或歧义风险,标准指数建议优先使用代码。
Q: 如果 realtime 参数传空会怎样?
A: 如果 realtime 缺省或传空,函数会返回当前时刻(最新)的成分股列表。在实盘交易中这是正确的,但在历史回测中这会导致“未来函数”错误。
Q: 如何将毫秒时间戳转换为可读的日期字符串?
A: 可以使用 QMT 内置的 timetag_to_datetime(timetag, format) 函数。例如:timetag_to_datetime(1640995200000, '%Y-%m-%d %H:%M:%S')。