☰
移动平均模型(MA)解析:用“意外”预测时间序列的未来
2026/9/28 1:53:01 网站建设 项目流程

移动平均模型(MA模型)这个主题,我第一次听就觉得名字有误导性。它并不是在算K线上的均线,也不是模型压缩里说的量化,而是在用一组随机冲击的滞后组合,去解释时间序列当前的值。用一句话概括:MA模型用过去的“意外”预测未来的值。这个“意外”在统计上叫白噪声或新息,在金融场景里可以理解为突发消息、超预期的成交变化、短期流动性扰动。它们本身不可预测,但一旦发生,会对后续几期产生残影效应。量化交易里,日收益率经常表现出这种特征:某个意外让收益率偏离均值,接下来几期可能继续受影响,然后慢慢消退。MA模型就是把这个“残影”结构建模出来。

这是量化笔记第43篇。我按自己的实操顺序把MA模型拆成六个部分:先讲它解决什么问题,再讲统计性质,然后用 Python 从模拟到建模跑一遍,接着讲阶数识别,再落到量化场景,最后给一份排查清单。适合刚开始学时间序列的人,也适合已经在用 ARIMA 但没仔细看 MA 部分的读者。读完你会发现,MA模型并不难,难点反而在概念区分和数据预处理。

1. MA模型到底在做什么:把“意外”变成可预测的结构

1.1 先搞清楚,这里不是均线,也不是模型量化

MA 这个缩写太容易撞名字了。量化交易社区里搜“MA”,会出现两组完全不相关的东西。

第一组是移动平均线(Moving Average),比如 MA5、MA10、MA20。这是 K 线技术指标,用来平滑价格,是趋势跟踪里最常见的工具。

第二组是模型量化(Quantization),比如把深度学习模型从 FP32 压缩成 INT8、INT4,大家经常说“量化模型”,那是优化推理速度和显存占用。

而本文说的 MA 模型,全称是 Moving Average model,属于时间序列分析中的经典模型,是 ARIMA 模型框架里专门描述短记忆随机冲击的部分。大家平时在统计教材里看到的 MA(1)、MA(2),指的就是它。三个“MA”中,只有这个 MA 真正在回答“过去一个无法预测的意外,如何通过线性结构影响今天和明天”的问题。

我在带量化学员时,最常遇到的一种困惑就是:去网上一搜“MA模型”,搜到一堆均线代码,然后越看越绕。所以先把这个概念划分清楚,整篇文章才有意义。

名称英文核心作用在量化里的常见用途
移动平均模型Moving Average model描述白噪声冲击的滞后影响对收益率序列建模、预测短期冲击残影
简单移动平均线Moving Average计算过去 N 期价格均值趋势跟踪、均线交叉信号
模型量化Quantization压缩模型精度,减少显存和计算量部署深度学习模型到低算力设备

1.2 用公式看 MA 模型怎么预测未来

MA(q) 模型写成公式是:

y_t = μ + ε_t + θ1 ε_{t-1} + θ2 ε_{t-2} + ... + θq ε_{t-q}

其中:

  • y_t 是 t 时刻的观测值,在量化里通常取收益率序列;
  • μ 是序列均值;
  • ε_t 是 t 时刻的新息(innovation),也叫白噪声、随机冲击、意外,均值为 0,方差恒定;
  • θ1 到 θq 是移动平均系数,表示过去的冲击对当前值的影响强度。

为什么说它“用意外预测未来”?因为 MA 模型把当前值分解成两部分:一部分是当前新息,另一部分是过去 q 期新息的加权组合。如果某个外部消息让今天产生了异常收益,这个异常会作为 ε_t 进入模型,并且在接下来几期继续通过 θ 系数影响预测值,直到 q 期后消失。

举个通俗例子。假设某天某只股票因为一条临时监管消息,收益率比均值低 2%,这是一个“意外”ε_t。如果 MA(1) 的 θ1 是 0.5,那么模型会认为,这个 -2% 的冲击会对下一次观测值继续产生 -1% 的影响,然后逐步衰减。这不是说消息会重复,而是说市场消化消息可能需要时间,这种短期的滞后效应,MA 模型正好能抓住。

