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

JoinQuant因子分析中 skip_paused=True 导致数据索引不匹配怎么办?

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

问题描述

因子分析中的一个问题

在因子分析计算中,当calc_factor函数中skip_paused参数为True时,从因子中获取量价信息返回的dataframe的index为int,而同时获取的财务数据返回的index为日期,当股票存在停盘日时,两种数据会出现不匹配,如果两者之间进行计算,该如何做到数据的匹配,而且这样设计的原因是为什么?

另外请问如何在因子分析中calc_factor函数中skip_paused参数为True时实现股票在停盘日返回的因子为nan?

考虑过从get_price中获取paused数据,但是其中end_date参数无法简便的获取,当然可以从上面的获取财务数据的index中获取相应日期,但是有没有其他相对简便的方法呢?

解决方案

1. 为什么这样设计?(索引不匹配的原因)

在 JoinQuant 的因子分析框架中,当 skip_paused=True 时,系统会为每只股票向前追溯,直到获取满 max_window实际交易日的量价数据。因为不同股票的停牌时间不同,它们凑满 max_window 个交易日所跨越的自然日历区间也是不同的。这就导致多只股票的量价数据无法对齐到同一个 datetime 索引上。因此,系统将量价数据的索引改为了 int(例如 0 到 N-1,值越大表示离当前日期越近)。

而财务数据(如单季度财报)属于低频的状态数据,它在某个时间点上是确定的,不需要像计算技术指标(如 MA5)那样严格要求连续的交易日,因此财务数据依然保留了 datetime 索引。

2. 如何做到数据的匹配?

如果你在 calc 函数中需要同时使用量价数据和财务数据:

  • 只取最新值计算:通常财务数据我们只需要用到当前逻辑日期的最新值。你可以直接使用 .iloc[-1] 来获取两者的最新状态进行横截面计算,这样就避开了历史时间序列索引不匹配的问题。
    latest_close = data['close'].iloc[-1]
    latest_pe = data['pe_ratio'].iloc[-1]
    factor_value = latest_close / latest_pe
    
  • 需要时间序列计算:如果你确实需要对财务数据和量价数据进行时间序列上的运算,强烈建议将 skip_paused 设置为 False。这样所有数据都会统一使用 datetime 索引,停牌日的量价数据会用停牌前最后一个交易日的数据进行前向填充(Forward Fill),你可以非常方便地使用 Pandas 进行对齐计算。

3. 如何简便地实现停牌日返回 NaN?

最简便且优雅的方法是:设置 skip_paused=False,并在 dependencies 中引入 'paused' 字段,在计算完因子后通过掩码(Mask)将停牌股票的因子值置为 NaN。

这样既解决了索引不匹配的问题,又完美实现了停牌日过滤,不需要额外调用 get_price

代码示例:

from jqfactor import Factor
import numpy as np

class MyCustomFactor(Factor):
    name = 'my_custom_factor'
    max_window = 5
    # 引入需要的量价、财务数据,以及 'paused' 字段
    dependencies = ['close', 'operating_revenue', 'paused']

    def calc(self, data):
        # 此时 skip_paused=False,所有 data 的 index 都是 datetime,完美对齐
        close_data = data['close']
        revenue_data = data['operating_revenue']
        paused_data = data['paused']
        
        # 1. 进行你的因子计算逻辑(例如计算过去5天收盘价均值 / 最新营收)
        ma5 = close_data.mean()
        latest_revenue = revenue_data.iloc[-1]
        factor_value = ma5 / latest_revenue
        
        # 2. 获取当天的停牌状态 (1表示停牌,0表示正常交易)
        is_paused = paused_data.iloc[-1] == 1
        
        # 3. 将停牌股票的因子值置为 NaN
        factor_value[is_paused] = np.nan
        
        return factor_value

总结:
在自定义因子时,处理停牌和数据对齐的最佳实践是保持 skip_paused=False(保留时间轴的统一性),并通过依赖 'paused' 字段在最后一步将停牌标的剔除(赋值为 np.nan)。