股票时序预测的可复现机器学习流程
2026/9/10 4:57:11 网站建设 项目流程

简介:本资源是一份面向高校计算机及相关专业学生的机器学习股票预测课程设计实践项目,适用于人工智能、自动化、电子信息等方向的本科生毕设、课设与进阶学习。项目提供完整可运行的Python代码体系,涵盖数据获取、特征工程、LSTM时序建模、Sklearn多模型回测及实时预测等核心环节,并配套详细设计文档与Word格式技术报告,助力理解金融时序预测全流程。压缩包共26个文件,含6个Jupyter Notebook(用于算法实验与可视化)、5个Python主程序(如get_data.py、singlelstm.py等)、3个CSV股票数据样本、2个Markdown说明文档及1个DOCX报告,整体大小2.57MB,结构清晰、模块解耦,便于调试与功能拓展。目前已有52人下载学习,代码经实测可直接运行,支持小白入门、中阶复现与高阶二次开发,亦提供远程配置指导。

1. 这不是“预测明天涨停”的黑箱,而是一套可复现、可调试、可验证的机器学习股票时序建模流程

你下载的这个名为“机器学习股票预测算法源码项目说明+报告(2024课设).zip”的压缩包,本质是一份面向高校课程设计场景的结构化实践材料:它不承诺收益率,不封装神秘指标,也不依赖未公开的行情接口;它提供的是从原始日频行情数据出发,经特征工程、模型训练、回测验证到结果可视化的完整闭环。核心价值在于——所有代码可本地运行(Python 3.9+ + scikit-learn / pandas / numpy / matplotlib),所有步骤可逐行调试,所有参数可对照报告中的算法流程图修改验证。适合两类人:一是正在准备机器学习期末复习或课程设计的学生,需要把周志华《机器学习》第10章“聚类”与第11章“降维”之外的时序建模落地;二是刚接触量化建模的IT从业者,想绕过Kronos类商业软件的黑盒逻辑,用Python亲手跑通一个带滑动窗口、带特征缩放、带模型对比的最小可行预测链路。它解决的不是“买什么”,而是“怎么让LSTM/RandomForest/XGBoost在收盘价序列上稳定输出未来3天的点估计与区间估计”。


2. 用scikit-learn和pandas构建可复现的股票时序特征工程 pipeline

股票价格预测区别于普通回归任务的核心,在于时间依赖性非平稳性。直接将收盘价作为y、日期作为x扔进LinearRegression必然失败。本课设源码采用经典三阶段特征构造法:基础统计量 + 技术指标衍生 + 滑动窗口滞后项。以下代码段来自feature_engineering.py,是整个项目可复现性的基石。

2.1 基础行情数据清洗与对齐

import pandas as pd import numpy as np # 读取原始CSV(含date, open, high, low, close, volume列) df = pd.read_csv("stock_data.csv", parse_dates=["date"], index_col="date") # 强制按交易日重采样(避免周末/节假日空缺导致滞后错位) df = df.asfreq("D").ffill() # 向前填充,保持时间连续性 # 删除首尾因填充产生的无效行(如开盘价为0) df = df[(df["close"] > 0) & (df["volume"] > 0)]

注意asfreq("D").ffill()是关键预处理。若跳过此步,后续shift(1)会因日期不连续导致滞后特征错位——这是学生作业中最常被忽略的坑。ffill()保证每日都有值,但需配合后续dropna()剔除填充引入的异常。

2.2 构造6类可解释技术特征

源码中generate_features()函数生成以下特征组(全部基于df["close"]计算,无需外部库):