1.3 MA 和 AR 的分工不同

AR 模型(自回归模型)用过去的“观测值”本身预测未来,MA 模型用过去的“误差项”预测未来。这是两者最本质的区别。

AR(1):y_t = μ + φ1 y_{t-1} + ε_t MA(1):y_t = μ + ε_t + θ1 ε_{t-1}

AR 模型适合描述“今天的位置影响明天的位置”,比如惯性、趋势;MA 模型适合描述“今天的意外影响明天的位置”,比如冲击后的短期回归。两者如果单独不够用,就组合成 ARMA 模型。

实际操作中,做量化收益率建模时,很多人一上来就拟合 ARMA(p,q),但从我的经验看,先分清“序列里到底是惯性强还是冲击残影强”,再去定 p 和 q,要比盲目调参靠谱得多。

2. 为什么“意外”会留下痕迹:MA模型核心性质

2.1 MA(q) 序列天然平稳

MA(q) 的一个关键性质是:只要系数 θ 是固定常数,且 ε_t 是稳定的白噪声,那么 MA(q) 就一定是平稳的。

直观理解:模型里所有项都是白噪声的线性组合,白噪声本身没有趋势、没有周期性、方差恒定,所以它们的线性组合也不会出现单位根或明显漂移。

这一点和 AR 模型很不一样。AR 模型需要满足 |φ| < 1 之类的平稳条件,如果系数太接近 1,序列会有很强的持续性甚至近似随机游走。MA 模型的平稳性条件宽松得多,代价是它能刻画的记忆也短,超过 q 期的自相关直接为 0。

在量化场景里,这意味着 MA 模型比较适合对经过处理后的收益率序列建模,而不是对价格序列建模。价格序列通常是非平稳的,不能用 MA 模型硬套。先对价格做对数差分得到收益率,再考虑 MA,才是常见顺序。

2.2 ACF 在 q 阶后截尾,这是识别信号

MA 模型最容易被利用的性质是自相关函数(ACF)。

对 MA(q) 来说,当前值只和过去 q 期的新息相关,所以理论上:

  • 滞后 1 到 q 阶的自相关系数可能显著;
  • 超过 q 阶的 ACF 为 0 或者接近 0;
  • 这叫做“ACF 在 q 阶截尾”。

这是判断序列是否适合 MA 模型的最直观工具。如果一组序列的 ACF 在滞后 2 阶之后突然掉进置信区间,之后几乎没有显著值,那就很有可能是 MA(2)。但如果 ACF 衰减得很慢,拖着长长的尾巴,那可能先考虑 AR 模型或者单位根问题。

实际操作中,我一般会先画 ACF 和 PACF 两张图。虽然样本估计值会有噪声,但“截尾”和“拖尾”的形态差异通常还是能看出来的。

2.3 为什么还需要可逆性

MA 模型还有一个约束条件叫可逆性。数学上,只有当 MA 特征方程的根都在单位圆外时,MA(q) 才能写成 AR(∞) 的形式,对应的系数才是唯一可估计的。

在 statsmodels 里拟合 MA 模型时,如果系数估计结果出现异常,比如多次运行结果不稳定,或者优化器提示收敛到边界,往往就是可逆性条件没有被满足或接近边界。

对量化应用来说,可逆性的实际意义是:只有满足可逆性的 MA 模型,才可以用历史信息逐步递推得到“当前新息”的估计,进而用于预测。如果模型不可逆,“意外”就是不可恢复的,预测也就无从谈起。

3. 先跑通一个 MA 模型:Python 实操流程

3.1 生成模拟数据:先知道真值

学习 MA 模型,我不建议一开始就直接拿真实行情数据来跑。真实数据噪声大、阶数不明确、还可能夹着缺失和异常,出问题时很难判断是模型问题还是数据问题。我建议先构造一组模拟 MA(1) 数据,自己知道真实的 θ1 是多少,再回头看模型能不能估计出来。

