首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >AI量化投资:从数据到策略的完整实战指南

AI量化投资:从数据到策略的完整实战指南

原创
作者头像
用户12339161
修改2026-07-29 11:15:18
修改2026-07-29 11:15:18
1440
举报

AI量化投资:从数据到策略的完整实战指南

当深度学习遇上金融时序,会碰撞出怎样的火花?本文带你从零构建一套完整的AI量化交易系统,涵盖数据清洗、特征工程、LSTM预测、强化学习交易及回测评估,并深入探讨实战中的“坑”与对策。


引言:为什么需要AI量化?

传统量化策略依赖人工设计的因子(如均线、MACD、RSI等)和线性模型,但金融市场具有高噪声、非平稳、非线性等特点,简单规则往往难以捕捉复杂模式。人工智能,尤其是深度学习,能够自动从海量数据中提取高阶特征,并适应市场结构的变化。

然而,AI量化绝不是“调参即可印钞”,它面临过拟合、生存偏差、交易成本等严峻挑战。本文力求客观,既展示技术路径,也揭示风险,希望对有志于AI量化的开发者提供一份可落地的参考。


一、AI量化的核心要素

一个完整的AI量化系统包含四个层次:

层次

内容

技术手段

数据层

行情、财报、舆情、另类数据

爬虫、API、数据仓库

特征层

因子构建、降维、归一化

PCA、标准化、时序特征提取

模型层

预测或决策模型

XGBoost、LSTM、Transformer、DQN

执行层

信号生成、风险控制、下单

回测引擎、实盘接口、止损止盈

本文聚焦于模型层与执行层,以股票日频数据为例,完整走一遍流程。


二、数据获取与预处理

我们使用akshare(免费)获取A股历史数据,当然也可用yfinance。以贵州茅台(600519)为例。

代码语言:javascript
复制
import akshare as ak
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore')

# 获取股票日线数据
stock_code = "600519"
df = ak.stock_zh_a_hist(symbol=stock_code, period="daily", start_date="2015-01-01", end_date="2025-01-01", adjust="qfq")
df.columns = ['date', 'open', 'close', 'high', 'low', 'volume', 'amount', 'amplitude', 'pct_change', 'change', 'turnover']
df['date'] = pd.to_datetime(df['date'])
df.sort_values('date', inplace=True)
df.reset_index(drop=True, inplace=True)

# 检查缺失
print(df.isnull().sum())
# 使用前复权价格,已包含分红除权调整

# 可视化
plt.figure(figsize=(12,5))
plt.plot(df['date'], df['close'], label='Close Price')
plt.title('Moutai (600519) Close Price')
plt.legend()
plt.show()

预处理要点

  • 前复权处理(akshare已支持)
  • 处理停牌:用前值填充(ffill)或剔除
  • 异常值:基于3-sigma或IQR剔除
  • 归一化:对特征使用StandardScalerMinMaxScaler,注意避免未来信息。

三、特征工程:构建多维度因子

AI模型需要输入特征,我们构建三类因子:

  1. 技术因子:动量、波动率、成交量、RSI、MACD等。
  2. 统计因子:历史分位数、最大回撤、偏度峰度。
  3. 宏观/情绪因子:可外接如北向资金、市场换手率(本文简化)。

我们手动计算常用因子,避免依赖TA-Lib(减少环境问题)。

