共计 1933 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
传统选股方法往往依赖人工经验和简单的财务指标,存在几个明显短板:

- 数据噪声大:市场数据包含大量无效或错误信息,比如停牌期间的异常价格、财报数据的修正等
- 特征冗余:原始数据维度高(如上百个财务指标),但有效信息可能只集中在少数几个特征上
- 过拟合严重:在历史数据上表现优异的策略,实盘经常失效,尤其在高频领域更为明显
技术选型
量化选股常用的机器学习框架各有特点:
- Scikit-learn:适合中小规模结构化数据,特征工程工具齐全但 GPU 加速支持有限
- TensorFlow/PyTorch:擅长处理非结构化数据(如图像、文本),但训练成本较高
- LightGBM:基于决策树的梯度提升框架,特别适合我们的场景,因为:
- 自动处理缺失值
- 内置特征重要性评估
- 训练速度快于 XGBoost
- 对类别特征有原生支持
核心实现
数据清洗
使用 Pandas 进行数据预处理的关键步骤:
- 处理缺失值:
- 对于时间序列数据,用前向填充(ffill)
- 对分类特征,用众数填充
-
对连续特征,用行业均值填充
-
异常值处理:
- 3σ 原则剔除极端值
-
对涨停 / 跌停数据单独标记
-
标准化:
- 对基本面数据采用 Z -score 标准化
- 对量价数据采用 MinMax 归一化
特征工程
通过两步降低特征维度:
- 先用互信息法筛选前 30% 的特征
- 再用 PCA 将维度压缩到 10-15 个主成分
注意要分开处理不同市场状态(牛市 / 熊市)的特征分布。
模型训练
LightGBM 的关键参数调优策略:
params = {
'boosting_type': 'gbdt',
'objective': 'binary', # 二分类问题
'metric': 'auc',
'num_leaves': 31, # 从 31 开始调参
'learning_rate': 0.05,
'feature_fraction': 0.9, # 防止过拟合
'bagging_fraction': 0.8,
'min_data_in_leaf': 20
}
采用 Walk-Forward 验证代替简单交叉验证:
- 按时间划分训练集 / 验证集
- 每 3 个月重新训练一次模型
- 保留最后 6 个月数据作为 out-of-sample 测试
完整代码示例
# 数据加载
import pandas as pd
from sklearn.model_selection import TimeSeriesSplit
data = pd.read_csv('stock_data.csv', parse_dates=['date'])
data = data.set_index(['date', 'ticker'])
# 特征工程
from sklearn.feature_selection import mutual_info_classif
X = data.drop('label', axis=1)
y = data['label']
# 互信息筛选
selected_features = mutual_info_classif(X, y, random_state=42)
X = X.iloc[:, selected_features > np.quantile(selected_features, 0.7)]
# PCA 降维
from sklearn.decomposition import PCA
pca = PCA(n_components=15)
X_pca = pca.fit_transform(X)
# 模型训练
import lightgbm as lgb
tscv = TimeSeriesSplit(n_splits=5)
for train_idx, test_idx in tscv.split(X_pca):
lgb_train = lgb.Dataset(X_pca[train_idx], y.iloc[train_idx])
lgb_eval = lgb.Dataset(X_pca[test_idx], y.iloc[test_idx])
gbm = lgb.train(params,
lgb_train,
valid_sets=lgb_eval,
early_stopping_rounds=50)
性能考量
回测与实盘的主要差异来自:
- 市场机制变化(如涨跌停规则调整)
- 交易成本被低估
- 因子失效(特别是技术指标)
防范过拟合的措施:
- 在多个市场周期测试
- 限制单因子最大权重
- 加入随机噪声测试鲁棒性
避坑指南
生产环境中常见问题:
- 数据泄漏:确保特征计算不使用未来数据
- 标签滞后:考虑交易执行延迟(T+ 1 结算)
- 模型衰减:建立定期 retrain 机制
开放性问题
在实际应用中,我们发现几个值得探讨的问题:
- 如何平衡模型复杂度与交易频率?复杂模型可能捕捉更多市场规律,但高频调仓会增加交易成本
- 如何处理不同市场状态下的特征漂移?牛市有效的因子在熊市可能完全失效
- 怎样构建动态的仓位分配策略?单纯的二分类预测如何转化为实际持仓
期待大家在实践中分享自己的解决方案。
正文完
