1. 时间序列预测的MATLAB实战指南
时间序列预测就像一场数据侦探游戏,我们需要从历史数据中找出隐藏的规律,然后预测未来走势。在金融、气象、销售预测等领域,这种技术有着广泛应用。今天我们就用MATLAB来探索几种实用的时间序列预测方法,从基础的AR模型到复杂的GARCH模型,我会用代码示例带你一步步理解这些"时间魔法"。
提示:本文所有代码基于MATLAB R2021b版本,建议使用相同或更新版本运行。所有示例数据均为模拟生成,可以直接复制代码运行测试。
1.1 准备工作:创建模拟数据
任何时间序列分析的第一步都是准备合适的数据。我们先创建一个模拟的股票价格序列,它具有真实金融数据的几个关键特征:随机波动、趋势性和持续性。
matlab复制% 生成500天的模拟股票价格数据
rng(42); % 设置随机种子保证结果可复现
daily_returns = randn(500,1)*0.5 + 0.01; % 日均收益率~N(0.01,0.5^2)
data = cumsum(daily_returns) + 50; % 累积收益率+初始价格50
% 可视化数据
figure('Position',[100,100,800,400])
plot(data,'LineWidth',1.5)
title('模拟股票价格序列 (500天)','FontSize',12)
xlabel('交易日','FontSize',10)
ylabel('价格','FontSize',10)
grid on
这段代码生成了一个带有微弱正趋势(日均收益率0.01)的随机游走序列,标准差设为0.5模拟中等波动市场。cumsum函数让每天的变动累积起来,形成价格序列的持续性特征——这是金融时间序列的典型表现。
2. 基础预测模型实战
2.1 自回归(AR)模型:用历史预测未来
AR模型的核心思想非常简单:用过去若干期的数据值来预测当前值。比如用前三天的价格预测今天价格,数学表达式为:
[ X_t = c + \phi_1 X_{t-1} + \phi_2 X_{t-2} + \phi_3 X_{t-3} + \epsilon_t ]
MATLAB实现代码如下:
matlab复制% 创建AR(3)模型
Mdl = arima('ARLags',1:3); % 指定使用1-3阶滞后
EstMdl = estimate(Mdl, data); % 估计模型参数
% 预测未来5天
[YF, YMSE] = forecast(EstMdl, 5, data);
% 可视化预测结果
figure('Position',[100,100,800,400])
plot(data,'b','LineWidth',1.5)
hold on
h = plot(length(data):length(data)+5, [data(end); YF],'r--','LineWidth',1.5);
plot(length(data):length(data)+5, [data(end); YF+1.96*sqrt(YMSE)],'k:')
plot(length(data):length(data)+5, [data(end); YF-1.96*sqrt(YMSE)],'k:')
title('AR(3)模型5天预测','FontSize',12)
legend([h],{'预测值'},'Location','best')
grid on
关键参数说明:
ARLags:指定使用哪些滞后项,1:3表示使用前三期estimate:估计模型参数,输出结果中要关注各系数的p值(应<0.05)forecast:第二个参数5表示预测未来5期,YMSE是预测误差方差
注意事项:AR模型最适合平稳序列。如果数据有明显趋势或季节性,需要先进行差分或变换处理。
2.2 ARIMA模型:处理非平稳数据
当数据不平稳(有趋势)时,ARIMA模型更为合适。它在AR模型基础上增加了差分(I)和移动平均(MA)组件。一个典型的ARIMA(p,d,q)模型中:
- p:AR阶数
- d:差分阶数
- q:MA阶数
matlab复制% 创建ARIMA(2,1,1)模型
Mdl = arima(2,1,1); % AR2, 差分1阶, MA1
EstMdl = estimate(Mdl, data);
% 预测未来5天
[YF, YMSE] = forecast(EstMdl, 5, 'Y0', data);
% 可视化
figure('Position',[100,100,800,400])
plot(data,'b','LineWidth',1.5)
hold on
h = plot(length(data):length(data)+5, [data(end); YF],'r--','LineWidth',1.5);
plot(length(data):length(data)+5, [data(end); YF+1.96*sqrt(YMSE)],'k:')
plot(length(data):length(data)+5, [data(end); YF-1.96*sqrt(YMSE)],'k:')
title('ARIMA(2,1,1)模型5天预测','FontSize',12)
legend([h],{'预测值'},'Location','best')
grid on
模型选择技巧:
- 通过ADF检验(
adftest)判断差分阶数d - 观察ACF/PACF图确定p和q的初始值
- 使用
aicbic函数比较不同模型的AIC/BIC值 - 检查残差是否为白噪声(
lbqtest)
3. 高级模型与应用
3.1 GARCH模型:预测波动率
金融时间序列的一个典型特征是"波动聚集"——高波动时期往往聚集出现。GARCH模型专门用于建模和预测这种波动性。
matlab复制% 创建GARCH(1,1)模型
Mdl = garch('GARCHLags',1,'ARCHLags',1);
returns = diff(data); % 使用收益率数据
EstMdl = estimate(Mdl, returns);
% 提取条件波动率
condVar = infer(EstMdl, returns);
% 可视化
figure('Position',[100,100,800,400])
subplot(2,1,1)
plot(returns)
title('收益率序列','FontSize',10)
subplot(2,1,2)
plot(condVar)
title('GARCH预测的波动率','FontSize',10)
GARCH(1,1)模型公式:
[ \sigma_t^2 = \omega + \alpha \epsilon_{t-1}^2 + \beta \sigma_{t-1}^2 ]
其中:
- α(ARCH项):反映新息冲击对波动的影响
- β(GARCH项):体现波动的持续性
3.2 多变量VAR模型
当多个时间序列相互影响时,向量自回归(VAR)模型可以捕捉变量间的动态关系。
matlab复制% 创建两个相关变量
data1 = cumsum(randn(500,1)*0.5 + 0.01) + 50;
data2 = 0.3*data1 + randn(500,1)*2 + 5;
data_multi = [data1, data2];
% 创建VAR(2)模型
Mdl = varm(2,2); % 2个变量,滞后2阶
EstMdl = estimate(Mdl, data_multi);
% 预测未来5期
[YF, YMSE] = forecast(EstMdl, 5, data_multi);
% 可视化第一个变量的预测
figure('Position',[100,100,800,400])
plot(data_multi(:,1),'b','LineWidth',1.5)
hold on
h = plot(length(data1):length(data1)+5, [data1(end); YF(:,1)],'r--','LineWidth',1.5);
title('VAR模型变量1的5期预测','FontSize',12)
legend([h],{'预测值'},'Location','best')
grid on
VAR模型使用要点:
- 所有变量需要是平稳的
- 最佳滞后阶数可以用
aicbic确定 - 可以用
irf函数分析冲击响应
4. 模型评估与实战技巧
4.1 模型诊断与验证
建立模型后,必须进行严格的诊断检验:
matlab复制% ARIMA模型残差诊断
res = infer(EstMdl, data); % 获取残差
% 1. 自相关检验
[h,p] = lbqtest(res,'Lags',[5,10,15])
% 2. 正态性检验
figure
histfit(res,50)
[h,p] = lillietest(res)
% 3. 样本外测试
train_ratio = 0.8;
train_data = data(1:floor(end*train_ratio));
test_data = data(floor(end*train_ratio)+1:end);
Mdl = arima(2,1,1);
EstMdl = estimate(Mdl, train_data);
[YF, YMSE] = forecast(EstMdl, length(test_data), 'Y0', train_data);
% 计算预测误差
RMSE = sqrt(mean((test_data - YF).^2))
4.2 实用技巧与避坑指南
-
参数初始化问题:
- GARCH类模型对初值敏感,可以尝试多组初值
- 使用
optimoptions调整估计算法选项
-
季节调整:
matlab复制% 使用X-13ARIMA-SEATS进行季节调整 [dts,sa] = x13series(dates,data); -
计算加速:
matlab复制% 使用并行计算加速参数搜索 options = optimoptions('fmincon','UseParallel',true); -
模型比较:
matlab复制% 计算不同模型的AIC/BIC logL = [logL1, logL2]; % 各模型对数似然 numParams = [n1, n2]; % 参数个数 [aic,bic] = aicbic(logL,numParams,length(data)) -
实时更新:
matlab复制% 滚动窗口预测 window_size = 200; for t = window_size:length(data)-1 current_data = data(t-window_size+1:t); Mdl = arima(2,1,1); EstMdl = estimate(Mdl, current_data); [YF(t+1), YMSE(t+1)] = forecast(EstMdl, 1, 'Y0', current_data); end
5. 模型选择与实战建议
没有放之四海皆准的最佳模型,选择取决于数据特征和应用场景:
- 平稳序列:AR/MA/ARMA足够
- 趋势性数据:ARIMA
- 波动聚集:GARCH家族
- 多变量系统:VAR/VECM
- 季节模式:SARIMA
- 高频数据:考虑长记忆模型(FIGARCH)
实际应用中,我通常会遵循以下流程:
- 可视化数据,识别趋势/季节/异常
- 进行平稳性检验(ADF/KPSS)
- 根据ACF/PACF初步确定模型阶数
- 估计多个候选模型
- 比较AIC/BIC选择最佳模型
- 残差诊断验证模型充分性
- 样本外测试评估预测性能
重要经验:时间序列预测中,模型复杂度与预测精度并非正相关。有时简单的指数平滑可能比复杂模型表现更好,特别是在短期预测中。