代码语言:javascript
复制
def add_technical_features(df):
    # 收益率
    df['return_1d'] = df['close'].pct_change()
    df['return_5d'] = df['close'].pct_change(5)
    df['return_20d'] = df['close'].pct_change(20)
    
    # 波动率 (滚动标准差)
    df['volatility_5d'] = df['return_1d'].rolling(5).std()
    df['volatility_20d'] = df['return_1d'].rolling(20).std()
    
    # 成交量比率
    df['volume_ratio'] = df['volume'] / df['volume'].rolling(20).mean()
    
    # RSI (14天)
    delta = df['close'].diff()
    gain = (delta.where(delta > 0, 0)).rolling(14).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(14).mean()
    rs = gain / loss
    df['rsi_14'] = 100 - (100 / (1 + rs))
    
    # MACD (快速12, 慢速26, 信号9)
    exp1 = df['close'].ewm(span=12, adjust=False).mean()
    exp2 = df['close'].ewm(span=26, adjust=False).mean()
    df['macd'] = exp1 - exp2
    df['macd_signal'] = df['macd'].ewm(span=9, adjust=False).mean()
    df['macd_hist'] = df['macd'] - df['macd_signal']
    
    # 价格位置 (当前价在20日区间的位置)
    high_20 = df['high'].rolling(20).max()
    low_20 = df['low'].rolling(20).min()
    df['price_position'] = (df['close'] - low_20) / (high_20 - low_20 + 1e-6)
    
    return df

df = add_technical_features(df)
# 删除前面因滚动产生的NaN
df.dropna(inplace=True)
print(df.shape)

四、模型选择:从传统ML到深度学习

模型

优点

缺点

适用场景

线性回归/逻辑回归

可解释性强

非线性捕捉弱

低噪声、稳定市场

随机森林/XGBoost

非线性、特征重要性

无法处理时序依赖

因子组合、分类预测

LSTM/GRU

捕捉长期时序依赖

训练慢、易过拟合

价格/波动率预测

Transformer

并行、长程依赖

数据量大、参数多

高频/多模态数据

强化学习 (DQN/PPO)

直接优化收益-风险

环境不稳定、收敛难

动态仓位管理

本文选择:LSTM进行价格方向预测(二分类:涨/跌),并基于预测结果生成交易信号。


五、实战:基于LSTM的日频交易策略

5.1 准备监督学习样本

我们预测未来一天的涨跌方向(label = 1 if return_1d_shift > 0 else 0)。使用前N天的特征序列作为输入。

代码语言:javascript
复制
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping

# 选取特征列
feature_cols = ['return_1d', 'return_5d', 'return_20d', 'volatility_5d', 'volatility_20d',
                'volume_ratio', 'rsi_14', 'macd', 'macd_signal', 'macd_hist', 'price_position']

# 标签:次日收益率正负
df['target'] = (df['return_1d'].shift(-1) > 0).astype(int)

# 去掉标签为NaN的行(最后一天)
df_model = df.dropna(subset=['target']).copy()

# 归一化特征
scaler = StandardScaler()
X_scaled = scaler.fit_transform(df_model[feature_cols])

# 构建时序样本:用过去WINDOW天的数据预测下一天
WINDOW = 20  # 回溯天数
X_seq, y_seq = [], []
for i in range(WINDOW, len(df_model) - 1):  # 保留第i+1天作为标签 (已有target)
    X_seq.append(X_scaled[i-WINDOW:i])
    y_seq.append(df_model['target'].iloc[i])  # 注意:target是当天对第二天的预测,所以i对应的target已经是对i+1的预测

X_seq = np.array(X_seq)
y_seq = np.array(y_seq)

print(f"X shape: {X_seq.shape}, y shape: {y_seq.shape}")

# 划分训练集(80%)、验证集(10%)、测试集(10%)按时间顺序
split1 = int(len(X_seq) * 0.8)
split2 = int(len(X_seq) * 0.9)
X_train, X_val, X_test = X_seq[:split1], X_seq[split1:split2], X_seq[split2:]
y_train, y_val, y_test = y_seq[:split1], y_seq[split1:split2], y_seq[split2:]

print(f"Train: {X_train.shape}, Val: {X_val.shape}, Test: {X_test.shape}")

5.2 搭建LSTM模型

