文章标签

#Python 数据分析 #时间序列预测 #股价预测 #ARIMA #线性回归 #Matplotlib 可视化 #机器学习实战

一、前言

股票价格预测是时间序列分析最经典的落地场景之一,股价受交易行为、市场情绪等多重因素影响,具备典型的时序特征(趋势、波动、滞后关联)。本文基于真实股票历史数据,使用 Python 完成数据探查、预处理、可视化分析、特征工程、模型训练、效果对比、未来预测全流程实战。

项目分别采用线性回归ARIMA两大主流模型搭建预测框架,对比两种算法在股价时序数据上的拟合效果,同时搭配 K 线图、均线图、成交量、涨跌幅分布等可视化图表,完整还原金融数据分析思路。代码可直接运行,适合数据分析初学者、金融量化入门、课程设计参考。

二、项目整体介绍

2.1 项目背景

本次使用某股票历史交易数据集,包含开盘价、收盘价、最高价、最低价、成交量、涨跌幅、5/10/20 日均线等核心金融指标。通过挖掘股价波动规律,构建预测模型,实现对股票收盘价的短期预测,辅助理解时间序列建模逻辑。

2.2 开发环境与依赖库

  • 运行环境:Python 3.x(推荐 Jupyter Notebook)
  • 核心依赖:
    • pandas/numpy:数据读取、清洗、特征构造
    • matplotlib:基础可视化(折线图、柱状图、直方图)
    • pyecharts:绘制交互式 K 线图
    • sklearn:线性回归模型、模型评估指标
    • statsmodels:实现 ARIMA 时间序列模型

2.3 数据集说明

数据集文件:股价数据.xlsx,总计 611 条交易数据,共 14 个字段,关键字段释义:

表格

字段名 含义
date 交易日期
open/high/low/close 开盘价、最高价、最低价、收盘价(核心预测目标)
volume 当日成交量
price_change / p_change 价格变动额、涨跌幅(%)
ma5/ma10/ma20 5 日、10 日、20 日移动平均线(技术分析核心指标)

2.4 整体分析流程

  1. 数据导入与基础探查(查看结构、缺失值、数据量)
  2. 数据预处理(时间格式转换、时序排序、字段筛选)
  3. 探索性可视化(均线走势、K 线、成交量、涨跌幅分布)
  4. 特征工程(构造滞后特征,适配监督学习)
  5. 数据集划分(训练集 80% + 测试集 20%)
  6. 模型一:线性回归股价预测 + 模型评估
  7. 模型二:ARIMA 时序预测 + 模型评估
  8. 双模型效果对比 + 未来 10 日股价预测

三、完整代码分步实现

3.1 环境初始化 & 数据加载与探查

首先导入库,解决 Matplotlib 中文乱码、负号不显示 问题,再读取数据并完成基础探查。

python

运行

# 导入基础库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 解决绘图中文、负号显示问题(金融绘图必备)
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False

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

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

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

# 4. 统计缺失值(时序数据缺失会严重影响建模)
print("\n缺失值统计:")
print(df.isnull().sum())

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

运行结果说明:数据集共 611 条记录,无缺失值,数据质量良好;date 为字符串类型,后续需转为时间格式。

3.2 数据预处理与特征筛选(时序数据核心步骤)

股票原始数据通常为时间倒序,必须按时间升序排列,保证时序连续性;同时剔除冗余字段,保留建模核心特征。

python

运行

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

# 2. 按交易时间【从早到晚】升序排序(时序数据强制要求)
df.sort_values(by='date', inplace=True)

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

# 4. 重置行索引,保证数据整洁
df.reset_index(drop=True, inplace=True)

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

3.3 探索性数据分析(EDA)+ 可视化

通过多类图表挖掘股价、成交量、涨跌幅的分布与波动规律。

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

均线是股票技术分析核心指标,可判断股价趋势、金叉 / 死叉信号。

python

运行

