时间序列分析

更新时间: 2026-06-08 15:42:25

# 时间序列模型

你认为金融交易有时间上的规律么?

# 案例:沪市指数预测

# 什么是时间序列模型

时间序列:

  • 建立了观察结果与时间变化的关系,能帮预测未来一段时间内的结果变化情况

时间序列分析与回归分析的区别:

  • 在选择模型前,我们需要确定结果与变量之间的关系。回归分析训练得到的是目标变量y与自变量x(一个或多个)的相关性,然后通过新的自变量x来预测目标变量y。而时间序列分析得到的是目标变量y与时间的相关性

  • 回归分析擅长的是多变量与目标结果之间的分析,即便是单一变量,也往往与时间无关。而时间序列分析建立在时间变化的基础上,它会分析目标变量的趋势、周期、时期和不稳定因素等。这些趋势和周期都是在时间维度的基础上,是我们要观察的重要特征

历史渊源:

  • 中国古代24节气就是时间序列的早期应用(横坐标时间,纵坐标农作物变化)

现代应用:

  • 金融领域:股票价格、海运价格预测
  • 其他领域:人流量、交通流量、客流量预测

模型类型:

  • 统计学模型:AR、MA、ARMA、ARIMA
  • 神经网络模型:LSTM(长短记忆网络)、基于Transformer的模型(如阿里FEDformer)

# 时间序列及分解:

  • 平稳序列,stationary series
    基本上不存在趋势(Trend)的序列,各观察值基本上在某个固定的水平上波动

  • 非平稳序列,non-stationary series
    包含趋势、季节性或周期性的序列,可以只有一种成分,也可能是多种成分的组合

判断要点: 需拉长时间维度观察,局部波动不能代表整体趋势

  • 趋势(trend): 时间序列在长时期内呈现出来的某种持续上升或持续下降的变动,也称长期趋势

  • 季节性(seasonality): 时间序列在一年内重复出现的周期波动。销售旺季,销售淡季,旅游旺季、旅游淡季

    季节,可以是任何一种周期性变化,不一定是一年中的四季

    含有季节成分的序列可能含有趋势,也可能不含有趋势

  • 周期性(cyclicity):
    通常是由经济环境的变化引起

    不同于趋势变动,不是朝着单一方向的持续运动,而是涨落相间的交替波动

    不同于季节变动,季节变动有比较固定的规律,变动周期大多为一年。周期性的循环波动无固定规律,变动周期多在一年以上,且周期长短不一

  • 随机性(Irregular)
    指受偶然因素影响所形成的的不规则波动,在时间序列中无法预估

    随机性是不规则波动,除去趋势、周期性、季节性的偶然性波动

因素 举例
长期趋势Trend(T) 国内生产总值
季节变动Season(S) 冰淇淋、暖宝宝、羽绒服、裙子等销售
周期性Cyclic(C) 太阳黑子数量变化
随机性Irregular(I) 股票市场受到突然的利好、利空等信息的影响,影响股价产生的波动

# 时间序列工具(statsmodels)

statsmodels工具:

  • statsmodels工具包提供统计计算,包括描述性统计以及统计模型的估计和推断

statsmodels主要包括如下子模块:

  • 回归模型:线性回归,广义线性模型,线性混合效应模
  • 方差分析(ANOVA)
  • 时间序列分析:AR,ARMA,ARIMA等

应用场景: 特别适用于金融数据分析,如股票价格分解为趋势(trend)、季节性(seasonal)和残差(residual)三部分

时间序列模型
├── 统计学模型(经典路线)
│   ├── AR   — 用过去的值预测未来
│   ├── MA   — 用过去的误差预测未来
│   ├── ARMA — AR + MA,适用于平稳序列
│   └── ARIMA — ARMA + 差分,适用于非平稳序列
│
└── 神经网络模型(深度学习路线)
    ├── LSTM — 能记忆长周期依赖
    └── Transformer系列 — 如FEDformer,适合多周期叠加