特征类型计算逻辑业务含义是否标准化
5日均值偏移(close - close.rolling(5).mean()) / close.rolling(5).mean()短期价格偏离均值程度
波动率(20日)close.rolling(20).std() / close.rolling(20).mean()价格稳定性度量
成交量变化率volume.pct_change(periods=5)资金活跃度趋势
最高/最低比high / low当日振幅压缩程度否(已归一化)
收盘价斜率(10日线性拟合)np.polyfit(range(10), close[-10:], 1)[0]短期趋势强度
MACD快慢线差close.ewm(span=12).mean() - close.ewm(span=26).mean()动量背离信号
def generate_features(df): feats = pd.DataFrame(index=df.index) # 示例:5日均值偏移(标准化前) feats["price_dev_5"] = (df["close"] - df["close"].rolling(5).mean()) / df["close"].rolling(5).mean() # 示例:MACD差值(使用pandas内置ewm) macd_fast = df["close"].ewm(span=12, adjust=False).mean() macd_slow = df["close"].ewm(span=26, adjust=False).mean() feats["macd_diff"] = macd_fast - macd_slow # 所有数值型特征统一做StandardScaler(fit_transform仅在训练集) from sklearn.preprocessing import StandardScaler scaler = StandardScaler() num_cols = feats.select_dtypes(include=[np.number]).columns feats[num_cols] = scaler.fit_transform(feats[num_cols]) return feats

提示StandardScaler().fit_transform()必须仅在训练集上调用一次,测试集用transform()。源码中train_test_split后立即保存scaler对象(joblib.dump(scaler, "scaler.pkl")),避免部署时特征尺度错乱。

2.3 滑动窗口构建时序样本

股票预测本质是多步向前回归。源码采用固定窗口长度window_size=30(即用过去30天特征预测第31天收盘价):

def create_sequences(X, y, window_size=30): X_seq, y_seq = [], [] for i in range(window_size, len(X)): X_seq.append(X.iloc[i-window_size:i].values) # shape: (30, n_features) y_seq.append(y.iloc[i]) # shape: (1,) return np.array(X_seq), np.array(y_seq) # 调用示例 X_feat = generate_features(df) y_target = df["close"].shift(-1) # 预测下一日收盘价 X_seq, y_seq = create_sequences(X_feat, y_target, window_size=30) # 输出形状:X_seq.shape -> (N-30, 30, 6), y_seq.shape -> (N-30,)

关键参数说明window_size=30对应约6周交易日,平衡记忆长度与样本量。若设为10,LSTM易过拟合;若设为60,训练样本锐减50%。课设报告中明确建议:在沪深300成分股上,30是实证最优起点。


3. 对比训练三种主流算法:RandomForest、XGBoost与LSTM的配置要点

本课设未采用单一模型,而是并行训练RandomForest(RF)、XGBoost(XGB)与LSTM,并在model_comparison.py中统一评估。选择依据明确:RF抗噪强、XGB精度高、LSTM捕获长周期依赖——覆盖机器学习课程设计要求的“算法多样性”。

3.1 RandomForestRegressor:无需调参的基线模型

from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error, r2_score # 初始化(课设报告强调:n_estimators=100足够,增加至500提升<0.5% R²但耗时翻倍) rf = RandomForestRegressor( n_estimators=100, max_depth=10, # 防止过拟合(默认None易过拟合时序数据) min_samples_split=5, # 提升泛化(默认2在小样本中易过拟合) random_state=42 # 保证课设结果可复现 ) rf.fit(X_train_2d, y_train) # 注意:RF输入为二维数组(N×F),需reshape

为什么用RF作基线?因其对异常值鲁棒、无需特征缩放、训练快。课设中RF在测试集MAE≈0.85元(以贵州茅台为例),R²≈0.72,构成后续模型改进的参照系。

3.2 XGBoostRegressor:精度提升的关键杠杆

import xgboost as xgb # 参数设置严格遵循课设报告Table 3(基于GridSearchCV在验证集寻优) xgb_model = xgb.XGBRegressor( n_estimators=200, learning_rate=0.05, # 降低学习率,增加迭代次数提升稳定性 max_depth=6, # 比RF更浅,抑制过拟合 subsample=0.8, # 行采样,增强泛化 colsample_bytree=0.8, # 列采样,防特征冗余 objective='reg:squarederror', random_state=42 ) xgb_model.fit(X_train_2d, y_train, eval_set=[(X_val_2d, y_val)], early_stopping_rounds=30, # 防止过拟合 verbose=False)

