资讯动态

基于Matlab的ARIMA电价预测与置信区间实现详解

发布时间:2026/10/18 4:22:14 来源:尧图企业网站定制
电价预测在电力市场里是个经久不衰的课题。想把它做好第一步往往不是急着选模型而是把手里的历史数据吃透。我在实际做这个方向时ARIMA模型是绕不开的基础工具——它不像LSTM那样需要大量样本和复杂调参也不像XGBoost那样需要精心构造一大堆特征它只靠电价序列自身的历史信息就能提取趋势和惯性结构而Matlab里的计量经济学工具箱让整个流程落地非常快。但今天想重点聊的不只是把ARIMA跑出来。很多入门分享只讲点预测拟合一条曲线就说“看预测得不错”这在真实场景里远远不够。电价预测最终要服务决策比如购电计划、售电竞价、风险对冲这些决策都需要知道预测值的不确定范围也就是说你得把置信区间一起算出来。这个置信区间不是后期拍脑袋加上的而是ARIMA模型自身的理论输出Matlab里几行代码就能拿到。这篇文章会以Matlab代码实现为主线把ARIMA电价预测的完整链路拆开讲从数据预处理、平稳性检验、定阶、参数估计到预测再到置信区间计算与可视化。每一步为什么这样做、哪里容易踩坑我会结合自己实际跑过的场景来聊。内容既适合刚接触时间序列建模的读者也适合已经用上机器学习模型、想补一个经典基准模型的同行参考。1. 为什么电价预测需要ARIMA建模1.1 电价数据的典型特征与建模难点电价序列与普通金融序列相比有几类显著特征。首先它有强周期性一天之内早高峰和晚高峰的价格上抬明显凌晨低谷几乎贴近地板价一周之内工作日的价格水平和周末有明显差异如果数据跨度足够长还能看到季节性的冷暖负荷影响。其次电价序列经常有尖峰和跳跃比如极端天气、机组非计划停机、负荷突增都会让价格瞬间冲到上限。这些特征意味着序列不平稳、分布厚尾、波动聚集直接套用标准模型很容易出问题。我在处理数据时的一个习惯是先画出完整的价格曲线不急着做任何变换。这个动作非常关键因为肉眼能看出很多统计检验未必能马上暴露的问题有没有明显的缺失段、有没有超出正常范围好几倍的异常值、有没有结构性突变。比如某一天的现货价格突然录到正常水平十倍这时候如果直接拿去建模后面所有估计都会被这个点带偏先把它识别出来做合理修正比任何高级算法都重要。1.2 ARIMA的建模逻辑与适用边界ARIMA模型的本质是用序列自身的历史值、历史预测误差以及白噪声的线性组合来描述当前值。它把“趋势”和“随机波动”分开处理d阶差分消去趋势自回归部分捕捉序列自身的惯性滑动平均部分捕捉不可直接观测的冲击效应。说白了ARIMA认为电价今天的值跟过去若干个时刻的值有关也跟过去若干个时刻预测不准的地方有关。但ARIMA也不是万能的。它假设线性关系、假设残差是白噪声、对突发尖峰和结构性突变应对能力有限。那为什么还要用因为对大多数常规时段的电价数据ARIMA已经能给出足够坦率的基准结果而且计算成本低、可解释性强、结果稳定性好。我们实验室内部做模型对比时ARIMA始终是那个“保底基准”——不管新模型多花哨如果打不过ARIMA那这个新模型就得好好复盘了。为了把这个问题说透我常给合作者看一张简单的对比表特性ARIMALSTMXGBoost数据量要求数百至数千点即可通常需要上万点数千至数万点特征工程几乎不需要需要特征构造高度依赖特征工程可解释性高低中置信区间模型自带解析结果需额外模拟或集成需分位数回归等计算开销低高中从这张表能看出ARIMA在“基准预测不确定性量化”这个组合任务上性价比其实很高。1.3 置信区间在电价预测里的实际价值点预测给出的是一个数值比如“明天下午四点电价是320元/MWh”。但实际决策不能只靠这一个数。假设你是售电公司要决策要不要提前锁定一部分购电合约你真正关心的不只是点预测而是“价格超过某阈值的概率有多大”。置信区间刚好回答这个问题如果95%的置信区间是[280, 360]你心里对波动范围大概有个底如果区间是[200, 440]点预测虽然相同但决策风险完全不同。在Matlab里ARIMA的forecast函数可以直接输出预测区间不需要额外手写复杂的统计公式。这一点是ARIMA在这个场景下比很多黑盒模型强的地方它给出了有统计依据的不确定性度量而不是靠交叉验证凑出来的近似置信带。对电力市场分析人员来说这种“白盒式”置信区间在报告和决策会议上也更容易解释。2. 前期处理从原始电价到可建模序列2.1 数据清洗与异常值修正我拿到的模拟数据是某区域电力市场连续半年的每小时现货电价一共4320个点。第一步先检查缺失值——电力市场的数据偶尔会有通信中断或者记录缺失如果缺失比例低于1%直接用线性插值补齐基本没有副作用。这里不推荐用“前一天同时刻值”来代替因为这会引入不必要的自相关污染影响后面模型的残差判断。异常值处理要讲策略。电价异常分两种一种是真实的天价尖峰比如供需极度紧张导致的超高价这类是电力市场的真实信号不能随便删删了会影响后续预测对极端情况的判断另一种是明显的数据错误比如价格录成负数、突然跳变到十倍正常水平随后又回落。第二种才需要修正常用方法是中位数滤波或者按“偏离滑动中位数超过若干倍MAD中位数绝对偏差”来识别然后替换为滑动中位数附近的值。这个处理顺序一定要放在平稳性检验之前。注意不要一上来就删尖峰。先判断尖峰是市场真实行为还是数据错误区分标准可以设定为一个可解释的物理阈值比如超过历史日均价5倍且持续不到1小时的可疑值再结合当日供需背景人工确认。2.2 平稳性检验的两种思路ARIMA建模有一个硬前提——序列必须平稳。所谓平稳直观理解就是统计性质不随时间变化均值不漂移、方差不明显变化、自相关结构相对稳定。电价序列原始数据通常不平稳因为均值会随季节和负荷变化而上下起伏。检验平稳性常用两类方法。一类是单位根检验Matlab里的adftest和kpsstest就是干这个的ADF检验的原假设是“存在单位根、序列不平稳”如果p值小于0.05就拒绝原假设认为序列平稳另一类是通过自相关图辅助判断如果自相关系数衰减得非常慢、接了十几阶还明显不为零基本可以断定不平稳。实际操作中我都是两个都看统计检验为主自相关图做交叉验证。% 假设price是原始电价序列 [h_adf, p_adf] adftest(price); disp([ADF检验p值: , num2str(p_adf)]); % h_adf 1 表示拒绝单位根原假设序列平稳 % h_adf 0 表示不能拒绝原假设序列不平稳需要差分如果p值大于0.05就需要做差分。差分阶数d该怎么选原则是“能用一阶就不用二阶”——因为过差分会引入额外的移动平均分量反而导致模型变复杂。观察差分后序列是否围绕零均值波动再跑一次adftest如果显著平稳就可以定d1了。2.3 周期项问题的处理方案电价序列还有一个ARIMA直接处理不了的问题24小时周期。ARIMA只能处理趋势性非平稳对周期性非平稳通常需要先做处理。这里有两个常见思路。第一个思路是直接对每个小时分别建ARIMA模型。24小时一个周期就把数据按小时切分成24条子序列每天0点的价格单独建模每天1点的价格单独建模以此类推。这个思路实现简单每个子序列的均值水平和波动特征一致ARIMA建模假设更容易满足缺点是每个模型样本量变成原来的1/24长周期信息利用不充分。第二个思路是差分预处理对序列做周期差分。如果周期是24小时则从当前值减去24步前的值从而将日内周期成分移除接着再对残差序列做常规ARIMA建模。这个方法保留了全部样本但需要注意差分后的序列可能引入额外的负自相关建模时需要适当提高MA阶数来适配。就我自己测试过的效果看如果数据量超过一年、主要目标是日内预报第一种方法通常整体误差更小如果数据只有一两个月第二种方法更稳因为样本没有萎缩。很多论文里直接对原始电价套一个ARIMA(p,d,q)也能跑但残差诊断时往往有很强的周期自相关滚动预测效果会打折扣。至于进一步引申出的季节ARIMA模型SARIMA就是另一套话题了这篇文章先把ARIMA的核心实现讲透。2.4 训练集与测试集的划分原则时间序列的划分跟普通机器学习不一样不能随机打乱只能按时间顺序切。我的习惯是留出最后7到14天做测试集前面的做训练集。测试集只用来做最终评估不能参与定阶调参否则会严重高估模型表现。trainLen length(price) - 24 * 14; % 留出14天做测试 trainData price(1:trainLen); testData price(trainLen 1:end);这里的核心原则是一切参数选择只基于训练集。你可以用训练集做滚动重估来模拟真实预测节奏但绝对不要碰测试集直到全部确定好、做最终预测那一刻。3. Matlab中ARIMA定阶与参数估计3.1 看图定阶自相关图与偏自相关图确定d之后接下来是定p和q。经典的定阶方法是看差分后序列的自相关函数ACF和偏自相关函数PACF图。对应关系如下如果ACF在滞后q阶后截尾而PACF逐步衰减倾向于MA(q)如果PACF在滞后p阶后截尾而ACF拖尾倾向于AR(p)如果两者都拖尾则需要用ARMA模型。Matlab里直接两条命令d1 diff(trainData); % 一阶差分 autocorr(d1, NumLags, 36); parcorr(d1, NumLags, 36);我观察电价序列差分后ACF和PACF通常都没有非常明显的截尾现象而是以较慢的拖尾形式存在这意味着纯AR或纯MA都不够需要ARMA。这时候看图只能起到初步框定范围的作用比如“p大概在1到3之间q大概率不超过2”细选就要靠信息准则。3.2 信息准则与网格搜索信息准则的本质是兼顾拟合优度和复杂度防止过拟合。AIC和BIC是常用选择两者的差异在于对参数个数的惩罚力度BIC对复杂模型的惩罚更重。在Matlab中可以非常方便地遍历不同的(p,q)组合逐个估计模型、计算信息准则值最后选最小的那组。best_aic inf; for p 0:4 for q 0:4 mdl arima(p, d, q); [est, estCov, logL] estimate(mdl, d1, Display, off); aicVal aicbic(logL, p q 1); if aicVal best_aic best_aic aicVal; best_p p; best_q q; end end end fprintf(最优阶数: p%d, d%d, q%d\n, best_p, d, best_q);需要强调几点。第一这里遍历的搜索空间不宜过大p和q都放到5以内已经覆盖绝大多数典型场景阶数过高反而容易让参数估计不稳定、信息准则优势也不明显。第二aicbic函数需要传入估计的对数似然值logL和有效参数个数如果差分后序列均值接近零可以考虑去掉常数项此时参数个数取pq如果保留常数项则取pq1。第三网格搜索是定阶的起点不是终点选出的最优阶数还需要配合残差诊断来验证——有些时候AIC最小的模型残差仍混有周期成分那就要人工干预。3.3 参数估计与残差诊断阶数定好之后直接用estimate函数拟合estMdl estimate(arima(best_p, d, best_q), d1, Display, on);拟合完之后必须做残差诊断。最基础的三件事看残差是否还有显著自相关、残差是否近似正态、残差方差是否稳定。Matlab里可以用infer函数拿到残差然后跑Ljung-Box检验res infer(estMdl, d1); [h_lb, p_lb] lbqtest(res, Lags, [10, 20, 30]);如果Ljung-Box检验的p值大部分大于0.05说明残差没有显著自相关模型对数据的时序信息利用得比较充分如果p值很小说明还有结构没提出来需要回去重新定阶或者处理周期项。这一步很多人跳过但恰恰是判断模型能不能用的核心标准——AIC再低、拟合图再好看残差带着自相关滚动预测也会翻车。4. 预测与置信区间的完整Matlab实现4.1 forecast 函数的关键用法Matlab的forecast函数是做ARIMA预测的核心入口。基本用法是horizon 24 * 7; % 预测未来7天共168小时 [YF, YMSE, V] forecast(estMdl, horizon, Y0, d1);这里有个容易忽略的细节Y0传入的是用于条件预测的历史序列。如果用差分后的序列做预测Y0要传差分后的序列不是原始电价序列同理预测出来的YF也是差分尺度上的值最终展示时需要通过累加差分反向变换回原始价格尺度。不少新手在这里直接传原始序列结果模型内部把差分逻辑再算一遍输出对不上。再补充一个细节forecast默认给出的预测区间是95%置信水平想改成90%或者99%可以设置参数[YF, YMSE, V] forecast(estMdl, horizon, Y0, d1, ConfidenceLevel, 0.90);V矩阵是horizon×2的数组第一列是下界第二列是上界。注意这个上下界也是基于Y0条件的所以跟点预测一样在差分尺度上展示前要一起反向变换。YMSE是各预测时点的均方误差也就是预测方差把它开根号得到的标准误差配合正态分布分位数实际上就是置信区间的基本构成但Matlab封装好了直接用V即可。差分序列的反向变换可以用cumsum实现base trainData(end); % 差分前的最后一个原始值 YF_original base cumsum(YF); lower_original base cumsum(V(:, 1)); upper_original base cumsum(V(:, 2));由于差分是线性操作置信区间同样可以通过相同变换映射回原始尺度区间覆盖率在线性变换下保持不变。4.2 置信区间的原理与结果解读ARIMA的预测区间本质上是基于预测误差分布推导出来的。以AR(1)模型为例一步预测误差的方差就等于白噪声方差两步预测误差的方差则等于噪声方差乘以一个含自回归系数的系数步数越大预测方差积累越多区间就越宽当预测步数趋向无穷大时区间宽度会收敛到一个与模型无条件方差有关的常数上。Matlab在内部把这条计算链用解析式算好了不需要你手工推导。实际打印出的95%置信区间宽度通常呈现三段特征近端较窄、中段逐渐变宽、远端渐趋稳定。也就是说ARIMA对近期的把握是相当有底气的越往远期越只能给一个“大致的波动范围”但不会再无限恶化。这个特性对电价预测特别有意义电价预测往往最关心未来一小时到未来一天的短期走势而ARIMA恰好在这个范围内置信度较高。但也要说清楚这个置信区间是纯模型理论意义上的它假设模型参数已知、误差服从正态分布。实际建模中参数是估计出来的估计本身有不确定性而且电价残差厚尾明显所以真实的不确定性通常比理论区间提示的要大。做严谨的实战评估时我会用滚动窗口的方式反复计算区间覆盖率如果覆盖率长期低于名义水平就调整展示区间的置信度而不是硬套95%。4.3 预测可视化与效果评估预测结果不能只给一张表画图是必须的。绘图代码的骨架如下t 1:length(price); figure; hold on; plot(t(1:trainLen), trainData, Color, [0.2 0.4 0.6]); plot(t(trainLen1:end), testData, Color, [0.8 0.3 0.3]); tPred trainLen (1:horizon); plot(tPred, YF_original, --r, LineWidth, 1.5); % 置信区间填充 fill([tPred fliplr(tPred)], ... [lower_original fliplr(upper_original)], ... [0.9 0.95 1.0], EdgeColor, none, FaceAlpha, 0.4); legend({训练数据, 测试数据, 预测值, 95%置信区间});画出来的图里最重要的观察点是真实测试曲线落在置信区间内的比例有多少这就是区间覆盖率。经验上95%置信区间对电价这类厚尾数据实际覆盖率往往会低于理论值——因为电价尖峰太多误差分布并不完全正态。如果覆盖率明显偏低比如不到70%就说明模型对不确定性的估计偏乐观这时候可以改用99%的区间来展示或者考虑引入波动率模型对残差方差做进一步建模。评估指标的程序化计算actual testData(1:horizon); mae mean(abs(YF_original - actual)); rmse sqrt(mean((YF_original - actual).^2)); inside mean(actual lower_original actual upper_original);MAE、RMSE是对点预测的评估覆盖率是对区间预测的评估。两者结合才是一个完整的预测评价链。很多学术文章只报RMSE不说覆盖率这对实际工程应用是不够的因为对决策者来说“未来这周价格落在什么范围内”往往比“平均偏差多少元”更有参考价值。5. 实测经验与常见障碍排查5.1 预测值发散或者漂移严重ARIMA做多步预测时预测值会逐渐收敛到序列的长期均值这个过程是正常的。但如果预测值在几步之内就出现严重漂移一般意味着模型参数出了问题。我遇到过两类常见情况。一类是过差分d取大了模型从平稳序列里提炼出多余成分预测曲线会表现出异常的上升或下降趋势解决办法是减小d回到一阶差分必要时直接处理趋势项。另一类是MA参数估计接近某个临界值模型出现近不可逆性预测误差方差不稳定预测值发散这时需要回看参数估计的标准误差如果参数估计的置信区间包含了临界值就要考虑降低q阶数或者使用约束估计。5.2 置信区间过宽或者过窄置信区间宽度直接取决于残差方差。如果区间宽得离谱比如上下界相差上千元首先检查训练数据是否包含少量极端异常值——这些点会把残差方差撑大好几倍把异常值修正后区间马上收紧。区间窄得不像话的情况也有常见原因是训练集数据过于“平静”残差方差估计偏低模型没有见过真实的尖峰波动解决方案一是扩大训练窗口把更多覆盖不同电价场景的历史数据纳入进来二是直接使用更高的置信水平来适应实际决策需求。5.3 残差仍有周期自相关电价数据如果没做周期处理残差自相关图在滞后24、48阶的地方会明显冒出高峰这就是常说的周期残留。碰到这种情况别急着加p、q阶数通常怎么加都压不下去正确做法是回到数据预处理阶段把24小时周期先行消解比如使用2.3节中的按小时分组或周期差分策略。我见过不少项目在这个问题上浪费大量调参时间原因就是没意识到问题根源在预处理而不在模型阶数。5.4 模型参数不稳定对于滚动预测场景每隔一段时间就要用最新数据重新估计模型参数。如果每次重估出来的p、q阶数都不同不必太惊讶——信息准则在一个平坦的最小值附近经常换选择这很正常。但如果你发现估计的参数值本身剧烈抖动比如AR系数从一个安全值跳到另一个方向那多半是训练数据里最近一段时间有异常结构比如发生了持续一周的特殊事件。这时候我会选择把异常段从训练数据中剔除而不是让模型去强行适配它。5.5 快速排查速查表现象可能原因处理办法预测曲线发散过差分或参数接近临界值降低d或q检查参数估计置信区间过宽训练集含异常尖峰修正异常值后重新估计残差有24阶自相关周期项未处理按小时分组或周期差分覆盖率偏低厚尾导致正态假设失效提高置信水平或换波动率模型参数每次重估变化大近期数据存在结构突变剔除异常段或缩短窗口这里再补充一点个人经验我始终建议在项目里保留一个“简单基线模型”作为对照。无论你最后用的是什么复杂模型ARIMA这个基线永远值得保留。它训练快、结果稳定、自带置信区间而且能在模型出问题的时候第一时间暴露异常。很多时候团队讨论半夜都说不清的预测问题拿ARIMA一跑问题到底出在数据还是模型立刻就有线索了。做电价预测这个行当能把基准线画准比追求高精度的花活重要得多。最后再分享一个我自己常用的判断技巧拿到一组新数据先用ARIMA跑一个24小时预测画出置信区间观察真实曲线的落点是否大致符合区间分布。如果偏差不大说明数据结构比较健康如果真实值经常冲出区间那后面不管上什么高级模型都要先回去清洗数据。这套习惯我保持了很久帮我避开了不少坑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