
简介这份资源是面向计算机、人工智能、通信工程、自动化等专业学生与科研人员的机器学习股票预测课程设计项目包可直接用于毕业设计、课程设计、作业提交或项目初期立项演示也适合具备一定基础的学习者进阶练手。压缩包共26个文件约2.57MB包含6个ipynb交互式笔记本、5个py脚本、3个csv数据文件以及xml配置、md说明、docx报告等辅助资料覆盖数据获取、特征工程、模型训练与回测的完整流程。内容涉及K线数据入库、小市值结合盈利指标过滤策略验证、FFT滤波、单票LSTM预测与sklearn回测等实践模块并附有项目说明文档与参考报告便于理解整体设计思路与代码组织方式。目前已有53人学习下载适合希望快速上手股票预测算法、借鉴完整课设方案并在此基础上二次开发的读者参考使用。1. 从一份课设包说起机器学习股票预测到底能不能跑通去年帮一个学弟看毕设他发来一个压缩包文件名是「机器学习股票预测算法源码项目说明报告2024课设.zip」。我第一反应是这类课设包十有八九是跑不起来的——环境缺依赖、数据路径写死、notebook 里全是执行过的缓存输出。但解压之后翻了翻结构比预想的规整code目录下有get_data.py、practice.py、real_time.py根目录散着几个 notebook包括singlelstm.ipynb、fft-filter.ipynb、sklearn机器学习单票回测.ipynb还有两个 CSV 数据文件600256.csv、002475.csv外加一份 docx 报告和packages.txt。这不是那种只有一张截图的空壳包是真的有人从头写过一遍的痕迹。这份资源适合谁如果你正在做机器学习、金融数据分析方向的课程设计或毕业设计需要一个能跑通、能改、有报告参考的完整案例它省掉的是「从零搭框架」那两周。如果你是想入门时序预测的从业者里面的 LSTM 单票预测和 sklearn 回测两条线正好覆盖了「深度学习」和「传统机器学习」两种做法。但它不是能直接拿去实盘的策略系统——课设的定位决定了它的数据粒度、回测严谨度都停留在教学层面这一点后面会反复提到。2. 拆包先看骨架目录结构与两条技术路线2.1 文件清单里藏着什么先把压缩包解开用tree或者直接看资源管理器能理出这么几类东西类别文件作用数据获取get_data.py、getstockcsv.py拉取股票历史数据存成 CSV数据处理newfeature.py、fft-filter.ipynb特征工程、FFT 滤波去噪模型训练singlelstm.ipynb、singlelstm2.ipynb单变量 LSTM 预测传统机器学习sklearn机器学习单票回测.ipynbsklearn 回测流程策略验证验证小市值结合盈利指标过滤策略.ipynb多因子过滤思路数据库ML_stock_qt 保存K线数据到数据库.ipynbK 线入库实时real_time.py实时数据接口示例文档报告 docx、README.md设计说明与使用说明packages.txt是依赖清单.idea目录说明原作者用的是 PyCharm。这个结构透露出的信息是作者走的是「先拿数据 → 做特征 → 上模型 → 回测」的标准流程而不是随便找个教程抄一段。2.2 两条路线怎么选包里其实并行了两套建模思路。一条是singlelstm.ipynb代表的深度学习路线用 LSTM 吃历史价格序列预测下一日收盘价。另一条是sklearn机器学习单票回测.ipynb代表的传统机器学习路线构造特征后用 sklearn 的模型做分类或回归再走回测。选哪条取决于你的课设要求。如果导师强调「深度学习」「神经网络」走 LSTM 那条报告里也好写创新点。如果要求「可解释性」「特征重要性」sklearn 那条更稳随机森林、梯度提升都能给出特征贡献度。我的建议是两条都跑一遍报告里做对比工作量够结论也扎实。提示不要一上来就改代码。先把两个 notebook 按原样跑通确认环境和数据没问题再动手改。很多人跳过这步改到一半发现是环境问题回头排查成本翻倍。2.3 环境准备与依赖安装packages.txt里列了依赖但课设包的依赖清单往往不全或者版本没锁。稳妥做法是自己建虚拟环境按需装。常见的是 Python 3.8 到 3.10 之间太新的版本某些库会有兼容问题。# 创建虚拟环境Python 版本建议 3.9 python -m venv stock_env # 激活Windows stock_env\Scripts\activate # 激活macOS / Linux source stock_env/bin/activate # 先装核心依赖版本按需调整 pip install numpy pandas matplotlib scikit-learn pip install torch --index-url https://download.pytorch.org/whl/cpu pip install jupyter notebook这里解释几个点。torch的安装命令带了--index-url是因为默认源在某些网络环境下拉取慢指定官方 CPU 版源更稳如果你有 GPU 且装了 CUDA换成对应的 cu 版本。jupyter notebook是为了打开那些.ipynb文件虽然 PyCharm 也能开但 notebook 的交互式调试在调参阶段更方便。装完之后用pip list核对一下重点看numpy、pandas、torch、scikit-learn四个在不在。2.4 数据从哪来get_data.py和getstockcsv.py是数据入口。这类脚本通常调用公开的行情接口拉日线数据存成 CSV。包里已经附了600256.csv和002475.csv两个文件说明作者至少跑通过两只票。你拿到手第一件事是打开 CSV 看列名import pandas as pd df pd.read_csv(600256.csv) print(df.columns.tolist()) print(df.head()) print(df.shape)常见的列是日期、开盘、收盘、最高、最低、成交量。如果列名是中文或者拼音后面特征工程里引用列名的地方都要跟着改这是第一个容易翻车的点。df.shape看行数日线数据一般几百到几千行如果只有几十行说明拉取范围太短模型学不出东西。3. 把 LSTM 预测跑起来从数据到训练到出图3.1 数据预处理与归一化打开singlelstm.ipynb核心流程是读 CSV → 取收盘价列 → 归一化 → 构造滑动窗口 → 喂给 LSTM。归一化这步不能省股价数值在几十到几百直接进网络梯度会炸。常见做法是 MinMax 缩放到 0 到 1from sklearn.preprocessing import MinMaxScaler import numpy as np # 只取收盘价reshape 成二维给 scaler close df[close].values.reshape(-1, 1) scaler MinMaxScaler(feature_range(0, 1)) scaled scaler.fit_transform(close) # 构造滑动窗口用前 60 天预测第 61 天 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) # LSTM 需要三维输入(样本数, 时间步, 特征数) X X.reshape(X.shape[0], X.shape[1], 1)window60是回看天数意思是拿最近 60 个交易日预测下一天。这个参数直接影响样本量和模型感受野调大到 120样本变少但信息更多调小到 20样本多但可能欠拟合。课设里 60 是个常见起点。reshape那步是 LSTM 的硬性要求输入必须是三维很多人卡在这里报维度错误。3.2 搭一个能用的 LSTMsinglelstm.ipynb里的网络结构一般不会太复杂一两层 LSTM 加一个全连接输出。用 PyTorch 写大概是这样import torch import torch.nn as nn class StockLSTM(nn.Module): def __init__(self, input_size1, hidden_size64, num_layers2, output_size1): super().__init__() self.hidden_size hidden_size self.num_layers num_layers # batch_firstTrue 让输入维度是 (batch, seq, feature) self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue) self.fc nn.Linear(hidden_size, output_size) def forward(self, x): # h0, c0 初始化为全零 h0 torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device) c0 torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device) out, _ self.lstm(x, (h0, c0)) # 只取最后一个时间步的输出 out self.fc(out[:, -1, :]) return outhidden_size64是隐藏层维度课设规模够用调大到 128 训练慢但可能更准。num_layers2是堆两层 LSTM再深容易过拟合小数据集。batch_firstTrue这个参数很关键不设的话输入维度顺序是(seq, batch, feature)和大多数人习惯相反报错时先检查这里。out[:, -1, :]取的是序列最后一步因为预测目标就是最后一步之后的那一天。3.3 训练循环与损失观察训练部分要盯住训练集和验证集的损失曲线。课设数据量小很容易过拟合训练损失一路降、验证损失反弹就是信号。model StockLSTM() criterion nn.MSELoss() optimizer torch.optim.Adam(model.parameters(), lr0.001) # 按 8:2 切训练和验证 split int(len(X) * 0.8) X_train, X_val X[:split], X[split:] y_train, y_val y[:split], y[split:] X_train torch.FloatTensor(X_train) y_train torch.FloatTensor(y_train).unsqueeze(1) epochs 50 for epoch in range(epochs): model.train() optimizer.zero_grad() pred model(X_train) loss criterion(pred, y_train) loss.backward() optimizer.step() if (epoch 1) % 10 0: print(fEpoch {epoch1}, Loss: {loss.item():.6f})lr0.001是 Adam 的常用学习率损失不降就调到 0.0005震荡就调到 0.0001。epochs50对课设够用但别只看训练损失一定要留验证集。unsqueeze(1)是把标签从一维变二维和模型输出对齐不加会报形状不匹配。3.4 预测结果反归一化与画图模型输出是 0 到 1 之间的数要还原成真实股价才有意义。用 scaler 的inverse_transform反变换然后和真实值画在一张图上对比。model.eval() with torch.no_grad(): pred_scaled model(torch.FloatTensor(X_val)).numpy() # 反归一化 pred_price scaler.inverse_transform(pred_scaled) true_price scaler.inverse_transform(y_val.reshape(-1, 1)) import matplotlib.pyplot as plt plt.plot(true_price, labelTrue) plt.plot(pred_price, labelPredicted) plt.legend() plt.title(LSTM Stock Prediction) plt.show()图出来之后重点看两件事预测曲线是不是明显滞后于真实曲线LSTM 预测股价的通病本质是它在「抄前一天」以及波动大的地方是不是完全跟不上。如果滞后严重说明模型没学到东西只是把输入平移了这时候要么加特征要么换思路。课设报告里如实写这个现象比硬说「预测准确」要诚实得多答辩时也扛得住问。4. 传统机器学习那条线sklearn 回测与 FFT 滤波4.1 sklearn 单票回测的流程sklearn机器学习单票回测.ipynb走的是另一条路不预测具体价格而是预测涨跌方向然后按信号回测收益。流程是构造特征 → 标签二分类 → 训练模型 → 按预测信号模拟买卖。import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split # 构造简单特征过去 5 天收益率、成交量变化 df[ret] df[close].pct_change() for lag in range(1, 6): df[fret_lag{lag}] df[ret].shift(lag) df[vol_change] df[volume].pct_change() # 标签明天涨为 1跌为 0 df[label] (df[close].shift(-1) df[close]).astype(int) df df.dropna() features [fret_lag{i} for i in range(1, 6)] [vol_change] X df[features] y df[label] X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, shuffleFalse) model RandomForestClassifier(n_estimators100, random_state42) model.fit(X_train, y_train) print(Accuracy:, model.score(X_test, y_test))shuffleFalse在时序数据里是必须的打乱顺序会造成未来信息泄露回测结果虚高。n_estimators100是随机森林的树数量课设够用。准确率能到 50% 出头就算正常别指望 80%那基本是泄露了。这个 notebook 的价值在于让你理解「分类 回测」的框架而不是追求高准确率。4.2 FFT 滤波去噪是怎么回事fft-filter.ipynb用的是傅里叶变换给价格序列去噪。思路是把价格序列做 FFT高频部分对应短期噪声低频对应趋势滤掉高频再逆变换回来得到一条平滑曲线。import numpy as np close df[close].values fft_vals np.fft.fft(close) freqs np.fft.fftfreq(len(close)) # 保留低频滤掉高频阈值按数据长度调 threshold 0.05 fft_filtered fft_vals.copy() fft_filtered[np.abs(freqs) threshold] 0 smoothed np.fft.ifft(fft_filtered).realthreshold0.05是频率阈值越小保留的低频越少、曲线越平滑。这个滤波结果可以当特征喂给模型也可以直接用来观察趋势。要注意的是 FFT 假设信号平稳股价并不平稳所以它只是教学演示别当成严谨的金融信号处理。4.3 多因子过滤策略的思路验证小市值结合盈利指标过滤策略.ipynb跳出了单票做的是选股逻辑先按市值筛出小市值股票池再用盈利指标比如 ROE、净利润增速过滤最后看这个组合的表现。这类 notebook 通常需要多只股票的数据包里只有两只 CSV跑之前要确认数据够不够不够就得自己补拉。注意这个 notebook 依赖的字段可能比单票数据多市值、财务指标如果 CSV 里没有这些列会直接报 KeyError。先看代码里引用了哪些列再决定是补数据还是跳过这个 notebook。5. 避坑与排查课设包跑不通的五个真实原因5.1 路径写死导致 FileNotFoundError现象一运行就报FileNotFoundError: [Errno 2] No such file or directory: 600256.csv。 原因notebook 里用的是相对路径而你的工作目录不是文件所在目录。Jupyter 的工作目录是启动时所在的目录不是 notebook 文件所在目录。 解决在 notebook 开头加一段切换目录的代码或者用绝对路径。更稳的做法是用os.path动态定位import os os.chdir(os.path.dirname(os.path.abspath(__file__))) # notebook 里 __file__ 不可靠 # 更推荐手动确认当前目录 print(os.getcwd()) # 然后 os.chdir(你的项目路径)5.2 列名不匹配导致 KeyError现象KeyError: close或者KeyError: 收盘价。 原因不同数据源导出的 CSV 列名不一样有的是英文close有的是中文收盘价有的是拼音shoupan。代码里写死了某一种。 解决先print(df.columns.tolist())看实际列名然后统一重命名df df.rename(columns{收盘价: close, 开盘价: open, 最高价: high, 最低价: low, 成交量: volume, 日期: date})5.3 归一化用错范围导致预测离谱现象预测出来的价格是负数或者比真实值大几十倍。 原因训练时用训练集 fit 了 scaler预测时又用测试集重新 fit 了一个新 scaler两次变换基准不一致。或者反归一化时用错了 scaler。 解决scaler 只在训练集上 fit 一次测试集和预测都用同一个 scaler 做 transform 和 inverse_transform。这个错误在课设里极其常见因为很多人把数据切分和归一化的顺序搞反了。5.4 时序数据 shuffle 导致回测虚高现象sklearn 回测准确率 85% 以上感觉好得不真实。 原因train_test_split默认shuffleTrue把未来数据混进了训练集模型「偷看」了答案。 解决时序数据必须shuffleFalse或者用时间序列专用的切分方式按时间点切前面训练后面测试。改完之后准确率大概率掉到 50% 到 55%这才是真实水平。5.5 依赖版本冲突导致 import 失败现象ImportError: cannot import name xxx或者AttributeError: module numpy has no attribute float。 原因packages.txt没锁版本你装的 numpy 或 pandas 版本和原作者不一致某些 API 改了。 解决按报错信息定位是哪个库降级到兼容版本。比如 numpy 1.24 移除了np.float老代码里用了就会报错降到 1.23 或者把代码里的np.float改成float。建虚拟环境就是为了这种时候能随便折腾不污染全局。6. 进阶玩法把课设包改成自己的东西跑通只是第一步课设要拿得出手得有自己的改动。我一般会从三个方向下手。第一个方向是加特征。原始 notebook 大多只用收盘价你可以把newfeature.py里的特征工程思路扩展开加入 MACD、RSI、布林带这些技术指标或者加入成交量的移动平均。特征多了之后用 sklearn 那条线跑特征重要性报告里能画出柱状图比单纯说「用了 LSTM」有说服力。加特征时注意别引入未来信息所有指标只能用当天及之前的数据算。第二个方向是换模型做对比。LSTM 跑完换成 GRU 或者一维 CNN 跑一遍或者用 XGBoost 跑传统机器学习那条线把几个模型的 RMSE、方向准确率列成表格对比。课设报告里有一张对比表档次立刻不一样。下面是个简单的对比记录方式模型RMSE方向准确率训练耗时LSTM待填待填待填GRU待填待填待填XGBoost待填待填待填第三个方向是把real_time.py用起来。这个脚本是实时数据接口的示例课设里通常只是摆设。你可以把它改成定时拉取最新数据、更新数据库、触发预测的流程哪怕只是本地跑一个循环报告里写「系统具备实时更新能力」就有依据了。ML_stock_qt 保存K线数据到数据库.ipynb里的入库逻辑可以复用把实时数据和历史数据存到同一张表。验证改动有没有效果别只看损失曲线。我的习惯是固定一个随机种子把改动前后的结果各跑三遍取平均避免单次运行的偶然性。torch.manual_seed(42)和np.random.seed(42)都设上这样结果可复现答辩时被问到也能当场重跑。从那以后我每次拿到这类课设包都强制自己先原样跑通、再记录基线指标、最后才动手改三步缺一不可。跳过基线直接改最后连「改好了还是改坏了」都说不清。希望这份拆解帮到你少走几个我踩过的坑。本文还有配套的精品资源点击获取