3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 JoinQuant 的因子分析框架中,当 skip_paused=True 时,系统会为每只股票向前追溯,直到获取满 max_window 个实际交易日的量价数据。因为不同股票的停牌时间不同,它们凑满 max_window 个交易日所跨越的自然日历区间也是不同的。这就导致多只股票的量价数据无法对齐到同一个 datetime 索引上。因此,系统将量价数据的索引改为了 int(例如 0 到 N-1,值越大表示离当前日期越近)。
而财务数据(如单季度财报)属于低频的状态数据,它在某个时间点上是确定的,不需要像计算技术指标(如 MA5)那样严格要求连续的交易日,因此财务数据依然保留了 datetime 索引。
如果你在 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 进行对齐计算。最简便且优雅的方法是:设置 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)。