一、文章前言

股票股价预测是经典的时间序列分析实战案例,股价受成交量、均线、历史价格等多重因素影响,属于典型的非平稳时间序列数据。

本文基于 Python 完成股价数据探索、数据预处理、可视化分析、双模型建模预测全流程,分别使用线性回归ARIMA 时间序列模型实现股价预测,并对比模型效果,最后完成未来 10 个交易日股价预测。全程代码可直接运行,适合数据分析、机器学习、时间序列入门学习者参考。

项目工具与依赖库

  • 开发环境:Python 3.x/ Jupyter Notebook
  • 核心库:pandasnumpymatplotlibscikit-learnstatsmodels
  • 数据集:Excel 股票历史数据(包含日期、开盘价、收盘价、均线、成交量、涨跌幅等 14 个字段)

二、整体项目流程

本项目分为七大模块,完整流程如下:

  1. 需求梳理 + 数据读取与基础探查
  2. 数据预处理 & 特征工程
  3. 探索性数据分析 (EDA) + 数据可视化
  4. 时间序列数据集构造、训练集 / 测试集划分
  5. 模型一:线性回归股价预测 + 模型评估
  6. 模型二:ARIMA 时间序列模型预测 + 模型评估
  7. 双模型效果对比 + 未来 10 日股价预测

三、完整代码实战(分步讲解)

3.1 阶段 1:导入库 + 数据读取与基础探查

首先导入数据分析、绘图相关库,解决 Matplotlib 中文乱码、负号显示问题,再读取 Excel 股票数据,完成基础数据探查。

python

运行

# 1. 导入依赖库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 解决Matplotlib中文、负号显示乱码问题
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False

# 2. 读取Excel股价数据
df = pd.read_excel("股价数据.xlsx")

# 3. 查看前5行数据
print("数据前5行:")
print(df.head())

# 4. 查看数据基本信息(字段类型、非空值)
print("\n数据基本信息:")
print(df.info())

# 5. 统计缺失值
print("\n各字段缺失值统计:")
print(df.isnull().sum())

# 6. 统计数据总条数
print(f"\n数据集总条数:{len(df)}")

代码说明

  • info():查看字段名称、数据类型、非空样本数;
  • isnull().sum():精准统计每一列缺失值数量,是数据质量校验核心步骤。

3.2 阶段 2:数据预处理与特征工程

股票原始数据大多为时间倒序,且日期为文本格式,需要完成时间格式转换、数据排序、字段筛选、索引重置等预处理。

python

运行

# 1. 将日期列转为标准时间格式
df["date"] = pd.to_datetime(df["date"])

# 2. 按时间升序排序(从早到晚)
df = df.sort_values(by="date").reset_index(drop=True)

# 3. 保留核心分析字段,剔除冗余字段
keep_cols = ["date", "open", "close", "high", "low", "volume", "p_change", "ma5", "ma10", "ma2Up20"]
df = df[keep_cols]

# 4. 重置索引
df = df.reset_index(drop=True)

print("预处理后数据前5行:")
print(df.head())

代码说明

  • pd.to_datetime():文本日期转为时间类型,是时间序列分析必备操作;
  • sort_values:修正股票数据倒序问题,保证时间连续性;
  • 筛选核心字段:仅保留股价、成交量、均线等对预测有效的特征。

3.3 阶段 3:探索性数据分析 (EDA) & 可视化

通过多张图表可视化股价走势、成交量、涨跌幅分布,挖掘数据潜在规律(均线金叉 / 死叉、量价关系等)。

3.3.1 收盘价 + 5/10/20 日均线走势图

python

运行

# 绘制收盘价与三条均线走势
plt.figure(figsize=(16, 6))
plt.plot(df["date"], df["close"], label="收盘价", linewidth=2)
plt.plot(df["date"], df["ma5"], label="5日均线")
plt.plot(df["date"], df["ma10"], label="10日均线")
plt.plot(df["date"], df["ma2Up20"], label="20日均线")

plt.title("股票收盘价与均线走势")
plt.xlabel("日期")
plt.ylabel("股价")
plt.legend()
plt.grid(alpha=0.3)
plt.show()
3.3.2 成交量柱状图

