问题描述
聚宽因子库中的 operating_revenue_growth_rate(营业收入增长率),计算方法为:营业收入增长率=(今年营业收入(TTM)/去年营业收入(TTM))-1。
这个增长率,是指最新的季度同比还是最新的年度同比?
而且我筛选了operating_revenue_growth_rate大于0的股票,为何实际筛选中的标的没有大于0,即今年营业收入还是小于去年营业收入,不管是最新的季度同比还是最新的年度同比都没有增长。
考虑到数据的更新时效,往前推一个季度看数据,也有股票的营收没有增长却被筛选到了。
麻烦小秘书看看能否解答。
解决方案
您好!关于聚宽因子库中 operating_revenue_growth_rate(营业收入增长率)的计算逻辑以及筛选结果与直观感受不符的问题,主要涉及到 TTM(滚动十二个月) 的计算机制以及**防未来函数(财报实际披露日)**的底层逻辑。以下为您详细解答:
1. 这个增长率是指最新的季度同比还是年度同比?
都不是。它是基于 TTM(Trailing Twelve Months,滚动十二个月)的同比。
根据聚宽因子库的定义:营业收入增长率 = (今年营业收入(TTM) / 去年营业收入(TTM)) - 1。
- 今年营业收入(TTM):指在您查询的那个日期,该股票最新已公布的财报所对应的过去连续 4 个季度的营业收入总和。
- 举例:假设当前是 2023 年 11 月,公司已发布 2023 年三季报。那么 今年 TTM = 2023Q3 + 2023Q2 + 2023Q1 + 2022Q4。
- 去年营业收入(TTM):指在“今年 TTM”的基础上,再往前推 12 个月(即 4 个季度)的营业收入总和。
- 举例:接上例,去年 TTM = 2022Q3 + 2022Q2 + 2022Q1 + 2021Q4。
因此,它既不是单季度的同比(如 23Q3 vs 22Q3),也不是自然年度的同比(如 2022年报 vs 2021年报),而是最近四个季度的总和与上一个四个季度总和的比较。
2. 为什么筛选出大于 0 的股票,实际看财报却没有增长?
您在行情软件或财报上看到的“没有增长”,通常是因为您看的是“单季度同比”或“累计同比”,这与 TTM 同比有本质区别。导致筛选结果与您直观感受不符的原因通常有以下几点:
原因一:TTM 的平滑效应(最常见原因)
TTM 包含的是过去 4 个季度的数据。有可能该股票最新的单季度营收确实是下滑的(同比 < 0),但是它前三个季度的营收非常高,导致这 4 个季度加起来的总和(今年 TTM),依然大于去年同期的 4 个季度总和(去年 TTM)。
- 结论:单季度同比下滑,不代表 TTM 同比下滑。因子库筛选的是 TTM 增长率 > 0。
原因二:财报实际披露日期的滞后性(防未来函数)
聚宽的底层逻辑是严格防止未来函数的。在回测或获取因子时,系统只会使用该日期当天及之前已经实际公告的财务数据。
- 举例:假设某公司在 2023 年 4 月 28 日才发布 2023 年一季报和 2022 年年报。如果您在 2023 年 4 月 25 日进行筛选,系统能看到的最新财报依然是 2022 年三季报。此时计算的 TTM 依然是基于 2022Q3 往前推的 4 个季度。如果您事后用上帝视角去看 2022 年报发现它下滑了,但在 4 月 25 日那个时间点,量化引擎是不知道它下滑的,依然会把它选出来。
原因三:财务数据的追溯调整
上市公司经常会因为会计准则变更、并购重组等原因,对历史财务数据进行“追溯调整”。
- 行情软件上显示的往往是调整后的最新数据。
- 聚宽因子库在历史某个时间点计算时,使用的是当时披露的原始数据(Point-in-Time 数据)。如果当时披露的数据算出来 TTM 是增长的,就会被筛选出来,即使后来这份财报被追溯调整为下滑。
💡 如何验证您的筛选结果?
如果您想验证某只被筛选出来的股票在特定日期的 operating_revenue_growth_rate 到底是怎么算出来的,建议您使用聚宽的 get_fundamentals API,指定 date 为您筛选的那一天,拉取底层的 TTM 数据进行手动核对:
from jqdata import *
# 假设您在 2023-05-10 筛选出了 000001.XSHE
check_date = '2023-05-10'
stock = '000001.XSHE'
# 查询当天的 营业收入TTM (今年TTM)
q_current = query(indicator.inc_revenue_year_on_year, income.operating_revenue).filter(valuation.code == stock)
df_current = get_fundamentals(q_current, date=check_date)
print(f"{check_date} 看到的最新营业收入: {df_current['operating_revenue'][0]}")
# 您还可以使用 get_factor_values 直接查看当天的因子值
from jqfactor import get_factor_values
factor_data = get_factor_values(securities=[stock], factors=['operating_revenue_growth_rate'], end_date=check_date, count=1)
print(f"因子库计算的增长率: {factor_data['operating_revenue_growth_rate'].iloc[0,0]}")
通过拉取当时的 Point-in-Time 数据,您就能明白量化引擎在那个瞬间是基于什么数据做出判断的了。