问题描述
df=get_industry_stocks('G55', date='2011-05-06')结果有'601975.XSHG'。
但是,该股票是2019年才上市。
get_industry_stocks在'2011-05-06'不应该取到这只2019年才上市的股票?
解决方案
问题解析
在 JoinQuant 平台上,使用 get_industry_stocks 获取历史某天的行业成分股时,确实偶尔会遇到返回了当时尚未上市的股票的情况。这通常是由以下几个原因造成的:
- 行业分类标准的历史快照缺失:某些行业分类标准(如证监会行业、某些自定义行业)在较早的年份(如 2011 年)可能尚未建立,或者平台底层数据库缺乏该分类在早期的精确每日快照。当查询一个没有历史快照的日期时,底层数据可能会默认返回该行业较新或当前的成分股列表。
- 数据回溯机制的瑕疵:部分行业数据的维护是基于“最新状态”向历史回溯的,如果在回溯处理时未能严格与股票的
start_date(上市日期)进行交叉校验,就会导致未来才上市的股票“穿越”到历史列表中。
这种现象在量化回测中是非常危险的,因为它引入了未来函数(使用了当时不可能知道的信息)。
解决方案:进行二次过滤
为了确保策略的严谨性,避免买入或处理当时还未上市的股票,我们可以在调用 get_industry_stocks 之后,结合 get_all_securities 函数进行一次简单的二次过滤。
get_all_securities(date=...) 函数非常可靠,当传入 date 参数时,它只会返回在该日期已经上市且尚未退市的股票列表。
过滤代码示例
您可以将获取行业股票的逻辑封装成一个安全的自定义函数:
from jqdata import *
def get_safe_industry_stocks(industry_code, query_date):
"""
安全获取指定日期的行业成分股,剔除未上市的股票
:param industry_code: 行业代码,如 'G55'
:param query_date: 查询日期,如 '2011-05-06'
:return: 过滤后的股票代码列表
"""
# 1. 获取原始的行业成分股列表(可能包含未上市股票)
raw_stocks = get_industry_stocks(industry_code, date=query_date)
# 2. 获取查询日期当天所有正常上市的股票列表
# 传入 date 参数后,返回的 DataFrame 的 index 就是当天已上市的股票代码
valid_securities = get_all_securities(types=['stock'], date=query_date).index.tolist()
# 3. 取交集,过滤掉在 query_date 尚未上市的股票
safe_stocks = [stock for stock in raw_stocks if stock in valid_securities]
return safe_stocks
# 测试代码
query_date = '2011-05-06'
industry_code = 'G55'
# 使用安全函数获取
stocks = get_safe_industry_stocks(industry_code, query_date)
# 验证 601975.XSHG 是否被剔除
if '601975.XSHG' in stocks:
print('警告:仍然包含未上市股票!')
else:
print('成功:未上市股票已被剔除。')
总结
在处理较早历史区间的板块、行业、概念成分股时,养成**“获取成分股 -> 与当日全市场已上市股票池取交集”**的习惯,是规避此类底层数据瑕疵和未来函数的最佳实践。这不仅适用于 get_industry_stocks,同样适用于 get_concept_stocks 等其他成分股获取函数。