python

运行

# 绘制成交量时间分布柱状图
plt.figure(figsize=(16, 6))
plt.bar(df["date"], df["volume"], alpha=0.7, color="#1f77b4")
plt.title("股票成交量时间分布")
plt.xlabel("日期")
plt.ylabel("成交量")
plt.grid(alpha=0.3, axis="y")
plt.show()
3.3.3 涨跌幅分布直方图

python

运行

# 绘制涨跌幅分布直方图
plt.figure(figsize=(10, 5))
plt.hist(df["p_change"], bins=50, alpha=0.7, color="#ff7f0e")
plt.title("股票涨跌幅分布直方图")
plt.xlabel("涨跌幅")
plt.ylabel("频次")
plt.grid(alpha=0.3)
plt.show()

分析思路

  1. 均线与收盘价交叉:金叉(短期均线上穿长期均线)通常视为上涨信号,死叉反之;
  2. 结合成交量:成交量放大阶段,往往伴随股价大幅波动;
  3. 涨跌幅直方图:可直观判断股价波动是否集中在合理区间。

3.4 阶段 4:构造时序特征 + 划分训练集 / 测试集

时间序列不能随机划分数据集,必须按时间顺序分割。本文使用前一日收盘价构造滞后特征,用历史数据预测当日收盘价。

python

运行

# 1. 构造滞后特征:前1天收盘价
df["close_lag1"] = df["close"].shift(1)

# 2. 删除因shift产生的空值
df = df.dropna()

# 3. 按时间划分:前80%训练集,后20%测试集
split_rate = 0.8
split_point = int(len(df) * split_rate)
train = df.iloc[:split_point]
test = df.iloc[split_point:]

# 4. 定义特征列与标签列
feature_cols = ["close_lag1", "open", "ma5"]
X_train = train[feature_cols]
y_train = train["close"]
X_test = test[feature_cols]
y_test = test["close"]

print(f"训练集数据量:{len(train)} 条")
print(f"测试集数据量:{len(test)} 条")

核心要点

  • shift(1):向下偏移一行,实现滞后特征构造,是时序预测常用手法;
  • 数据集划分:严格按时间切割,禁止随机打乱,保证时序逻辑。

3.5 阶段 5:模型一 线性回归预测

使用线性回归模型完成股价预测,并通过 MAE、RMSE、R² 三大指标评估模型效果。

python

运行

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# 定义模型评估函数
def eval_model(y_true, y_pred):
    mae = mean_absolute_error(y_true, y_pred)
    rmse = np.sqrt(mean_squared_error(y_true, y_pred))
    r2 = r2_score(y_true, y_pred)
    print(f"平均绝对误差 MAE: {mae:.2f}")
    print(f"均方根误差 RMSE: {rmse:.2f}")
    print(f"拟合优度 R²: {r2:.2f}")

# 1. 初始化并训练线性回归模型
lr = LinearRegression()
lr.fit(X_train, y_train)

# 2. 测试集预测
y_pred_lr = lr.predict(X_test)

# 3. 模型评估
print("===== 线性回归模型评估结果 =====")
eval_model(y_test, y_pred_lr)

# 4. 可视化:真实值 VS 预测值
plt.figure(figsize=(16, 6))
plt.plot(test["date"], y_test, label="真实收盘价", linewidth=2)
plt.plot(test["date"], y_pred_lr, label="线性回归预测值", linestyle="--")
plt.title("线性回归模型 - 股价预测结果")
plt.xlabel("日期")
plt.ylabel("收盘价")
plt.legend()
plt.grid(alpha=0.3)
plt.show()

评估指标解释

  • MAE(平均绝对误差):预测值与真实值平均差值,越小效果越好;
  • RMSE(均方根误差):放大较大误差,对异常波动更敏感;
  • R²(拟合优度):取值[0,1],越接近 1 代表模型拟合效果越好。

3.6 阶段 6:模型二 ARIMA 时间序列模型预测

ARIMA 是经典单变量时间序列预测模型,适用于股价、销量、流量等时序数据,采用滚动一步预测方式。

python

运行

from statsmodels.tsa.arima.model import ARIMA

