因子挖掘CogAlphaLLMAlpha158量化研究

量化因子挖掘引擎:从Alpha158到CogAlpha LLM启发式挖掘的完整实战


为什么需要因子挖掘引擎

传统量化研究的瓶颈在于因子发现依赖人力。一个有经验的量化研究员,一年能手工构造20-50个因子,其中有效的可能只有3-5个。而CogAlpha论文(arXiv:2511.18850)提出了一种革命性的方法:让LLM自动编写因子代码,用遗传算法驱动因子进化

本文分享我们基于CogAlpha论文搭建的因子挖掘引擎——从Alpha158精简因子库到LLM驱动的7级Agent层次进化系统,覆盖5000+只A股和988只可转债。

架构全景

整个因子挖掘引擎分为三层:

┌─────────────────────────────────────────────────┐
│              因子挖掘引擎架构                       │
├─────────────────────────────────────────────────┤
│                                                   │
│  Layer 1: 经典因子层                               │
│  ├── Alpha158精简版 (20个量价因子)                 │
│  ├── 可转债5维因子 (技术/信用/正股/组合/定价)       │
│  └── 股票30+因子 (动量/波动/成交量/形态)            │
│                                                   │
│  Layer 2: LLM因子生成层                            │
│  ├── 7级Agent层次 (21个领域专家Agent)              │
│  ├── 遗传进化 (Mutation + Crossover)              │
│  ├── 多样化引导 (5种释义模式)                       │
│  └── Multi-Agent质量检查器                         │
│                                                   │
│  Layer 3: 五维评估层                               │
│  ├── IC (Pearson相关性)                            │
│  ├── RankIC (Spearman秩相关)                      │
│  ├── ICIR (IC信息比率)                             │
│  ├── RankICIR (秩IC信息比率)                       │
│  └── MI (互信息)                                   │
│                                                   │
└─────────────────────────────────────────────────┘

第一层:经典因子库

Alpha158精简版

微软Qlib的Alpha158因子库是业界标准,包含158个量价因子。但完整安装Qlib依赖复杂,我们从Alpha158中提取了最相关的20个因子,直接用pandas计算:

def calc_factors(df: pd.DataFrame) -> pd.DataFrame:
    """从日频OHLCV计算Alpha158精选因子"""
    f = pd.DataFrame(index=df.index)
    c, o, h, l, v = df['close'], df['open'], df['high'], df['low'], df['vol']

    # ---- 动量类 ----
    ema12 = c.ewm(span=12, adjust=False).mean()
    ema26 = c.ewm(span=26, adjust=False).mean()
    dif = ema12 - ema26
    dea = dif.ewm(span=9, adjust=False).mean()
    f['macd'] = dif - dea

    delta = c.diff()
    gain = delta.where(delta > 0, 0).rolling(14).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(14).mean()
    rs = gain / loss.replace(0, np.nan)
    f['rsi_14'] = 100 - 100 / (1 + rs)

    f['roc_5'] = c.pct_change(5)
    f['roc_10'] = c.pct_change(10)
    f['roc_20'] = c.pct_change(20)

    # ---- 波动率类 ----
    ret = c.pct_change()
    f['volatility_5'] = ret.rolling(5).std() * np.sqrt(252)
    f['volatility_10'] = ret.rolling(10).std() * np.sqrt(252)
    f['volatility_20'] = ret.rolling(20).std() * np.sqrt(252)

    # ATR
    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

    # ---- 成交量类 ----
    f['vol_ma_5'] = v.rolling(5).mean()
    f['vol_ma_20'] = v.rolling(20).mean()
    f['vol_ratio'] = f['vol_ma_5'] / f['vol_ma_20'].replace(0, np.nan)

    # OBV
    obv_dir = np.sign(c.diff())
    f['obv'] = (obv_dir * v).cumsum()

    # 量价相关
    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

可转债五维因子体系

可转债因子比股票复杂——它同时具有债性和股性。我们设计了5大类36个因子:

因子类别因子数量代表因子核心逻辑
技术面13个价格位置、波动率CV、网格潜力从OHLCV提取的量价信号
信用面7个转股溢价率、纯债价值、债底距离可转债特有的定价因子
正股因子10个正股动量、正股波动率、CB对正股Beta正股驱动的转债信号
组合因子5个低溢价高动量、深度价值、波动率套利多因子合成
定价因子1个BS错误定价Black-Scholes模型定价偏差

