🚀 AI 一键生成 joinquant 策略代码
立即体验
👉 AI 生成代码 👈

如何解决 JoinQuant 中 get_fundamentals 传入 pandas.Timestamp 报错的问题?

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

问题描述

get_fundamentals使用问题

我使用jqdatasdk的代码如下:
def stocksget_valuation(stocks,date):
q = query(valuation).filter(valuation.code.in(stocks))
df = get_fundamentals(q, date)
return df

def index_pettm(index,date):
stocks = get_index_stocks(index,date)
df = stocks_get_valuation(stocks,date)
if len(df)>0:
pettm = len(df) / sum([1 / p if p > 0 else 0 for p in df.pe_ratio])
return pettm
else:
return float('NaN')

indexcode = '000300.XSHG'
start = '2020-1-1'
end = pd.datetime.today();
dates = []

print(pd.date_range(start,end,freq = 'M'))

for d in pd.date_range(start,end,freq = 'M'): #频率为月
dates.append(d)
print(d)

print(dates)
print(dates[0])
print(dates[1])
print(dates[2])

pe = index_pettm(indexcode,dates[0])
print(pe)
然后打印出来的结果和报错:
DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31'], dtype='datetime64[ns]', freq='M')
2020-01-31 00:00:00
2020-02-29 00:00:00
2020-03-31 00:00:00
[Timestamp('2020-01-31 00:00:00', freq='M'), Timestamp('2020-02-29 00:00:00', freq='M'), Timestamp('2020-03-31 00:00:00', freq='M')]
2020-01-31 00:00:00
2020-02-29 00:00:00
2020-03-31 00:00:00
Traceback (most recent call last):
File "ts4.py", line 58, in < module>
pe = index_pettm(indexcode,dates[0])
File "ts4.py", line 35, in index_pettm
df = stocks_get_valuation(stocks,date)
File "ts4.py", line 30, in stocks_get_valuation
df = get_fundamentals(q, date)
File "D:\Users\H\AppData\Local\Programs\Python\Python38\lib\site-packages\jqdatasdk\utils.py", line 230, in _wrapper
return func(args, *kwargs)
File "D:\Users\H\AppData\Local\Programs\Python\Python38\lib\site-packages\jqdatasdk\api.py", line 85, in get_fundamentals
sql = get_fundamentals_sql(query_object, date, statDate)
File "D:\Users\H\AppData\Local\Programs\Python\Python38\lib\site-packages\jqdatasdk\finance_service.py", line 118, in get_fundamentals_sql
sql = compile_query(query_object)
File "D:\Users\H\AppData\Local\Programs\Python\Python38\lib\site-packages\jqdatasdk\utils.py", line 104, in compile_query
v = escape_item(v, conversions, encoders)
File "D:\Users\H\AppData\Local\Programs\Python\Python38\lib\site-packages\pymysql\converters.py", line 27, in escape_item
val = encoder(val, mapping)
File "D:\Users\H\AppData\Local\Programs\Python\Python38\lib\site-packages\pymysql\converters.py", line 118, in escape_unicode
return u"'%s'" % _escape_unicode(value)
File "D:\Users\H\AppData\Local\Programs\Python\Python38\lib\site-packages\pymysql\converters.py", line 73, in _escape_unicode
return value.translate(_escape_table)
AttributeError: 'Timestamp' object has no attribute 'translate'
问题的源头是在get_fundamentals(q, date)的时间参数上,如果使用如:date = '2020-04-02 00:00:00'就可以正常运行,但是使用pd.date_range(start,end,freq = 'M')的就会出问题,我该如何修改使用呢?

解决方案

报错原因分析

在 JoinQuant (聚宽) 的 API 中,get_fundamentals(query_object, date=None, statDate=None) 函数的 date 参数期望接收的类型是 字符串 (如 '2020-04-02') 或者标准的 datetime.date / datetime.datetime 对象。

当你使用 pd.date_range(start, end, freq='M') 时,生成的是一个 DatetimeIndex,遍历它得到的元素类型是 pandas.Timestamp。底层的 pymysql 库在拼接 SQL 语句时,无法直接解析 pandas.Timestamp 对象,因此抛出了 AttributeError: 'Timestamp' object has no attribute 'translate' 的错误。

解决方法

要解决这个问题,只需要将 pandas.Timestamp 对象转换为 get_fundamentals 能够识别的字符串或标准 datetime 对象即可。以下提供两种常用的修改方式:

方法一:将 Timestamp 转换为字符串 (推荐)

在将日期添加到 dates 列表时,或者在调用函数传参时,使用 .strftime('%Y-%m-%d') 将其格式化为字符串。

修改你的循环代码:

for d in pd.date_range(start, end, freq='M'): 
    # 使用 strftime 将 Timestamp 转换为 'YYYY-MM-DD' 格式的字符串
    dates.append(d.strftime('%Y-%m-%d'))

这样 dates 列表里存储的就是 ['2020-01-31', '2020-02-29', ...] 这样的字符串,后续调用 pe = index_pettm(indexcode, dates[0]) 时就不会报错了。

方法二:将 Timestamp 转换为标准的 datetime.date 对象

如果你希望保持日期对象的属性,可以使用 .date() 方法将其转换为 Python 原生的 datetime.date 对象。

修改你的循环代码:

for d in pd.date_range(start, end, freq='M'): 
    # 使用 .date() 转换为标准的 datetime.date 对象
    dates.append(d.date())

完整修改后的代码示例

import pandas as pd
from jqdatasdk import *

# 假设已经 auth 登录
# auth('账号', '密码')

def stocks_get_valuation(stocks, date):
    # 注意:in 操作在 sqlalchemy 中应为 in_()
    q = query(valuation).filter(valuation.code.in_(stocks))
    df = get_fundamentals(q, date)
    return df

def index_pettm(index, date):
    stocks = get_index_stocks(index, date)
    df = stocks_get_valuation(stocks, date)
    if len(df) > 0:
        pettm = len(df) / sum([1 / p if p > 0 else 0 for p in df.pe_ratio])
        return pettm
    else:
        return float('NaN')

indexcode = '000300.XSHG'
start = '2020-01-01'
end = pd.datetime.today()
dates = []

# 核心修改点:将 Timestamp 转换为字符串
for d in pd.date_range(start, end, freq='M'):
    dates.append(d.strftime('%Y-%m-%d'))

print("转换后的日期列表:", dates)

# 调用函数
pe = index_pettm(indexcode, dates[0])
print(f"{dates[0]} 的 PE_TTM 为: {pe}")

总结

在量化数据处理中,pandas 的时间格式 (Timestamp) 和 Python 标准库的时间格式 (datetime) 经常混用。在调用 JoinQuant API 时,养成将时间参数显式转换为 'YYYY-MM-DD' 格式字符串 的习惯,可以有效避免此类底层序列化报错。