问题描述
这是我的代码:
start_d = pd.to_datetime(filtered_df.iloc[-1,1], format='%Y%m%d')
end_d = pd.to_datetime(today)
trade_ds = get_trade_days(start_date=start_d, end_date=end_d)
trade_days = get_all_trade_days()
days = [date for date in trade_days if start_d.date() < = date < = end_d.date()]
print(f"start_d: {start_d}\nend_d: {end_d}\ntrade_ds: {trade_ds}\ndays: {days}\nlen_days: {len(days)}")
输出为:
start_d: 2024-09-02 00:00:00
end_d: 2024-09-28 00:00:00
trade_ds: 26
days: [datetime.date(2024, 9, 2), datetime.date(2024, 9, 3), datetime.date(2024, 9, 4), datetime.date(2024, 9, 5), datetime.date(2024, 9, 6), datetime.date(2024, 9, 9), datetime.date(2024, 9, 10), datetime.date(2024, 9, 11), datetime.date(2024, 9, 12), datetime.date(2024, 9, 13), datetime.date(2024, 9, 18), datetime.date(2024, 9, 19), datetime.date(2024, 9, 20), datetime.date(2024, 9, 23), datetime.date(2024, 9, 24), datetime.date(2024, 9, 25), datetime.date(2024, 9, 26), datetime.date(2024, 9, 27)]
len_days: 18
我理解应该是18天那个才是交易日的数量,但是为什么get_trade_days 会得到26日,是我哪里理解错了嘛?
解决方案
您好!您理解的完全正确,2024年9月2日到9月28日之间的实际交易日确实是 18天。get_trade_days 返回异常结果(甚至直接返回了整数 26),主要是因为 参数类型兼容性问题。
问题原因分析
在您的代码中,start_d 和 end_d 是通过 pd.to_datetime() 转换得到的,它们的数据类型是 pandas.Timestamp。
根据 JoinQuant 的官方 API 文档,get_trade_days 接受的 start_date 和 end_date 参数类型应为:
str(字符串,如'2024-09-02')datetime.datedatetime.datetime
虽然 pandas.Timestamp 在 Python 中是 datetime.datetime 的子类,但 JoinQuant 底层的 C 扩展或日期解析引擎在处理 pandas.Timestamp 时可能会出现解析偏差,导致它没有正确识别日期区间,从而返回了错误的结果(有时甚至会触发底层异常,返回一个毫无关联的数字或默认长度)。
解决方案
为了确保 API 能够正确解析日期,建议在调用 get_trade_days 之前,将 pandas.Timestamp 显式转换为 字符串 (str) 或 原生 datetime.date。
修改方法 1:转换为字符串(推荐)
start_d = pd.to_datetime(filtered_df.iloc[-1,1], format='%Y%m%d')
end_d = pd.to_datetime(today)
# 使用 strftime 转换为 'YYYY-MM-DD' 格式的字符串
trade_ds = get_trade_days(start_date=start_d.strftime('%Y-%m-%d'), end_date=end_d.strftime('%Y-%m-%d'))
print(f"trade_ds 数量: {len(trade_ds)}") # 此时应该正确输出 18
修改方法 2:转换为 datetime.date
start_d = pd.to_datetime(filtered_df.iloc[-1,1], format='%Y%m%d')
end_d = pd.to_datetime(today)
# 使用 .date() 转换为原生 datetime.date 对象
trade_ds = get_trade_days(start_date=start_d.date(), end_date=end_d.date())
print(f"trade_ds 数量: {len(trade_ds)}") # 此时应该正确输出 18
补充说明
您在代码中自己编写的备用方案:
trade_days = get_all_trade_days()
days = [date for date in trade_days if start_d.date() <= date <= end_d.date()]
这是一种非常稳健且完全正确的做法!get_all_trade_days() 返回的是包含原生 datetime.date 的 numpy 数组,通过列表推导式进行过滤,不仅避开了底层 API 对 pandas 类型的兼容性问题,而且执行效率极高。如果您在后续开发中频繁遇到类似的时间类型兼容问题,完全可以继续沿用您自己写的这种过滤方式。