1
2
3
4
5
6
7
8
9
10
import statsmodels.api as sm
#数据加载
data = pd.read_csv('shanghai_index_1990_12_19_to_2020_03_12.csv',
usecols=['Timestamp', 'Price'])
data.Timestamp = pd.to_datetime(data.Timestamp)
data = data.set_index('Timestamp')
data['Price'] = data['Price'].apply(pd.to_numeric, errors='ignore')
#进行线性插补缺漏值
data.Price.interpolate(inplace=True)
#返回三个部分trend(趋势),seasonal(季节性)和residual (残留)
result = sm.tsa.seasonal_decompose(data.Price,period=250)
result.plot()
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13

这段代码就是在做你刚学的时间序列分解——把沪市指数的收盘价拆成趋势、季节性、残差三个部分。逐行讲:

# 数据准备阶段

import statsmodels.api as sm
1

导入statsmodels,这是你刚学的统计学工具包,ARIMA、分解等都在里面。

data = pd.read_csv('shanghai_index_1990_12_19_to_2020_03_12.csv', 
                    usecols=['Timestamp', 'Price'])
1
2

读CSV,只取时间戳和价格两列。这是沪市从1990年开市到2020年的指数数据,近30年。

data.Timestamp = pd.to_datetime(data.Timestamp)
data = data.set_index('Timestamp')
1
2

把时间列转成datetime类型,然后设为索引。这一步很关键——时间序列分析要求索引是时间类型,这样pandas才知道数据是按时间排列的。

data['Price'] = data['Price'].apply(pd.to_numeric, errors='ignore')
1

把Price列强制转成数值。加errors='ignore'是因为原始数据里可能混入了非数字(比如空值、文字),遇到这些不报错,保持原样。

data.Price.interpolate(inplace=True)
1

线性插补补缺漏值。比如第3天和第5天有数据,第4天缺失,就用(第3天+第5天)/2来填充。inplace=True直接在原数据上改。时间序列不能有缺失,否则分解会报错。

# 核心分解

result = sm.tsa.seasonal_decompose(data.Price, period=250)
1

这是整段代码的灵魂。seasonal_decompose是加法分解:

原始序列 = 趋势(Trend) + 季节性(Seasonal) + 残差(Residual)  
1

period=250是什么意思?——一个季节周期的长度是250个交易日,大约相当于一年的交易日数量(一年约250个交易日)。意思就是:假设沪市指数存在"一年为单位"的季节性规律。

这个参数怎么选:

如果数据是按天的,一年≈250个交易日 → period=250
如果数据是按月的,一年=12个月 → period=12
如果数据是按周的,一年≈52周 → period=52

# 可视化

result.plot()
plt.show()
1
2

画出四张子图:原始数据、趋势、季节性、残差。

# 这件事的意义

  1. 看趋势 — 沪市30年到底涨没涨?趋势线会把短期噪音过滤掉,你看到的是长期方向。大概率是一条从几百点上升到几千点的曲线。

  2. 看季节性 — 有没有"春季行情""年底效应"这种规律?如果季节性成分的振幅很小,说明沪市的季节性规律不明显(相比美股的"Sell in May"效应,A股的季节性确实弱一些)。

  3. 看残差 — 去掉趋势和季节性之后还剩什么?残差大,说明市场受随机因素(政策、突发事件)影响大,可预测性就低。这对你的认知很重要——如果残差占比很高,就别指望用简单的时间序列模型稳定赚钱。

# 一个延伸思考

这里用的是加法分解(Additive),意味着假设三个成分是相加关系。如果数据的波动幅度随趋势增大(比如涨到5000点时波动比1000点时大得多),应该用乘法分解:

result = sm.tsa.seasonal_decompose(data.Price, period=250, model='multiplicative')   
1
原始序列 = 趋势 × 季节性 × 残差
1

股市数据通常更适合乘法模型,因为波动幅度确实会随指数点位增大。你可以两种都试试对比一下。

# AR模型

  • Auto Regressive,中文叫自回归模型
  • 认为过去若干时刻的点通过线性组合,再加上白噪声就可以预测未来某个时刻的点
  • 日常生活环境中就存在白噪声,在数据挖掘的过程中,可以把它理解为一个期望为0,方差为常数的纯随机过程
  • AR模型存在一个阶数p,称为AR(p)模型,也叫作p阶自回归模型。指的是通过这个时刻点的前p个点,通过线性组合再加上白噪声来预测当前时刻点的值
  • AR是线性时间序列分析模型中最简单的模型,通过前面部分的数据与后面部分的数据之间的相关关系来建立回归方程:

