
简介这是一份面向计算机相关专业学生、教师及企业员工的外汇预测学习资源基于LSTM网络构建汇率走势预测模型适合作为深度学习与时间序列分析的入门实践也可用于课程设计、毕业设计或作业参考。压缩包共31个文件约13.41MB包含Python脚本、Jupyter Notebook、CSV汇率数据、模型权重与配置文件等覆盖数据准备、模型训练、测试与预测的完整流程并附有README说明使用方法与依赖安装。资源中提供了USDJPY、GBPUSD等外汇对的历史数据与已训练模型读者可借此理解LSTM门控机制、数据标准化与序列切分等关键环节同时对照代码掌握TensorFlow/Keras的建模思路。目前已有48人学习下载适合希望快速上手深度学习预测项目、积累实战经验的学习者参考但需注意市场预测存在不确定性模型结果仅供学习交流不可用于商业用途。1. 外汇预测模型用 LSTM 到底靠不靠谱先看清它的能力边界很多人第一次接触外汇预测都是被“用 LSTM 预测汇率准确率 90%”这类标题吸引进来的。我当初也一样觉得只要把历史价格喂进 LSTM它就能吐出明天的收盘价。实际跑过几轮之后才发现LSTM 在外汇这种高噪声、低信噪比的时间序列上既不是万能钥匙也不是完全没用——它的价值在于捕捉序列里的非线性惯性而不是预测每一次跳动。这个标题里的“Python 源码、数据、模型”三件套本质上就是一条从原始汇率数据到可训练张量、再到 LSTM 网络、最后到预测输出的完整链路。适合谁适合已经会一点 Python、想拿真实金融数据练手时间序列建模的工程师也适合做量化策略原型、需要快速验证特征工程是否有效的人。如果你指望它直接拿去实盘赚钱那大概率会失望但如果你想搞懂 LSTM 在金融序列上的真实表现、知道它什么时候翻车、怎么调参能稳住那这套东西值得动手复现一遍。2. 数据从哪来、怎么洗外汇日线数据的获取与预处理2.1 外汇数据的常见来源与字段选择做外汇预测第一步不是写模型而是搞到干净的数据。常见做法有三种一是用免费金融数据接口拉取历史汇率比如通过yfinance获取主要货币对EURUSD、USDJPY、GBPUSD 等的日线数据二是从公开的经济数据库下载 CSV比如部分央行或国际组织发布的汇率时间序列三是用券商或数据商提供的 API但这类通常有权限门槛。我一般会先用yfinance快速拉一份 EURUSD 的日线字段至少保留Open、High、Low、Close、Volume其中外汇现货没有真实成交量Volume经常是 0 或缺失所以实际建模时我通常只保留 OHLC 四个价格字段。选日线而不是分钟线是因为 LSTM 对序列长度敏感分钟级数据噪声更大、样本量爆炸新手很容易在数据量上先把自己拖垮。日线数据一天一条十年也就 2500 条左右配合滑动窗口构造样本足够跑通一个最小可用的 LSTM 预测流程。2.2 用 Pandas 做缺失值处理与收益率转换原始价格序列不能直接喂给 LSTM原因有两个一是价格是非平稳的均值方差随时间漂移二是不同货币对的价格量级差异大直接输入会让网络偏向大数值。我一般会把收盘价转成对数收益率再做标准化。下面这段代码是从拉取数据到生成训练用数组的完整过程import yfinance as yf import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler # 拉取 EURUSD 日线数据周期选 2015-01-01 到 2024-12-31 df yf.download(EURUSDX, start2015-01-01, end2024-12-31) df df[[Open, High, Low, Close]].copy() # 前向填充缺失值再删掉仍然为 NaN 的行 df.ffill(inplaceTrue) df.dropna(inplaceTrue) # 计算对数收益率避免价格非平稳 df[log_return] np.log(df[Close] / df[Close].shift(1)) df.dropna(inplaceTrue) # 只用收益率作为特征做 MinMax 标准化到 [0,1] scaler MinMaxScaler(feature_range(0, 1)) scaled scaler.fit_transform(df[[log_return]].values) # 构造滑动窗口用过去 60 天预测下一天 def create_sequences(data, window60): X, y [], [] for i in range(window, len(data)): X.append(data[i-window:i, 0]) y.append(data[i, 0]) return np.array(X), np.array(y) X, y create_sequences(scaled, window60) X X.reshape((X.shape[0], X.shape[1], 1)) # LSTM 需要 [样本, 时间步, 特征] print(X.shape, y.shape)这段代码里几个关键点ffill是前向填充外汇数据周末停盘周一开盘前会有缺口前向填充比插值更符合实际交易逻辑log_return把价格转成收益率这一步不做的话后面 LSTM 很可能只是学会“预测昨天的价格”看起来 loss 很低实际没有预测能力window60是回看窗口我一般会在 30 到 120 之间试60 是日线数据里比较稳的起点reshape成三维是 PyTorch 和 Keras 的 LSTM 层要求的输入格式漏掉这一步会直接报维度错误。注意yfinance的汇率数据偶尔会有异常跳点拉下来之后最好画一下收盘价曲线肉眼扫一遍有没有明显错误再往下走。3. 搭一个能跑的 LSTM 模型PyTorch 实现与训练参数3.1 网络结构怎么定层数、隐藏单元与 DropoutLSTM 做时间序列预测结构不需要太深。我试过 1 层、2 层、3 层在外汇日线这种数据量下2 层 LSTM 加一层全连接输出通常就够了再深容易过拟合。隐藏单元数一般取 32、64、128我习惯从 64 开始。Dropout 放在 LSTM 层之间取 0.2 左右能明显缓解训练集 loss 下降但验证集 loss 反弹的问题。下面是一个可以直接跑的 PyTorch 模型定义和训练循环import torch import torch.nn as nn from torch.utils.data import DataLoader, TensorDataset # 划分训练集和测试集前 80% 训练后 20% 测试 split int(len(X) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] train_ds TensorDataset(torch.tensor(X_train, dtypetorch.float32), torch.tensor(y_train, dtypetorch.float32)) train_loader DataLoader(train_ds, batch_size32, shuffleTrue) class LSTMModel(nn.Module): def __init__(self, input_size1, hidden_size64, num_layers2, dropout0.2): super().__init__() self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue, dropoutdropout) self.fc nn.Linear(hidden_size, 1) def forward(self, x): out, _ self.lstm(x) # out: [batch, seq, hidden] out out[:, -1, :] # 取最后一个时间步 return self.fc(out) model LSTMModel() criterion nn.MSELoss() optimizer torch.optim.Adam(model.parameters(), lr1e-3) for epoch in range(50): model.train() total_loss 0 for xb, yb in train_loader: pred model(xb).squeeze() loss criterion(pred, yb) optimizer.zero_grad() loss.backward() optimizer.step() total_loss loss.item() if (epoch 1) % 10 0: print(fEpoch {epoch1}, Loss: {total_loss/len(train_loader):.6f})batch_firstTrue表示输入张量第一维是 batch这是 PyTorch 里最容易搞混的参数之一不设的话默认 batch 在第二维后面取out[:, -1, :]就会取错。out[:, -1, :]是取序列最后一个时间步的隐藏状态因为我们要预测的是下一天用最后一步的输出最合理。损失函数用 MSE优化器用 Adam学习率 1e-3 是常规起点如果 loss 震荡厉害就降到 1e-4。3.2 训练轮数与早停怎么判断模型有没有学废50 个 epoch 是保守设置实际跑的时候我会同时看训练 loss 和测试 loss。如果训练 loss 一直降、测试 loss 先降后升说明过拟合需要加 Dropout 或减层数如果两个 loss 都不降可能是学习率太大或者数据标准化有问题。早停策略我一般设 patience10连续 10 个 epoch 测试 loss 不改善就停。还有一个容易被忽略的点LSTM 的初始隐藏状态默认是全零短序列没问题但如果你把 window 拉到 200 以上可以考虑用前一段序列的最终状态作为下一段的初始状态不过在外汇日线上这个技巧带来的提升很有限新手可以先不碰。4. 预测结果怎么评估别只看 MSE方向准确率才是关键4.1 反标准化与预测值还原模型输出的是标准化后的收益率要还原成可解释的数值得用 scaler 逆变换。下面这段代码把测试集预测结果还原并计算两个指标MSE 和方向准确率。model.eval() with torch.no_grad(): pred_test model(torch.tensor(X_test, dtypetorch.float32)).squeeze().numpy() # 逆变换回原始收益率尺度 pred_inv scaler.inverse_transform(pred_test.reshape(-1, 1)).flatten() true_inv scaler.inverse_transform(y_test.reshape(-1, 1)).flatten() mse np.mean((pred_inv - true_inv) ** 2) # 方向准确率预测涨跌方向是否和真实一致 direction_acc np.mean((pred_inv 0) (true_inv 0)) print(fMSE: {mse:.8f}, Direction Accuracy: {direction_acc:.4f})MSE 衡量的是数值误差但外汇预测里更关心方向对不对。方向准确率能到 55% 以上说明模型有一点预测能力如果只有 50% 左右基本等于随机猜。我跑过多次EURUSD 日线方向准确率通常在 52% 到 56% 之间波动超过 60% 的要么是数据泄漏要么是过拟合。4.2 可视化对比与误差分布检查光看数字不够我习惯把预测值和真实值画在同一张图上再画一下误差的直方图。如果误差分布明显偏离零均值说明模型有系统性偏差可能需要加特征或者换损失函数。这一步用 Matplotlib 几行就能搞定不展开代码但强烈建议做。提示测试集千万别拿去调参调参只看验证集。我见过太多人反复在测试集上试参数最后报出来的指标好看实际一上模拟盘就原形毕露。5. 避坑与排查外汇 LSTM 预测里最容易翻车的 4 个地方5.1 现象训练 loss 很低但预测是一条直线原因数据没有做平稳化处理模型学会了直接输出均值。价格序列本身有趋势LSTM 发现预测昨天收盘价就能让 MSE 很小于是躺平。解决一定要转成收益率或做差分确保输入是平稳序列。5.2 现象验证集 loss 比训练集还低原因数据泄漏。常见于滑动窗口构造时训练集和验证集之间有重叠或者标准化时用了全量数据的均值和方差。解决标准化参数只在训练集上 fit再 transform 验证集和测试集滑动窗口切分时确保训练集和验证集在时间上不重叠。5.3 现象方向准确率忽高忽低换一段数据就崩原因外汇市场本身存在 regime shift某段时间趋势明显LSTM 表现好震荡市里就失效。解决不要指望一个模型通吃所有行情可以加波动率特征或者用滚动窗口重新训练但根本上是接受它的局限性。5.4 现象GPU 上跑得飞快但结果和 CPU 不一致原因PyTorch 在 GPU 上默认使用非确定性算法LSTM 的 cuDNN 实现有随机性。解决设置torch.manual_seed和torch.backends.cudnn.deterministic True但会牺牲一点速度。如果只是做原型验证CPU 跑也够用。6. 进阶技巧用多特征输入和滚动预测提升实用性单变量 LSTM 只用了历史收益率信息量有限。我后来习惯加几个外生特征一是过去 5 天的波动率用收益率标准差算二是星期几的 one-hot 编码外汇有周一效应三是简单移动平均线的偏离度。这些特征不需要额外数据源从 OHLC 里就能算出来。多特征输入时input_size改成特征数X的最后一维对应增加。另一个实用技巧是滚动预测每次预测完一天把预测值当作已知输入继续预测下一天。但这样误差会累积我一般只滚动 3 到 5 步再远就没有参考价值了。下面是一个滚动预测的简化写法def rolling_predict(model, last_window, steps5): model.eval() preds [] window last_window.copy() # shape: [1, seq_len, features] for _ in range(steps): with torch.no_grad(): p model(torch.tensor(window, dtypetorch.float32)).item() preds.append(p) # 把预测值拼到窗口末尾去掉最早一天 new_step np.array([[[p]]]) # 单特征时这样拼多特征要补齐其他维度 window np.concatenate([window[:, 1:, :], new_step], axis1) return preds这段代码里window[:, 1:, :]是去掉最早的时间步new_step是预测出的新一步拼成新的窗口。多特征时new_step的其他特征可以用最近值填充或者简单复制但会引入额外误差所以滚动步数不宜多。最后说一个我自己的习惯每次跑完模型不管指标好坏我都会把数据区间、窗口大小、网络结构、学习率、最终方向准确率记在一个表格里。跑过十几轮之后你就能看出哪些参数组合在你用的数据上更稳而不是每次凭感觉调。这个方案值不值得做如果你是想学 LSTM 在真实序列上的完整流程它值得如果你想靠它直接做交易决策那还需要加上风控、仓位管理和更严谨的回测框架。希望帮到你。本文还有配套的精品资源点击获取