其中BS错误定价因子特别有趣——用Black-Scholes期权定价模型计算可转债内含期权部分的”理论价值”,与市场价格比较,发现系统性低估/高估:

from bs_pricing_factor import compute_bs_mispricing, load_maturity_cache

# BS定价因子:正=市场低估,负=市场高估
# 利用可转债的期权属性,用BS模型反推隐含波动率,
# 与历史波动率比较,发现定价偏差

第二层:LLM驱动的因子进化

这是整个引擎的核心创新——让LLM扮演量化研究员,自动提出因子假设、编写因子代码、接受评估反馈、然后改进

7级Agent层次

借鉴CogAlpha论文Section 3.1,我们定义了7个层次21个领域专家Agent:

层级名称Agent数量探索方向
Level I市场结构与周期2长周期相位转移、波动率状态切换
Level II极端风险与脆弱性2尾部风险暴露、崩溃早期预警
Level III量价动力学4流动性、订单不平衡、量价一致性
Level IV价格-波动行为3波动率曲面、GARCH效应
Level V多尺度特征4跨时间尺度因子(微观/中观/宏观)
Level VI稳定性与持续性3因子衰减速度、信号持续性
Level VII几何与拓扑融合3非线性组合、曲面几何特征

每个Agent都有专属的Prompt模板:

SEVEN_LEVEL_HIERARCHY = {
    1: {
        "name": "Level I: 市场结构与周期",
        "agents": [
            {"id": "AgentMarketCycle", "description": "长周期相位转移与结构性拐点"},
            {"id": "AgentVolatilityRegime", "description": "平静与波动状态切换检测"},
        ],
        "prompt_template": """你是一个量化因子发现Agent,专注于{level_name}
你的探索方向: {agent_desc}

从5分钟OHLCV数据中,设计一个可计算的可转债因子函数。
因子的核心逻辑应围绕{agent_desc}
函数接收DataFrame(df)包含: datetime, open, high, low, close, volume。
函数返回一个pandas Series(因子值序列)。

请输出:
1. 因子名称和公式
2. 完整的Python函数代码
3. 因子逻辑的经济学/金融学解释
4. 预期预测方向(正/负)及原因"""
    },
    # ... Level II ~ VII 类似
}

遗传进化流程

初始Alpha池 (80个候选)


   ┌─────────┐
   │ 五维评估 │ ─── IC / RankIC / ICIR / RankICIR / MI
   └────┬────┘


   ┌─────────┐
   │ 分级筛选 │ ─── Qualified (65th percentile)
   │         │ ─── Elite (80th percentile, Top2保留到下一代)
   └────┬────┘


   ┌─────────┐
   │ 遗传变异 │ ─── Mutation: LLM对单个因子改写
   │         │ ─── Crossover: LLM对两个因子交叉融合
   └────┬────┘


   ┌─────────┐
   │ 多样化引导 │ ─── light / moderate / creative / divergent / concrete
   └────┬────┘


    新一代Alpha池 → 进入下一轮进化

关键配置参数:

COGALPHA_CONFIG = {
    "qualified_percentile": 65,       # Qualified ≥ 65th percentile
    "elite_percentile": 80,           # Elite ≥ 80th percentile
    "ic_min": 0.005,                  # IC最小绝对值
    "icir_min": 0.05,                 # ICIR最小值
    "elite_carryforward": 2,          # 每代保留Top2精英
    "parent_pool_size": 32,           # 父代池容量
    "generations": 24,                # 进化代数
    "diversified_modes": ["light", "moderate", "creative", "divergent", "concrete"],
    "generation_temps": [0.7, 0.8, 0.9, 1.0, 1.1, 1.2],
}

LLM生成因子代码

我们用DeepSeek/GLM API让LLM直接生成可执行的Python因子代码:

def create_llm_generator():
    """创建LLM因子生成器"""
    creds = get_credentials()  # 优先DeepSeek, fallback GLM
    client = OpenAI(api_key=creds["api_key"], base_url=creds["base_url"])

    def generate(prompt: str) -> Optional[str]:
        resp = client.chat.completions.create(
            model=creds["model"],
            messages=[
                {"role": "system", "content": "你是一个专业的量化因子发现Agent。"
                 "你从OHLCV数据中设计有经济解释的Alpha因子。"},
                {"role": "user", "content": prompt},
            ],
            temperature=0.8,
            max_tokens=8192,
            timeout=180,
        )
        content = resp.choices[0].message.content

        # 提取Python代码块
        code_match = re.search(r"```python\n(.*?)```", content, re.DOTALL)
        if code_match:
            return code_match.group(1).strip()
        return content.strip()

    return generate