模拟代码如下:

import numpy as np import pandas as pd import matplotlib.pyplot as plt from statsmodels.tsa.arima.model import ARIMA from statsmodels.graphics.tsaplots import plot_acf, plot_pacf np.random.seed(42) n = 1000 eps = np.random.normal(0, 1, n) theta1 = 0.6 y = np.zeros(n) y[0] = eps[0] for t in range(1, n): y[t] = eps[t] + theta1 * eps[t-1]

这里的 eps 就是白噪声序列,代表每一天的“意外”。y 就是 MA(1) 序列,理论上的 ARIMA 阶数为 (0,0,1)。先画个图,观察序列是否存在明显趋势。MA 序列应该是围绕均值波动的,不会出现持续上行的形态。

3.2 用 statsmodels 估计 MA(q)

statsmodels 里的 ARIMA 类可以直接拟合 MA 模型。只要把 order 设为 (0,0,q) 即可:

model = ARIMA(y, order=(0, 0, 1)) res = model.fit() print(res.summary())

注意 ARIMA 的 order 参数顺序:order=(p,d,q)。p 是自回归阶数,d 是差分次数,q 是移动平均阶数。MA(q) 就对应 (0,0,q)。

拟合完成后,summary 里会给出:

  • coef:θ1 的估计值;
  • std err:标准误;
  • z、P>|z|:显著性检验;
  • AIC、BIC:信息准则,用于模型比较。

理想情况下,θ1 估计值应该接近 0.6。如果模拟数据量够大,估计结果应该很接近真值。这里不需要把每一步输出都当作硬标准,重点是观察估计流程是不是顺利。

接着预测未来 5 期:

forecast = res.get_forecast(steps=5) print(forecast.predicted_mean) print(forecast.conf_int())

MA 模型的预测有一个特点:当预测步长超过 q 后,预测值很快回到序列均值 μ,置信区间也会逐渐变大。这是因为超过 q 期之后,模型里没有新的信息可用了。这不是 bug,而是 MA 模型本身的短记忆特性。

3.3 识别 ACF 和 PACF 的形态

拟合完后,可以画 ACF 和 PACF:

fig, axes = plt.subplots(1, 2, figsize=(12, 4)) plot_acf(y, ax=axes[0], lags=20) plot_pacf(y, ax=axes[1], lags=20) plt.show()

对于纯 MA(1) 序列,ACF 应该在第 1 阶显著,之后快速进入置信区间;PACF 则表现为逐渐衰减。如果你的序列同时出现 ACF 和 PACF 都拖尾,那可能要考虑 ARMA 模型,或者序列本身有结构变化。

3.4 真实数据里要小心的问题

从模拟数据切换到真实行情数据时,我一般会先做这些预处理:

  • 先取对数价格,再做一阶差分,得到收益率序列;
  • 处理缺失值和停牌日,不要把 NaN 直接交给模型;
  • 剔除明显的极端值或做 winsorize 处理,避免单日异常收益影响参数估计;
  • 检查序列是否近似平稳,必要时用 ADF 检验辅助判断。

很多报错,比如“convergence failed”“NaN results”,其实不是模型问题,而是数据里有缺失、无穷或极端值。

4. 怎么判断用 MA(q) 而不是其他模型

4.1 一张图、一组检验,先给出方向

识别 MA 阶数,最常见的顺序是:

  1. 计算收益率序列的 ACF 和 PACF;
  2. 看 ACF 是否在某一阶后突然截尾;
  3. 看 PACF 是否拖尾或衰减;
  4. 结合信息准则 AIC/BIC,对 q=0、1、2、3 分别建模;
  5. 选择信息准则最低、且参数显著的模型。

举一个典型判断。如果 ACF 在滞后 2 阶后全部落在置信区间内,而 PACF 从滞后 3 阶也开始逐渐消失,那么可以先按 MA(2) 尝试。如果 ACF 截尾不太明显,PACF 同样很快消失,可以同时尝试 ARMA(1,1) 和 MA(1),用 AIC 比较。