xt = ‌‌Φ1xt-1 + ‌‌Φ2xt-2 + ... + ‌‌Φpxt-p + ut

  • AR(p),表示p阶的自回归过程,为自回归系数
  • ut 表示白噪声,是时间序列中的数值的随机波动。这些波动会相互抵消,即累计为0
  • 如果只有一个时间记录点时,则为AR(1),即一阶自回归过程:

xt = ‌‌Φ1xt-1 + ut

# 先理解"自回归"这三个字

自:自己,意思是只用自己过去的数据,不需要别的变量

回归:你学过的线性回归,找线性关系

合起来就是:用自己的过去预测自己的未来

举个生活例子:你明天体重多少?很大程度上取决于你前几天吃了什么、运动了没。不需要知道别人体重多少,光看自己的历史数据就能大致推。这就是"自回归"的思想。

# 白噪声是啥

你住路边,窗外一直有嗡嗡声,时大时小,完全没规律——这就是白噪声。

在数据里,白噪声就是:

完全随机的波动
有时候正,有时候负
长期看正负互相抵消,平均为0

你可以理解为:模型预测不到的那部分"运气"。就像你预测明天体重,但突然感冒了没吃饭,这个感冒就是白噪声——你没法提前预知,但它影响了结果。

# 阶数p:看多远的历史

p就是"我要往前看几个点":

AR(1):只看昨天 → 用1天预测今天
AR(2):看昨天和前天 → 用2天预测今天
AR(p):看前p天 → 用p天预测今天

就像你判断今天该穿多厚:

AR(1):只看昨天热不热
AR(3):看最近三天热不热,综合判断

# 公式翻译成人话

原始公式:

xt = ‌‌Φ1xt-1 + ‌‌Φ2xt-2 + ... + ‌‌Φpxt-p + ut

翻译:

今天的值 = Φ1 × 昨天的值 + Φ2 × 前天的值 + ... + Φp × 前p天的值 + 运气(白噪声)
1

xt:今天要预测的值
xt-1:昨天的值(t-1就是往前推1步)
Φ1:昨天的影响有多大(系数/权重)
ut:白噪声,预测不准的那部分

Φ就是权重,模型训练要学的就是这个——到底昨天的影响大还是前天的影响大。

# 最简单的AR(1)

xt = ‌‌Φ1xt-1 + ut

人话:今天的值 ≈ 昨天的值乘个系数 + 随机波动

比如股票:如果Φ1=0.9,意思是今天的价格90%取决于昨天,只有10%是随机波动——趋势延续性强,不太会大起大落。

如果Φ1=0.1,意思是今天跟昨天关系不大,基本靠随机——市场很混乱。

# 举个数字例子

假设你在记录每天步数,发现AR(1)模型,Φ1=0.7:

昨天走了10000步
白噪声今天碰巧是+500

预测今天:0.7 × 10000 + 500 = 7500步

核心逻辑:你昨天走了1万步,今天大概率也差不多,但会往均值方向缩一点(乘了0.7),再加点随机波动。

# 一句话总结

AR模型就是:未来的值,是过去几个值的加权和,再凑点随机噪音。多简单——它假设历史会重演,只是不会完全一样重演。

# MA模型:

  • Moving Average,中文叫做滑动平均模型
  • 与AR模型大同小异,AR模型是历史时序值的线性组合,MA是通过历史白噪声进行线性组合来影响当前时刻点
  • MA模型中的历史白噪声是通过影响历史时序值,从而间接影响到当前时刻点的预测值
  • MA模型存在一个阶数q,称为MA(q)模型,也叫作q阶移动平均模型
  • AR和MA模型都存在阶数,在AR模型中,用p表示,在MA模型中用q表示,这两个模型大同小异,与AR模型不同的是MA模型是历史白噪声的线性组合
  • MA模型,通过前面通过将一段时间序列中白噪声序列进行加权和,可以得到移动平均方程:

