
简介这份资源是2024年课程设计级别的机器学习股票预测算法项目源码包面向计算机、人工智能、通信工程、自动化等专业的高校学生与科研从业者可用于毕业设计、课程设计、作业提交或项目初期立项演示也适合具备一定基础的学习者进阶练手。压缩包共26个文件约2.57MB包含6个ipynb交互式笔记、5个py脚本、6个xml配置、3个csv数据文件以及md说明、docx报告、txt依赖清单等覆盖数据获取、特征工程、模型训练与回测的完整链路。内容涉及K线数据入库、小市值结合盈利指标过滤策略验证、FFT滤波、单票LSTM预测与sklearn回测等实践模块并附有项目说明与参考报告便于理解整体设计思路。目前已有53人学习下载适合希望快速上手股票预测实战、借鉴代码结构或在此基础上二次开发的学习者参考使用。1. 机器学习股票预测课设从一份源码包到能跑通的预测流水线很多人第一次拿到「机器学习股票预测算法源码项目说明报告」这类课设压缩包时第一反应是解压、找main.py、直接python main.py然后被一堆ModuleNotFoundError和空白的收益曲线劝退。这个标题背后其实是一套完整的工程链路数据获取与清洗、特征工程、标签构造、模型训练、回测评估最后还要写一份能自圆其说的报告。它解决的不是「预测明天涨跌」这种玄学问题而是让你在有限数据上跑通一条可复现、可解释、可写进报告的流水线。适合正在做课设的学生、想入门量化特征工程的开发者以及需要一份能讲清楚「为什么这么做」的模板的人。下面我按自己踩过坑的顺序把这条链路拆开讲。2. 先搞清楚预测目标回归、分类还是排序2.1 三种目标定义决定了后面所有代码结构股票预测听起来是一件事落到代码里至少分三种目标。第一种是回归预测未来 N 日收益率的具体数值损失函数用 MSE 或 Huber输出是一个连续值。第二种是分类预测未来 N 日涨跌方向二分类用 0/1三分类加上震荡损失函数用交叉熵。第三种是排序在候选股票池里预测相对强弱常用于多标的选股损失函数用 pairwise ranking loss。课设里最常见的是二分类因为报告好写、指标直观准确率、AUC、F1。但这里有个血泪经验股票涨跌本身噪声极大二分类准确率能稳定在 53% 以上就已经不容易别指望 80%。如果你的模型在测试集上准确率 90%先检查是不是标签泄漏了。我一般会先确定三件事预测周期1 日、5 日还是 20 日、标签阈值涨跌幅超过多少算正样本、以及是否做中性化减去行业或大盘收益。这三件事写在报告的方法章节里比模型结构更能体现你的思考。2.2 标签构造的代码骨架与参数说明下面这段代码是标签构造的最小实现假设你已经有一个包含close列的 DataFrame索引是交易日。import pandas as pd import numpy as np def make_labels(df, horizon5, threshold0.02, price_colclose): df: 含 close 列的行情数据按日期升序 horizon: 预测未来多少个交易日 threshold: 涨跌幅阈值超过该值记为正样本 # 未来 horizon 日的收益率 future_ret df[price_col].shift(-horizon) / df[price_col] - 1 # 三分类1 涨、0 震荡、-1 跌 labels np.where(future_ret threshold, 1, np.where(future_ret -threshold, -1, 0)) # 最后 horizon 行没有未来数据必须丢弃 df df.iloc[:-horizon].copy() df[label] labels[:-horizon] df[future_ret] future_ret[:-horizon] return df逻辑说明shift(-horizon)把未来价格拉到当前行这是标签构造的核心。参数horizon越大标签噪声越低但样本越少threshold越大正负样本越不平衡。我通常先跑一遍df[label].value_counts()如果某一类占比低于 15%就要考虑用class_weightbalanced或者调整阈值。注意最后 horizon 行必须切掉否则最后几行的标签是 NaN训练时会报错或者被静默填充成 0这就是典型的翻车点。2.3 特征工程别一上来就堆几百个因子课设报告里常见「使用了 200 个技术指标」但真正有效的往往不到 20 个。我建议按三类组织特征价量特征收益率、波动率、换手率、趋势特征均线偏离、MACD、RSI、统计特征过去 N 日收益的偏度、峰度。每类先选 3 到 5 个跑一遍特征重要性再决定要不要加。def add_features(df, windows(5, 10, 20)): for w in windows: df[fret_{w}] df[close].pct_change(w) df[fvol_{w}] df[ret_1].rolling(w).std() df[fma_dev_{w}] df[close] / df[close].rolling(w).mean() - 1 # RSI 简化版 delta df[close].diff() gain delta.clip(lower0).rolling(14).mean() loss (-delta.clip(upper0)).rolling(14).mean() df[rsi_14] 100 - 100 / (1 gain / (loss 1e-9)) return df.dropna()参数说明windows控制回看周期短周期捕捉反转长周期捕捉趋势。dropna()会丢掉前 20 行这是正常的。注意loss 1e-9是防止除零这个细节在报告里可以提一句体现工程严谨性。3. 数据切分与模型训练时间序列不能随机打乱3.1 为什么随机切分会让你的报告直接失效这是课设里最致命的错误。很多人习惯train_test_split(shuffleTrue)但在时间序列上这等于用未来数据预测过去测试集准确率会虚高到离谱。正确做法是按时间切分前 70% 训练中间 15% 验证最后 15% 测试。更严格一点用滚动窗口或扩展窗口交叉验证。def time_split(df, train_ratio0.7, val_ratio0.15): n len(df) train_end int(n * train_ratio) val_end int(n * (train_ratio val_ratio)) train df.iloc[:train_end] val df.iloc[train_end:val_end] test df.iloc[val_end:] return train, val, test逻辑说明iloc按位置切分保证时间顺序。参数train_ratio和val_ratio根据样本量调整样本少于 2000 行时验证集可以只留 10%。切分后检查一下三段的日期范围有没有重叠我见过有人切完发现验证集日期在训练集之前原因是原始数据没按日期排序。3.2 树模型和线性模型的选型理由课设里最稳的是 LightGBM 或 XGBoost原因是能处理缺失值、对特征缩放不敏感、训练快。线性模型逻辑回归、 Ridge适合做 baseline报告里放一个对比表格会加分。神经网络不是不能做但样本量小的时候容易过拟合调参成本高。import lightgbm as lgb from sklearn.metrics import roc_auc_score, accuracy_score feature_cols [c for c in train.columns if c not in (label, future_ret)] X_train, y_train train[feature_cols], (train[label] 1).astype(int) X_val, y_val val[feature_cols], (val[label] 1).astype(int) model lgb.LGBMClassifier( n_estimators300, learning_rate0.05, max_depth5, num_leaves31, subsample0.8, colsample_bytree0.8, class_weightbalanced, random_state42 ) model.fit(X_train, y_train, eval_set[(X_val, y_val)], eval_metricauc, callbacks[lgb.early_stopping(30)]) pred model.predict_proba(X_val)[:, 1] print(AUC:, roc_auc_score(y_val, pred))参数说明n_estimators配合early_stopping用防止过拟合max_depth5和num_leaves31是控制复杂度的关键股票数据信噪比低树太深必然过拟合class_weightbalanced处理样本不平衡。early_stopping(30)表示验证集 AUC 30 轮不提升就停。跑完打印一下特征重要性如果某个特征重要性异常高检查它是不是未来函数。3.3 评估指标不能只看准确率准确率在样本不平衡时会骗人。假设正样本只占 20%模型全预测负样本也有 80% 准确率。报告里至少放三个指标AUC、F1、以及按预测概率分组的收益表现。更贴近实战的是看 Top 20% 预测概率的样本平均收益如果这个值显著高于全样本平均说明模型有区分能力。def topk_metrics(y_true, pred_prob, future_ret, k0.2): n len(pred_prob) top_idx np.argsort(pred_prob)[-int(n * k):] return { top_avg_ret: future_ret.iloc[top_idx].mean(), all_avg_ret: future_ret.mean(), hit_rate: y_true.iloc[top_idx].mean() }逻辑说明argsort取概率最高的 k 比例样本计算平均未来收益。参数k一般取 0.1 到 0.3。如果top_avg_ret和all_avg_ret差不多说明模型没有实际选股能力报告里要如实写别硬吹。4. 避坑与排查课设里最容易翻车的五个地方4.1 标签泄漏特征里混入了未来信息现象验证集 AUC 0.95 以上测试集掉到 0.5。原因某个特征在计算时用了未来数据比如用全样本均值做标准化或者用shift(-1)构造特征。解决所有特征计算只允许用当前及历史数据标准化参数只能在训练集上拟合。检查方法把特征和标签的相关系数按时间画出来如果某个特征在测试期相关性突然飙升基本就是泄漏。4.2 数据对齐错误停牌和缺失值处理不当现象回测收益曲线出现不合理的跳空。原因停牌日数据缺失dropna()后日期不连续收益率计算错位。解决先按交易日历 reindex停牌日用前值填充但标签构造时要标记停牌期并剔除。我一般会在数据加载后先df.index pd.to_datetime(df.index)再df df.asfreq(B)对齐工作日。4.3 过拟合训练集完美测试集崩盘现象训练集 AUC 0.99验证集 0.55。原因树太深、特征太多、样本太少。解决限制max_depth不超过 6min_child_samples设到 50 以上特征数控制在样本数的十分之一以下。另外早停是必须的别手动设n_estimators1000跑满。4.4 随机种子没固定结果无法复现现象每次跑出来的 AUC 都不一样报告里的数字对不上。原因random_state没设或者 LightGBM 的bagging_seed、feature_fraction_seed没设。解决在模型初始化时把random_state、bagging_seed、feature_fraction_seed都固定成同一个值数据切分也用固定种子。4.5 报告和代码脱节数字对不上现象报告里写准确率 65%代码跑出来 58%。原因报告里的数字是某次调参后的结果但代码没保存那次配置。解决每次实验把参数和指标写进一个experiment_log.csv报告里的每个数字都能追溯到具体命令。这个习惯在课设答辩时能救命。5. 把源码包变成可展示的成果报告结构与复现技巧课设的最终交付不只是代码还有一份能讲清楚来龙去脉的报告。我一般按「问题定义 → 数据说明 → 特征工程 → 模型与参数 → 实验结果 → 局限性」六段写。其中「局限性」这段最容易被忽略但恰恰是加分项写清楚样本量小、未考虑交易成本、未做行业中性化反而显得你懂行。复现技巧上建议在项目根目录放一个run.sh把数据下载、特征生成、训练、评估串起来。这样别人拿到压缩包后一条命令就能跑通而不是逐个文件找入口。#!/bin/bash set -e python src/build_features.py --input data/raw.csv --output data/features.csv python src/train.py --data data/features.csv --model lgb --horizon 5 python src/evaluate.py --pred outputs/pred.csv --report reports/metrics.json逻辑说明set -e让脚本在任一步失败时停止避免错误累积。参数--horizon和--model暴露出来方便做对比实验。如果数据文件较大可以在build_features.py里加缓存避免重复计算。最后一个具体技巧在报告里放一张「特征重要性 Top 10」的表格比放十张收益曲线更有说服力。因为收益曲线受市场行情影响大而特征重要性反映的是模型逻辑。我习惯用lgb.plot_importance导出后手动整理成表格标注每个特征的经济含义比如ma_dev_20代表价格偏离 20 日均线程度这样答辩时老师一看就懂。我自己做这类课设最大的教训是别在模型结构上炫技把数据切分、标签构造、评估指标这三件事做扎实比换十个模型都管用。每次跑实验前先问自己一句「这个特征在实盘里能不能实时拿到」能过滤掉一大半未来函数。希望帮到你。本文还有配套的精品资源点击获取