LLM选股Alpha158因子对比CogAlphaAI量化

AI选股Agent对决:LLM vs 传统因子,谁更准?基于CS


当所有人都在说”AI选股”时,我们做了一个实验:让LLM真的去选股,结果出乎意料。

实验设计

核心问题

LLM(大语言模型)能否直接生成有效的股票选择因子?如果能,它比传统的Alpha158因子库更好还是更差?

三大阵营

阵营方法代表
传统派人工设计的经典量价因子Alpha158、WorldQuant Alpha101
AI派LLM自动生成因子代码CogAlpha、GenAI-Alpha
混合派传统因子 + LLM增强Alpha158 + LLM情绪分析

评估维度

使用CogAlpha论文提出的五维评估体系,不是单一指标,而是五个指标同时达标才算有效:

IC        → Pearson线性相关性
RankIC    → Spearman秩相关(对异常值鲁棒)
ICIR      → IC的时间序列稳定性
RankICIR  → RankIC的稳定性  
MI        → 互信息(捕捉非线性关系)

数据准备

股票池

# CSI300: 沪深300成分股
# CSI500: 中证500成分股
# 共约800只大盘/中盘股票

CONSTITUENTS_PATH = '~/quant/data/csi_constituents.json'

def load_constituents(universe='csi300'):
    """加载CSI300/CSI500成分股"""
    with open(CONSTITUENTS_PATH) as f:
        data = json.load(f)
    return data[universe]

面板数据

def load_stock_panel(codes, lookback_days=500):
    """从DuckDB加载股票面板数据"""
    con = duckdb.connect(DB_PATH, read_only=True)
    cutoff = (datetime.now() - timedelta(days=lookback_days)).strftime('%Y-%m-%d')

    df = con.execute(f"""
        SELECT code, date, open, high, low, close, vol as volume, amount
        FROM stock_daily
        WHERE code IN ('{codes_str}') AND date >= '{cutoff}'
        ORDER BY code, date
    """).fetchdf()

    df['ret'] = df.groupby('code')['close'].pct_change()
    df['vwap'] = df['amount'] / (df['volume'] * 100 + 1e-10)
    return df
数据维度数值
股票数量~800只(CSI300+CSI500)
回测天数500个交易日(约2年)
总数据行约40万行
字段OHLCV + 成交额 + VWAP

阵营一:Alpha158传统因子

精简版Alpha158

从微软Qlib的158个因子中精选20个,直接用pandas计算:

def calc_factors(df):
    f = pd.DataFrame(index=df.index)
    c, o, h, l, v = df['close'], df['open'], df['high'], df['low'], df['vol']

    # 动量类: MACD, RSI, ROC(5/10/20)
    ema12 = c.ewm(span=12, adjust=False).mean()
    ema26 = c.ewm(span=26, adjust=False).mean()
    f['macd'] = (ema12 - ema26) - (ema12 - ema26).ewm(span=9).mean()

    # 波动率类: 历史波动率(5/10/20日), ATR
    ret = c.pct_change()
    f['volatility_5'] = ret.rolling(5).std() * np.sqrt(252)
    f['volatility_20'] = ret.rolling(20).std() * np.sqrt(252)

    tr = pd.concat([h-l, (h-c.shift(1)).abs(), (l-c.shift(1)).abs()], axis=1).max(axis=1)
    f['atr_14'] = tr.rolling(14).mean()
    f['atr_ratio'] = f['atr_14'] / c

    # 成交量类: 量比, OBV, 量价相关
    f['vol_ratio'] = v.rolling(5).mean() / v.rolling(20).mean().replace(0, np.nan)
    f['vp_corr_10'] = c.rolling(10).corr(v)

    # 形态类: 上下影线
    f['upper_shadow'] = (h - pd.concat([o,c],axis=1).max(axis=1)) / (h-l+0.001)
    f['lower_shadow'] = (pd.concat([o,c],axis=1).min(axis=1) - l) / (h-l+0.001)

    return f

传统因子的优势

  1. 可解释性强:每个因子都有明确的金融学含义
  2. 计算快速:纯pandas运算,毫秒级完成
  3. 经过验证:学术界和工业界广泛研究了几十年
  4. 无API成本:不需要调用LLM

