问题描述
解决方案
在 JoinQuant(聚宽)平台上获取指标数据(如换手率 HSL 或其他因子数据)时返回 NaN 是正常现象。同时,模拟实盘环境中确实存在特定的数据延时机制。以下是详细的解析:
一、 获取指标数据返回 NaN 的常见原因
获取数据返回 NaN(Not a Number,即数据缺失)通常由以下几种情况引起:
- 数据尚未更新(T+1 机制):
- 因子数据:聚宽的因子库数据(如换手率、各种技术/基本面因子)通常是基于日线数据在盘后计算的。官方文档指出:“频率为天,每天05:00更新前一天数据”。因此,如果你在当天盘中尝试获取当天的因子数据,或者在回测中没有正确处理时间窗口,就会获取到
NaN。 - 财务数据:为了避免未来函数,财务数据在盘后(15:00)才能获取当天交易日的数据,在当天收盘前只能获取以前的数据。
- 因子数据:聚宽的因子库数据(如换手率、各种技术/基本面因子)通常是基于日线数据在盘后计算的。官方文档指出:“频率为天,每天05:00更新前一天数据”。因此,如果你在当天盘中尝试获取当天的因子数据,或者在回测中没有正确处理时间窗口,就会获取到
- 标的处于特殊状态:
- 停牌:如果股票在查询期间停牌,某些依赖交易量或价格变动的指标(如换手率)可能无法计算,从而返回
NaN。 - 新股上市/退市:新股上市初期,由于历史数据不足(例如需要计算60日均线,但上市才10天),相关指标会返回
NaN。退市后的股票也会返回空值。
- 停牌:如果股票在查询期间停牌,某些依赖交易量或价格变动的指标(如换手率)可能无法计算,从而返回
- 财务数据未披露:
- 如果指标依赖于特定的财务报表字段,而该上市公司未披露该字段(或披露规则变更),依赖数据不完整就会导致计算结果为
NaN。
- 如果指标依赖于特定的财务报表字段,而该上市公司未披露该字段(或披露规则变更),依赖数据不完整就会导致计算结果为
二、 模拟实盘环境的延时情况
模拟实盘环境与回测环境在数据获取上存在差异,确实存在延时:
- 系统级延时:
- 官方文档明确指出:“模拟盘有10s系统延迟”。日志中的时间是逻辑时间,如需获取实际物理时间需要使用
datetime.datetime.now()。
- 官方文档明确指出:“模拟盘有10s系统延迟”。日志中的时间是逻辑时间,如需获取实际物理时间需要使用
- 日线与因子数据的延时(T+1):
- 在模拟盘中,如果你在盘中(如上午10:00)调用
get_factor_values或查询某些日频指标,你只能获取到昨天(或更早)的数据。当天的日线级别指标必须等当天收盘并经过系统计算后(通常是第二天凌晨)才能获取。
- 在模拟盘中,如果你在盘中(如上午10:00)调用
- 财务数据的延时:
- 模拟盘中,当天发布的财报数据,通常需要在当天收盘后(15:00之后)才能通过 API 获取到,盘中获取的依然是上一期的财报数据。
三、 应对建议与代码技巧
为了保证策略的健壮性,建议在代码中主动处理 NaN 值:
1. 数据清洗(剔除或填充 NaN)
import pandas as pd
def handle_data(context, data):
# 获取因子数据
factor_data = get_factor_values(securities=context.universe, factors=['VOL5'], start_date=context.previous_date, end_date=context.previous_date)
df = factor_data['VOL5']
# 方法一:直接剔除包含 NaN 的股票
df_clean = df.dropna(axis=1)
# 方法二:使用行业均值或特定值填充 NaN(聚宽提供了 neutralize 和 winsorize 等处理函数)
# df_filled = df.fillna(0)
2. 开启避免未来数据模式
在 initialize 中加入 set_option("avoid_future_data", True),这有助于在回测阶段就暴露因为时间错位导致的数据获取问题。
总结:返回 NaN 是量化数据处理中的常态,主要源于数据计算的 T+1 属性或标的自身的特殊状态。在模拟实盘中,请务必基于“盘中只能获取昨日日线/因子数据”的逻辑来编写策略。