问题描述
set_option("avoid_future_data", True)就能彻底规避未来函数吗
比如今天是3月31日,我想看今天的财报,但现实世界财报发布时间会晚几天我看不到,假如放在历史回测中,是不是就能看到当天的财报,聚宽上通过set_option("avoid_future_data", True)能规避这个问题吗?
解决方案
结论:不能彻底规避
在 JoinQuant 聚宽平台上,使用 set_option("avoid_future_data", True) 不能彻底规避所有的未来函数。它只是一个辅助工具,能够帮助你避免一些常见的、通过 API 时间参数引入的未来数据问题,但它不是万能的。
针对你提到的财报问题
关于财报发布延迟的问题,是否会引入未来函数,取决于你查询财务数据时使用的参数,而不是仅仅依赖 avoid_future_data。
在聚宽中,查询财务数据通常使用 get_fundamentals 函数,它有两个关键的时间参数:date 和 statDate。
1. 使用 date 参数(推荐,无未来函数)
如果你使用 date 参数(例如 date='2023-03-31'),系统会查找上市公司在 该日期之前(包括此日期)实际发布 的最新数据。
- 现实情况:3月31日当天,一季报通常还没发布,你能看到的最新财报可能是去年的年报或三季报。
- 回测情况:系统会严格按照历史上的实际发布时间来返回数据。因此,在回测到3月31日时,你看不到尚未发布的3月31日当季财报,只能看到当时已经公开的旧财报。
- 结论:使用
date参数本身就不会产生未来函数,不需要依赖avoid_future_data来规避。
2. 使用 statDate 参数(危险,极易产生未来函数)
如果你使用 statDate 参数(例如 statDate='2023q1'),系统会直接返回 2023 年第一季度的财务报表数据。
- 回测情况:由于公司发布财报不及时,在回测到 3月31日 或 4月初时,如果你强制请求
2023q1的数据,系统可能会把后来才发布的财报数据提前给你。 - 结论:这会严重引入未来函数。聚宽官方文档明确指出:“由于公司发布财报不及时,一般是看不到当季度或年份的财务报表的,回测中使用这个数据可能会有未来函数,请注意规避。” 即使你开启了
avoid_future_data,也无法完全检测和拦截这种通过statDate强制获取特定季度财报的行为。
avoid_future_data 的作用与局限性
它能做什么?
- 拦截时间超前的 API 调用:如果你在盘中(如 10:00)尝试获取当天的收盘价(
close),系统会抛出FutureDataError异常。 - 剔除无法主动避免的未来数据:对于某些无法通过参数避免的未来数据(如集合竞价数据),系统会自动将返回结果中的未来数据剔除。
它不能做什么?(局限性)
- 不当使用
statDate查询财报:如上文所述,强制查询未发布的季度财报。 - 引入外部数据:如果你在策略中读取本地文件或联网获取外部数据,这些数据如果包含了未来信息,系统是无法检测的。
- 幸存者偏差与固定股票池:如果你在策略中硬编码了一个股票列表(例如:选了今年涨幅最大的10只股票,然后把它们写死在代码里去回测去年的行情),这就是典型的未来函数,系统无法检测。
- 利用未来复权因子:如果在回测中关闭了真实价格模式(
set_option('use_real_price', False)),使用了基于未来某天的前复权价格进行撮合,这也会引入未来函数。
总结与建议
为了在聚宽中彻底规避未来函数,你应该做到以下几点:
- 开启真实价格模式:
set_option('use_real_price', True),这是避免价格复权未来函数的基础。 - 开启防未来数据选项:
set_option("avoid_future_data", True),作为第一道防线。 - 查询财报务必使用
date参数:在调用get_fundamentals时,尽量使用date参数(或不传时间参数,让其默认使用context.current_dt的前一天),坚决避免在回测中使用statDate。 - 不要硬编码“未来表现好”的股票池,选股逻辑必须基于当时可获得的数据动态生成。