深度学习选股
🧠 深度学习 = 模式识别 + 大数据 —— 找到人眼看不到的统计规律。
🎯 深度学习为什么有效
| 优势 | 说明 |
|---|---|
| 非结构化数据 | 新闻 / 研报 / 图像 |
| 复杂模式 | 因子交互作用 |
| 自动特征 | 不需要人工选因子 |
| 持续学习 | 模型可定期重训 |
📊 主流模型
| 模型 | 适合 | 优点 | 缺点 |
|---|---|---|---|
| MLP | 简单特征 | 训练快 | 难抓时序 |
| CNN | K线形态 | 自动学习形态 | 黑盒 |
| LSTM / GRU | 时序数据 | 长期记忆 | 训练慢 |
| Transformer | 长序列 | 并行训练 | 数据需求大 |
| 图神经网络 | 关系数据 | 行业联动 | 复杂 |
| 强化学习 | 决策 | 持续学习 | 训练不稳 |
📐 1. CNN 时序模式
python
"""
CNN 时序模式识别
适合:K 线形态 / 短期价格模式
"""
import torch
import torch.nn as nn
class CNNStockPredictor(nn.Module):
def __init__(self, n_features=20, seq_len=60, n_classes=3):
super().__init__()
# 输入: (batch, n_features, seq_len)
self.conv1 = nn.Conv1d(n_features, 64, kernel_size=5, padding=2)
self.bn1 = nn.BatchNorm1d(64)
self.pool1 = nn.MaxPool1d(2)
self.conv2 = nn.Conv1d(64, 128, kernel_size=5, padding=2)
self.bn2 = nn.BatchNorm1d(128)
self.pool2 = nn.MaxPool1d(2)
self.conv3 = nn.Conv1d(128, 64, kernel_size=3, padding=1)
self.bn3 = nn.BatchNorm1d(64)
self.global_pool = nn.AdaptiveAvgPool1d(1)
self.fc1 = nn.Linear(64, 32)
self.dropout = nn.Dropout(0.3)
self.fc2 = nn.Linear(32, n_classes)
def forward(self, x):
# x: (batch, n_features, seq_len)
x = self.pool1(torch.relu(self.bn1(self.conv1(x))))
x = self.pool2(torch.relu(self.bn2(self.conv2(x))))
x = torch.relu(self.bn3(self.conv3(x)))
x = self.global_pool(x).squeeze(-1)
x = torch.relu(self.fc1(x))
x = self.dropout(x)
return self.fc2(x)
# 使用
model = CNNStockPredictor(n_features=20, seq_len=60, n_classes=3)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)📐 2. Transformer 选股
python
"""
Transformer 选股
适合:长序列 / 多因子交互
"""
import torch
import torch.nn as nn
import math
class PositionalEncoding(nn.Module):
def __init__(self, d_model, max_len=5000):
super().__init__()
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
self.register_buffer('pe', pe.unsqueeze(0))
def forward(self, x):
return x + self.pe[:, :x.size(1)]
class TransformerStockModel(nn.Module):
def __init__(self, n_features=20, d_model=64, nhead=4, num_layers=3, seq_len=60):
super().__init__()
self.input_proj = nn.Linear(n_features, d_model)
self.pos_encoder = PositionalEncoding(d_model, max_len=seq_len)
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model, nhead=nhead,
dim_feedforward=256, dropout=0.1,
batch_first=True
)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers)
self.fc = nn.Linear(d_model, 1)
def forward(self, x):
# x: (batch, seq_len, n_features)
x = self.input_proj(x)
x = self.pos_encoder(x)
x = self.transformer(x)
return self.fc(x[:, -1, :]) # 取最后时间步
# 训练
model = TransformerStockModel(n_features=20)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.0005)📐 3. 强化学习
python
"""
强化学习选股(DQN)
状态:市场行情
动作:买/卖/持有
奖励:收益
"""
import torch
import torch.nn as nn
import random
from collections import deque
class DQN(nn.Module):
def __init__(self, state_dim, action_dim=3, hidden=64):
super().__init__()
self.net = nn.Sequential(
nn.Linear(state_dim, hidden),
nn.ReLU(),
nn.Linear(hidden, hidden),
nn.ReLU(),
nn.Linear(hidden, action_dim)
)
def forward(self, x):
return self.net(x)
class TradingAgent:
def __init__(self, state_dim, action_dim=3):
self.policy_net = DQN(state_dim, action_dim)
self.target_net = DQN(state_dim, action_dim)
self.target_net.load_state_dict(self.policy_net.state_dict())
self.optimizer = torch.optim.Adam(self.policy_net.parameters(), lr=0.001)
self.memory = deque(maxlen=10000)
self.epsilon = 0.1
def act(self, state):
if random.random() < self.epsilon:
return random.randrange(3)
with torch.no_grad():
return self.policy_net(state).argmax().item()
def remember(self, state, action, reward, next_state, done):
self.memory.append((state, action, reward, next_state, done))
def replay(self, batch_size=32):
if len(self.memory) < batch_size:
return
batch = random.sample(self.memory, batch_size)
# ... 标准 DQN 更新
for state, action, reward, next_state, done in batch:
target = reward + (0.99 * self.target_net(next_state).max() * (1 - done))
current = self.policy_net(state)[action]
loss = nn.functional.mse_loss(current, target)
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()📊 实战建议
📌 模型选择
| 场景 | 推荐 |
|---|---|
| 因子多(20+) | MLP / Transformer |
| 时序明显 | LSTM / Transformer |
| 形态交易 | CNN |
| 多资产配置 | Transformer |
| 决策优化 | 强化学习 |
📌 数据准备
- 数据量大(5+ 年日线)
- 因子质量高
- 标签清晰(5 日收益 > 2%)
- 样本平衡
📌 防止过拟合
- 早停(early stopping)
- Dropout / 正则化
- 样本外测试
- 滚动训练
📖 相关阅读
来源
- 证监会公开公告
- 上交所交易规则
- 深交所 / 北交所规则
- 中国证券业协会(SAC)、中国证券投资基金业协会(AMAC)公开资料
- 国家金融监督管理总局、人社部、财政部、税务总局公开资料
💡 数据截至 2026-08;具体规则以交易所/监管机构最新公告为准。