问题描述
同样是get_fundamentals,2018年4月2日获取数据会有很多缺失值,2018年4月1日就不会有缺失值,可能是什么原因?
解决方案
在 JoinQuant (聚宽) 平台中使用 get_fundamentals 获取财务数据时,如果相邻两天(如 2018-04-01 和 2018-04-02)获取到的数据出现明显差异(一天完整,另一天出现大量缺失值 NaN),通常是由上市公司财报的新披露引起的。
以下是导致该现象的几个核心原因及排查解决方法:
1. 核心原因:新财报披露导致数据覆盖
get_fundamentals 在使用 date 参数时,其底层逻辑是获取指定日期(含)之前上市公司最新发布的一期财务报表数据。
- 4月份是财报密集披露期:4月份是A股上市公司披露上一年度年报和当年一季报的密集期。
- 新财报字段不全:在 2018-04-02 这一天,某些上市公司可能刚刚发布了最新的财报(例如 2017 年年报或 2018 年一季报)。如果这份新财报中某些特定的财务指标(如某些细分的营业成本、研发费用等)未披露或为空,系统就会返回
NaN。 - 对比 4月1日:在 2018-04-01 时,这些公司的新财报还未发布,系统获取到的是上一期(例如 2017 年三季报)的数据,而那一期财报中这些字段是完整的,因此没有缺失值。
2. 行业特殊性或财报类型差异
- 金融类 vs 非金融类:银行业、券商、保险等金融行业的财报科目与普通企业不同。如果新披露的财报导致了报表模板的切换,或者某些专项数据只有年报有而季报没有,也会在财报更新的节点出现大面积缺失。
- 业绩快报/预告的影响:有时公司会先发布业绩快报,快报中的字段非常少。如果系统将其作为最新财务数据更新,会导致大量非核心财务字段变为
NaN。
3. 排查方法
为了验证是否是因为财报更新导致的缺失,您可以在查询时把财报的统计周期 (statDate) 和 发布日期 (pubDate) 一并查出来对比一下:
from jqdata import *
# 查询您需要的字段,同时加上 statDate
q = query(
valuation.code,
income.statDate, # 财报所属的报告期
income.pubDate, # 财报实际发布日期
income.operating_revenue
).filter(
valuation.code == '000001.XSHE'
)
# 分别打印两天的结果进行对比
df_0401 = get_fundamentals(q, date='2018-04-01')
df_0402 = get_fundamentals(q, date='2018-04-02')
print("4月1日数据:\n", df_0401)
print("4月2日数据:\n", df_0402)
如果发现 statDate 从 2017-12-31 变成了 2018-03-31,或者 pubDate 刚好是 2018-04-02,这就印证了是新财报披露导致的数据缺失。
4. 解决方法
如果您希望在回测或研究中保持数据的一致性,避免因为新财报披露导致突然的缺失值,可以采取以下方案:
-
方案一:使用
statDate明确指定报告期
如果您需要特定季度的完整数据,可以直接放弃date参数,改用statDate参数(例如statDate='2017q4')。
注意:在回测中使用statDate极易引入未来函数(因为您可能在财报实际发布前就获取到了该数据),请务必谨慎使用,通常仅建议在研究环境中使用。 -
方案二:数据清洗与前值填充 (Fillna)
在量化策略中,遇到财务数据缺失是常态。建议在获取数据后,使用 Pandas 的fillna方法,利用行业均值或该股票的历史前值进行填充:# 使用前值填充或设为0 df = get_fundamentals(q, date='2018-04-02') df = df.fillna(method='ffill').fillna(0) -
方案三:使用
get_history_fundamentals获取历史多期数据
使用get_history_fundamentals可以一次性获取过去多个季度的财务数据,如果最新一期有缺失,可以在代码逻辑中回退使用上一季度的有效数据。