参数逻辑subsamplecolsample_bytree均设为0.8,是课设报告中针对股票数据噪声高的特别调整。实测显示,若设为1.0,XGB在测试集R²反降0.03——证明适度随机性对金融时序至关重要。

3.3 LSTM:处理时序依赖的深度模型实现

import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout # 构建LSTM(课设报告强调:单层LSTM+Dropout足够,双层易过拟合) model = Sequential([ LSTM(50, return_sequences=False, input_shape=(X_train.shape[1], X_train.shape[2])), Dropout(0.2), Dense(25), Dense(1) ]) model.compile(optimizer='adam', loss='mse') # 训练(batch_size=32, epochs=100,课设验证过100轮收敛稳定) history = model.fit( X_train, y_train, batch_size=32, epochs=100, validation_data=(X_val, y_val), verbose=0 )

关键约束return_sequences=False确保输出为单步预测(非序列到序列)。课设源码中X_train形状为(N, 30, 6),即30个时间步、6个特征,LSTM层输出50维向量后接全连接层回归。若误设return_sequences=True,会导致维度不匹配报错。

3.4 三模型性能对比表(课设实测结果)

模型测试集MAE(元)测试集R²训练耗时(秒)过拟合风险
RandomForest0.8520.71812.3
XGBoost0.6910.79348.7中(需早停)
LSTM0.7340.772216.5高(需Dropout+早停)

结论来源:该表直接摘自课设报告第4.2节。XGBoost在精度与效率间取得最佳平衡,成为课设推荐主模型。LSTM虽理论优势明显,但在30日窗口下未显著超越XGB——印证了“简单模型在小样本金融时序中常更可靠”的经验法则。


4. 回测验证:用backtrader框架实现策略级效果评估

模型输出的是“下一日收盘价预测值”,但课程设计要求上升到策略层面验证。源码配套backtest_strategy.py,使用轻量级回测框架backtrader,将预测结果转化为具体买卖信号。这不是展示“年化收益”,而是检验预测方向性是否具备统计显著性。

4.1 定义预测驱动的交易逻辑

import backtrader as bt class PredictStrategy(bt.Strategy): params = (('predict_threshold', 0.005),) # 预测涨跌幅阈值(0.5%) def __init__(self): self.predictions = self.datas[0].predicted_close # 从data加载预测列 self.order = None def next(self): if self.order: return # 有挂单则跳过 # 仅当预测涨幅>0.5%且无持仓时买入 if (self.predictions[0] > self.data.close[0] * (1 + self.p.predict_threshold) and not self.position): self.buy() # 仅当预测跌幅>0.5%且持有时卖出 elif (self.predictions[0] < self.data.close[0] * (1 - self.p.predict_threshold) and self.position): self.sell()

逻辑说明:该策略不追求满仓,只在预测信号强于阈值时操作。predict_threshold=0.005是课设报告中通过网格搜索确定的最优值——低于0.003则交易频繁、手续费侵蚀利润;高于0.008则信号过少、错过机会。

4.2 执行回测并提取关键指标

# 加载历史数据(含predicted_close列) data = bt.feeds.PandasData(dataname=df_with_pred) cerebro = bt.Cerebro() cerebro.adddata(data) cerebro.addstrategy(PredictStrategy) cerebro.broker.setcash(100000.0) cerebro.broker.setcommission(commission=0.001) # 千分之一手续费 # 运行回测 results = cerebro.run() strat = results[0] # 输出课设要求的3个核心指标 print(f"最终资产: {cerebro.broker.getvalue():.2f}") print(f"总交易次数: {strat.total_trades}") # 来自策略内部计数 print(f"胜率: {strat.winning_trades / strat.total_trades:.3f}")

课设验收点:报告要求必须输出胜率(盈利交易数/总交易数)。实测XGBoost预测信号在2023年沪深300成分股上平均胜率58.3%,显著高于随机猜测的50%——证明预测方向具备信息价值。

4.3 可视化预测误差分布(验证模型稳健性)

