3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 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 对象即可。以下提供两种常用的修改方式:
在将日期添加到 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]) 时就不会报错了。
如果你希望保持日期对象的属性,可以使用 .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' 格式字符串 的习惯,可以有效避免此类底层序列化报错。