🚀 AI 一键生成 ptrade 策略代码
立即体验

PTrade 多因子模型:截面回归与因子标准化去极值实战(附 Python 代码)

ptrade | 发布时间: 2026/7/31
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: PTrade 多因子模型:截面回归与因子标准化去极值实战

Question: 请提供一份在 ptrade 中进行因子去极值、标准化及截面回归的完整代码示例。

解决方案

在 PTrade 平台搭建多因子模型时,因子的数据预处理(去极值、标准化)与截面回归是因子分析和选股的核心步骤。通过对因子进行清洗,可以消除异常值(Outliers)与量纲差异对预测结果的干扰。

1. 多因子预处理与截面回归核心步骤

  1. 数据获取:利用 get_fundamentals 提取多只标的的财务因子或估值指标(如 PB、ROE、PE 等)。
  2. 中位数去极值 (MAD):计算因子的中位数及绝对偏差中位数,将超过指定倍数阈值的数据重置到边界,防止极值拉偏回归系数。
  3. Z-score 标准化:将因子序列处理为均值为 0、标准差为 1 的无量纲分布。
  4. 截面回归:以截面因子的标准化数值作为自变量 $X$,下期收益率为因变量 $Y$,使用 statsmodelsnumpy 进行 OLS 线性回归,获取因子收益率(因子载荷)。

2. PTrade 实战代码示例

以下代码展示了在 PTrade 的 before_trading_starthandle_data 事件中提取沪深 300 成分股的估值与盈利因子,进行 MAD 去极值、Z-score 标准化以及 OLS 截面回归的过程:

import numpy as np
import pandas as pd
import statsmodels.api as sm

def initialize(context):
    # 设置参考基准与股票池
    set_benchmark('000300.SS')
    g.security = '000300.SS'
    # 定时在盘前运行因子计算与回归分析
    run_daily(context, factor_analysis, time='9:15')

def factor_analysis(context):
    # 1. 获取沪深300成分股列表
    stocks = get_index_stocks('000300.XBHS')
    if not stocks:
        return
    
    # 2. 获取财务/估值因子数据 (以PB和ROE为例)
    # balance_statement/valuation 等表可通过 get_fundamentals 查询
    df_val = get_fundamentals(stocks, 'valuation', fields=['pb'])
    df_profit = get_fundamentals(stocks, 'profit_ability', fields=['roe'])
    
    if df_val.empty or df_profit.empty:
        log.info("未获取到足够的因子数据")
        return
        
    # 合并因子数据
    factors_df = pd.DataFrame({
        'pb': df_val['pb'],
        'roe': df_profit['roe']
    }).dropna()
    
    # 3. 因子预处理:中位数去极值 (MAD)
    def mad_de_extreme(series, n=3):
        median = series.median()
        mad = (series - median).abs().median()
        max_limit = median + n * 1.4826 * mad
        min_limit = median - n * 1.4826 * mad
        return np.clip(series, min_limit, max_limit)
    
    # 4. 因子预处理:Z-score 标准化
    def z_score_standardize(series):
        mean = series.mean()
        std = series.std()
        if std == 0:
            return series - mean
        return (series - mean) / std

    # 对每个因子依次进行去极值与标准化
    processed_factors = pd.DataFrame()
    for col in factors_df.columns:
        de_ext = mad_de_extreme(factors_df[col])
        processed_factors[col] = z_score_standardize(de_ext)
    
    # 5. 获取未来一期的截面收益率作为因变量 Y (假设以过去5天历史收益率替代测试)
    hist_price = get_history(5, frequency='1d', field='close', security_list=list(processed_factors.index))
    # 计算近期收益率
    returns = (hist_price.iloc[-1] - hist_price.iloc[0]) / hist_price.iloc[0]
    
    # 对齐因子数据与收益率数据
    data = processed_factors.copy()
    data['returns'] = returns
    data = data.dropna()
    
    # 6. 截面 OLS 回归
    X = data[['pb', 'roe']]
    X = sm.add_constant(X) # 添加常数项
    Y = data['returns']
    
    model = sm.OLS(Y, X).fit()
    
    # 7. 输出截面回归结果
    log.info("--- 截面回归系数 (因子收益率) ---")
    log.info(model.params)
    log.info("--- 回归 p 值 ---")
    log.info(model.pvalues)
    log.info("--- R-squared ---")
    log.info(model.rsquared)

def handle_data(context, data):
    pass

3. 注意事项

  1. 数据缺失处理:在调用 get_fundamentals 提取财务因子时,部分股票可能因未披露或数据停牌返回 NaN,必须使用 .dropna() 进行清理。
  2. 未来函数规避:在回测环境中使用财务数据和收益率进行截面回归时,因变量收益率 $Y$ 必须是因子观测点之后的实际收益率,避免引入未来数据。
  3. 多重共线性:若多个因子间相关性过高,可在截面回归前增加 正交化 (Orthogonalization) 处理。