Skip to content

超越LSTM!TCN模型如何精准预测股市波动(附代码)

作者:老余捞鱼

原创不易,转载请标明出处及原作者。

写在前面的话:最近我用TCN时间卷积网络预测了标普500指数(SPX)的每日回报率,发现效果远超传统方法。TCN通过因果卷积和膨胀卷积捕捉时间序列的长期依赖关系,结合残差连接提升模型性能。这篇文章将带你从数据准备到模型训练,一步步实现金融预测的AI实战。

一、什么是时序卷积网络(TCN)?

时序卷积网络(Temporal Convolutional Network, TCN)是一种用于处理序列数据的深度学习模型。与传统的循环神经网络(RNN)不同,TCN利用卷积操作来捕捉时间序列中的依赖关系。TCN通过因果卷积和扩张卷积的组合,能够有效地处理长序列数据,并且在许多任务中表现出色,如时间序列预测、语音处理和自然语言处理等。

1.1 TCN的基本原理

TCN的核心思想是使用卷积层来替代RNN中的递归结构。其主要特点包括:

  • 因果卷积:确保当前时刻的输出仅依赖于当前及之前的输入,避免未来信息的泄露。
  • 扩张卷积:通过在卷积核之间引入间隔,使得网络能够在不增加计算复杂度的情况下,捕捉更长范围的依赖关系。
  • 残差连接:通过引入残差连接,TCN能够更好地训练深层网络,减轻梯度消失的问题。

上为TCN的简单架构示意图。

1.2 TCN的优点

  • 并行计算:与RNN不同,TCN的卷积操作可以并行计算,显著提高训练速度。
  • 长距离依赖:扩张卷积使得TCN能够有效捕捉长距离的时间依赖关系。
  • 灵活性:TCN可以轻松调整卷积核的大小和扩张因子,以适应不同的序列长度和特征。

1.3 TCN的应用场景

TCN在多个领域得到了广泛应用,包括但不限于:

  • 时间序列预测:如股市预测、气象预测等。
  • 语音识别:处理音频信号中的时间特征。
  • 自然语言处理:用于文本生成和情感分析等任务。

时序卷积网络(TCN)是一种强大的序列建模工具,凭借其独特的卷积结构和高效的训练方式,在处理时间序列数据方面展现了优越的性能。随着深度学习技术的不断发展,TCN有望在更多应用场景中发挥重要作用。

二、TCN的应用实例

下面这个实例将基于标普500指数(SPX)过去15年的历史数据进行模型训练。

为了提高模型的稳定性和预测效果,我们选择使用收益序列而非价格序列,因为收益序列具有更好的静态特性。

此外,在特征工程环节,我们还引入了最近10天的波动率和成交量数据作为补充特征,这些数据能够有效捕捉市场动态,从而进一步提升预测的准确性。

2.1 导入库

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from tensorflow.keras import layers, models
import yfinance as yf
  • numpy 和 pandas 用于数据处理。
  • matplotlib.pyplot 用于绘图。
  • StandardScaler 用于特征标准化。
  • train_test_split 用于划分训练集和测试集。
  • tensorflow.keras 用于构建和训练深度学习模型。
  • yfinance 用于从 Yahoo Finance 获取金融数据。

2.2 数据准备

data_spx = yf.download("^GSPC", start="2010-01-01", end="2024-12-01")
price = data_spx['Adj Close']
volume = data_spx['Volume']

使用 yfinance 下载标普500指数(SPX)从2010年1月1日到2024年12月1日的调整后收盘价和成交量数据。

data = pd.DataFrame({
    'Price': price,
    'Volume': volume
})

将价格和成交量数据存储在一个 DataFrame 中。

data['Return'] = np.log(data['Price'] / data['Price'].shift(1))

计算对数收益率(log returns),即每日价格变化的对数。

rolling_window = 10
data['Volatility'] = data['Return'].rolling(window=rolling_window).std()

计算10天滚动窗口的波动率(volatility),即收益率的滚动标准差。

data['LogVolume'] = np.log(data['Volume'] + 1)

对成交量进行对数变换,以减小数据的尺度差异。

data = data.dropna()

删除由于滚动操作产生的 NaN 值。

2.3 特征和标签准备

features = data[['Return', 'Volatility', 'LogVolume']].values
labels = data['Return'].shift(-10).dropna().values
  • 特征包括收益率、波动率和对数成交量。
  • 标签是未来10天的收益率。
features = features[:-10]

对齐特征和标签,确保特征和标签的长度一致。

scaler = StandardScaler()
features = scaler.fit_transform(features)

对特征进行标准化处理,使其均值为0,标准差为1。

sequence_length = 30
X, y = [], []
for i in range(len(features) - sequence_length):
    X.append(features[i:i + sequence_length])
    y.append(labels[i + sequence_length - 1])
X, y = np.array(X), np.array(y)

将特征数据转换为时间序列格式,每个样本包含30个时间步的特征。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

将数据集划分为训练集和测试集,测试集占20%。

2.4 TCN模型定义

model = models.Sequential([
    layers.Input(shape=(sequence_length, X.shape[2])),
    layers.Conv1D(filters=64, kernel_size=3, dilation_rate=1, activation='relu'),
    layers.Conv1D(filters=64, kernel_size=3, dilation_rate=2, activation='relu'),
    layers.GlobalAveragePooling1D(),
    layers.Dense(1)
])
  • 定义一个简单的TCN模型,包含两个1D卷积层,分别使用不同的膨胀率(dilation rate)。
  • 使用全局平均池化层(GlobalAveragePooling1D)将时间维度压缩为单个值。
  • 最后是一个全连接层(Dense),输出未来10天的收益率预测。
