You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CNN+LSTM预测SPY实际次日收盘价及代码修改

用CNN+LSTM预测SPY次日收盘价的代码修改方案

基于你已验证有效的模型结构,要实现次日收盘价预测,需针对数据划分、归一化逻辑和预测流程做如下修改:

一、核心问题修正

现有代码用shuffle=True的随机划分打乱了时间序列顺序,且归一化依赖窗口内的未来数据,这会导致模型在真实预测场景下失效。需调整为时间顺序划分+全局归一化的方案。

二、具体修改步骤

1. 替换随机数据划分为时间顺序划分

时间序列预测必须保证训练数据早于测试数据,避免数据泄露:

# 提取收盘价(假设df第2列为Adj Close)
close_prices = df.iloc[:, 2].values

# 按时间比例划分训练/测试集(例:前90%训练,后10%验证)
split_idx = int(len(df) * 0.9)
train_close = close_prices[:split_idx]
test_close = close_prices[split_idx:]

2. 改用全局归一化(适配未来预测)

用训练集的均值和标准差做归一化,确保未来预测时无需依赖未知数据:

# 计算训练集归一化参数
mean_train = train_close.mean()
std_train = train_close.std()

# 归一化/反归一化函数
def normalize(data, mean, std):
    return (data - mean) / std

def denormalize(data, mean, std):
    return (data * std) + mean

3. 重构训练/测试数据生成逻辑

调整窗口逻辑,输入为前100天收盘价,目标为次日收盘价:

window_size = 100

# 生成训练数据
X_train = []
Y_train = []
for i in range(window_size, len(train_close)):
    # 输入:i-window_size到i-1的收盘价
    X_train.append(normalize(train_close[i-window_size:i], mean_train, std_train))
    # 目标:i日的收盘价(即次日相对于输入窗口的价格)
    Y_train.append(normalize(train_close[i], mean_train, std_train))

# 生成测试数据
X_test = []
Y_test = []
for i in range(window_size, len(test_close)):
    X_test.append(normalize(test_close[i-window_size:i], mean_train, std_train))
    Y_test.append(normalize(test_close[i], mean_train, std_train))

# 转换为模型要求的输入形状
X_train = np.array(X_train).reshape(-1, 1, window_size, 1)
Y_train = np.array(Y_train).reshape(-1, 1)
X_test = np.array(X_test).reshape(-1, 1, window_size, 1)
Y_test = np.array(Y_test).reshape(-1, 1)

4. 调整训练参数

关闭shuffle=True,避免破坏时间序列的依赖关系:

history = model.fit(X_train, Y_train, validation_data=(X_test,Y_test), 
                    epochs=75,batch_size=40, verbose=1, shuffle=False)

5. 实现次日收盘价预测函数

用最新的100条收盘价数据生成预测输入,再反归一化得到真实价格:

# 获取最新的window_size条收盘价
latest_window = close_prices[-window_size:]
# 归一化处理
normalized_window = normalize(latest_window, mean_train, std_train)
# 转换为模型输入形状
input_data = normalized_window.reshape(1, 1, window_size, 1)

# 预测并还原真实价格
normalized_pred = model.predict(input_data, verbose=0)[0][0]
next_day_pred = denormalize(normalized_pred, mean_train, std_train)

print(f"次日SPY收盘价预测值: {next_day_pred:.2f}")

三、完整修改后的核心代码

import numpy as np
import pandas as pd
from pandas_datareader import data as web
import tensorflow as tf
from tensorflow.keras.layers import TimeDistributed, Conv1D, MaxPooling1D, Flatten, Bidirectional, LSTM, Dropout, Dense
from tensorflow.keras.optimizers import Adam

# 1. 获取SPY数据
df = web.DataReader("SPY", data_source="yahoo", start="2000-01-01", end="2022-10-19")
close_prices = df.iloc[:, 2].values  # 取Adj Close列作为预测目标

# 2. 时间顺序划分数据集
split_idx = int(len(df) * 0.9)
train_close = close_prices[:split_idx]
test_close = close_prices[split_idx:]

# 3. 计算训练集归一化参数
mean_train = train_close.mean()
std_train = train_close.std()

# 4. 定义归一化/反归一化函数
def normalize(data, mean, std):
    return (data - mean) / std

def denormalize(data, mean, std):
    return (data * std) + mean

# 5. 生成训练/测试数据
window_size = 100
X_train = []
Y_train = []
for i in range(window_size, len(train_close)):
    X_train.append(normalize(train_close[i-window_size:i], mean_train, std_train))
    Y_train.append(normalize(train_close[i], mean_train, std_train))

X_test = []
Y_test = []
for i in range(window_size, len(test_close)):
    X_test.append(normalize(test_close[i-window_size:i], mean_train, std_train))
    Y_test.append(normalize(test_close[i], mean_train, std_train))

# 转换输入形状适配模型
X_train = np.array(X_train).reshape(-1, 1, window_size, 1)
Y_train = np.array(Y_train).reshape(-1, 1)
X_test = np.array(X_test).reshape(-1, 1, window_size, 1)
Y_test = np.array(Y_test).reshape(-1, 1)

# 6. 构建并训练模型(原结构保留)
model = tf.keras.Sequential()
model.add(TimeDistributed(Conv1D(64, kernel_size=3, activation='relu', input_shape=(None, window_size, 1))))
model.add(TimeDistributed(MaxPooling1D(2)))
model.add(TimeDistributed(Conv1D(128, kernel_size=3, activation='relu')))
model.add(TimeDistributed(MaxPooling1D(2)))
model.add(TimeDistributed(Conv1D(64, kernel_size=3, activation='relu')))
model.add(TimeDistributed(MaxPooling1D(2)))
model.add(TimeDistributed(Flatten()))

model.add(Bidirectional(LSTM(100, return_sequences=True)))
model.add(Dropout(0.5))
model.add(Bidirectional(LSTM(100, return_sequences=False)))
model.add(Dropout(0.5))

model.add(Dense(1, activation='linear'))
model.compile(optimizer=Adam(), loss='mse', metrics=['mse', 'mae'])

history = model.fit(X_train, Y_train, validation_data=(X_test,Y_test), 
                    epochs=75,batch_size=40, verbose=1, shuffle=False)

# 7. 预测次日收盘价
latest_window = close_prices[-window_size:]
normalized_window = normalize(latest_window, mean_train, std_train)
input_data = normalized_window.reshape(1, 1, window_size, 1)

normalized_pred = model.predict(input_data, verbose=0)[0][0]
next_day_pred = denormalize(normalized_pred, mean_train, std_train)

print(f"次日SPY收盘价预测值: {next_day_pred:.2f}")

内容的提问来源于stack exchange,提问作者ajffz402

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:56:08