简介这份资源面向具备一定Python基础、希望入门数据挖掘与机器学习实战的学习者聚焦线性回归在股票预测中的完整落地流程。内容围绕数据获取与清洗、特征工程、模型训练、预测与评估展开涉及pandas数据处理、NumPy特征计算以及移动平均、MACD、RSI等技术指标的构建思路并借助sklearn线性回归完成拟合通过MSE、RMSE与R²衡量预测效果同时点明线性假设的局限与组合其他模型的改进方向。压缩包共2个文件包含1个py源码与1个pdf讲解文档源码对应完整实现过程文档辅助理解原理与步骤整体约2.34MB结构精简便于快速上手。目前已有4741人学习下载适合作为课程设计、项目练手或进一步研究股票预测的参考案例帮助读者把数据预处理、特征选择、模型训练与结果评估串联成一条可复用的实践路径。1. 从一份股票预测源码说起线性回归到底能挖出什么很多人第一次接触「Python数据挖掘与机器学习开发实战」都是从一份股票预测的源码压缩包开始的。解压、装依赖、跑通、看到一条拟合曲线然后心里冒出一个问题这条线真能预测明天的涨跌吗我当年也是这么入门的跑完第一遍兴奋跑完第十遍就冷静了——因为每次结果都不一样模型像在掷骰子。这份以线性回归为核心的股票预测案例真正值钱的地方不是那条线本身而是它把数据挖掘的完整链路摊开了怎么取数、怎么构造特征、怎么切分训练测试集、怎么评估、怎么避免自欺欺人。它适合两类人刚学完 Python 语法、想找一个能跑通的机器学习入门项目的新手以及做过业务数据分析、想把线性回归真正用到时间序列场景的从业者。下面我不复述某份源码而是按这个标题最常见的落地路径把每一步讲清楚让你能自己复现、自己调参、自己判断值不值得继续投入。2. 数据挖掘到线性回归股票预测的链路拆解与选型理由2.1 为什么股票预测常从线性回归起步线性回归是机器学习里最容易被低估的算法。它假设目标值 y 和特征 X 之间存在线性关系形式是 y wX b训练过程就是找一组权重 w 和偏置 b让预测值和真实值的残差平方和最小。放到股票场景里y 通常是「下一日收盘价」或「下一日涨跌幅」X 是各种技术指标、成交量、历史价格衍生出来的特征。选它起步有三个现实理由。第一可解释性强每个特征的系数直接告诉你它和预测目标的正负相关以及影响幅度这在金融场景里比黑盒模型更容易被接受。第二训练快几千到几万条样本在普通笔记本上秒级完成方便你快速验证特征工程有没有效果。第三它是理解过拟合、正则化、交叉验证这些概念的绝佳载体Lasso 和 Ridge 就是在它基础上加惩罚项。但必须说清楚边界股票价格序列是非平稳的今天和半年前的统计规律可能完全不同线性回归假设的独立同分布在这里并不成立。所以这个案例的正确用法是「学习完整流程」而不是「直接拿去实盘」。我一般会把它当成一个教学骨架跑通之后再往上加滚动窗口、加正则化、换模型对比。2.2 数据获取与特征构造的最小可用方案数据来源常见做法是用公开的行情接口拉日线数据字段包括日期、开盘、最高、最低、收盘、成交量。拿到原始数据后第一步是排序和去重确保按日期升序且没有重复交易日。第二步是构造特征这一步决定了模型上限。import pandas as pd import numpy as np # 假设 df 已包含 date, open, high, low, close, volume 列 df df.sort_values(date).drop_duplicates(date).reset_index(dropTrue) # 基础衍生特征 df[ret1] df[close].pct_change(1) # 日收益率 df[ma5] df[close].rolling(5).mean() # 5日均线 df[ma20] df[close].rolling(20).mean() # 20日均线 df[vol_ma5] df[volume].rolling(5).mean() # 成交量5日均 df[hl_range] (df[high] - df[low]) / df[close] # 振幅 # 预测目标下一日收盘价 df[target] df[close].shift(-1) # 去掉滚动窗口和 shift 产生的空值 df df.dropna().reset_index(dropTrue)这段代码的逻辑是用历史窗口统计量刻画趋势用收益率和振幅刻画波动用 shift(-1) 把「明天」对齐到「今天」这一行。参数上5 日和 20 日是常见短中期组合你可以改成 10 和 60 观察效果变化。注意 target 用 shift(-1) 之后最后一行没有未来数据必须 dropna 掉否则会引入空值报错。提示特征里不要直接放「当日收盘价」去预测「下一日收盘价」那样模型会学到 close 和 target 高度接近的伪关系评估指标好看但毫无预测意义。这是新手最容易翻车的地方。2.3 训练测试切分与评估指标怎么选时间序列不能随机切分这是血泪经验。随机切分会让未来数据泄漏到训练集模型在测试集上表现虚高。正确做法是按时间顺序切比如前 80% 做训练后 20% 做测试。from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score feature_cols [ret1, ma5, ma20, vol_ma5, hl_range] split int(len(df) * 0.8) train df.iloc[:split] test df.iloc[split:] X_train, y_train train[feature_cols], train[target] X_test, y_test test[feature_cols], test[target] model LinearRegression() model.fit(X_train, y_train) pred model.predict(X_test) print(MAE:, mean_absolute_error(y_test, pred)) print(RMSE:, np.sqrt(mean_squared_error(y_test, pred))) print(R2:, r2_score(y_test, pred))评估指标里MAE 和 RMSE 衡量误差绝对大小单位是价格单位直观R2 衡量拟合优度但股票预测里 R2 经常很低甚至为负不要因为 R2 低就否定整个流程。更贴近实战的做法是把预测价格转成涨跌方向算方向准确率。direction_acc ((pred test[close].values) (y_test.values test[close].values)).mean() print(方向准确率:, direction_acc)参数说明split 比例 0.8 是常见起点样本少时可以试 0.7feature_cols 要和你实际构造的列名一致多一列少一列都会报 KeyError。2.4 每次结果不一样随机性到底来自哪里热搜里有个高频疑问「模型预测股票涨跌每次结果不一样」这背后通常有三个来源。第一如果你用了随机切分或打乱数据每次划分不同结果自然不同。第二如果特征里有随机初始化或用了带随机性的模型比如 SGDRegressor随机种子没固定。第三数据本身在更新你两次跑用的数据范围不同。解决办法是固定随机种子并固定切分方式。LinearRegression 本身是确定性解法正常不会随机但只要你用了 train_test_split 且没设 random_state就会变。from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, shuffleFalse )注意 shuffleFalse 在时间序列里很关键它保证按顺序切分。random_state42 只是让任何内部随机过程可复现。把这两个参数固定后同一份数据跑出来的系数和指标应该完全一致。如果还不一致去检查数据读取环节有没有排序不稳定或去重逻辑有随机性。3. 从零复现环境、代码与参数调优的完整步骤3.1 环境准备与依赖安装新手最容易卡在环境上。推荐用 Python 3.9 到 3.11太新的版本某些科学计算库轮子还没跟上。用虚拟环境隔离依赖避免和系统 Python 冲突。python -m venv venv # Linux / macOS source venv/bin/activate # Windows venv\Scripts\activate pip install pandas numpy scikit-learn matplotlib如果你用 VSCode装好 Python 插件后按 CtrlShiftP 选择解释器指向 venv 里的 python。这一步没做对后面 import 报 ModuleNotFoundError 会浪费你半小时。参数上pandas 和 numpy 版本建议配套scikit-learn 用 1.2 以上即可不需要追最新。3.2 数据清洗与缺失值处理真实行情数据常见问题有三类停牌导致某天缺失、字段类型是字符串、除权除息造成价格跳变。处理顺序是先转类型再补缺失最后检查异常值。df[date] pd.to_datetime(df[date]) for col in [open, high, low, close, volume]: df[col] pd.to_numeric(df[col], errorscoerce) # 前向填充停牌日再用后向填充兜底 df[[open, high, low, close, volume]] ( df[[open, high, low, close, volume]].ffill().bfill() ) # 简单异常值检查单日涨跌幅超过 20% 标记出来人工确认 df[pct] df[close].pct_change() outliers df[df[pct].abs() 0.2] print(outliers[[date, close, pct]])逻辑说明errorscoerce 把无法转换的值变成 NaN避免字符串混入计算。ffill 用前一个有效值填充符合停牌期间价格不变的现实。异常值不一定要删但必须知道它们存在否则模型会被极端值带偏。参数 0.2 是经验阈值不同市场可以调整。3.3 特征标准化与多重共线性处理线性回归对特征尺度敏感尤其是你用了正则化的时候。标准化让每个特征均值为 0、方差为 1系数之间可比。另外 ma5 和 ma20 高度相关会带来多重共线性导致系数不稳定。from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) # 用方差膨胀因子检查共线性 from statsmodels.stats.outliers_influence import variance_inflation_factor import statsmodels.api as sm X_const sm.add_constant(X_train) vif pd.DataFrame({ feature: X_const.columns, VIF: [variance_inflation_factor(X_const.values, i) for i in range(X_const.shape[1])] }) print(vif)关键点scaler 只能在训练集上 fit然后 transform 测试集。如果对整个数据集 fit测试集的统计信息就泄漏进训练过程了。VIF 大于 10 通常认为共线性严重可以考虑删掉其中一个均线或改用均线差值作为特征。参数上VIF 阈值 5 到 10 都是常见判断区间。3.4 用 Ridge 和 Lasso 抑制过拟合普通最小二乘在特征多、样本少时容易过拟合。Ridge 加 L2 惩罚让系数整体收缩Lasso 加 L1 惩罚能把部分系数压到 0 实现特征选择。from sklearn.linear_model import Ridge, Lasso ridge Ridge(alpha1.0) ridge.fit(X_train_scaled, y_train) print(Ridge R2:, ridge.score(X_test_scaled, y_test)) lasso Lasso(alpha0.001, max_iter10000) lasso.fit(X_train_scaled, y_train) print(Lasso R2:, lasso.score(X_test_scaled, y_test)) print(非零系数特征:, [f for f, c in zip(feature_cols, lasso.coef_) if abs(c) 1e-6])参数说明alpha 是惩罚强度越大正则化越强。Ridge 的 alpha 从 0.1、1、10 试起Lasso 的 alpha 要小一些0.001 到 0.1 之间太大会把所有系数压成 0。max_iter 调大是防止 Lasso 在数据尺度大时不收敛。判断标准是看测试集指标不要只看训练集。3.5 滚动窗口验证更接近实盘的评估方式单次切分只能看一个时间段的表现滚动窗口能看模型在不同市场阶段的稳定性。做法是用固定长度训练窗向后滚动预测下一段。def walk_forward(df, feature_cols, train_size250, test_size20): results [] for start in range(0, len(df) - train_size - test_size, test_size): train df.iloc[start:start train_size] test df.iloc[start train_size:start train_size test_size] model LinearRegression() model.fit(train[feature_cols], train[target]) pred model.predict(test[feature_cols]) mae mean_absolute_error(test[target], pred) results.append({start: start, mae: mae}) return pd.DataFrame(results) res walk_forward(df, feature_cols) print(res[mae].describe())逻辑说明train_size250 约等于一年交易日test_size20 约一个月。每滚一次重新训练模拟「用历史数据预测未来一个月」的真实节奏。看 mae 的均值和标准差如果某些窗口误差突然飙升说明那段行情模型不适应这比单一 R2 有信息量得多。4. 避坑与排查股票预测里最容易翻车的五个地方4.1 未来函数泄漏指标好看但实盘必亏现象测试集 R2 高达 0.95 以上方向准确率 80%兴奋地以为找到了圣杯。原因特征里混入了未来信息比如用当日最高价预测当日收盘价或者标准化时对全量数据 fit。解决逐列检查特征生成时间戳确保每个特征在预测时刻只依赖历史数据标准化、填充、编码全部只在训练集 fit。我一般会写一个时间对齐检查函数把特征列和 target 的日期错位打印出来核对。4.2 用收盘价预测收盘价伪相关陷阱现象模型系数里 close 的权重接近 1其他特征权重接近 0。原因target 是下一日收盘价而 close 和它数值上高度接近模型直接抄近路。解决要么把 target 改成收益率或涨跌方向要么把 close 从特征里彻底移除只保留衍生指标。这个坑非常隐蔽因为指标不会报错只会让你误判模型能力。4.3 数据频率与对齐错误现象回测收益异常高或者出现未来日期。原因不同数据源日期格式不一致或者用了未复权的价格导致除权日出现巨大跳空。解决统一日期格式为 YYYY-MM-DD合并数据时用 merge 并检查行数变化价格数据确认是前复权还是后复权同一份分析里不要混用。参数上merge 之后用 df.shape 和 df.isna().sum() 快速体检。4.4 过拟合调参在测试集上反复试现象换一组参数测试集指标就涨一点最后参数多到记不清。原因把测试集当成了验证集反复使用信息泄漏。解决从训练集里再切一段验证集或者直接用滚动窗口的均值做选型依据。测试集只在最后用一次。这是方法论层面的坑比代码 bug 更难自查。4.5 忽略交易成本与滑点现象方向准确率 55%感觉能赚钱。原因没算手续费和滑点高频调仓下成本吃掉全部利润。解决在回测里加入单边千分之一到千分之三的成本假设并统计换手率。如果策略在加入成本后收益归零说明它赚的是噪声不是规律。这一步不做前面所有指标都是自嗨。5. 把线性回归股票预测用出价值三个进阶技巧第一个技巧是把预测目标从价格改成方向并做概率校准。价格回归的误差在震荡市里很难压低但方向分类配合阈值过滤能筛掉低置信度信号。做法是用 LogisticRegression 或对线性输出做符号判断只在高置信区间交易。# 用线性回归输出构造方向信号设置阈值过滤 pred model.predict(X_test) signal np.where(pred test[close].values * 1.005, 1, 0) # 预测涨幅超0.5%才看多 print(有效信号数:, signal.sum(), 总样本:, len(signal))阈值 1.005 表示预测涨幅超过 0.5% 才产生信号这个参数要根据波动率调整高波动市场可以放宽。第二个技巧是特征重要性分析配合业务解释。线性回归系数标准化后可以直接排序找出对预测贡献最大的因子。我一般会把系数和 VIF 放一起看系数大但 VIF 也大的特征要警惕它可能只是共线性的代表。特征标准化系数VIF处理建议ret10.421.8保留ma50.3112.5与 ma20 二选一ma200.2811.9与 ma5 二选一vol_ma5-0.152.1保留hl_range0.091.5保留第三个技巧是模型集成与对比基线。永远保留一个「预测明天等于今天」的朴素基线如果你的模型连这个基线都跑不赢说明特征工程没带来增量信息。把线性回归、Ridge、Lasso、朴素基线放同一张表对比才能判断投入是否值得。baseline_pred test[close].values # 朴素预测明天等于今天 baseline_mae mean_absolute_error(y_test, baseline_pred) print(基线 MAE:, baseline_mae, 模型 MAE:, mean_absolute_error(y_test, pred))如果模型 MAE 只比基线低一点点别急着高兴先检查这点差距在滚动窗口里是否稳定。我自己踩过的最大坑就是单窗口指标好看就上线结果换一段行情直接失效。后来养成习惯任何结论至少跑三个不同时间窗口指标一致才认。这套流程不保证你赚钱但能保证你不被自己骗。希望帮到你。本文还有配套的精品资源点击获取