xt = ‌‌ ut + Φ1ut-1 + ‌‌Φ2ut-2 + ... + ‌‌Φqut-q

  • MA(q)表示q阶移动平均过程,Φ为移动回归系数,ut为不同时间点的白噪声
  • Xt为第t天的股票价格,而Ut为第t天的新闻影响,当天的股票价格受当天的新闻影响,也受昨天的新闻影响(但影响力要弱些,所以要乘上系数)

AR你刚搞懂了,MA就轻松了,因为思路是一样的,只是换了个"原料"。

# AR vs MA:一句话区别

AR:用过去的值预测未来 → 今天价格 = 昨天价格 × 系数 + ...
MA:用过去的意外事件预测未来 → 今天价格 = 昨天的意外 × 系数 + ...

一个是看"过去的成绩",一个是看"过去的突发事件"。

# 回忆一下白噪声

上节说了,白噪声就是模型预测不到的随机波动,比如:

突然出的利好政策
某公司爆出丑闻
大佬发了一条推特

这些事你没法提前知道,但它发生了就会影响价格。这个影响就是白噪声。

# MA的核心思想

关键来了——一个突发事件不是只影响一天,它的影响会持续几天。

举个例子:

周一:突然降息了(白噪声u₁,影响很大)
周二:降息的影响还在,但比周一弱了(u₁的影响力衰减)
周三:影响更弱了,几乎消失了

MA模型就是在说:今天的值,是最近几天突发事件影响的叠加。

# 公式翻译

原始公式:

xt = ‌‌ ut + Φ1ut-1 + ‌‌Φ2ut-2 + ... + ‌‌Φqut-q

翻译:

今天的值 = 今天的意外 + Φ1×昨天的意外 + Φ2×前天的意外 + ... + Φq×前q天的意外
1

ut:今天新发生的意外(白噪声)
ut-1:昨天发生的意外
Φ1:昨天的意外对今天还有多大影响(权重)

注意:这里的ut不是今天的股价,而是今天的随机冲击。Φ是这些冲击的衰减系数。

# 用课件的新闻例子讲

Xt为第t天的股票价格,ut为第t天的新闻影响

假设MA(2),系数Φ1=0.6,Φ2=0.3:

今天:出了一则大新闻,影响u₃=+100
昨天:出了个小新闻,影响u₂=+50
前天:没新闻,影响u₁=0

预测今天价格变化:

xt = 100 + 0.6×50 + 0.3×0 = 100 + 30 + 0 = 130  
1

意思:今天自己的新闻直接贡献了+100,昨天新闻的余波还贡献了+30(0.6×50),前天的新闻已经基本没影响了。

# 和AR对比着看

AR MA
用什么预测 过去的值
输入 昨天股价、前天股价...
直觉 惯性:昨天涨了今天可能还涨
公式 xt = Φ₁·xt-1 + Φ₂·xt-2 + ... + ut

一个看"过去的走势",一个看"过去的冲击"。

# 一个生活类比

你考试分数:

AR思维:你上次考了90分,这次大概率也差不多,因为你的水平是稳定的 → 用过去的分数预测
MA思维:你上次考试前一天熬夜了(意外),影响了3分;上上次生病了(意外),影响了5分 → 用过去的意外事件预测

两种思路都有道理,所以后面会学ARMA = AR + MA,两个一起用。

# 一句话总结

MA模型就是:今天的值,是最近几次突发事件的叠加影响。事件越近影响越大(系数越大),远的就衰减掉了。

AR和MA搞懂了没?下一个ARMA就是哥俩合体,到时候会更顺。

# ARMA模型:

  • Auto Regressive Moving Average,中文叫做自回归滑动平均模型
  • AR模型和MA模型的混合,相比AR模型和MA模型,它有更准确的估计
  • ARMA模型存在p和q两个阶数,称为ARMA(p,q)模型:

xt = ut + Φ1ut-1 + ‌‌Φ2ut-2 + ... + ‌‌Φqut-q + θ1xt-1 + ‌‌θ2xt-2 + ... + ‌‌θpxt-p

  • 自回归模型结合了两个模型的特点,AR解决当前数据与后期数据之间的关系,MA则可以解决随机变动,即噪声问题

