聚宽多因子Alpha行业中性化组合优化量化策略

聚宽组合策略:4因子Alpha挖掘+行业中性化实现Sharpe 1.94的高夏普组合


从单因子到多因子:为什么要组合?

单因子策略(如纯ROE选股或纯动量选股)有一个致命问题:因子会周期性失效

2023年ROE因子表现优异,2024年Q3突然回撤;动量因子在趋势市表现好,震荡市就变成”追涨杀跌”。解决方案就是多因子组合——把不同特性的因子组合在一起,利用因子间的低相关性,实现更稳定的Alpha。

四因子模型设计

因子选择

因子类别代表指标Alpha来源预期IC
价值EP(盈利收益率)市场低估修复0.03-0.05
动量近60日涨幅趋势延续0.02-0.04
质量ROE变化率基本面改善0.02-0.03
低波动20日波动率倒数低波动异常0.02-0.03

因子预处理流程

import pandas as pd
import numpy as np

class FactorProcessor:
    """因子预处理标准流程"""
    
    @staticmethod
    def winsorize(series, n_sigma=3):
        """去极值:MAD法"""
        median = series.median()
        mad = (series - median).abs().median()
        upper = median + n_sigma * 1.4826 * mad
        lower = median - n_sigma * 1.4826 * mad
        return series.clip(lower, upper)
    
    @staticmethod
    def neutralize(df, factor_col, industry_col='industry'):
        """行业中性化:回归取残差"""
        from sklearn.linear_model import LinearRegression
        
        # 行业one-hot
        industry_dummies = pd.get_dummies(df[industry_col], prefix='ind')
        
        # 回归取残差
        X = industry_dummies.values
        y = df[factor_col].values
        model = LinearRegression().fit(X, y)
        residuals = y - model.predict(X)
        
        df[factor_col + '_neutral'] = residuals
        return df
    
    @staticmethod
    def normalize(series):
        """标准化:Z-Score"""
        return (series - series.mean()) / series.std()
    
    def process(self, df, factor_col):
        """完整预处理:去极值→中性化→标准化"""
        df[factor_col] = self.winsorize(df[factor_col])
        df = self.neutralize(df, factor_col)
        df[factor_col] = self.normalize(df[factor_col])
        return df

因子合成

class FactorCombination:
    """多因子合成"""
    
    # 等权方案(v1.0)
    WEIGHTS_EQUAL = {
        'ep': 0.25,
        'momentum_60d': 0.25,
        'roe_change': 0.25,
        'low_volatility': 0.25
    }
    
    # IC加权方案(v2.0,当前实盘)
    WEIGHTS_IC = {
        'ep': 0.35,           # IC最高,权重最大
        'momentum_60d': 0.20, # IC较低,权重小
        'roe_change': 0.25,
        'low_volatility': 0.20
    }
    
    def combine(self, factor_df, weights='ic'):
        """合成综合因子"""
        w = self.WEIGHTS_IC if weights == 'ic' else self.WEIGHTS_EQUAL
        
        factor_df['composite_score'] = sum(
            factor_df[factor] * weight
            for factor, weight in w.items()
        )
        return factor_df

组合优化

行业中性化

不只做因子层面的中性化,还做组合层面的行业中性——确保持仓的行业分布与基准一致。

def industry_neutral_selection(scores, benchmark_weights, n_stocks=50):
    """行业中性选股"""
    selected = []
    
    for industry, target_weight in benchmark_weights.items():
        # 该行业内的股票按因子得分排序
        industry_stocks = scores[scores['industry'] == industry]
        n_pick = max(1, int(n_stocks * target_weight))
        
        # 选该行业得分最高的股票
        picks = industry_stocks.nlargest(n_pick, 'composite_score')
        selected.append(picks)
    
    return pd.concat(selected)

组合权重优化

from scipy.optimize import minimize

def optimize_weights(expected_returns, cov_matrix, target_vol=0.15):
    """最小方差 + 收益约束"""
    n = len(expected_returns)
    
    def objective(weights):
        portfolio_var = weights @ cov_matrix @ weights
        return portfolio_var
    
    constraints = [
        {'type': 'eq', 'fun': lambda w: np.sum(w) - 1},  # 权重和=1
        {'type': 'ineq', 'fun': lambda w: target_vol - np.sqrt(w @ cov_matrix @ w)},
    ]
    bounds = [(0, 0.05)] * n  # 单只最大5%
    
    result = minimize(
        objective, 
        x0=np.ones(n) / n,
        method='SLSQP',
        bounds=bounds,
        constraints=constraints
    )
    return result.x

