问题描述
回测中get_fundamentals不支持statDate参数,请使用date参数
我希望在回测中获取某个季度的报表数据,如果使用date参数,获取的是最近的报表,那么如4月份有可能获取的是年报或者一季报,如何才能确保获取的是年报?
解决方案
在JoinQuant(聚宽)平台的回测中,强烈建议使用 date 参数而不是 statDate 参数来获取财务数据。这是因为使用 statDate(如指定获取去年的年报)时,如果该年报在当前回测日期尚未实际发布,系统仍会返回数据,从而引入未来函数,导致回测结果失真。
在4月份这种财报密集披露期,使用 date 参数确实会遇到获取到的是一季报还是去年年报的不确定性。为了确保在避免未来函数的前提下准确获取到年报数据,您可以采用以下两种方法:
方法一:使用 get_history_fundamentals 函数(推荐)
聚宽提供了专门用于获取历史多期财务数据的 API get_history_fundamentals。您可以使用 watch_date 参数(观察日期,即当前回测日期),并结合 stat_by_year=True 来严格获取该日期前已发布的最新年报数据。
from jqdata import *
def handle_data(context, data):
# 假设我们要查询平安银行的年报营业收入
security = ['000001.XSHE']
# watch_date 设为当前回测日期,确保没有未来函数
# stat_by_year=True 表示获取年度数据
# interval='1y' 表示间隔为1年,count=1 表示获取最近1期
df = get_history_fundamentals(security,
fields=[income.total_operating_revenue],
watch_date=context.current_dt.date(),
count=1,
interval='1y',
stat_by_year=True)
if not df.empty:
print("获取到的年报数据:\n", df)
方法二:使用 get_fundamentals 结合 statDate 字段进行逻辑判断
如果您坚持使用 get_fundamentals,可以在查询时将报表的统计日期字段(如 income.statDate 或 indicator.statDate)一并查出。通过判断返回的报表是哪个季度的,来决定下一步操作。
from jqdata import *
def handle_data(context, data):
# 1. 先用 date 参数获取当前能看到的最新财报
q = query(
valuation.code,
income.statDate,
income.total_operating_revenue
).filter(
valuation.code == '000001.XSHE'
)
# 使用当前回测日期
df_current = get_fundamentals(q, date=context.current_dt)
if not df_current.empty:
stat_date = df_current['statDate'][0]
# 2. 判断获取到的是否是年报(年报的 statDate 通常以 '12-31' 结尾)
if stat_date.endswith('12-31'):
print("当前最新财报即为年报:", df_current)
else:
# 如果获取到的是一季报(例如 03-31),说明去年的年报肯定已经发布了!
# 此时我们可以安全地使用 statDate 参数去获取去年的年报,而不会引入未来函数。
last_year = str(context.current_dt.year - 1)
df_annual = get_fundamentals(q, statDate=last_year)
print("当前最新为一季报,已安全获取去年年报:", df_annual)
总结
- 避免未来函数是量化回测的第一要务。直接使用
statDate极易踩坑。 - 推荐使用
get_history_fundamentals,它原生支持按watch_date视角获取年度数据,代码更简洁且绝对安全。 - 如果使用
get_fundamentals,请务必先用date探路,确认年报已发布后,再定向获取。