import matplotlib.pyplot as plt # 计算每日预测误差(绝对值) errors = np.abs(y_pred - y_true) plt.hist(errors, bins=50, alpha=0.7, label="XGBoost Error") plt.axvline(np.mean(errors), color='r', linestyle='--', label=f'Mean: {np.mean(errors):.3f}') plt.xlabel("Absolute Error (CNY)") plt.ylabel("Frequency") plt.title("Prediction Error Distribution (2023 Test Set)") plt.legend() plt.savefig("error_distribution.png", dpi=300, bbox_inches='tight')

为什么看误差分布?课设报告第5.1节指出:若误差呈尖峰厚尾(如大量小误差+少量极大误差),说明模型对极端行情失效。XGBoost在此分布中峰度=2.1(接近正态),证实其在常规波动中稳健——这比单纯看MAE更有教学意义。


5. 课设交付物检查清单:从源码结构到报告撰写要点

一份合格的“2024机器学习课设”交付物,绝不仅是.py文件堆砌。本项目源码结构严格遵循课程要求,且报告撰写有明确技术锚点。以下是学生自查与教师验收的硬性标准。

5.1 源码包必须包含的5个核心文件

文件名作用课设评分关键点
main.py总控脚本,依次调用数据清洗→特征工程→模型训练→回测必须有清晰的if __name__ == "__main__":入口,且各模块调用顺序正确
feature_engineering.py封装所有特征计算逻辑必须包含generate_features()create_sequences()两个函数,且create_sequences支持任意window_size
model_training.py三模型训练与保存(含joblib.dump每个模型必须保存为.pkl文件,路径写入config.py而非硬编码
backtest_strategy.pybacktrader策略类定义必须实现next()中基于predicted_close的买卖逻辑,且含手续费设置
config.py全局参数(DATA_PATH,WINDOW_SIZE,TEST_SIZE所有路径与超参必须从此文件读取,禁止在.py中写死字符串

提示:教师抽查时,会直接修改config.py中的WINDOW_SIZE=20,运行main.py——若报错或结果异常,则特征工程模块不合格。

5.2 报告撰写必须覆盖的4个技术章节

课设报告非作文,而是技术文档。以下为评分细则中明确要求的章节及内容深度:

  • 第3章 算法流程图:必须手绘或用draw.io绘制,包含“数据输入→清洗→特征生成→窗口切片→模型训练→预测输出→回测信号生成”全链路,箭头标注数据形状变化(如[N,6] → [N-30,30,6])。
  • 第4章 实验结果分析:表格需同时列出三模型的MAE/R²/训练时间,文字分析必须引用误差分布图(图4.1)说明XGBoost为何优于LSTM。
  • 第5章 局限性讨论:必须指出“未考虑停牌、涨跌停、分红送转等事件”,并说明asfreq("D").ffill()在此类事件中的缺陷。
  • 附录A 源码关键片段:粘贴generate_features()函数全文(含注释),以及PredictStrategy.next()方法体——证明代码自主编写。

5.3 一键验证环境兼容性的命令

为应对答辩现场环境差异,课设提供requirements_check.sh(Linux/Mac)或requirements_check.bat(Windows):

# Linux/Mac版 python -c "import pandas,numpy,scikit_learn,xgboost,tensorflow,backtrader; print('All libs OK')" pip list | grep -E "(scikit-learn|xgboost|tensorflow|backtrader)" | awk '{print $1,$2}'

执行效果:若输出All libs OK及四库版本号(如scikit-learn 1.3.0),则环境达标。课设明确要求:scikit-learn>=1.2.0,xgboost>=1.7.0,tensorflow>=2.13.0,backtrader>=1.9.77.123——版本过低将导致StandardScalerLSTM接口报错。

最后提醒:所有图表必须用plt.savefig()生成PNG,禁止截图;报告PDF中公式用LaTeX渲染(如$y_{t+1} = f(X_{t-29:t})$);回测曲线图横轴必须标注交易日期而非序号。这些细节,正是区分“能跑通”与“符合课设规范”的分水岭。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询