问题描述
必现:
使用get_fundamentals接口传参date的时候,第一次可以调用,第二次继续调用该接口的时候date日期与上一次日期不一样,然后会报如下图的错。请问这个怎么使用?我回测的时候每天要拉一下换手率,市值,但是现在跑起来的第二天就报错了
解决方案
在 JoinQuant (聚宽) 的回测环境中,使用 get_fundamentals 接口时,强烈建议不要手动传入 date 参数。
报错原因分析
在回测引擎中,系统维护了一个严格的时间上下文(context.current_dt)。根据 API 文档,当 date 和 statDate 都不传入时,date 的默认值会自动随着回测日期变化而变化,等于 context.current_dt 的前一天(因为在实际交易中,今天只能看到昨天的财务和市值数据)。
如果您手动传入 date,可能会遇到以下问题:
- 未来函数报错:如果传入的日期大于当前回测逻辑时间,会触发未来数据异常。
- Query 对象复用冲突:在循环中不断修改日期参数,可能会导致底层 SQLAlchemy 的 Query 对象状态异常,从而引发报错。
正确的使用方法
如果您需要在回测中每天拉取换手率(turnover_ratio)和市值(market_cap),只需在 handle_data 或定时运行函数中直接调用 get_fundamentals(q) 即可,不要传 date 参数。
代码示例
以下是一个每天获取指定股票池市值和换手率的标准写法:
import jqdata
def initialize(context):
# 设定要操作的股票池
g.stocks = ['000001.XSHE', '600000.XSHG']
# 每天开盘前运行
run_daily(before_market_open, time='09:00')
def before_market_open(context):
# 构造查询对象:查询代码、换手率、总市值
q = query(
valuation.code,
valuation.turnover_ratio,
valuation.market_cap
).filter(
valuation.code.in_(g.stocks)
)
# 直接调用,不传 date 参数!
# 系统会自动获取 context.current_dt 前一天的最新数据
df = get_fundamentals(q)
# 打印查看结果
log.info("当前回测时间: %s" % context.current_dt)
log.info("\n%s" % df)
# 您可以将获取到的数据存入全局变量供盘中使用
g.fund_data = df
总结
- 回测/模拟中:直接
get_fundamentals(q),系统自动处理时间对齐,避免未来函数。 - 研究环境中:可以手动传入
date参数(如date='2023-01-01')来探究历史特定日期的数据。