# 绘制收盘价+三条均线折线图
plt.figure(figsize=(14, 6))
plt.plot(df['date'], df['close'], label='收盘价', linewidth=2)
plt.plot(df['date'], df['ma5'], label='5日均线', linestyle='--')
plt.plot(df['date'], df['ma10'], label='10日均线', linestyle='--')
plt.plot(df['date'], df['ma20'], label='20日均线', linestyle='--')

plt.legend()
plt.title('股票收盘价与均线走势图')
plt.grid(alpha=0.3)  # 添加网格,提升可读性
plt.show()
3.3.2 交互式 K 线图(pyecharts)

K 线图直观展示每日开盘、收盘、最高、最低价格,是金融分析标配图表。

python

运行

from pyecharts.charts import Kline
from pyecharts import options as opts

# 组装K线所需数据:open,close,high,low
k_data = df[['open','close','high','low']].values.tolist()

# 绘制K线图
kline = (
    Kline()
    .add_xaxis(df['date'].tolist())
    .add_yaxis("股票K线图", k_data)
    .set_global_opts(
        title_opts=opts.TitleOpts(title="股票交易K线图"),
        toolbox_opts=opts.ToolboxOpts(is_show=True)  # 开启工具箱,支持缩放、下载
    )
)
# 在Notebook中展示,也可使用 kline.render("K线图.html") 生成网页文件
kline.render_notebook()
3.3.3 成交量时间分布柱状图

成交量反映市场交易活跃度,常与股价联动分析。

python

运行

plt.figure(figsize=(14, 6))
plt.bar(df['date'], df['volume'], color='#4682B4')
plt.title('股票每日成交量柱状图')
plt.ylabel('成交量')
plt.show()
3.3.4 涨跌幅分布直方图

分析股价单日涨跌幅度的分布规律,红色虚线区分上涨 / 下跌区间。

python

运行

plt.figure(figsize=(14, 6))
# 绘制涨跌幅直方图
plt.hist(df['p_change'], bins=40, alpha=0.7, color='#2E8B57')
# 绘制0值分界线:左侧下跌,右侧上涨
plt.axvline(0, color='red', linestyle='--', label='跌涨分界线')

plt.legend()
plt.title('股票单日涨跌幅分布直方图')
plt.xlabel('涨跌幅(%)')
plt.ylabel('频次')
plt.show()

3.4 特征工程 & 数据集划分

时间序列无法直接随机划分数据集,必须按时间顺序分割;同时构造滞后特征(用前一日数据预测当日股价),将时序任务转为监督学习任务。

python

运行

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

# 2. shift会产生空值,删除缺失行
df = df.dropna()

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

# 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)} 条")

3.5 模型一:线性回归预测收盘价

使用 sklearn 线性回归模型训练,并通过 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)                      # 拟合优度(越接近1效果越好)
    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=(14, 6))
plt.plot(test["date"], y_test, label="真实收盘价", linewidth=2)
plt.plot(test["date"], y_pred_lr, label="线性回归预测值", linestyle="--", color='red')

plt.title("线性回归模型 - 股价预测对比")
plt.xlabel("交易日期")
plt.ylabel("股价(元)")
plt.legend()
plt.grid(alpha=0.3)
plt.show()

指标解读:本次线性回归模型 R² 达到 0.98,拟合效果优秀,说明股价与前一日收盘价、开盘价、5 日均线存在强线性关联。

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

ARIMA 是传统时间序列标杆模型,无需过多人工特征,直接基于序列本身趋势预测,采用滚动一步预测(金融时序标准用法)。

python

运行

from statsmodels.tsa.arima.model import ARIMA

# 1. 初始化列表,存储历史数据与预测结果
predictions = []
history = list(train["close"])  # 训练集收盘价作为初始历史序列

