🚀 AI 一键生成 joinquant 策略代码

JoinQuant 平台如何创建并计算自定义因子?(Factor 类详解)

joinquant | 发布时间: 2025/12/3
以下内容由 EasyQuant 生成。

问题描述

如何创建我自己的因子?

解决方案

在聚宽(JoinQuant)平台上创建自定义因子,主要是在研究环境中通过继承 jqfactor.Factor 类来实现。

以下是创建自定义因子的标准流程、代码示例及详细参数说明。

创建自定义因子的步骤

  1. 导入模块:引入 jqfactor 中的 Factor 类。
  2. 定义类:创建一个继承自 Factor 的类。
  3. 设置属性:在类中定义 name(因子名称)、max_window(所需历史数据长度)、dependencies(依赖的基础数据)。
  4. 实现计算逻辑:重写 calc(self, data) 方法,利用 data 中的数据计算并返回因子值。

完整代码示例

以下代码定义了一个简单的自定义因子:5日乖离率 (Bias5)。即当前收盘价相对于过去5日均价的偏离程度。

# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
from jqfactor import Factor, calc_factors

# 1. 定义因子类,继承自 Factor
class Bias5(Factor):
    # 因子名称,必须唯一
    name = 'bias5'
    
    # 获取数据的时间窗口长度(例如计算5日均线,至少需要5天数据)
    max_window = 5
    
    # 依赖的基础数据字段,可以是行情数据('close', 'open'等)或财务数据
    dependencies = ['close']
    
    # 2. 实现计算逻辑
    def calc(self, data):
        """
        data 是一个字典,key 是 dependencies 中的字段名,
        value 是 pandas.DataFrame (index为日期,columns为股票代码)
        """
        # 获取收盘价数据 (DataFrame: 行=日期, 列=股票)
        close_df = data['close']
        
        # 计算过去5天的均值 (按列求均值,返回 Series)
        ma5 = close_df.mean()
        
        # 获取当前的收盘价 (最后一行)
        current_close = close_df.iloc[-1]
        
        # 计算乖离率: (当前价格 - 均价) / 均价
        bias = (current_close - ma5) / ma5
        
        # 返回结果必须是 pandas.Series (index为股票代码,value为因子值)
        return bias

# --- 以下为测试因子计算的代码 ---

# 定义股票池
securities = ['000001.XSHE', '600000.XSHG', '000300.XSHG']

# 计算因子值
# start_date 和 end_date 是因子值的日期
factors = calc_factors(
    securities=securities,
    factors=[Bias5()],
    start_date='2023-01-01',
    end_date='2023-01-05'
)

# 打印结果
print(factors['bias5'])

关键属性与方法详解

1. 类属性

  • name (str): 因子的唯一标识符。
  • max_window (int): 计算因子所需的历史数据天数。例如计算10日均线,该值至少为10。系统会自动截取过去 max_window 天的数据传给 calc 方法。
  • dependencies (list): 依赖的数据列表。支持以下类型:
    • 行情数据: 'open', 'close', 'high', 'low', 'volume', 'money'
    • 财务数据: 如 'total_operating_revenue' (营业总收入), 'net_profit' (净利润) 等。
    • 行业/概念: 如 'HY001' (某行业代码)。
    • 其他因子: 可以依赖聚宽因子库中的因子。

2. calc(self, data) 方法

  • 输入参数 data: 一个字典 (dict)。
    • Key: dependencies 中定义的字符串。
    • Value: pandas.DataFrame
      • Index: 时间序列(长度为 max_window,最后一行是当前计算日期)。
      • Columns: 股票代码。
  • 返回值: 必须是一个 pandas.Series
    • Index: 股票代码。
    • Value: 计算出的因子值。

进阶:使用财务数据和额外数据

如果需要同时使用财务数据或指数数据,可以参考以下示例(计算市销率倒数):

class SalesToPrice(Factor):
    name = 'sales_to_price'
    max_window = 1
    # 依赖营业收入(财务数据)和总市值(基础数据)
    dependencies = ['operating_revenue', 'market_cap']
    
    def calc(self, data):
        # 获取财务数据:营业收入 (TTM或单季度,取决于具体字段定义,通常因子库默认为TTM或最新报告期)
        revenue = data['operating_revenue']
        # 获取市值
        mcap = data['market_cap']
        
        # 注意:data中的DataFrame包含max_window行,这里我们只取最新的一行(即当前日期)
        #以此计算当天的因子值
        current_revenue = revenue.iloc[-1]
        current_mcap = mcap.iloc[-1]
        
        # 计算 市销率倒数 = 营收 / 市值
        return current_revenue / current_mcap

常见问题 Q&A

Q: calc 函数中可以直接获取大盘指数的数据吗?
A: 不能直接通过 dependencies 获取指数数据。如果在计算个股因子时需要用到指数(如计算Beta),需要在 calc 方法内部使用 self._get_extra_data(securities=['000300.XSHG'], fields=['close']) 来获取额外数据。

Q: max_window 设置为1时,data 中的数据是什么样的?
A: 当 max_window=1 时,data['close'] 等 DataFrame 只有一行(即当前计算日的数据)。在进行计算时,通常需要使用 .iloc[-1].mean() (结果相同) 将其转换为 Series 进行运算。

Q: 如何处理停牌股票的数据?
A: 在调用 calc_factors 时,有一个参数 skip_paused

  • 如果设为 True,停牌股票会被跳过(不计算)。
  • 如果设为 False(默认),停牌股票的数据会包含在 data 中(通常是前复权价格),你需要自己在 calc 逻辑中决定如何处理(例如返回 NaN)。

Q: 因子计算结果全是 NaN 怎么办?
A: 请检查:

  1. max_window 是否足够长(例如计算60日均线但窗口只设了10)。
  2. dependencies 中的财务字段在选定的时间内是否有数据(部分财务数据在财报发布前可能为空)。
  3. 股票池是否包含未上市或已退市的股票。