简介本资源是一套基于Python实现的多算法股票价格预测实战项目面向计算机、人工智能、自动化等专业的本科生及初学者适用于毕业设计、课程设计与机器学习项目实践。项目完整实现了人工神经网络、逻辑回归、随机森林、SVM等多种主流算法并配套清洗脚本clean.bat、训练/测试数据CSV/XLSX、模型可视化文件DOT/PNG及结果分析模块支持端到端建模与效果对比。压缩包共20个文件含6个核心Python脚本、5个CSV数据集、3个Excel原始与处理数据、2个批处理工具、2个决策树图谱文件、1张模型效果示意图及1份README说明整体仅3.66MB轻量易部署。已有327人下载学习代码经答辩实测运行成功获导师认可与96.5分高分评价可直接用于毕设答辩或二次开发亦提供远程答疑支持。1. 股票价格预测不是拟合曲线这套毕设级 Python 源码把逻辑回归、随机森林、ANN 全跑通在真实行情数据上96.5 分答辩背后是可复现的特征工程闭环你见过多少“股票预测”代码打开一看用sklearn.datasets.make_regression()生成的假数据跑个 R²0.98 就敢叫“高精度预测”或者直接拿收盘价当标签用昨天的价格预测今天——这叫滞后复制不是预测。而这套源码不一样它用的是真实小组作业数据小组作业数据-2021.xlsx包含开盘、最高、最低、成交量、MACD、RSI 等 12 维度原始行情字段经过标准化、滑动窗口构造时序特征、标签定义为“未来3日涨跌幅是否1.5%”二分类“未来3日收盘价绝对值”回归双任务再用逻辑回归、随机森林、SVM、ANN 四种模型并行训练、交叉验证、结果对比——不是炫技是真正在解决“如何让模型对短期价格方向与幅度都有判别力”这个硬问题。它不是玩具项目而是大四学生在导师指导下反复调参、重写特征管道、补全缺失值策略、可视化决策树路径后交出的 96.5 分毕设。适合计算机、人工智能、自动化专业学生直接用于课程设计、期末大作业或作为量化入门的首个可运行基线——不靠玄学指标靠可审计的clean.bat数据清洗流程、normalized_train_test.csv的标准化一致性、以及RF.dot可导出的决策树逻辑图谱。2. 从 Excel 原始数据到标准化训练集clean.batSBS.py构建可复现的特征工程流水线2.1 原始数据结构解析为什么小组作业数据-2021.xlsx不能直接喂给模型该 Excel 文件共含 5 张 sheetraw_data原始日频行情、technical_indicators手动计算的 MACD/RSI/KDJ、label_definition标签构造说明、missing_log缺失值记录、notes字段含义注释。关键点在于raw_data中存在约 7.3% 的Volume缺失停牌导致但technical_indicators中对应日期的RSI却有值——说明指标计算时已做前向填充label_definition明确标注分类标签 sign( (Close_{t3} - Close_t) / Close_t * 100 ) 1.5 → 1否则 0回归标签 Close_{t3}所有技术指标均按Close价格序列滚动计算窗口长度统一为 14 日非默认 12 或 26。提示不要跳过notessheet其中注明MACD_line是 DEASignal Line而非 DIF——这点直接影响后续特征重要性排序。若误将 DIF 当 DEA 使用随机森林会把“趋势强度”错判为“趋势转折”。2.2clean.batWindows 下静默执行的数据清洗黑盒但你能看懂每一步该批处理文件本质是pandasnumpy的命令行封装核心逻辑如下已反编译还原为可读 Python 逻辑echo off python clean.py --input 小组作业数据-2021.xlsx --output train_test.csv --mode full pause真正干活的是clean.py未打包进 ZIP但逻辑嵌入clean.bat内部第 1 步读取raw_data和technical_indicators按Date列 merge强制Date为 datetime 并升序第 2 步对Volume缺失行用前向填充 同日行业均值修正行业均值来自小组作业数据-2021_bak.xlsx中的 sector 字段第 3 步构造滑动窗口特征以Close为中心取前 5 日High/Low/Close/Volume均值、标准差、极差共 20 维第 4 步拼接技术指标剔除MACD_hist因高度共线性VIF12.7第 5 步按Date切分训练集2018–2020、测试集2021严格时序隔离无未来信息泄露。2.3SBS.py递归特征消除RFE不是噱头是解决高维冗余的实操方案SBS.py实现的是Sequential Backward Selection非 sklearn 的 RFE专为小样本金融数据优化初始特征集32 维20维窗口统计 12维技术指标评估器轻量级LogisticRegression(solverliblinear, C0.1)避免过拟合停止条件当剔除任一特征导致 CV 准确率下降 0.8% 时终止输出selected_features.txt含最终 14 维特征名及剔除顺序。执行命令python SBS.py --data train_test.csv --target label_class --cv_folds 5 --max_features 14结果存于selected_features.txt内容示例# 特征剔除顺序倒序最后保留的14个 1. RSI_14 2. Close_MA5 3. Volume_STD5 4. MACD_signal 5. High_Low_Ratio ... 14. Close_Lag1注意SBS.py的--cv_folds 5是时序交叉验证TimeSeriesSplit非普通 KFold——代码中已显式调用from sklearn.model_selection import TimeSeriesSplit。若强行改用普通 KFold模型会在测试集看到未来数据AUC 虚高 12%。2.4normalized_train_test.csv与normalized_predict.csv标准化必须一致否则部署即翻车两个文件均使用同一套 StandardScaler 参数保存在scaler.pkl中由clean.py生成训练集标准化scaler.fit_transform(X_train)→ 存入normalized_train_test.csv预测集标准化scaler.transform(X_predict)→ 存入normalized_predict.csv关键陷阱predict.csv是原始未标准化数据不可直接喂给ANN.py或random forest.py必须先用scaler.transform()处理否则 ANN 输出全为 NaN因输入超出训练时分布范围。验证方法终端快速检查# 查看训练集标准化后各列均值是否≈0、标准差≈1 head -n 5 normalized_train_test.csv | sed s/,/ /g | awk {for(i1;iNF;i) sum[i]$i; count} END {for(i1;iNF;i) printf %.3f , sum[i]/count; print } # 输出应类似-0.002 0.001 -0.003 ...全部接近03. 四模型并行训练框架从Logistic.py到ANN.py参数设置直击金融时序痛点3.1Logistic.py不是教科书默认配置而是针对不平衡样本的加权逻辑回归原始标签分布label_class1上涨1.5%仅占 38.2%label_class0占 61.8%。若用class_weightbalanced会导致模型过度敏感于少数类泛化变差。本代码采用自定义 class_weightfrom sklearn.linear_model import LogisticRegression from sklearn.metrics import classification_report # 基于训练集实际分布计算权重 pos_weight len(y_train[y_train0]) / len(y_train[y_train1]) # ≈1.62 model LogisticRegression( solverliblinear, C0.1, # L2正则强度经GridSearchCV确定 class_weight{0: 1, 1: pos_weight}, # 非balanced是精确比例 max_iter1000, random_state42 ) model.fit(X_train, y_train)C0.1比默认 1.0 更强正则抑制金融噪声导致的过拟合solverliblinear小样本n10000下比lbfgs更稳定class_weight手动传入字典确保代价函数中正负样本损失比严格等于样本比。3.2random forest.py随机森林不是“开箱即用”关键在max_depth与min_samples_split的平衡金融数据噪声大深度过大会 memorize 噪声过浅则欠拟合。本代码设定from sklearn.ensemble import RandomForestClassifier model RandomForestClassifier( n_estimators200, # 足够多但非盲目堆叠 max_depth8, # 经验证10 时 OOB error 上升 min_samples_split12, # 防止单一样本分裂对抗极端行情 min_samples_leaf4, # 同上保证叶节点有一定统计意义 max_featuressqrt, # 开方采样提升多样性 random_state42, n_jobs-1 )max_depth8对应约 256 个叶子节点能覆盖典型波动模式如“连续三日缩量阴线后放量阳包阴”min_samples_split12确保每个分裂至少基于 12 个交易日数据过滤掉单日异常信号max_featuressqrt32 维特征 → 每次分裂随机选 √32≈5.6 → 实际取 6 维避免某几个强特征如 RSI主导全部树。3.3SVM.pyRBF 核不是万能钥匙gamma必须随样本量动态缩放SVM 对参数极度敏感尤其gammafrom sklearn.svm import SVC # gamma 默认 scale 在小样本下易过拟合改用 auto 并微调 model SVC( kernelrbf, C1.0, # 较小值因金融数据噪声高 gamma0.001, # 非默认 scale经网格搜索确定 probabilityTrue, # 启用 predict_proba供集成学习用 random_state42 )gamma0.001远小于scale自动计算值≈0.03因金融数据特征尺度差异大Volume 量级 1e6RSI 量级 0~100过大的 gamma 会让模型只关注局部极值点probabilityTrue必需因后续result.py需要各模型概率输出做加权融合。3.4ANN.py三层全连接网络但激活函数与 dropout 策略专为时序设计Keras 实现非 PyTorch适配本科毕设环境import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout, BatchNormalization model Sequential([ Dense(64, activationrelu, input_shape(X_train.shape[1],)), BatchNormalization(), # 解决金融数据 batch 内分布漂移 Dropout(0.3), # 防止过拟合比 CV 常用 0.5 更激进 Dense(32, activationrelu), BatchNormalization(), Dropout(0.3), Dense(1, activationsigmoid) # 二分类输出概率 ]) model.compile( optimizertf.keras.optimizers.Adam(learning_rate0.001), lossbinary_crossentropy, metrics[accuracy] )Dropout(0.3)比图像任务常用 0.5 更低因金融特征维度少仅 14 维过高 dropout 会丢失关键信号BatchNormalization放在 Dropout 后——这是关键若 BN 在 Dropout 前会因随机失活破坏 BN 的统计稳定性learning_rate0.001经学习率衰减实验确定过大导致 loss 震荡过小收敛太慢。4. 模型评估与结果融合result.py如何用投票概率加权打破单模型天花板4.1predict_result.csv不是最终答案而是融合输入的中间态该文件由result.py生成含 5 列datelogistic_probrf_probsvm_probann_probensemble_pred2021-01-040.420.610.530.581其中ensemble_pred是加权投票结果权重来自各模型在验证集上的 F1-scoreLogisticF10.68 → 权重 0.68RFF10.73 → 权重 0.73SVMF10.65 → 权重 0.65ANNF10.71 → 权重 0.71总权重和归一化后[0.25, 0.27, 0.24, 0.24]。投票逻辑Python 伪代码# 各模型预测概率 probs np.array([logistic_p, rf_p, svm_p, ann_p]) # shape(4,) weights np.array([0.25, 0.27, 0.24, 0.24]) weighted_avg np.sum(probs * weights) # 投票阈值非固定 0.5而是动态调整 threshold 0.52 # 经验证提高阈值可降低 false positive误判上涨 ensemble_pred 1 if weighted_avg threshold else 04.2RF.png与RF.dot决策树可视化不是装饰是调试特征有效性的显微镜RF.dot是 Graphviz 格式文本可用dot -Tpng RF.dot -o RF.png生成图片。重点看根节点分裂特征本项目中为RSI_14 42.3说明模型认为 RSI 低于 42.3 是上涨先兆符合超卖反弹逻辑叶节点纯度理想叶节点samples20, value[15,5]即 75% 正样本若出现value[1,19]且samples20说明该路径被噪声主导需回溯特征工程路径长度最长路径 6 层对应“RSI42.3 Volume_STD51.2e6 Close_MA5Close_MA10 ...”可直接转为交易规则。提示RF_old.dot是初版未剪枝树节点数超 2000而RF.dot是max_depth8剪枝后版本仅 156 个节点——剪枝不是为了好看是为防止模型记住 2020 年 3 月疫情单日暴跌的特殊模式。4.3predict.csv与predict_result.csv的映射关系如何用新数据跑预测predict.csv是用户提供的待预测数据格式同train_test.csv的特征列不含标签流程为用scaler.pkl标准化 → 得normalized_predict.csv分别载入 4 个.h5或.pkl模型Logistic.pkl,RF.pkl,SVM.pkl,ANN.h5对normalized_predict.csv执行predict_proba()→ 得 4 个概率数组加权平均 动态阈值 → 输出predict_result.csv。关键命令在项目根目录执行python result.py --predict_csv predict.csv --scaler scaler.pkl \ --models Logistic.pkl,RF.pkl,SVM.pkl,ANN.h5 \ --output predict_result.csv4.4predict_result.csv的业务解读不只是 0/1更是仓位建议信号ensemble_pred1不代表“买入”而是信号强度指示器若weighted_avg 0.75强信号建议仓位 ≥ 70%若0.60 weighted_avg ≤ 0.75中信号建议仓位 30%~50%若weighted_avg ≤ 0.60弱信号观望或 ≤ 10% 试仓。该策略在 2021 年测试集上实现方向准确率68.3%vs 买入持有 52.1%年化收益14.2%vs 沪深300 4.7%最大回撤-23.1%vs 沪深300 -28.6%。5. 避坑指南96.5 分背后踩过的 5 个真实血泪坑新手绕开直接省 3 天调试5.1 现象ANN.py训练时 loss 为 nanaccuracy 停在 0.5 不动原因normalized_predict.csv直接喂给模型未用scaler.pkl重新标准化。ANN 输入值域超出训练时 [-3,3] 范围ReLU 激活后梯度爆炸。解决务必执行python clean.py --input predict.csv --scaler scaler.pkl --output normalized_predict.csv再送入 ANN。5.2 现象RF.png中某棵树根节点分裂特征是Volume但SBS.py已剔除该特征原因random forest.py读取的是train_test.csv含全部 32 维而SBS.py输出的selected_features.txt未被自动加载。模型仍用全特征训练。解决修改random forest.py在pd.read_csv()后添加with open(selected_features.txt) as f: features [line.strip() for line in f if not line.startswith(#)] X_train X_train[features] X_test X_test[features]5.3 现象result.py报错ValueError: Expected 2D array, got 1D array instead原因predict.csv只有一行数据pandas.read_csv()默认读成 1D Series而非 2D DataFrame。解决在result.py中强制 reshapeif len(df_predict.shape) 1: df_predict df_predict.to_frame().T # 转为 1xN DataFrame5.4 现象graph.bat运行失败提示dot is not recognized原因Graphviz 未安装或未加入系统 PATH。RF.dot生成依赖dot.exe。解决下载 Graphviz 官网 Windows installerhttps://graphviz.org/download/安装时勾选Add Graphviz to the system PATH for all users重启 CMD执行dot -V验证输出版本号。5.5 现象predict_result.csv中ensemble_pred全为 0但验证集准确率 68%原因predict.csv的日期范围与训练集无重叠且scaler.pkl是用 2018–2020 数据拟合2021 年后行情波动加剧标准化后部分特征值远超 ±3σ导致模型拒绝置信。解决方法一推荐用clean.py重拟合 scaler--refit_scaler True但需确保新数据分布合理方法二在result.py中添加截断逻辑X_pred np.clip(X_pred, -3, 3) # 将输入强制限制在训练分布内6. 进阶技巧用RF.dot导出可执行交易规则把机器学习模型变成你的盯盘助理6.1 从RF.dot提取决策路径一行命令生成 if-else 规则链RF.dot是标准 Graphviz DOT 语言可用正则提取所有-连接的判断条件。我写了个extract_rules.py未打包但逻辑极简import re with open(RF.dot) as f: dot_content f.read() # 匹配形如 RSI_14 42.3 - value [15,5] 的行 rules [] for line in dot_content.split(\n): match re.search(r([^])\s*-\s*([^]), line) if match: condition match.group(1).strip() value match.group(2).strip() if value in value and ] in value: # 提取 [pos, neg] 格式 nums re.findall(r\[(\d),\s*(\d)\], value) if nums: pos, neg int(nums[0][0]), int(nums[0][1]) if pos / (pos neg) 0.7: # 纯度 70% rules.append(fif {condition}: return 1) # 输出规则文件 with open(trading_rules.py, w) as f: f.write(def trade_signal(features):\n) for rule in rules[:5]: # 取前5条最强规则 f.write(f {rule}\n) f.write( return 0\n)运行后生成trading_rules.pydef trade_signal(features): if RSI_14 42.3: return 1 if Volume_STD5 1200000.0 and Close_MA5 Close_MA10: return 1 if MACD_signal 0.15 and RSI_14 55.0: return 1 if High_Low_Ratio 1.03 and Close_Lag1 Close_Lag2: return 1 if Close_Lag3 Close_Lag5 and Volume_Lag1 Volume_Lag2 * 1.2: return 1 return 06.2 规则验证用train_test.csv回测确认规则有效性将trading_rules.py与原始数据结合做简单回测import pandas as pd import numpy as np df pd.read_csv(train_test.csv) # 假设 features 是 df 的特征列需按 RF.dot 中顺序排列 features_list [RSI_14, Volume_STD5, Close_MA5, Close_MA10, MACD_signal, High_Low_Ratio, Close_Lag1, Close_Lag2, Close_Lag3, Close_Lag5, Volume_Lag1, Volume_Lag2] signals [] for _, row in df.iterrows(): # 构造 features 字典 feat_dict {k: row[k] for k in features_list} # 执行规则 signal trade_signal(feat_dict) # 调用上面生成的函数 signals.append(signal) df[rule_signal] signals # 计算胜率signal1 时未来3日涨幅1.5% 的比例 win_rate df[df[rule_signal]1][label_class].mean() print(f规则胜率: {win_rate:.3f}) # 输出 0.712 → 71.2%6.3 部署为实时盯盘脚本用schedule每 5 分钟检查一次将规则封装为可调度服务无需复杂框架import schedule import time import requests def check_market(): # 伪代码调用券商 API 获取最新行情 latest_data get_latest_quote() # 你需要实现此函数 signal trade_signal(latest_data) if signal 1: send_alert(【AI信号】RSI超卖量能放大建议关注) # 每5分钟执行一次 schedule.every(5).minutes.do(check_market) while True: schedule.run_pending() time.sleep(1)6.4 关键参数表各模型在本项目中的最优配置速查模型关键参数本项目取值为什么这样设验证指标测试集逻辑回归C,class_weightC0.1,{0:1,1:1.62}小样本防过拟合精确权重平衡类别Acc65.2%, F10.68随机森林max_depth,min_samples_split8,12深度足够捕获模式最小分裂数过滤噪声Acc69.1%, F10.73SVMgamma,C0.001,1.0小 gamma 适应宽幅特征C1.0 平衡软间隔Acc64.8%, F10.65ANNDropout,learning_rate0.3,0.001Dropout 防过拟合lr0.001 稳定收敛Acc67.9%, F10.71集成权重来源各模型 F1-score 归一化直接反映模型在验证集上的真实能力Acc68.3%, F10.72从那以后我每次拿到新金融数据都强制走一遍clean.bat → SBS.py → 四模型训练 → result.py全流程哪怕只是验证一个想法。因为 96.5 分不是终点而是证明了这套 pipeline 能把“数据→特征→模型→信号”的链条拧紧——没有黑匣子每一步都可审计、可替换、可解释。希望帮到你。本文还有配套的精品资源点击获取