# 2. 滚动预测:逐行预测,每次预测后加入真实值更新模型
for i in range(len(test)):
    # ARIMA(p,d,q):p=10 自回归阶数,d=1 差分阶数,q=0 移动平均阶数
    model = ARIMA(history, order=(10, 1, 0))
    model_fit = model.fit()
    yhat = model_fit.forecast()[0]  # 预测下1个交易日收盘价
    predictions.append(yhat)
    # 把当日真实收盘价加入历史数据,实现滚动更新
    history.append(test["close"].iloc[i])

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

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

# 4. 可视化:真实值 VS ARIMA预测值
plt.figure(figsize=(14, 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()

3.7 双模型效果综合对比

将线性回归与 ARIMA 预测结果放在同一张图中,直观对比两者差异:

python

运行

plt.figure(figsize=(15, 6))
# 真实值
plt.plot(test["date"], y_test, label="真实收盘价", linewidth=2, color='black')
# 线性回归预测
plt.plot(test["date"], y_pred_lr, label="线性回归", linestyle="--", color='red')
# ARIMA预测
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()

3.8 基于 ARIMA 预测未来 10 个交易日股价

使用全量数据训练 ARIMA 模型,实现未来 10 日短期股价预测

python

运行

# 提取全量收盘价序列
full_series = df["close"]

# 训练ARIMA模型,预测未来10步
final_arima = ARIMA(full_series, order=(5, 1, 0)).fit()
future_pred = final_arima.get_forecast(steps=10).predicted_mean

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

四、模型结果分析与总结

4.1 两大模型指标对比

表格

模型 MAE(平均绝对误差) RMSE(均方根误差) R²(拟合度) 综合评价
线性回归 0.16 0.21 0.98 拟合效果最优,计算速度快,依赖人工特征
ARIMA 0.18 0.25 0.97 拟合略逊,无需复杂特征,纯时序建模

4.2 可视化与业务解读

  1. 均线分析:中长期均线(20 日)走势平滑,代表股价长期趋势;短期均线(5 日)波动更大,反映短期资金博弈。
  2. 涨跌幅分布:大部分交易日涨跌幅集中在 0 附近,极端涨跌(大涨 / 大跌)频次较低,符合常规股票波动特征。
  3. 模型适配场景
    • 线性回归:适合特征明确、线性关联强的场景,建模简单、运行高效,适合快速预测;缺点是依赖人工构造优质特征。
    • ARIMA:纯时间序列模型,专注挖掘数据自身趋势,无需额外业务特征,是传统时序问题首选;缺点是对非线性波动拟合能力一般,参数调优成本较高。

4.3 项目总结

  1. 技术层面:完整实现时序数据预处理、特征工程、数据集划分、双模型建模、可视化评估全链路,掌握金融时序分析标准流程。
  2. 知识点复盘
    • 时序数据禁止随机划分数据集,必须按时间顺序分割;
    • 滞后特征(shift)是时序转监督学习的核心手段;
    • MAE/RMSE 衡量预测误差大小,R² 衡量模型整体拟合能力;
    • ARIMA 核心三参数 (p,d,q):p 自回归阶数、d 差分阶数、q 移动平均阶数。
  3. 局限性与优化方向
    • 本案例仅使用历史价格、均线特征,未引入成交量、市场指数、舆情等外部特征;
    • 股票价格受政策、消息面等非线性因素影响大,传统线性模型有上限,可进阶尝试 LSTM、Prophet 等模型;
    • ARIMA 参数可通过 ACF/PACF 图、AIC/BIC 准则自动寻优,进一步提升精度。

五、常见问题答疑

  1. 运行代码提示中文乱码? 检查是否添加两行配置:plt.rcParams["font.family"] = "SimHei"plt.rcParams["axes.unicode_minus"] = False
  2. ARIMA 出现索引警告? 属于正常提示,不影响预测结果,原因是原始时间索引未设置时序频率,可忽略。
  3. 数据读取失败? 确保 股价数据.xlsx 文件与代码文件放在同一目录,或填写文件绝对路径。

更多推荐