# 1. 初始化历史数据与预测列表
history = list(train["close"])
predictions = []

# 2. 滚动预测(逐行预测,动态更新历史数据)
for i in range(len(test)):
    # ARIMA(p,d,q) 本文使用 order=(10,1,0)
    model = ARIMA(history, order=(10, 1, 0))
    model_fit = model.fit()
    # 预测未来1步
    yhat = model_fit.forecast()[0]
    predictions.append(yhat)
    # 将真实值加入历史数据,更新模型
    history.append(test["close"].iloc[i])

# 转为数组
y_pred_arima = np.array(predictions)

# 3. 模型评估
print("\n===== ARIMA模型评估结果 =====")
eval_model(y_test, y_pred_arima)

# 4. 可视化预测结果
plt.figure(figsize=(16, 6))
plt.plot(test["date"], y_test, label="真实收盘价", linewidth=2)
plt.plot(test["date"], y_pred_arima, label="ARIMA预测值", linestyle="--", color="orange")
plt.title("ARIMA模型 - 股价预测结果")
plt.xlabel("日期")
plt.ylabel("收盘价")
plt.legend()
plt.grid(alpha=0.3)
plt.show()

ARIMA 参数说明 order=(p,d,q)

  • p:自回归阶数;
  • d:差分阶数(非平稳序列转为平稳序列);
  • q:移动平均阶数。

3.7 阶段 7:双模型对比 + 未来 10 日股价预测

3.7.1 线性回归 & ARIMA 同图对比

python

运行

# 双模型预测效果对比图
plt.figure(figsize=(18, 6))
plt.plot(test["date"], y_test, label="真实收盘价", linewidth=2)
plt.plot(test["date"], y_pred_lr, label="线性回归", linestyle="--")
plt.plot(test["date"], y_pred_arima, label="ARIMA", linestyle="--", color="red")

plt.title("线性回归 VS ARIMA 股价预测效果对比")
plt.xlabel("日期")
plt.ylabel("收盘价")
plt.legend()
plt.grid(alpha=0.3)
plt.show()
3.7.2 预测未来 10 个交易日股价

python

运行

# 使用全量数据训练ARIMA,预测未来10日股价
full_close = df["close"]
final_model = ARIMA(full_close, order=(5, 1, 0)).fit()

# 预测未来10步
future_10 = final_model.get_forecast(steps=10).predicted_mean

# 打印预测结果
print("\n===== 未来10个交易日收盘价预测 =====")
for idx, price in enumerate(future_10, 1):
    print(f"第{idx}个交易日 预测股价:{price:.2f} 元")

四、模型总结与项目分析

4.1 模型效果对比

  1. 线性回归

    • 优点:模型简单、训练速度快、可解释性强;
    • 缺点:属于线性模型,难以捕捉股价非线性波动,对暴涨 / 暴跌行情预测偏差较大。
  2. ARIMA 模型

    • 优点:专门针对时间序列设计,擅长挖掘时序趋势与周期性;
    • 缺点:仅使用单变量(收盘价)建模,未结合成交量、均线等外部特征,极端行情依然存在误差。

4.2 项目拓展方向

  1. 引入LSTM、Prophet等深度学习 / 专业时序模型,提升预测精度;
  2. 增加技术指标(MACD、KDJ、BOLL)作为特征;
  3. 做多因子融合,结合大盘、行业数据联合预测;
  4. 对 ARIMA 的 p/d/q 参数做网格搜索,优化模型参数。

4.3 重要提醒

本项目仅为编程与数据分析学习实战,股市行情受政策、消息、资金等多重不可控因素影响,模型预测结果不能作为实际炒股依据

五、完整项目源码汇总

将以上所有代码按顺序拼接,即可直接在 Jupyter Notebook / Python 编辑器中运行,仅需保证 股价数据.xlsx 文件和代码在同一目录下。

六、博文结尾

本篇文章从零到一完成了股票时间序列预测全流程实战,覆盖数据处理、可视化、传统机器学习、经典时序模型三大板块,是入门时间序列分析非常经典的练手项目。

如果文章对你有帮助,欢迎点赞、收藏、评论,后续会持续分享 Python 数据分析、机器学习、时间序列相关实战案例~

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