代码语言:javascript
复制
model = Sequential()
model.add(LSTM(64, input_shape=(WINDOW, len(feature_cols)), return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(32, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(16, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(optimizer=Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy'])
model.summary()

# 早停
early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)

history = model.fit(X_train, y_train, epochs=100, batch_size=32, 
                    validation_data=(X_val, y_val), callbacks=[early_stop], verbose=1)

5.3 预测与信号生成

代码语言:javascript
复制
# 在测试集上预测概率
y_pred_prob = model.predict(X_test).flatten()
y_pred_class = (y_pred_prob > 0.5).astype(int)

# 计算准确率(作为参考,但不是核心)
from sklearn.metrics import accuracy_score, classification_report
print("Test Accuracy:", accuracy_score(y_test, y_pred_class))
print(classification_report(y_test, y_pred_class))

# 生成交易信号:将概率映射为仓位(阈值可调)
# 简化:预测涨则买入(全仓),预测跌则空仓(或做空,这里仅做多)
signal = np.where(y_pred_prob > 0.55, 1, 0)  # 提高阈值减少交易次数

六、回测评估:收益率、夏普比率、最大回撤

我们使用自定义回测,计算累计收益和风险指标。假设无交易成本(实际需扣除滑点和佣金)。

代码语言:javascript
复制
# 获取测试集对应的日期和真实收益率(用于回测)
test_start = split2 + WINDOW  # 因为X_seq索引偏移
test_dates = df_model.index[test_start:test_start + len(y_pred_prob)]  # 注意对齐

# 实际收益率序列(测试期间每日收益)
test_returns = df_model['return_1d'].iloc[test_start:test_start + len(y_pred_prob)].values

# 策略信号与日期对齐
# signal长度等于预测样本数,但每日收益率数量少一天?仔细检查:
# 我们预测的是第i天的标签(对应第i+1天收益率),所以信号应在第i天收盘后使用,用于第i+1天的交易。
# 简化:信号序列从第i天开始,对应第i+1天的收益
# 构造一个DataFrame
backtest_df = pd.DataFrame({
    'date': df_model['date'].iloc[test_start:test_start + len(y_pred_prob)],
    'return': test_returns,
    'signal': signal
})
# 策略收益 = signal * 当日收益率(因为信号在当天生效,用于当天收盘价买入?实际上信号是预测次日,所以应该用次日收益)
# 更准确:信号在第t天产生,用于第t+1天的收益。
# 所以将信号shift(1)
backtest_df['strategy_return'] = backtest_df['signal'].shift(1) * backtest_df['return']
# 去掉首日NaN
backtest_df.dropna(inplace=True)

# 计算累计收益
backtest_df['cum_return'] = (1 + backtest_df['return']).cumprod()
backtest_df['cum_strategy'] = (1 + backtest_df['strategy_return']).cumprod()

# 计算风险指标
total_return = backtest_df['cum_strategy'].iloc[-1] - 1
annual_return = (1 + total_return) ** (252 / len(backtest_df)) - 1
daily_std = backtest_df['strategy_return'].std()
sharpe_ratio = np.sqrt(252) * daily_std  # 无风险利率为0
# 最大回撤
cum_wealth = backtest_df['cum_strategy']
rolling_max = cum_wealth.expanding().max()
drawdown = (cum_wealth - rolling_max) / rolling_max
max_drawdown = drawdown.min()

print(f"总收益率: {total_return:.2%}")
print(f"年化收益率: {annual_return:.2%}")
print(f"夏普比率: {sharpe_ratio:.3f}")
print(f"最大回撤: {max_drawdown:.2%}")

# 绘图
plt.figure(figsize=(14,6))
plt.plot(backtest_df['date'], backtest_df['cum_strategy'], label='Strategy')
plt.plot(backtest_df['date'], backtest_df['cum_return'], label='Buy & Hold')
plt.title('Backtest Performance')
plt.legend()
plt.grid()
plt.show()

注意:实际回测应加上交易成本(假设千分之三),并考虑滑点。上述代码为简化演示。


七、强化学习交易:DQN初探

与有监督预测不同,强化学习(RL)将交易视为序列决策问题,智能体(Agent)根据当前状态(价格、持仓等)选择动作(买入、卖出、持有),环境返回奖励(收益或夏普)。优点是可以直接优化风险调整后的收益。

下面给出一个极简DQN框架(基于gymtensorflow),仅示意:

代码语言:javascript
复制
import gym
from gym import spaces
from tensorflow.keras import layers, models

class TradingEnv(gym.Env):
    def __init__(self, data, initial_capital=100000):
        super().__init__()
        self.data = data
        self.initial_capital = initial_capital
        self.current_step = 0
        self.action_space = spaces.Discrete(3)  # 0:持有, 1:买入, 2:卖出
        self.observation_space = spaces.Box(low=-np.inf, high=np.inf, shape=(len(feature_cols)+1,), dtype=np.float32)  # 特征+持仓
        
    def reset(self):
        self.current_step = 0
        self.capital = self.initial_capital
        self.position = 0  # 持股数量
        return self._get_obs()
    
    def _get_obs(self):
        features = self.data.iloc[self.current_step][feature_cols].values
        return np.append(features, [self.position])
    
    def step(self, action):
        # 简化:价格变化,执行动作
        # ... 实现买卖逻辑,计算奖励
        pass

实际应用中,RL需要大量训练和稳定环境,且存在过拟合风险,部署难度较高。目前学术界和工业界都在探索,但尚未成为主流。


八、风险与挑战(重点)

1. 过拟合

金融数据信噪比极低(通常小于0.01),复杂模型容易记住噪声。解决方案:

  • 交叉验证、早停、正则化(Dropout、L2)。
  • 样本外检验(时间序列必须按时间划分,不能随机打乱)。
  • 使用简单模型作为基准。

2. 非平稳性

市场风格、波动率、制度都会变化。模型需要定期在线学习或自适应更新。

  • 采用滚动窗口训练(如每月重新训练)。
  • 使用元学习或模型集成提高鲁棒性。

3. 交易成本与流动性

预测准确率即便只有52%,扣除手续费后可能亏损。必须将成本纳入回测。

  • 真实滑点模拟:挂单簿深度、买卖价差。

4. 黑天鹅事件

2020年熔断、2015年股灾等极端行情,AI模型没有经验,容易爆仓。应设置止损线最大仓位限制

5. 数据泄漏

绝对避免使用未来信息,如用未来数据归一化、标签错误等。需严格顺序划分。


九、优化方向与展望

  1. 多模态数据融合:结合新闻情绪(NLP)、宏观经济指标、订单簿数据。
  2. Transformer架构:处理更长序列,捕捉复杂交互。
  3. 元学习(Meta-Learning):快速适应新市场环境。
  4. 因果推断:识别真正驱动价格变动的因素,避免虚假相关。
  5. 联邦学习:保护隐私的前提下共享策略知识。

十、总结

本文从数据获取、特征工程、LSTM预测到回测评估,完整实现了一个AI量化策略。但必须清醒认识到:回测中的高收益往往无法复现,真正的壁垒在于对市场的深刻理解和持续的风险管理。

作为开发者,我们应当将AI视为辅助工具,而非自动取款机。建议从模拟交易开始,逐步完善系统,并始终保持敬畏之心。

所有代码已开源在GitHub(示例地址),欢迎探讨和改进。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • AI量化投资:从数据到策略的完整实战指南
    • 引言:为什么需要AI量化?
    • 一、AI量化的核心要素
    • 二、数据获取与预处理
    • 三、特征工程:构建多维度因子
    • 四、模型选择:从传统ML到深度学习
    • 五、实战:基于LSTM的日频交易策略
      • 5.1 准备监督学习样本
      • 5.2 搭建LSTM模型
      • 5.3 预测与信号生成
    • 六、回测评估:收益率、夏普比率、最大回撤
    • 七、强化学习交易:DQN初探
    • 八、风险与挑战(重点)
      • 1. 过拟合
      • 2. 非平稳性
      • 3. 交易成本与流动性
      • 4. 黑天鹅事件
      • 5. 数据泄漏
    • 九、优化方向与展望
    • 十、总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档