model.compile(optimizer='adam', loss='mse')

使用Adam优化器和均方误差(MSE)作为损失函数来编译模型。

2.5 模型训练

epochs = 1000
batch_size = 32
history = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=batch_size)

训练模型,设置1000个epoch,批量大小为32。

2.6 模型评估

y_pred = model.predict(X_test)

使用测试集进行预测。

plt.figure(figsize=(10, 6))
plt.plot(y_test[-50:], label='Actual Returns', alpha=0.7)
plt.plot(y_pred[-50:], label='Predicted Returns', alpha=0.7)
plt.title('Comparison of Actual vs Predicted Returns')
plt.legend()
plt.show()

绘制实际收益率和预测收益率的对比图。

2.7 保存模型和结果

model.save("tcn_model.h5")

将训练好的模型保存为 tcn_model.h5 文件。

model.summary()

打印模型的摘要信息。

下图为TCN 基础预测与 SPX 最近 50 天的实际回报率对比。

这段代码实现了一个基于TCN的模型,用于预测标普500指数未来10天的收益率。代码涵盖了数据获取、预处理、模型构建、训练、评估和保存的完整流程。

全源代码如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from tensorflow.keras import layers, models
import yfinance as yf

# === Data Preparation ===
# Simulate example data (replace this with actual SPX data)
#np.random.seed(42)
#n_days = 1000
#price = np.cumprod(1 + np.random.normal(0, 0.01, n_days)) * 1000
#volume = np.random.randint(1e6, 1e7, n_days)

# Step 1: Fetch SPX data
data_spx = yf.download("^GSPC", start="2010-01-01", end="2024-12-01")
price = data_spx['Adj Close']
volume = data_spx['Volume']

# Create a DataFrame
data = pd.DataFrame({
    'Price': price,
    'Volume': volume
})

# Compute returns (log returns)
data['Return'] = np.log(data['Price'] / data['Price'].shift(1))

# Compute rolling volatility (10-day window)
rolling_window = 10
data['Volatility'] = data['Return'].rolling(window=rolling_window).std()

# Log-transform volume
data['LogVolume'] = np.log(data['Volume'] + 1)

# Drop NaN values caused by rolling operations
data = data.dropna()

# Prepare features and labels
features = data[['Return', 'Volatility', 'LogVolume']].values
labels = data['Return'].shift(-10).dropna().values  # Predict 10-day-ahead return

# Align features with labels
features = features[:-10]

# Standardize features
scaler = StandardScaler()
features = scaler.fit_transform(features)

# Reshape features for TCN (samples, timesteps, features)
sequence_length = 30  # Lookback window
X, y = [], []
for i in range(len(features) - sequence_length):
    X.append(features[i:i + sequence_length])
    y.append(labels[i + sequence_length - 1])
X, y = np.array(X), np.array(y)

# Split into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# === TCN Model Definition ===
# Define the TCN architecture
model = models.Sequential([
    layers.Input(shape=(sequence_length, X.shape[2])),
    layers.Conv1D(filters=64, kernel_size=3, dilation_rate=1, activation='relu'),
    layers.Conv1D(filters=64, kernel_size=3, dilation_rate=2, activation='relu'),
    layers.GlobalAveragePooling1D(),
    layers.Dense(1)  # Single output for next return prediction
])

# Compile the model
model.compile(optimizer='adam', loss='mse')

# === Model Training ===
# Train the model
epochs = 1000
batch_size = 32
history = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=batch_size)

# === Model Evaluation ===
# Predict on the test set
y_pred = model.predict(X_test)

# Plot actual vs predicted returns
plt.figure(figsize=(10, 6))
plt.plot(y_test[-50:], label='Actual Returns', alpha=0.7)
plt.plot(y_pred[-50:], label='Predicted Returns', alpha=0.7)
plt.title('Comparison of Actual vs Predicted Returns')
plt.legend()
plt.show()

# === Save Model and Results ===
# Save the model
model.save("tcn_model.h5")

# Print summary
model.summary()

三、观点总结

时序卷积网络(TCN)在时间序列预测任务中表现卓越,主要得益于其出色的长程依赖关系建模能力。与传统的递归架构(如LSTM或GRU)不同,TCN采用扩张卷积运算,能够高效捕捉长时间跨度内的时间模式,同时避免了递归模型中常见的梯度消失问题。这种独特的设计使其在处理复杂时间序列数据时更具优势。

  • TCN的关键组成部分包括随意卷积(Casual Convolutions)、稀释卷积(Dilated Convolutions)和残差连接(Residual Connection)。
  • TCN能够并行处理整个序列,这使得它比RNN更快地训练。
  • TCN通过稀释卷积能够捕捉跳跃时间序列,并且能够处理长内存
  • 通过残差连接和无递归,TCN减少了梯度消失等不稳定性问题
  • 在实际应用中,TCN模型使用了SPX指数的历史数据,包括收益率、波动性和成交量,以及如何预测未来10天的回报率
  • TCN在时间序列预测任务中的优越性能,尤其是在处理长期依赖关系和避免梯度消失问题方面有良好表现。

感谢您阅读到最后,希望这篇文章为您带来了新的启发和实用的知识!如果觉得有帮助,请不吝点赞和分享,您的支持是我持续创作的动力。祝您投资顺利,收益长虹!如果对文中内容有任何疑问,欢迎留言,我会尽快回复!


本文内容仅限技术探讨和学习,不构成任何投资建议。

Published inAI&Invest专栏

Be First to Comment

发表回复