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

为什么在 JoinQuant 中使用 get_price 获取的数据为空或 NaN?

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

问题描述

为什么用get_price获得的数据为空?

为什么用get_price获得的数据为nan?
df = get_price('000001.XSHE', count = 2, end_date='2015-01-31', frequency='daily', fields=['open', 'close'])
df

解决方案

在 JoinQuant (聚宽) 平台中使用 get_price 函数获取数据时,如果遇到返回结果为空(Empty DataFrame)或包含 NaN(Not a Number)的情况,通常是由以下几个原因导致的:

1. 股票未上市或已退市(导致 NaN)

如果你查询的时间段(start_dateend_date,或 end_date 往前推 count 个周期)内,该股票尚未上市已经退市,API 无法获取到有效的交易价格,此时返回的数据中对应字段的值就会是 NaN

2. 股票停牌(可能导致 NaN 或数据缺失)

  • 默认情况 (skip_paused=False):如果股票在查询期间停牌,get_price 默认不会跳过停牌日,而是使用停牌前最后一个交易日的数据进行填充。但如果该股票在停牌前没有任何历史数据(例如刚上市就停牌),则会返回 NaN
  • 跳过停牌 (skip_paused=True):如果你设置了 skip_paused=True,API 会直接剔除停牌的日期。如果查询的时间段内该股票全程停牌,返回的 DataFrame 就会是的。

3. 回测中的“未来函数”限制(导致空数据)

如果你是在回测环境中运行这段代码,需要特别注意 end_date 的设置。为了防止策略引入“未来函数”(即提前偷看未来的数据),如果你设置的 end_date 大于当前回测的逻辑时间 (context.current_dt),系统可能会限制数据的获取,导致返回空数据或报错。在回测中,建议不要手动硬编码 end_date,而是使用 end_date=context.current_dt

4. 分钟数据的日期边界问题

虽然你的代码中 frequency='daily' 没有这个问题,但如果是获取分钟数据(frequency='1m'),当 end_date 只传入日期字符串(如 '2015-01-31')时,系统会将其解析为 '2015-01-31 00:00:00'。这意味着它不包含 1 月 31 日当天的任何交易时段数据。如果往前推的 count 落在非交易时间,也可能导致数据为空。


针对你提供的代码分析:

df = get_price('000001.XSHE', count = 2, end_date='2015-01-31', frequency='daily', fields=['open', 'close'])

对于平安银行(000001.XSHE),它在 2015 年 1 月是正常交易的。2015年1月31日是周六(非交易日),往前推 count=2 个交易日,应该返回 2015-01-30(周五)和 2015-01-29(周四)的数据。

如果你运行这段代码返回了空或 NaN,请检查以下几点:

  1. 运行环境:你是在“研究环境”还是“回测环境”运行的?如果在回测环境中,且回测的开始时间晚于 2015-01-31,或者当前运行到的时间早于 2015-01-31,可能会因为时间轴不匹配导致获取不到数据。
  2. 数据权限:确保你的账号有权限获取该时间段的数据(通常基础 A 股数据都是开放的)。

解决方法与建议:

  • 检查上市/退市时间:使用 get_security_info('000001.XSHE').start_date 查看股票的上市日期,确保查询时间在上市之后。
  • 处理停牌:如果不需要停牌数据,可以加上 skip_paused=True 参数;如果需要连续的时间序列,保持默认即可,但要做好 NaN 值的处理(如使用 df.dropna()df.fillna())。
  • 回测中动态获取时间:在策略代码中,尽量使用 end_date=context.current_dt 来代替硬编码的日期字符串,避免未来函数问题。