问题描述
【context.previous_date】和【context.current_dt的前一天】是一天吗?
我问这个问题是因为get_fundamentals 这个API里,如果不填date,默认是【context.current_dt的前一天】。可是如果指定日期是context.previous_date,回测结果是不一样的,不知道你们碰到过这个问题不?
以下是对这个问题的更新,我自己测试了一下:
代码运行是monthly的,到了5月份,21年的第一个交易日是5月6号,上个交易日是4月30号,date用previous_date的话,得到的财报就不是21年一季度的了,而是20年报甚至20年三季度了
解决方案
这是一个非常经典且容易踩坑的问题!直接回答你的疑问:【context.previous_date】和【context.current_dt的前一天】在绝大多数情况下不是同一天,特别是在周末和长假之后。
导致你回测结果不一致的核心原因在于**“交易日”与“自然日”的区别,以及财报披露的截止时间点**。
1. 概念解析:前一交易日 vs 前一自然日
在 JoinQuant 的 API 中:
context.previous_date:指的是前一个交易日。get_fundamentals默认的date:官方文档明确指出,如果不填date,回测模块中默认值等于context.current_dt的前一天(即前一个自然日)。
在连续的交易日(比如周三和周四),这两者是同一天。但是一旦跨越周末或法定节假日,两者就会产生分歧。
2. 结合你的案例分析(5月6日调仓)
你提到在5月份的第一个交易日(5月6日)进行 monthly 调仓:
- 当前时间 (
context.current_dt):5月6日 - 前一个交易日 (
context.previous_date):4月30日 - 前一个自然日 (
context.current_dt的前一天):5月5日
为什么获取到的财报不一样?
A股的一季报和上一年的年报,法定的最后披露期限是 4月30日。很多公司会“压轴”在4月30日晚间(收盘后)甚至深夜发布财报。
-
情况 A:使用
date=context.previous_date(4月30日)
get_fundamentals获取的是指定日期收盘后所能看到的最近数据。在4月30日收盘时,那些在4月30日晚间才发布一季报的公司,其数据在系统中尚未更新(因为你查询的是4月30日白天的数据状态)。因此,系统只能返回它们上一期的数据(即20年年报或20年三季报)。 -
情况 B:不填
date,默认使用前一自然日 (5月5日)
系统查询的是5月5日收盘后能看到的数据。此时,五一长假期间,所有在4月30日晚间披露的财报都已经入库。因此,你能准确地获取到所有公司的21年一季报。
3. 最佳实践建议
为了贴近真实的交易场景并避免未来函数,建议在获取财务数据时遵循以下原则:
- 推荐使用默认值(不填
date):在回测中,如果不填date,系统默认使用context.current_dt的前一天(自然日)。这完全符合现实逻辑——你在今天开盘前,理应能看到昨天(哪怕昨天是休息日)晚上披露的所有公告和财报。 - 慎用
context.previous_date获取财报:除非你的策略逻辑严格要求只使用上一个交易日收盘时的信息,否则在长假后(尤其是4月底、8月底、10月底这些财报密集披露期后)使用previous_date会导致你丢失假期期间披露的最新财务数据。 - 注意避免未来函数:
get_fundamentals传入date时,查询的是该日期收盘后的数据。如果你在盘中(如 9:30)传入当天的日期,会获取到当天收盘后才有的数据,从而引入未来函数。这也是为什么官方默认使用“前一天”的原因。
总结来说,你的测试结果完全符合 JoinQuant 的底层数据逻辑。在处理财务数据时,**自然日(前一天)比交易日(previous_date)**更能真实反映信息披露的时间线。