如果只依赖 ACF,很容易误判。样本较短时,即使理论上 ACF 在 q 阶后为 0,估计值也会有波动,偶尔冒出一两个超过置信区间的柱子,不代表模型真的很复杂。

4.2 用 AIC/BIC 做数量上的对比

阶数识别不能只看图,还需要信息准则做定量比较。AIC、BIC 越低,表示模型在拟合优度和复杂度之间取得了更好平衡。

一个简单做法是循环几个候选阶数:

best_aic = np.inf best_q = 0 for q in range(0, 4): model = ARIMA(y, order=(0, 0, q)) res = model.fit() print(f"q={q}, AIC={res.aic:.3f}, BIC={res.bic:.3f}") if res.aic < best_aic: best_aic = res.aic best_q = q print("best_q:", best_q)

注意:这里只是示例代码。实际数据里,q=0 代表纯白噪声,如果 AIC 最低的是 q=0,说明序列本身几乎没有短期相关结构,就不要勉强加 MA 项。

4.3 低样本下的识别误区

如果样本量很少,比如只有 50 期收益率,ACF 和 PACF 的置信区间会很宽,识别结果很不稳定。这种情况下,即使 AIC 选出了 MA(2),也可能只是过拟合。

我更倾向于:样本低于 100 时,优先使用简单模型,比如 MA(1) 或 MA(2),不要轻易尝试太高的阶数。模拟数据里可以任意选阶数,但真实量化数据里,高阶 MA 参数往往缺乏稳定性,输出结果也难解释。

另一个常见误区是把“收益率存在自相关”等同于“必须用 MA”。自相关可能来自波动率聚集、市场微观结构效应、交易时段差异等,需要先做预处理或加入外生变量再建模。MA 模型只是其中一种建模方式,不是万能解法。

5. 量化场景里,MA 模型到底怎么用

5.1 选择适合 MA 模型的数据

MA 模型在量化里最适合的建模对象是收益率序列,尤其是日频、小时频的收益率。这种数据通常围绕 0 波动,偶尔出现冲击,冲击会以线性衰减的方式影响后面几期。

价格序列不平稳,直接建模经常出现伪回归。指数收盘价、个股价格、累计净值,都属于“今天和昨天高度相关”的序列,先差分再建模是标准做法。哪怕是对数价格,也不能直接放进 MA 模型。

另外,MA 模型对低频数据的适用性一般。如果数据是周频或月频,样本量通常不够,而且冲击传导路径往往更复杂,很难用几阶 MA 描述。这时更适合引入宏观变量、因子暴露,或者采用更完整的 ARIMA、状态空间模型。

5.2 一个均值回归信号的搭建思路

MA 模型本身不产生“买入卖出”信号,它更多是描述数据生成过程。量化应用里常见的方式,是用 MA 模型拟合收益率后,把预测的收益率方向或残差转成信号。

比如,对某指数的日收益率拟合 MA(1),得到:

  • 预测值接近 0,说明当前看不到明显的冲击残影;
  • 预测值连续为正,说明短期动量还在延续;
  • 残差出现较大负值,说明模型外出现了新意外,需要关注均值回归潜力。

实际回测时,我一般会先构造一个最朴素的规则:当模型预测的下一期收益率在历史分布的某个分位点以上或以下时,生成做多或做空信号。这种信号不会很复杂,但能帮助你验证 MA 模型是否在样本外有增量信息。用 Python 写这个策略代码,核心其实就几步:取数据、滚动估计、生成信号、回测。

需要提醒一句:模型只是量化研究中的一个环节,不构成投资建议。把信号直接当策略用之前,必须做样本外验证,尤其要防止参数被反复调整导致过拟合。

5.3 从研究到策略要注意的坑

这里有三个坑特别常见。

第一,未来函数。很多人用全样本收益率计算均值、方差、模型参数,然后逐日回测,这等于把未来信息泄露到了历史回测里。正确做法是:每天只用截至当天的数据重新估计参数,或者至少使用滚动窗口。