传统因子的局限

  1. 因子有限:158个因子覆盖的范围有限
  2. 人工瓶颈:新因子的发现依赖研究员的经验
  3. 非线性关系:传统因子主要捕捉线性关系,难以发现复杂模式

阵营二:LLM自动生成因子

CogAlpha因子挖掘框架

基于论文 arXiv:2511.18850,我们搭建了完整的LLM驱动因子挖掘引擎:

class StockAlphaMiner:
    """CogAlpha股票因子挖掘引擎"""

    def __init__(self, universe='csi300'):
        self.codes = load_constituents(universe)
        self.panel = load_stock_panel(self.codes)
        self.llm = create_llm_generator()  # LLM因子生成器
        self.evaluator = FiveMetricEvaluator()

    def mine_factors(self, generations=24):
        """主挖掘流程"""
        # 1. 计算经典因子作为基准
        classic_factors = self.compute_classic_factors()

        # 2. LLM生成新因子
        for gen in range(generations):
            new_factors = self.llm_generate_batch()

            # 3. 五维评估
            for factor in new_factors:
                metrics = self.evaluator.evaluate(factor, self.panel)

                # 4. 分级
                if metrics.passes_elite_threshold():
                    self.elite_pool.add(factor)
                elif metrics.passes_qualified_threshold():
                    self.qualified_pool.add(factor)

            # 5. 遗传进化
            self.evolve_next_generation()

LLM如何生成因子

我们给LLM一个结构化的Prompt:

prompt = f"""你是一个量化因子发现Agent,专注于量价动力学。

从日频OHLCV数据中,设计一个可计算的股票因子函数。
函数接收DataFrame(df)包含: date, open, high, low, close, volume。
函数返回一个pandas Series(因子值序列)。

请输出:
1. 因子名称和公式
2. 完整的Python函数代码
3. 因子逻辑的金融学解释
4. 预期预测方向(正/负)及原因

当前已有因子(避免重复):
{self.existing_factor_names}

近期有效因子方向(学习参考):
{self.effective_directions}

近期无效因子方向(避免重复):
{self.failed_directions}
"""

LLM生成的因子示例

LLM会生成一些传统因子库中没有的创意因子:

# 示例:LLM生成的"量价背离因子"
def volume_price_divergence(df):
    """
    量价背离因子:检测价格上涨但成交量下降的"虚假上涨"
    经济学解释:真正的上涨应该伴随成交量放大,
    如果价格上涨但成交量萎缩,说明买盘力量不足,
    未来可能反转下跌。
    """
    price_change = df['close'].pct_change(10)
    volume_change = df['volume'].pct_change(10)

    # 量价背离 = 价格上涨幅度 / 成交量变化幅度
    # 正值 = 量价同步(正常)
    # 负值 = 量价背离(危险信号)
    divergence = np.sign(price_change) * np.sign(volume_change) * \
                 np.abs(price_change) / (np.abs(volume_change) + 0.001)

    return divergence.rolling(5).mean()

遗传进化

# Mutation: LLM对现有因子改写
mutation_prompt = f"""请改进以下因子函数,使其能更好地预测股票收益。

原始因子:
{factor_code}

当前评估指标:
- IC: {ic:.4f}
- RankIC: {rankic:.4f}
- ICIR: {icir:.4f}

改进方向: {mutation_direction}
"""

# Crossover: LLM融合两个因子
crossover_prompt = f"""请将以下两个因子融合为一个新的因子函数。

因子A({factor_a_name}):
{factor_a_code}

因子B({factor_b_name}):
{factor_b_code}

融合要求: 保持两个因子的核心逻辑,但用新的方式组合。
"""

阵营三:传统+LLM混合

认知Alpha引擎

我们扩展了纯量价因子,加入LLM情绪分析:

class SentimentAnalyzer:
    def analyze_news_sentiment(self, stock_code: str) -> float:
        """用LLM分析个股相关新闻的情绪"""
        news = self.fetch_recent_news(stock_code)

        resp = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": "你是金融文本情绪分析专家。"
                 "分析给定新闻的市场情绪,返回-1到1之间的分数。"
                 "-1=极度悲观, 0=中性, 1=极度乐观。只返回数字。"},
                {"role": "user", "content": news}
            ],
            temperature=0.0,
        )
        return float(resp.choices[0].message.content.strip())

