A 股量化进阶:机器学习因子与高频策略 (2026-04-30)
核心目标:在传统多因子模型基础上,引入机器学习方法和另类数据源,提升 A 股量化策略的预测能力。
一、机器学习在 A 股量化中的应用
1.1 因子挖掘的 ML 方法
传统因子 vs ML 因子
| 维度 | 传统因子 | ML 因子 |
|---|---|---|
| 构建方式 | 人工设计 (PE/PB/ROE) | 自动发现 (神经网络/树模型) |
| 因子数量 | 10-50 个 | 100-1000+ 个 |
| 非线性关系 | 难捕捉 | 自动捕捉 |
| 过拟合风险 | 低 | 高 (需正则化) |
| 可解释性 | 高 | 低 (黑盒) |
LightGBM/XGBoost 因子挖掘
import lightgbm as lgb
import pandas as pd
import numpy as np
# 特征工程: 构建原始因子池
def build_factor_pool(df):
"""构建 200+ 原始因子"""
factors = pd.DataFrame(index=df.index)
# 量价因子
factors['return_1d'] = df['close'].pct_change(1)
factors['return_5d'] = df['close'].pct_change(5)
factors['return_20d'] = df['close'].pct_change(20)
factors['volatility_20d'] = df['close'].pct_change().rolling(20).std()
# 成交量因子
factors['vol_ratio'] = df['volume'] / df['volume'].rolling(20).mean()
factors['vol_ma_ratio'] = df['volume'].rolling(5).mean() / df['volume'].rolling(20).mean()
factors['amount_ma_ratio'] = df['amount'].rolling(5).mean() / df['amount'].rolling(20).mean()
# 技术指标因子
factors['rsi_14'] = compute_rsi(df['close'], 14)
factors['macd'] = compute_macd(df['close'])
factors['boll_width'] = compute_bollinger_width(df['close'], 20)
# 横截面因子 (行业中性化)
factors = industry_neutralize(factors, df['industry_code'])
# 市值中性化
factors = market_cap_neutralize(factors, df['total_mv'])
return factors
# 市值中性化
factors = market_cap_neutralize(factors, df['total_mv'])
return factors# LightGBM 训练
def train_lgb_factor_model(X_train, y_train, X_valid, y_valid):
"""训练 LightGBM 预测下期收益率排名"""
params = {
'objective': 'regression',
'metric': 'ic', # 信息系数
'boosting_type': 'gbdt',
'num_leaves': 31,
'learning_rate': 0.05,
'feature_fraction': 0.8,
'bagging_fraction': 0.8,
'bagging_freq': 5,
'reg_alpha': 0.1,
'reg_lambda': 0.1,
'min_child_samples': 100,
'verbose': -1,
}
train_data = lgb.Dataset(X_train, label=y_train)
valid_data = lgb.Dataset(X_valid, label=y_valid, reference=train_data)
model = lgb.train(
params,
train_data,
num_boost_round=500,
valid_sets=[valid_data],
callbacks=[lgb.early_stopping(50), lgb.log_evaluation(100)]
)
return model
# 模型评估: IC/IR
def compute_ic_ir(predictions, actual_returns):
"""计算信息系数和信息比率"""
ic_series = []
for date in predictions.index.get_level_values(0).unique():
pred = predictions.loc[date]
actual = actual_returns.loc[date]
ic = pred.corr(actual, method='spearman')
ic_series.append(ic)
ic_mean = np.mean(ic_series)
ic_std = np.std(ic_series)
icir = ic_mean / ic_std if ic_std > 0 else 0
return {
'IC_mean': ic_mean,
'IC_std': ic_std,
'ICIR': icir,
'IC>0.03_pct': np.mean(np.abs(ic_series) > 0.03) * 100,
}
1.2 深度学习因子模型
': icir, 'IC>0.03_pct': np.mean(np.abs(ic_series) > 0.03) * 100, }
### 1.2 深度学习因子模型#### LSTM/GRU 时序预测
```python
import torch
import torch.nn as nn
class StockLSTM(nn.Module):
"""基于 LSTM 的股票收益率预测模型"""
def __init__(self, input_dim=50, hidden_dim=128, num_layers=2):
super().__init__()
self.lstm = nn.LSTM(
input_size=input_dim,
hidden_size=hidden_dim,
num_layers=num_layers,
batch_first=True,
dropout=0.3
)
self.fc = nn.Sequential(
nn.Linear(hidden_dim, 64),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(64, 1)
)
def forward(self, x):
# x: (batch, seq_len, features)
lstm_out, _ = self.lstm(x)
# 取最后一个时间步
last_hidden = lstm_out[:, -1, :]
return self.fc(last_hidden).squeeze(-1)
# 训练策略
# 1. 滚动窗口训练 (避免未来信息泄露)
# 2. 每 60 个交易日 retrain 一次
# 3. 使用 purged k-fold 交叉验证
Transformer 因子模型
# TabTransformer: 表格数据的 Transformer
# 适合处理异构因子 (量价+财务+另类数据)
# TabNet: 可解释的深度学习模型
# 自动特征选择,输出特征重要性
# 推荐方案:
# 短周期 (1-5 日): LSTM/GRU (时序建模)
# 中周期 (5-20 日): LightGBM/XGBoost (因子组合)
# 长周期 (20+ 日): TabNet (可解释深度学习)
二、另类数据因子
2.1 新闻舆情因子
二、另类数据因子
2.1 新闻舆情因子
# 新闻情绪分析
from transformers import pipeline# 使用中文财经情感模型
sentiment_analyzer = pipeline(
"sentiment-analysis",
model="uer/roberta-base-finetuned-jd-binary-chinese"
)
def compute_news_sentiment(news_list):
"""计算新闻情绪得分"""
scores = []
for news in news_list:
result = sentiment_analyzer(news['title'] + news['content'][:200])
label = result[0]['label']
score = result[0]['score']
scores.append(1 if label == 'positive' else -1 * score)
return np.mean(scores) if scores else 0
# 新闻情绪因子构建:
# 1. 抓取当日所有新闻
# 2. 计算股票级情绪得分
# 3. 横截面标准化
# 4. 作为因子输入模型
2.2 社交媒体因子
# 东方财富股吧/雪球情绪因子
# 关注指标:
# - 帖子数量 (关注度)
# - 正面/负面情绪比
# - 大 V 观点聚合
# - 散户情绪指数
def compute_social_sentiment(stock_code, date):
"""计算社交媒体情绪因子"""
# 伪代码:
# 1. 爬取当日股吧/雪球帖子
# 2. NLP 情感分析
# 3. 聚合情绪得分
# 4. 标准化到 [-1, 1]
pass
# 因子有效性:
# 散户极度乐观 → 反向指标 (短期见顶)
# 散户极度悲观 → 反向指标 (短期见底)
# 大 V 一致看好 → 趋势延续
2.3 资金流向因子
# 北向资金因子
import akshare as ak
def compute_north_flow_factor(date):
"""计算北向资金因子"""
# 获取北向资金数据
north_data = ak.stock_hsgt_north_net_flow_in_em(symbol="北上")
# 因子计算:
# 1. 当日净流入/总市值
# 2. 5 日累计净流入
# 3. 北向资金持股变化率
# 4. 北向 vs 南向资金差
return factors
# 主力资金因子
def compute_main_money_factor(date):
"""计算主力资金流向因子"""
# 超大单净流入
# 大单净流入
# 中单净流入
# 小单净流入 (散户)
# 因子: (超大单 + 大单) / 总成交额
# 因子: 超大单 - 小单 (主力散户差)
pass
三、组合优化与风险控制
小单净流入 (散户)
# 因子: (超大单 + 大单) / 总成交额
# 因子: 超大单 - 小单 (主力散户差)
pass
```
三、组合优化与风险控制### 3.1 组合构建
python
import cvxpy as cp
def construct_portfolio(predicted_returns, covariance, constraints=None):
"""均值-方差优化"""
n_assets = len(predicted_returns)
w = cp.Variable(n_assets)
# 目标: 最大化风险调整后收益
gamma = 1.0 # 风险厌恶系数
objective = cp.Maximize(
w.T @ predicted_returns - gamma * cp.quad_form(w, covariance)
)
# 约束
constraints = [
cp.sum(w) == 1, # 全仓
w >= 0, # 不做空
w <= 0.1, # 单票上限 10%
w >= -0.001, # 允许微量做空 (数值稳定)
]
# 行业中性约束
# sector_exposure = sector_matrix.T @ w
# constraints += [sector_exposure == benchmark_sector_weights]
problem = cp.Problem(objective, constraints)
problem.solve()
return w.value
3.2 风险模型
# Barra 风险模型 (A 股适配)
def compute_risk_factors(portfolio_weights, factor_returns):
"""计算组合风险暴露"""
# 风格因子暴露:
# - Size (市值)
# - Beta (市场敏感度)
# - Momentum (动量)
# - Volatility (波动率)
# - Liquidity (流动性)
# - Growth (成长性)
# - Value (价值)
# 行业因子暴露:
# 申万一级行业权重
# 风险分解:
# 总风险 = 因子风险 + 特异性风险
# 因子风险 = w' * F * Cov(F) * F' * w
# 特异性风险 = w' * Cov(epsilon) * w
pass
pass
### 3.3 回撤控制python
def drawdown_control(positions, nav_history, max_drawdown=0.15):
"""最大回撤控制"""
current_nav = nav_history[-1]
peak_nav = max(nav_history)
current_dd = (peak_nav - current_nav) / peak_nav
if current_dd > max_drawdown * 0.8:
# 接近最大回撤阈值,减仓 50%
return positions * 0.5
elif current_dd > max_drawdown:
# 超过最大回撤阈值,清仓
return positions * 0.0
return positions
```
四、高频策略入门
4.1 订单簿分析
# Level-2 订单簿因子
def compute_orderbook_factors(orderbook):
"""从订单簿提取因子"""
bids = orderbook['bids'] # 买盘
asks = orderbook['asks'] # 卖盘
# 买卖压力比
bid_volume = sum(v for p, v in bids[:5])
ask_volume = sum(v for p, v in asks[:5])
pressure_ratio = bid_volume / (bid_volume + ask_volume)
# 买卖价差
spread = asks[0][0] - bids[0][0]
spread_pct = spread / bids[0][0]
# 订单簿斜率
bid_slope = compute_slope(bids[:10])
ask_slope = compute_slope(asks[:10])
return {
'pressure_ratio': pressure_ratio,
'spread_pct': spread_pct,
'bid_slope': bid_slope,
'ask_slope': ask_slope,
}
4.2 统计套利
4.2 统计套利
```python# 配对交易 def find_pairs(prices, threshold=0.8): """寻找协整配对""" from statsmodels.tsa.stattools import coint
pairs = []
stocks = prices.columns
for i in range(len(stocks)):
for j in range(i+1, len(stocks)):
score, pvalue, _ = coint(prices[stocks[i]], prices[stocks[j]])
if pvalue < 0.05:
pairs.append((stocks[i], stocks[j], pvalue))
return sorted(pairs, key=lambda x: x[2])
def pair_trade_signal(price_a, price_b, window=60, entry_z=2.0, exit_z=0.5): """配对交易信号""" spread = price_a - price_b z_score = (spread - spread.rolling(window).mean()) / spread.rolling(window).std()
if z_score.iloc[-1] > entry_z:
return "SHORT_A_LONG_B"
elif z_score.iloc[-1] < -entry_z:
return "LONG_A_SHORT_B"
elif abs(z_score.iloc[-1]) < exit_z:
return "CLOSE"
return "HOLD"
```
五、回测框架选择
5.1 主流框架对比
| 框架 | 语言 | 特点 | 适用场景 |
|---|---|---|---|
| Backtrader | Python | 成熟稳定,社区大 | 中低频策略 |
| vn.py | Python | 国内生态好,实盘支持 | A 股实盘 |
| Zipline | Python | Quantopian 遗产 | 研究 |
| Qlib | Python | 微软出品,AI 优化 | 机器学习策略 |
| 自研 | Python | 完全定制 | 复杂策略 |
| ### 5.2 Qlib 推荐 (AI 策略) | |||
| ```python | |||
| # Qlib: 微软量化 AI 平台 | |||
| # 优势: | |||
| # 1. 内置多种 AI 模型 (LightGBM, LSTM, Transformer) | |||
| # 2. 自动化因子挖掘 | |||
| # 3. 回测+模拟交易一体化 | |||
| # 4. A 股数据源支持 | |||
| from qlib.contrib.model.gbtrees import LGBModel | |||
| from qlib.workflow import R | |||
| 测+模拟交易一体化 | |||
| # 4. A 股数据源支持 | |||
| from qlib.contrib.model.gbtrees import LGBModel | |||
| from qlib.workflow import R# 配置 | |||
| provider_uri = "~/.qlib/qlib_data/cn_data" | |||
| qlib.init(provider_uri=provider_uri, region="cn") | |||
| # 训练 | |||
| model = LGBModel( | |||
| loss="mse", | |||
| colsample_bytree=0.8879, | |||
| learning_rate=0.0421, | |||
| subsample=0.8789, | |||
| lambda_l1=205.6999, | |||
| lambda_l2=580.9768, | |||
| max_depth=8, | |||
| num_leaves=210, | |||
| num_threads=20, | |||
| ) | |||
| model.fit(dataset) | |||
| prediction = model.predict(dataset) | |||
| ``` |
六、策略评估指标
6.1 核心指标
年化收益率 = (期末净值/期初净值)^(252/N) - 1
最大回撤 = max((峰值 - 谷值) / 峰值)
夏普比率 = (年化收益 - 无风险利率) / 年化波动率
索提诺比率 = (年化收益 - 无风险利率) / 下行波动率
卡尔玛比率 = 年化收益 / 最大回撤
信息比率 (ICIR) = IC_mean / IC_std
胜率 = 盈利交易数 / 总交易数
盈亏比 = 平均盈利 / 平均亏损
6.2 评估阈值
优秀策略标准 (A 股日线):
- 年化收益 > 20%
- 最大回撤 < 20%
- 夏普比率 > 1.0
- 卡尔玛比率 > 1.0
- IC_mean > 0.03
- ICIR > 0.5
- 胜率 > 50%
七、避坑指南
常见陷阱
- 未来函数: 使用了未来才知道的信息 → 严格时间对齐
- 幸存者偏差: 只用了存活的股票 → 包含退市股票
- 过拟合: 参数过多 → 使用 out-of-sample 测试
- 滑点忽略: 实际交易有冲击成本 → 加入滑点模型
- 涨跌停忽略: A 股有涨跌停限制 → 无法成交的需剔除
- 手续费忽略: 高频交易手续费影响大 → 双边 0.15% 起
- 因子共线性: 多个因子高度相关 → 先做因子正交化
最后更新: 2026-04-30 | 来源: Qlib 文档、券商金工研报、CSDN 量化专栏 风险等级: 所有量化策略存在亏损风险,历史回测不代表未来表现 免责声明: 本内容仅供学习研究,不构成投资建议