如何用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
相关产品推荐
相关产品推荐