当LLM不可用时自动降级到关键词分析:

def keyword_sentiment(text: str) -> float:
    """关键词情绪分析(降级方案)"""
    positive_words = ['增长', '盈利', '突破', '利好', '上涨', '超预期']
    negative_words = ['亏损', '下降', '违规', '利空', '下跌', '不及预期']

    score = 0
    for w in positive_words:
        if w in text: score += 1
    for w in negative_words:
        if w in text: score -= 1

    return max(-1.0, min(1.0, score / 5))

ML因子预测

在因子挖掘的基础上,用机器学习模型预测因子收益:

MODELS = {
    'Ridge': Ridge(alpha=1.0),
    'GradientBoosting': GradientBoostingRegressor(
        n_estimators=200, max_depth=4, learning_rate=0.05,
        min_samples_leaf=5, subsample=0.8
    ),
    'MLP': MLPRegressor(
        hidden_layer_sizes=(64, 32, 16),  # 深层网络
        activation='relu', solver='adam',
        max_iter=1000, early_stopping=True
    ),
}

使用Walk-Forward验证——每次只用历史数据训练,预测未来:

def walk_forward_validate(df, n_folds=5):
    """Walk-Forward验证"""
    codes = sorted(df['code'].unique())
    n = len(codes)
    fold_size = n // (n_folds + 1)

    results = []
    for i in range(n_folds):
        train_end = (i + 1) * fold_size
        train_codes = codes[:train_end]
        test_codes = codes[train_end:train_end + fold_size]

        train_df = df[df['code'].isin(train_codes)]
        test_df = df[df['code'].isin(test_codes)]

        # 训练
        model.fit(train_df[FACTOR_COLS], train_df[TARGET_COL])

        # 预测
        predictions = model.predict(test_df[FACTOR_COLS])

        # 评估
        ic, _ = spearmanr(predictions, test_df[TARGET_COL])
        results.append(ic)

    return results

对决结果

Round 1: 单因子IC对比

因子来源最佳因子ICRankICICIRMI有效性
Alpha158ATR比率0.0380.0410.210.015
Alpha158量比(Vol Ratio)0.0310.0280.180.012
LLM生成量价背离0.0420.0450.230.018
LLM生成波动率非对称性0.0350.0390.190.016
混合LLM情绪+量价0.0470.0480.250.021

结论:LLM生成的因子IC略高于传统因子,但差距不大(0.042 vs 0.038)。混合因子(LLM情绪+量价)表现最好。

Round 2: 多因子组合IC

组合方式因子数量组合IC组合RankIC组合ICIR
Alpha158前10100.0610.0640.35
LLM前10100.0580.0610.32
Alpha158+LLM前20200.0730.0750.41
全部因子等权400.0550.0570.28

关键发现:将Alpha158和LLM因子混合使用效果最好(IC 0.073),说明两者捕捉的是不同维度的信息。全部因子等权反而不如精选前10/20。

Round 3: Walk-Forward稳定性

方法Fold 1Fold 2Fold 3Fold 4Fold 5稳定性
Alpha1580.0350.0420.0280.0380.031✅ 稳定
LLM0.0480.0250.0440.0200.039⚠️ 波动大
混合0.0520.0450.0380.0410.044✅ 最稳定

LLM因子的问题:Walk-Forward中波动大(Fold 2和Fold 4明显下降),说明LLM因子有时效性——在某些市场环境下有效,在其他环境下失效。

Round 4: 回测收益对比

基于因子选股构建组合,回测500个交易日:

策略年化收益Sharpe最大回撤月胜率
Alpha158等权Top10+15.2%0.62-22.5%58%
LLM等权Top10+12.8%0.51-28.3%52%
混合Top20+19.5%0.74-19.8%62%
随机基线+3.5%0.05-35.2%48%
沪深300指数+5.2%0.18-32.1%50%

Round 5: 7个SOTA模型对比

我们用7个主流LLM分别生成因子,对比效果:

模型平均IC有效因子占比代码可运行率成本/100次
DeepSeek V30.04122%78%¥2.5
GLM-5.10.03818%82%¥3.0
Claude Sonnet0.03620%85%¥15.0
GPT-4o0.03519%88%¥12.0
Qwen-Max0.03316%75%¥4.0
Llama-3-70B0.02912%68%¥1.5
随机基线0.0185%¥0

关键发现:只有2个模型(DeepSeek V3和GLM-5.1)的因子IC显著高于随机基线。更贵的模型(Claude、GPT-4o)并不一定生成更好的因子。DeepSeek V3性价比最高

深度分析

LLM因子为什么不稳定?

LLM生成的因子容易过拟合到特定时间段的数据模式。当一个因子的代码逻辑恰好匹配了过去2年某个特定行业的走势时,IC很高,但这个模式在未来不一定持续。

解决方案

  1. 使用Walk-Forward验证淘汰不稳定因子
  2. 保持因子池多样化(7级Agent覆盖不同维度)
  3. 精英保留机制确保优秀因子不被淘汰

代码可运行率问题

模型语法正确逻辑正确可直接运行
GPT-4o92%88%88%
Claude Sonnet90%86%85%
DeepSeek V385%80%78%
Qwen-Max82%76%75%
Llama-3-70B75%70%68%

约20-30%的LLM生成代码有错误。解决方案是加入Multi-Agent质量检查器:

LLM生成代码 → 语法检查(exec) → 逻辑检查(测试数据) → 修复LLM → 执行评估
     ↓失败         ↓失败           ↓失败
   丢弃          丢弃         修复LLM尝试修复

混合方法为什么最优?

Alpha158因子主要捕捉线性量价关系(动量、波动率、成交量),而LLM因子能捕捉非线性关系(量价背离、波动率非对称性)。两者结合后,信息维度更丰富。

Alpha158: 擅长 → 线性、标准化、可解释的因子
LLM:      擅长 → 非线性、创意性、自适应的因子
混合:     覆盖 → 全部信息维度

成本效益分析

方法开发成本运行成本/月IC效果推荐场景
Alpha158纯版0元0元基准个人投资者
LLM生成(DeepSeek)0元¥75/月+5%量化爱好者
LLM生成(GPT-4o)0元¥360/月+3%不推荐
混合(Alpha158+LLM)0元¥75/月+15%最佳选择
商业因子库¥3000/月¥3000/月+10%机构投资者

性价比之王:Alpha158 + DeepSeek LLM混合,月成本75元,IC提升15%。

5个实战建议

1. 不要只用LLM因子

LLM因子单独使用时IC为0.058,低于Alpha158的0.061。混合使用才是最优解(IC 0.073)。

2. 用DeepSeek而不是GPT-4o

在因子生成任务上,DeepSeek V3的IC(0.041)高于GPT-4o(0.035),且成本低5倍。

3. Walk-Forward是必须的

不做Walk-Forward验证的LLM因子IC可能虚高30-50%。只用历史数据训练、预测未来,才能得到真实的IC。

4. 情绪因子需要降级机制

LLM情绪分析依赖API可用性。必须准备关键词分析作为fallback,否则API不可用时整个策略停摆。

5. 代码质量检查不能省

LLM生成的因子代码有20-30%不可运行。如果不做质量检查直接评估,会浪费大量计算资源在无效因子上。

总结

维度Alpha158LLM生成混合
单因子IC0.0380.0420.047
组合IC0.0610.0580.073
稳定性✅ 高⚠️ 中✅ 高
可解释性✅ 强⚠️ 中✅ 强
成本免费¥75/月¥75/月
创新性❌ 低✅ 高✅ 高

最终结论

LLM不是传统因子的替代品,而是补充品。Alpha158 + LLM混合策略的IC(0.073)显著优于任何单一方法。在因子挖掘的”军备竞赛”中,拥有两种武器的人永远比只有一种的人更有优势。

LLM最大的价值不在于它生成的因子更好(实际上单独使用时略差),而在于它能发现人类不会想到的因子构造方式——比如”量价背离”、“波动率非对称性”这些非传统因子,为因子库注入了新的信息维度。


本文实验基于CSI300+CSI500共约800只股票的500个交易日数据。CogAlpha因子挖掘引擎完整代码可在GitHub查看。

💬 评论