第二,参数更新频率。MA 模型的参数并不是固定的。市场状态变化后,θ 系数可能变化。如果一个月甚至一季度才更新一次参数,模型可能早就偏离当前数据。具体更新频率要和持仓周期匹配,持仓周期短,参数更新也要更频繁。

第三,过度迷信模型。MA 模型是线性模型,只能刻画线性滞后关系。真实市场的冲击传播往往有非线性、不对称性,比如利好和利空的衰减速度不同。MA 模型作为基线工具很好,但不能要求它解释所有收益率的变动。在聚宽、QMT 这类量化研究环境里,取数、回测框架大同小异,但核心还是要先把模型逻辑验证清楚,再换平台。

6. 参数估计、残差诊断和排查清单

6.1 参数估计方法:最大似然

大多数量化工具里的 MA 模型,都是用最大似然估计(MLE)来估计参数。简单理解,就是找一组 θ 参数,让当前样本出现的概率最大。

MLE 估计对样本量有一定要求。样本太少时,标准误很大,参数显著性不稳定。如果拟合结果里某个 θ 的 P 值大于 0.05,说明这个参数可能不显著,可以考虑降低阶数。

一个更实际的建议是观察拟合结果里的“常数项”和“残差方差”是否合理。常数项应该接近收益率均值,残差方差应该和样本方差接近。如果出现异常大的参数或方差,很可能数据预处理有问题。

6.2 残差要像白噪声才算合格

模型拟合完,最该看的是残差,不是拟合优度。残差应该接近白噪声:不存在显著自相关、均值接近 0、方差稳定。

可以观察残差 ACF,并做 Ljung-Box 检验:

from statsmodels.stats.diagnostic import acorr_ljungbox lb = acorr_ljungbox(res.resid, lags=10, return_df=True) print(lb)

判断标准:

  • Ljung-Box 的 p 值大于 0.05,表示残差在对应滞后期内没有显著自相关;
  • 如果 p 值很小,说明模型还没把信息提取干净,需要增加阶数或改用 ARMA;
  • 如果残差 ACF 在低阶仍有明显相关,优先考虑调整 p 或 q,而不是直接加高复杂性模型。

很多新手看到训练集拟合得很好,就急着进入回测。实际上,训练集拟合优度高不代表预测能力强。残差诊断的意义在于确认模型已经把数据中的线性相关结构吸收干净了,剩下的部分才是真正的随机意外。

6.3 常见报错和排查顺序

最后给一份我自己排查 MA 模型问题时的顺序清单。

先看现象:

  • 拟合报错收敛失败;
  • 拟合出的参数全是 NaN;
  • 预测结果非常不合理;
  • 残差 ACF 仍然显著。

再看输入数据:

  • 是否有缺失值、NaN、无穷值;
  • 是否做了差分,数据是否近似平稳;
  • 是否混入了未来数据;
  • 收益率是否做了极端值处理。

再看环境:

  • statsmodels、numpy、pandas 版本是否兼容;
  • 是否用了过旧的 statsmodels,部分版本对 ARIMA 类支持不足;
  • 模型是否有收敛警告,是否被忽略。

再看模型设定:

  • order 参数是否写错,(0,0,1) 才是 MA(1),写成 (1,0,0) 就是 AR(1);
  • q 是否选得过高;
  • 是否没有添加常数项;
  • 是否对原始价格直接建模。

最后看结果:

  • 参数是否在合理范围;
  • 残差白噪声是否通过;
  • 样本外预测是否比随机基线好。

按这个顺序查,能省下很多时间。很多看起来很玄的问题,最后都是数据或参数写错。

写到这里,MA 模型的核心内容已经梳理完了。个人建议是:先用模拟数据把概念和代码流程跑通,再切到真实行情数据;先把单条序列的单任务模型跑稳,再考虑批量选股、滚动预测和策略回测。MA 模型不是一劳永逸的赚线工具,但它是理解 ARIMA、理解短期冲击、理解“什么叫做信息被逐步消化”的好起点。量化交易里,能稳定复现的建模思路,往往比一个看起来很巧妙的信号更值得花时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询