Mutation与Crossover

遗传算法的两大操作:

  • Mutation(变异):LLM对单个因子进行改写,比如将简单移动平均替换为指数加权,或加入成交量条件
  • Crossover(交叉):LLM将两个因子的逻辑融合,比如将波动率因子与动量因子结合

每代进化时,有效因子和无效因子的分析摘要会注入到下一代的生成Prompt中,让LLM”学习”什么方向有效:

# 自适应学习:将历史经验注入Prompt
effective_summary = f"""
基于前{generation}代进化结果:
- 有效方向: {top_factors} (IC>0.03)
- 无效方向: {failed_factors} (IC<0.01)
- 共性特征: {common_patterns}

请在新的方向上探索,避免重复无效的因子构造方式。
"""

第三层:五维评估体系

传统因子评估只看IC(信息系数),CogAlpha提出五维评估:

def compute_five_metrics(factor_values, returns) -> dict:
    """CogAlpha五维评估: IC, RankIC, ICIR, RankICIR, MI"""
    from scipy.stats import spearmanr, pearsonr

    vals = np.asarray(factor_values, dtype=float)
    rets = np.asarray(returns, dtype=float)
    mask = ~(np.isnan(vals) | np.isnan(rets))
    vals, rets = vals[mask], rets[mask]

    if len(vals) < 10:
        return {"ic": 0, "rankic": 0, "icir": 0, "rankicir": 0, "mi": 0}

    # 1. IC: Pearson线性相关
    ic, _ = pearsonr(vals, rets)

    # 2. RankIC: Spearman秩相关(对异常值更鲁棒)
    rankic, _ = spearmanr(vals, rets)

    # 3 & 4. ICIR / RankICIR: 时间序列上的稳定性
    # (需要按日期分组计算每日IC的均值/标准差)

    # 5. MI: 互信息(捕捉非线性关系)
    from sklearn.feature_selection import mutual_info_regression
    mi = mutual_info_regression(
        vals.reshape(-1, 1), rets,
        random_state=42, n_neighbors=3
    )[0]

    return {"ic": ic, "rankic": rankic, "icir": icir,
            "rankicir": rankicir, "mi": mi}
指标计算方式捕捉的关系阈值
ICPearson相关线性相关性≥ 0.005
RankICSpearman秩相关单调关系(对异常值鲁棒)≥ 0.005
ICIRmean(IC) / std(IC)IC的时间序列稳定性≥ 0.05
RankICIRmean(RankIC) / std(RankIC)RankIC的稳定性≥ 0.05
MI互信息非线性关系≥ 0.02

分级机制

不是所有因子都能通过——CogAlpha采用百分位分级:

  • Qualified(合格):五维指标全部超过65th percentile + 绝对值门槛
  • Elite(精英):超过80th percentile + 更高绝对值门槛,Top2精英自动保留到下一代

这个机制确保了因子池的质量随进化代数递增,而不是被平庸因子稀释。

股票因子挖掘:CSI300/CSI500

除了可转债,我们还针对股票市场搭建了独立的因子挖掘引擎:

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

    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()
    con.close()

    df['ret'] = df.groupby('code')['close'].pct_change()
    df['vwap'] = df['amount'] / (df['volume'] * 100 + 1e-10)
    return df

评估配置针对股票市场做了调整——前向收益周期从1天到20天,每日最少50只股票才计算截面IC:

EVAL_CONFIG = {
    'forward_periods': [1, 3, 5, 10, 20],
    'ic_min': 0.005,
    'icir_min': 0.05,
    'qualified_pct': 65,
    'elite_pct': 80,
    'min_stocks_per_day': 50,
}

ML因子预测

在因子挖掘的基础上,我们还搭建了ML因子预测Pipeline,用机器学习模型预测哪些因子在当前市场环境下更有效:

MODELS = {
    'Ridge': Ridge(alpha=1.0),
    'Lasso': Lasso(alpha=0.1),
    'RandomForest': RandomForestRegressor(
        n_estimators=200, max_depth=5, min_samples_leaf=5, random_state=42
    ),
    'GradientBoosting': GradientBoostingRegressor(
        n_estimators=200, max_depth=4, learning_rate=0.05,
        min_samples_leaf=5, subsample=0.8, random_state=42
    ),
    'MLP': MLPRegressor(
        hidden_layer_sizes=(64, 32, 16),  # 类似ResNet的深层结构
        activation='relu', solver='adam',
        max_iter=1000, early_stopping=True,
        validation_fraction=0.2, random_state=42
    ),
}

使用Walk-Forward验证而非简单train/test split,避免过拟合。核心思想:只用历史数据训练,预测未来

认知Alpha引擎:LLM情绪分析

除了量价因子,我们还扩展到了文本因子——利用LLM分析新闻和研报的情绪,构建情绪因子:

class SentimentAnalyzer:
    def __init__(self):
        self.creds = get_credentials()
        self.client = OpenAI(
            api_key=self.creds['api_key'],
            base_url=self.creds.get('base_url')
        )
        self.model = self.creds.get('model', 'glm-5.1')

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

当LLM不可用时,自动降级到关键词情绪分析,确保系统始终可用。

实战效果

因子挖掘结果

在实际运行中,系统从988只可转债的5分钟数据中:

  • 初始因子池:80个经典因子(技术面+信用面+正股+组合+定价)
  • LLM进化:3代进化,每代生成32个子代因子
  • 有效因子:IC ≥ 0.03的因子约占15-20%
  • 精英因子:IC ≥ 0.05且ICIR ≥ 0.3约占5%

因子有效性验证

对7个经典因子做8个季度截面的Spearman IC检验:

因子IC均值ICIR方向一致性有效性
非流动性(Amihud)+0.116+1.0688%✅ 有效
5日最大跌幅(反转)+0.109+0.6988%✅ 有效
20日动量(追涨)-0.082-0.9225%❌ 反向
20日波动率-0.150-0.8725%❌ 反向

这个结果验证了一个重要结论:可转债市场存在显著的反转效应,而动量效应是反向的(追涨反而亏钱)。

5个实战避坑

1. LLM生成的代码有30%直接不可运行

LLM生成的因子代码中,约30%有语法错误或调用了不存在的pandas方法。解决方案是加入Multi-Agent质量检查器:

# 质量检查流水线
# Step 1: 语法检查 → exec() 能否通过
# Step 2: 逻辑检查 → 输入测试数据,看是否返回有效Series
# Step 3: 修复 → 如果有bug,让另一个LLM尝试修复
# Step 4: 执行评估 → 通过的因子进入五维评估

2. 互信息(MI)计算极慢

sklearn的mutual_info_regression在数据量大时极慢(单次计算>30秒)。建议先用IC/RankIC快速筛选,只对通过初筛的因子计算MI。

3. 温度参数影响因子多样性

temperature=0.7时LLM生成的因子高度雷同,temperature=1.2时因子创意丰富但质量下降。我们的经验是6个温度轮流采样(0.7~1.2),每个温度生成5-10个因子。

4. 精英保留(Elite Carryforward)防止退化

不加精英保留时,进化3代后因子池质量开始下降(优秀因子被平庸因子稀释)。保留Top2精英到下一代是必要的。

5. 前向收益计算容易引入未来函数

计算因子值时用的是当前bar的数据,计算前向收益时用的是未来bar的收益。如果两者使用了同一根bar的close价格,就会引入look-ahead bias。正确做法是因子值用t-1 bar,前向收益从t bar开始计算

总结

维度传统人工CogAlpha LLM挖掘
因子发现速度20-50个/年100+个/天
因子多样性受研究员经验限制7级21个Agent覆盖全维度
因子质量依赖人工审核五维评估+百分位分级
迭代速度人工修改→回测→验证遗传进化自动迭代
成本研究员年薪API调用费约10元/代

核心启示:LLM不会直接给你赚钱的因子,但它能帮你快速探索因子空间,发现你可能从未想到的因子构造方式。最终决定因子是否有效的,还是五维评估和严格的回测验证。


本文所有代码均来自实际运行的因子挖掘引擎,完整源码可在GitHub仓库查看。

延伸阅读

💬 评论