回测结果

整体表现

指标四因子组合沪深300超额
总收益率(36个月)+103.2%+18.7%+84.5%
年化收益率+27.8%+5.8%+22.0%
最大回撤-15.2%-28.3%+13.1%
Sharpe比率1.940.24
信息比率1.47
月胜率68%

因子贡献分析

因子IC均值ICIR多空收益贡献占比
EP(价值)0.0480.72+22.3%35%
ROE变化(质量)0.0350.58+18.1%28%
低波动0.0290.51+14.2%20%
动量0.0220.39+11.8%17%

关键发现

  1. 价值因子贡献最大:EP因子IC均值0.048,是四个因子中最稳定的Alpha来源。在A股市场,低PE策略长期有效。

  2. 动量因子波动大:ICIR仅0.39,在2023年Q3出现显著回撤。但加入组合后,被其他因子的正收益对冲。

  3. 行业中性化有效:不做行业中性化时,策略在2024年金融板块大涨期间严重跑输。中性化后,不再依赖某个行业的beta。

  4. 组合优化的价值:等权组合的Sharpe是1.52,优化后提升到1.94。权重优化降低了组合波动率约2个百分点。

聚宽平台实现

# 聚宽平台代码框架
def initialize(context):
    """策略初始化"""
    set_benchmark('000300.XSHG')
    set_slippage(FixedSlippage(0.002))
    set_commission(PerTrade(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    set_option('use_real_price', True)
    
    # 调仓日:每月第一个交易日
    run_monthly(rebalance, monthday=1, time='9:30')

def rebalance(context):
    """月度调仓"""
    # 1. 计算因子
    factor_data = calculate_all_factors(context.now)
    
    # 2. 因子预处理
    processor = FactorProcessor()
    for factor in ['ep', 'momentum_60d', 'roe_change', 'low_volatility']:
        factor_data = processor.process(factor_data, factor)
    
    # 3. 因子合成
    combiner = FactorCombination()
    factor_data = combiner.combine(factor_data, weights='ic')
    
    # 4. 行业中性选股
    benchmark_weights = get_industry_weights('000300.XSHG')
    selected = industry_neutral_selection(
        factor_data, benchmark_weights, n_stocks=50
    )
    
    # 5. 组合优化
    target_weights = optimize_weights(
        expected_returns=selected['composite_score'].values,
        cov_matrix=calculate_cov_matrix(selected.index, context.now)
    )
    
    # 6. 执行交易
    for stock, weight in zip(selected.index, target_weights):
        order_target_value(stock, context.portfolio.total_value * weight)

从聚宽到实盘

迁移到Ptrade

聚宽平台适合做策略研发和回测,但实盘需要迁移到券商交易系统:

聚宽功能Ptrade对应迁移注意
get_fundamentals()财务数据接口数据源不同,需校准
run_monthly()after_trading_end()日内vs日间执行差异
order_target_value()order_value()参数含义略有不同
回测引擎模拟交易验证先跑1个月模拟盘对齐

实盘表现追踪

策略上线Ptrade后,需要持续跟踪实盘vs回测的差异:

  • 跟踪误差:实盘收益与回测收益的偏差,正常范围月均±2%
  • 滑点影响:实际成交价与信号价的差异,大市值股票影响小
  • 因子衰减:每月检查IC变化,IC持续下降时考虑因子替换

风险提示

多因子策略虽然通过分散化降低了单因子风险,但仍然面临:因子同质化(多个因子实际上捕捉同一个风险溢价)、市场 regime 切换(如2024年小盘股风格极端行情)、以及过度拟合风险。建议在实盘前进行充分的样本外检验。

总结

四因子组合策略通过价值+动量+质量+低波动的多元Alpha来源,配合行业中性化和组合优化,实现了Sharpe 1.94的高夏普表现。核心经验:

  1. 因子组合 > 单因子:降低因子失效风险
  2. 行业中性化是必须的:否则就是在赌行业beta
  3. IC加权 > 等权:让数据告诉你哪个因子更有效
  4. 组合优化提升显著:Sharpe从1.52提升到1.94

延伸阅读

💬 评论