简介:这份资料是一套基于MATLAB实现的支持向量机改进ARIMA股票价格预测源码,适合金融数据分析爱好者、量化研究者以及学习时间序列与机器学习结合的开发者。方案先用ARIMA模型对历史收盘价做基础预测,利用其处理趋势性与随机波动的能力;再引入SVM对ARIMA预测残差进行非线性修正,通过核函数映射在高维空间拟合复杂规律,从而提升预测准确度。同时给出R方、MSE、相对误差等评价指标,便于量化对比改进前后的性能提升。压缩包共3个文件,包含主程序main.m、SVM预测函数svmfun.m和上证指数收盘价.xlsx历史数据,整体仅13KB,结构清晰、轻量可行,替换数据即可用于其他股票或指数预测。该资源已被1047人学习浏览,代码注释明确、流程完整,能帮助读者掌握ARIMA与SVM组合建模的完整思路,并可直接用于课程设计、毕业设计或量化策略研究验证。
1. 股票价格预测里的另一个选型:为什么用 SVM 改进 ARIMA 而不是直接上深度学习
股票价格预测这个题目,很多同学一上来就选 LSTM,觉得深度学习才够“高级”。但真拿到一份上证指数收盘价.xlsx 的时候才会发现:样本量可能只有几千条,调参却要花好几个小时,最后指标还不一定比简单模型好。ARIMA+SVM 是一个更务实的组合:ARIMA 先把序列里的线性趋势和自相关性吃掉,SVM 再针对 ARIMA 的预测值做非线性修正,实现思路清晰,MATLAB 跑起来也快。这套方案按可交付的课设或毕设标准来写,从需求、总体设计、具体实现到验收答辩都会覆盖,适合想用 MATLAB 做股票价格预测,同时需要把“改进点”讲清楚的场景。
2. 需求分析与总体设计:先定评价口径,再拆 ARIMA 与 SVM 的协作关系
2.1 预测目标与评价口径:R²、MSE、相对误差怎么统一
做方案先别急着写代码,得把“什么叫预测成功”定下来。这里的数据是上证指数收盘价,属于单一时间序列,目标很清楚:用历史收盘价预测未来一段的收盘价,并证明 ARIMA+SVM 比单独 ARIMA 更好。常见做法是按时间顺序切分样本,前 70% 作为训练集,后 30% 作为验证集,不能随机打乱,否则时间序列的先后依赖关系会被破坏。
评价指标里,R²(决定系数)表示模型解释的变异程度,越接近 1 说明拟合越好;MSE 是预测值与真实值差值的平方均值,越小越好;相对误差用预测值与真实值的差除以真实值,再取平均,能反映误差在价格水平中的占比。实际验收时这三个指标要一起看,不能只挑 R² 高的说事。
注意:股票价格序列的“下一步预测”天然会滞后,R² 很容易被高估。验收时最好同时报多步预测的误差,或者画出预测对比图让评委直观看到。
| 指标 | 计算口径 | 方向 | 验收要求 |
|---|---|---|---|
| R² | 1 - 残差平方和 / 总平方和 | 越接近 1 越好 | 对比 ARIMA 与 ARIMA+SVM |
| MSE | 预测值与真实值差值的平方均值 | 越小越好 | 在同一测试集上计算 |
| 相对误差 | |预测值 - 真实值| / 真实值 取平均 | 越小越好 | 按价格水平归一,防止高价股虚高 |
2.2 模块结构与调用关系:main.m、svmfun.m 和 Excel 数据的分工
工程结构采用“主脚本 + 功能函数”的组织方式。main.m 是入口,负责读入上证指数收盘价.xlsx、画时序图、调用 ARIMA 建模、再把预测结果交给 svmfun.m,最后计算指标并输出对比图。svmfun.m 是独立的 SVM 功能函数,接收价格序列、ARIMA 预测值和真实值,内部完成特征构造、归一化、模型训练和预测,返回修正后的最终结果。
这样拆分的好处是责任清楚:main.m 里不堆机器学习代码,svmfun.m 也不处理 Excel 读取和画图。数据流可以简单描述为:Excel 收盘价 → main.m 做差分与 ARIMA 拟合 → 输出 ARIMA 预测 → 将 ARIMA 预测值和滞后价格组成特征 → svmfun.m 完成 SVM 训练与预测 → 叠加 ARIMA 基线 → 计算 R²、MSE、相对误差 → 出图。
| 文件 | 职责 | 关键内容 |
|---|---|---|
| main.m | 流程调度 | 数据读取、ARIMA 定阶与预测、调用 svmfun.m、指标汇总 |
| svmfun.m | SVM 实现 | 特征构造、标准化、fitrsvm 训练、预测与反归一化 |
| 上证指数收盘价.xlsx | 数据源 | 历史收盘价序列,也可替换为其他股票数据 |
2.3 技术选型为什么是 MATLAB:工具箱让 ARIMA 和 SVM 都变成“配置”
用 MATLAB 做这个项目,最大优势是官方工具箱把底层数学封装好了。ARIMA 部分对应 Econometrics Toolbox,核心函数是 arima、estimate、forecast;平稳性检验用 adftest;SVM 回归用 Statistics and Machine Learning Toolbox 的 fitrsvm;模型定阶比较用 aicbic。相比 Python 里要分别装 statsmodels 和 scikit-learn,MATLAB 一个环境就能完成数据处理、建模、画图,出图样式也更适合直接放进论文。
但要注意,MATLAB 版本差异会带来函数名和参数名变化。比如 SVM 相关函数在不同版本里可能是 svmtrain 或 fitrsvm,拟合选项写法也有区别。我一般会先运行doc fitrsvm确认当前环境的接口,再决定写不写参数。不要把预测做成“黑匣子”——这里的黑匣子不是指 MATLAB,而是不思考参数含义、跑一个默认 SVM 就交差,后面第 5 章会专门讲最容易翻车的几个点。
3. ARIMA 基线实现:从平稳性检验到 p、d、q 定阶,先让线性部分收敛
3.1 数据预处理与平稳性检验:先看图,再差分,别急着拟合
拿到收盘价序列,第一件事不是直接拟合 ARIMA,而是先画时序图和自相关图。价格序列在水平值上通常不平稳:长期趋势明显,ACF 衰减极慢。先用 adftest 做单位根检验,若 p 值大于显著性水平,做一阶差分,再检验。这一步直接决定 ARIMA 的差分阶数 d。
% main.m 中的数据读取与平稳性检查 data = readtable('上证指数收盘价.xlsx'); price = data.Close; % 收盘价列,按实际 Excel 列名修改 dates = data.Date; % 水平值检验:H=1 表示拒绝单位根,序列平稳 [H1, pValue1] = adftest(price); if ~H1 dPrice = diff(price); % 一阶差分 else dPrice = price; end % 差分后再次检验 [H2, pValue2] = adftest(dPrice); fprintf('diff H=%d, pValue=%.4f\n', H2, pValue2);这里 readtable 读取 Excel 后返回 table,直接用data.Close取收盘价列;如果列名不是 Close,改成实际列名即可。adftest 默认形式包含常数项,对带趋势的序列不一定敏感,需要时可以加'model', 'trend'再检验一次。差分不是越多越好,d=1 对金融价格序列通常够用,过度差分会把趋势信息变成噪声。
3.2 ARIMA 模型拟合与预测:用 AIC 在有限范围里选 p、q
定完 d 之后,剩下的是自回归阶数 p 和移动平均阶数 q。选阶数有两种常见做法:一是看 ACF/PACF 的截尾和拖尾特征,二是把 p、q 各从 0 到 5 遍历,用 AIC 比较拟合优度。第二种更适合课设和毕设,结果可复现,代码也短。main.m 里的实际实现就是遍历法。
% main.m 中 ARIMA 定阶与预测 pRange = 0:5; qRange = 0:5; bestAIC = inf; bestPQ = [0 0]; bestModel = []; for p = pRange for q = qRange mdl = arima(p, d, q); % d 来自差分检验 try [estMdl, ~, logL] = estimate(mdl, dPrice, 'Display', 'off'); [aic, ~] = aicbic(logL, p + q + 1, numel(dPrice)); if aic < bestAIC bestAIC = aic; bestPQ = [p q]; bestModel = estMdl; end catch continue; % 参数不收敛时跳过该组合 end end end % 对原始收盘价序列做 h 步预测 h = 20; predARIMA = forecast(bestModel, h, 'Y0', price);p 是自回归阶数,表示用过去 p 个时刻的值解释当前值;q 是移动平均阶数,表示用过去 q 个时刻的预测误差修正当前值;d 是差分次数。aicbic 的第二个参数是模型参数个数,这里用p + q + 1表示包含常数项;如果常数项不显著,可以去掉并改成p + q。forecast 的Y0要传原始价格序列,这样返回的预测值才是价格水平而不是差分值。需要说明的是,forecast 默认做静态多步预测,也就是用预测出来的值继续往后推,这和每一步都用真实值修正的滚动预测不同,写论文时要把预测口径写清楚。
3.3 ARIMA 基线局限:为什么 R² 不低,转折点还是跟不上
纯 ARIMA 对股票序列的经典问题是:预测值像是“昨天的价格加上一个线性惯性”,在单边趋势段表现不错,但遇到反转和波动率聚集时明显滞后。原因是 ARIMA 建模的是条件均值,而股票价格里还包含波动率聚集、跳跃、市场情绪等非线性结构,这些结构不会出现在 ARIMA 的线性假设里。
这一步是后面引入 SVM 的动机。ARIMA 预测值与真实值之间的残差并不一定是白噪声,里面可能还残留可学习的信息。如果残差完全随机,那 SVM 也救不回来;如果残差存在某种模式,比如下跌后反弹、上涨后回调,SVM 就有机会把它学出来。我一般会在这里多画一张残差图,如果残差 ACF 上还挂着几个显著的点,就说明模型有改进空间,这也可以作为论文里“为什么要做 SVM 改进”的直接证据。
4. SVM 改进实现:用 svmfun.m 学习 ARIMA 残差并做非线性补偿
4.1 改进思路:串联修正比并联融合更适合“改进 ARIMA”这个题目
SVM 和 ARIMA 结合有两种常用结构。第一种是并联:把 ARIMA 预测值当作特征之一,让 SVM 直接预测价格,相当于两个模型竞争融合。第二种是串联:先用 ARIMA 得到基础预测,再让 SVM 对“真实值与 ARIMA 预测之间的差”建模,最后把修正量叠加到 ARIMA 预测上。本项目 svmfun.m 走的是串联修正路线,因为这样解释起来最顺:ARIMA 解决线性主趋势,SVM 在高维特征空间拟合残差中的非线性成分,两个模型不是抢活,而是接力。
答辩时常被问“你的改进在哪”,串联结构可以明确回答:改进的是 ARIMA 残差的利用方式,不是把两个模型结果强行平均。svmfun.m 的输入包含 ARIMA 预测值、历史价格、滚动统计量,输出是修正后的最终预测。这个设计也方便扩展,后续想加入成交量、涨跌幅、宏观经济指标等外部特征,只需要在特征矩阵里多拼一列。
4.2 svmfun.m 的实现:特征构造、归一化、RBF 回归与反归一化
svmfun.m 的核心代码可以按下面这个框架来实现。它不承担数据读取和画图职责,只负责 SVM 相关逻辑,保证 main.m 调用时接口清晰。
function [finalPred, metrics] = svmfun(price, arimaPred, yTrue, params) % svmfun.m 核心实现:用支持向量机回归学习 ARIMA 预测的修正量 % 输入: % price 历史收盘价列向量 % arimaPred ARIMA 对测试集的预测值 % yTrue 测试集真实值 % params BoxConstraint, KernelScale, Epsilon % 1. 构造特征:使用滞后价格与 ARIMA 预测 X = [price(end-numel(arimaPred)+1:end-1), ... arimaPred(1:end-1), ... movmean(price(end-numel(arimaPred):end-1), 5)]; y = yTrue(2:end) - arimaPred(2:end); % 目标:ARIMA 的误差项 % 2. 按时间顺序切分训练/测试 trainN = round(size(X,1) * 0.7); Xtrain = X(1:trainN,:); ytrain = y(1:trainN); Xtest = X(trainN+1:end,:); ytest = y(trainN+1:end); % 3. 训练集上计算归一化参数,测试集只用同一组参数 muX = mean(Xtrain); sx = std(Xtrain); Xtrain = (Xtrain - muX) ./ sx; Xtest = (Xtest - muX) ./ sx; % 4. RBF 核 SVM 回归 svmMdl = fitrsvm(Xtrain, ytrain, ... 'KernelFunction', 'rbf', ... 'BoxConstraint', params.BoxConstraint, ... 'KernelScale', params.KernelScale, ... 'Epsilon', params.Epsilon, ... 'Standardize', false); % 已手动标准化,避免重复 % 5. 预测修正量并叠加到 ARIMA 预测 corr = predict(svmMdl, Xtest); corr = corr(:); finalPred = arimaPred(2:end) + corr; % 6. 计算评价指标 residual = ytest - finalPred; metrics.R2 = 1 - sum(residual.^2) / sum((ytest - mean(ytest)).^2); metrics.MSE = mean(residual.^2); metrics.RelErr = mean(abs(residual ./ ytest)); end参数说明:BoxConstraint 是回归误差的惩罚系数,值越大模型越努力拟合训练集,但容易过拟合;KernelScale 控制 RBF 核的宽度,值越小拟合越精细,值越大越平滑;Epsilon 是回归不敏感带的宽度,值越大允许误差越大,预测结果越平。这三个参数是调 SVM 时最常碰到的旋钮,可以在 main.m 里写一个简单网格循环,用验证集 MSE 选最优组合。这里的特征矩阵刻意保持保守:只用滞后价格、ARIMA 预测和滚动均值,没有使用任何“未来时刻才知道”的信息,这是数据泄漏方面最重要的一条底线。
4.3 对比实验与指标解读:ARIMA 与 ARIMA+SVM 的差距从哪里来
跑完 main.m 后会得到一张对比表和三条指标。下面是一个示例输出,具体数值会随数据和参数变化,但趋势有参考价值:
| 模型 | R² | MSE | 平均相对误差 |
|---|---|---|---|
| 单独 ARIMA | 0.9123 | 42.7 | 3.85% |
| ARIMA + SVM | 0.9375 | 31.9 | 2.91% |
从这个示例可以看到,R² 提升约 2.5 个百分点,MSE 下降约 25%,相对误差降低近 1 个百分点。提升主要来自 SVM 修正了 ARIMA 在转折点处的系统偏差,而不是把每个点都猜得更准。如果你的数据跑出来没有提升,优先检查三件事:特征里是否混入了未来信息、Epsilon 是否设得太大导致预测太平滑、训练集是否太短以至于无法学出残差模式。指标提升不明显时,不要强行改数据,更不要再造一组“看起来更好”的标签,答辩时被追问反而更危险。
5. 常见问题与避坑:数据泄漏、预测滞后和 SVM 平线的排查方法
模型跑得好不好有时确实带点玄学,但最容易翻车的几个点几乎是固定的。下面这五条按“现象 → 原因 → 解决”写,出自相似预测项目里的血泪经验,可以直接对照排查。
5.1 数据泄漏:归一化之后才切分,测试集指标虚高
现象:测试集 R² 高得离谱,接近 0.99,但把同一套模型用到新数据上立刻失效。
原因:常见有两种。一是用全序列的均值和标准差做标准化,测试集的信息提前进入了训练流程;二是特征构造时不小心使用了“未来”的真实价格,比如用 t 日的收盘价去预测 t 日的价格。
解决:标准化参数只在训练段计算,测试段套用同一组参数;构造滞后特征时统一用 t-1 及之前的数据。上面 svmfun.m 的写法已经体现这个原则,如果你把代码改成“全序列一起归一化”,指标会虚高,但答辩时会被一眼看穿。
5.2 差分阶数设过头:ARIMA 模型把趋势学成了噪声
现象:d=2 时差分序列的方差明显变大,预测曲线频繁抖动,ACF 反而出现异常负相关。
原因:平稳性检验只回答了“是否平稳”,没回答“差分是否必要”。过度差分会去掉价格序列里的长期记忆,让模型去拟合随机噪声。
解决:用 adftest 从 d=0 开始逐级检验,只要 p 值小于 0.05 就停;金融价格序列一般 d=1 够用。不要为了“让序列更平稳”而无限差分,差分次数越多,模型离真实价格水平越远。
5.3 SVM 预测结果是一条平线
现象:最终预测在某个常数附近小幅波动,与 ARIMA 预测几乎无关,画出图来像一条直线。
原因:可能是特征与目标相关性太弱,模型只能学到均值;也可能是 Epsilon 设得太大,回归不敏感带过宽;还可能是 BoxConstraint 太小,模型被强制拉平。
解决:先固定 Epsilon=0.1、BoxConstraint=1 试跑,再看训练集和测试集 MSE。如果训练集上也几乎是平线,说明特征没构造好,要把滞后价格和 ARIMA 预测的交互信息加进去。如果训练集能拟合但测试集平线,则是过拟合,需要调大 KernelScale 或减小 BoxConstraint。
5.4 p、q 自动寻优结果不稳定:换一段数据最优参数就变
现象:同一段数据里 AIC 选出的 p/q 是 (2,3),换成另一段数据就变成 (4,1),验证集误差没有明显改善。
原因:AIC 是样本内拟合准则,参数范围一大,就容易在噪声上找到“最优”组合。p、q 阶数过高时,模型把随机波动也记住了。
解决:把 p、q 限制在 0~5,不要放开到 10 以上;用滚动时间序列交叉验证代替单次切分;对多个候选模型都记录验证误差,选最稳定的而不是 AIC 最小的。论文里可以写“限定 p、q 范围为 0~5,用 AIC 结合验证误差选择”,这句话比“自动寻优得到最优模型”严谨得多。
5.5 预测曲线总是滞后一拍
现象:把预测值和真实值画在一起,预测曲线几乎是真实值向右平移了一天,但 R² 还挺高。
原因:主要特征包含 t-1 的真实收盘价,模型学会的是“复制上一个价格”,而不是真正预测未来。滞后越明显,说明模型对历史价格的依赖越强。
解决:在论文里明确报告的是“下一步预测”还是“多步预测”。如果必须用滞后价格做特征,同时报告 h=3 或 h=5 的多步预测误差。答辩时主动讲“我这里展示的是一步滚动预测,多步预测误差会变大”,比被评委问出来要体面得多。
6. 验收与答辩:从跑通脚本到讲清楚“改进在哪”的完整清单
6.1 验收清单:跑通、指标、图表、替换数据
拿到这套完整工程后,建议按下面的清单走一遍。直接运行 main.m,能输出 ARIMA 与 ARIMA+SVM 的对比图和三个指标;把上证指数收盘价.xlsx 换成另一只股票的数据,修改 readtable 的路径和列名,再运行,不报错;残差图里 ARIMA 的残差仍有聚集现象,ARIMA+SVM 的残差更接近白噪声;论文里至少放一张预测对比图、一个指标表、一段超参数选择说明。完整工程包里已经包含 main.m、svmfun.m 和上证指数收盘价.xlsx,拿到后按这份清单跑一遍即可。
6.2 答辩时怎么讲“改进在哪”
高频问题可以这样准备。问“SVM 做了什么”,回答:对 ARIMA 预测误差建模,在高维特征空间拟合残差中的非线性模式。问“为什么不用 LSTM”,回答:当前数据量不大,LSTM 调参成本高,SVM 更容易解释,也能用 MATLAB 快速完成。问“参数是不是随便试的”,回答:p/d/q 用 AIC 在限定范围里选,SVM 超参数用交叉验证做网格搜索。问“如何避免数据泄漏”,回答:标准化参数和特征构造都在训练段内完成,测试段只做预测。
6.3 一个自查习惯
我现在的习惯是,每次拿到预测结果都强制走一遍自查:先看残差图,再打乱标签跑一次对照实验。如果打乱标签后指标没有明显变差,说明模型学到的是噪声而不是规律,这份结果就不能写进结论。ARIMA+SVM 方案里同样建议你这么检查一遍。希望帮到你。
本文还有配套的精品资源,点击获取