🚀 AI 一键生成 joinquant 策略代码

为什么 JoinQuant 的 get_trade_days 返回的交易日数量不正确?

joinquant | 发布时间: 2026/5/21
以下内容由 EasyQuant 生成。

问题描述

关于`get_trade_days`的疑问

这是我的代码:

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_dend_d 是通过 pd.to_datetime() 转换得到的,它们的数据类型是 pandas.Timestamp

根据 JoinQuant 的官方 API 文档,get_trade_days 接受的 start_dateend_date 参数类型应为:

  • str (字符串,如 '2024-09-02')
  • datetime.date
  • datetime.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 类型的兼容性问题,而且执行效率极高。如果您在后续开发中频繁遇到类似的时间类型兼容问题,完全可以继续沿用您自己写的这种过滤方式。