# ARMA = AR + MA

你回顾一下:

AR:用过去的值预测 → "惯性派",相信历史会延续
MA:用过去的意外预测 → "余波派",相信突发事件有持续影响

ARMA:两个都用 → "惯性+余波",更全面

# 生活类比

你预测明天体重:

AR说:你昨天140斤,今天大概率也差不多,因为体重有惯性

MA说:你昨天火锅吃撑了(意外事件),今天可能还水肿一点

ARMA说:两个都考虑 → 你本身140斤的基础(AR),加上昨天火锅的余波(MA),综合预测

显然ARMA考虑得更全面,所以课件说"有更准确的估计"。

# 公式拆成两半看

xt = ut + Φ₁ut-1 + ... + Φqut-q  |  + θ₁xt-1 + ... + θpxt-p
     —————— MA部分 ——————          |    ———— AR部分 ————
1
2

左半边(MA):最近q次意外的叠加影响
右半边(AR):最近p天值的惯性延续
ut:今天新来的意外(白噪声)

两个加一起就是今天的预测值。

# p和q怎么理解

ARMA(p, q)两个阶数:

p:看前p天的值(AR部分,看多远的历史走势)
q:看前q天的意外(MA部分,突发事件影响持续几天)

比如ARMA(2, 1):

AR(2):看最近2天的价格走势
MA(1):只考虑昨天1次突发事件的余波

# 为什么ARMA比单独AR或MA更准

因为现实世界不是只有惯性,也不是只有意外,是两个都有:

光用AR → 突然出了大事你反应不过来
光用MA → 市场本身的趋势方向你把握不住
用ARMA → 趋势+冲击都考虑到了

和你项目的联系

你蚂蚁金服项目里:

AR部分对应:昨天申购2亿,今天大概率也差不多(惯性)
MA部分对应:昨天是月末发工资日(突发周期事件),影响会延续到今天(余波)

你之前用树模型只能靠特征工程硬编码这些关系,而ARMA天然就在建模这种时间依赖。

# 一句话总结

ARMA就是把"历史惯性"和"突发事件余波"两个角度合在一起预测,比单用任何一个都更靠谱。p管看几天历史,q管看几天意外。

到这里AR、MA、ARMA三兄弟你都搞定了。下一个ARIMA就是在这个基础上加一个"差分"操作——处理非平稳数据的。

# ARIMA模型:

  • Auto Regressive Integrated Moving Average模型,中文叫差分自回归滑动平均模型,也叫求合自回归滑动平均模型
  • 相比于ARMA,ARIMA多了一个差分的过程,作用是对不平稳数据进行差分平稳,在差分平稳后再进行建模
  • ARIMA的原理和ARMA模型一样。相比于ARMA(p,q)的两个阶数,ARIMA是一个三元组的阶数(p,d,q),称为ARIMA(p,d,q)模型,其中d是差分阶数
  • AR,MA是ARMA的特殊形式,而ARMA是ARIMA的特殊形式

ARIMA模型步骤:

  • Step1,观察时间序列数据,是否为平稳序列
  • Step2,对于非平稳时间序列要先进行d阶差分运算,化为平稳时间序列
  • Step3,使用ARIMA(p,d,q)模型进行训练拟合,找到最优的(p, d, q),及训练好的模型
  • Step4,使用训练好的ARIMA模型进行预测,并对差分进行还原

ARIMA用差分将不平稳数据先变得平稳,再用ARMA模型

ARIMA你就当它是ARMA的"升级版",多了一步预处理而已。

# ARIMA比ARMA多了什么?

多了个I——Integrated,中文叫"差分"。

ARMA有个前提:数据必须是平稳的(没有明显趋势,在一个水平附近波动)。但现实数据大部分都有趋势,比如股价长期往上走,这就不是平稳的。

ARIMA的思路很简单:你不是不平稳吗?我先把你不平稳的部分去掉,变平稳了再交给ARMA处理。

# 什么是差分

差分就是用今天的值减昨天的值:

差分 = 今天 - 昨天
1

举个例子:

日期 原始值 一阶差分
周一 100
周二 103 103-100 = 3
周三 108 108-103 = 5
周四 110 110-108 = 2

原始值:100→103→108→110,明显在涨,不平稳

差分后:3→5→2,变成了围绕某个数波动,平稳多了

这就叫一阶差分(d=1)。

# 如果一阶差分还不平稳呢?

那就对差分结果再做一次差分——二阶差分(d=2):

二阶差分 = 今天的差分 - 昨天的差分
1

大部分情况一阶差分就够用了,很少用到d=2以上。

# d是啥

d就是差分几次:

d=0:数据本身就是平稳的,不用差分,ARIMA(0,p,q)就是ARMA
d=1:做一次差分变平稳,最常见
d=2:做两次差分才平稳,很少见

# ARIMA(p, d, q)三个参数

参数 含义 大白话
p AR阶数 看前p天的走势惯性
d 差分阶数 做几次差分才能变平稳
q MA阶数 看前q天的意外余波

比如ARIMA(2, 1, 1):

d=1:先做一次差分把趋势去掉
p=2:看前2天的走势
q=1:看前1天的意外

# 四步流程用人话讲

Step 1:看数据平不平稳

→ 画个图,如果明显在涨或跌,就不平稳

Step 2:不平稳就差分

→ 做d次差分,直到平稳为止

Step 3:用ARMA建模

→ 数据平稳了,用你刚学的ARMA去找最优的p和q

Step 4:预测,然后把差分还原回去

→ 模型预测的是差分后的值,要还原成原始值才能用

# Step 4的还原怎么理解

差分是"今天减昨天",那还原就是**"昨天加上差分"**:

预测的原始值 = 昨天的真实值 + 预测的差分值
1

比如昨天股价110,预测差分是+3,那预测今天就是110+3=113。

# 课件的包含关系

课件说"ARMA是ARIMA的特殊形式",现在你明白了吧:

ARIMA(p, 0, q) = ARMA(p, q)    ← d=0,不用差分
ARMA(p, 0)     = AR(p)          ← q=0,没有MA部分
ARMA(0, q)     = MA(q)          ← p=0,没有AR部分
1
2
3

所以它们是一层一层套的:

ARIMA 包含 ARMA 包含 AR / MA  
1

# 一句话总结

ARIMA就是:先差分把趋势抹平,再用ARMA建模预测,最后把差分还原回去。多了一个d参数,让ARMA能处理不平稳的现实数据。

四兄弟你全搞定了:AR → MA → ARMA → ARIMA,就是一步步升级的过程。

# ARMA工具

  • from statsmodels.tsa.arima_model import ARMA

  • ARMA(endog,order,exog=None)

  • endog:endogenous variable,代表内生变量,又叫非政策性变量,它是由模型决定的,不被政策左右,可以说是我们想要分析的变量,或者说是我们这次项目中需要用到的变量
    "内生"就是"模型内部产生的",模型要研究的对象
    比如你要预测股价,那股价就是内生变量
    简单说:你把要预测的那列数据扔进来

  • order:代表是p和q的值,也就是ARMA中的阶数
    "内生"就是"模型内部产生的",模型要研究的对象
    比如你要预测股价,那股价就是内生变量
    简单说:你把要预测的那列数据扔进来

  • exog:exogenous variables,代表外生变量。外生变量和内生变量一样是经济模型中的两个重要变量。相对于内生变量而言,外生变量又称作为政策性变量,在经济机制内受外部因素的影响,不是我们模型要研究的变量 "内生"就是"模型内部产生的",模型要研究的对象
    比如你要预测股价,那股价就是内生变量
    简单说:你把要预测的那列数据扔进来

如果我们想要创建ARMA(7,0)模型,可以写成:
ARMA(data,(7,0)),其中data是我们想要观察的变量,(7,0)代表(p,q)的阶数。

fit函数,进行拟合
predict(start, end)函数,进行预测,其中start为预测的起始时间,end为预测的终止时间

# 创建ARMA(7, 0)模型,就是AR(7)
model = ARMA(data, (7, 0))

# 拟合,让模型学习数据中的规律
result = model.fit()

# 预测,从第100天预测到第110天
pred = result.predict(start=100, end=110)
1
2
3
4
5
6
7
8