时间序列学习(2):白噪声、随机游走

时间序列学习(2):白噪声、随机游走

1、白噪声

白噪声是非常简单的一种建模时间序列的模型。

对于时间序列 { w t } \{w_t\} {wt​},若满足下面三个条件,该序列为一个离散的白噪声(white noise)

  • 每个时间点均值为0;
  • 每个时间点方差为 σ 2 \sigma^2 σ2;
  • 对于任意 k ≥ 1 k\ge1 k≥1,自相关系数 ρ k = 0 \rho_k=0 ρk​=0。

前两个条件并没有规定 w t w_t wt​一定是正态分布。如果是正态分布,那么这个时间序列又叫高斯白噪声(Gaussian white noise)

回顾上一篇笔记中的平稳性要求,显然一个白噪声序列是符合弱平稳性的(其均值和自相关系数均为固定值,比弱平稳性更加严格一些)。

2、对数收益率序列

上一篇笔记中的日收益率序列,不严格地说,其实是一个差分序列。也就是每一个时间点的价格减去前一个时间点的价格(当然,还除以了前一时间点的价格)。

现在我们利用对数收益率处理成纯的差分序列,即每一个时间点价格的对数减去前一个时间点价格的对数。

对于价格的时间序列 { p t } \{p_t\} {pt​},其对数收益率序列用下面的公式得到:

α t = ln ⁡ p t − ln ⁡ p t − 1 \alpha_t = \ln{p_t}-\ln{p_{t-1}} αt​=lnpt​−lnpt−1​

如果价格序列 { p t } \{p_t\} {pt​}体现出足够的自相关性(今天的价格和昨天强相关),那么对数收益率序列应该没有显著的自相关性了(自己减掉自己了)。也就是说对数收益率序列应该近似为一个白噪声。

我们将上一篇笔记的日收益率序列处理成对数收益率序列(即沪深300自2018年1月1日至2019年12月13日的对数收益率序列),如下:

import pandas as pd
import math


prices = get_price('000300.XSHG', start_date='2018-01-01', end_date='2019-12-13', frequency='daily', fields='close')

returns = {'return':{}}
for i in range(len(prices)):
    current_price = prices.iloc[i,0]
    if i == 0:
        current_return = 0
    else:
        last_price = prices.iloc[i-1,0]
        current_return = math.log(current_price)-math.log(last_price)
    date = list(prices.index)[i]
    returns['return'][date] = current_return
return_df = pd.DataFrame(returns, columns=['return'], index=list(prices.index))

fig = plt.figure(figsize=(10, 6))
ax = fig.add_axes([0.2, 0.2, 1.2, 1.2])
ax.plot(return_df, color="blue", linewidth=1.5, linestyle="-", label=r'hs300-daily-log-returns')
plt.legend(loc='upper right', frameon=False)

时间序列学习(2):白噪声、随机游走

return_df.mean()
return_df.std()

它的均值和标准差分别是:-0.000062,0.01315。

然后看看其时间间隔在50以下的相关图(相关图是啥,见上一篇笔记)。

import matplotlib.pyplot as plt
from statsmodels.graphics.tsaplots import plot_acf

fig = plt.figure(figsize=(10, 6))
ax = fig.add_axes([0.2, 0.2, 1.2, 1.2])
plot_acf(return_df, ax, lags=50)
plt.show()

时间序列学习(2):白噪声、随机游走

可以看到,上述收益率序列的均值-0.000062,非常接近于0;样本方差不能代表时间序列的方差,所以方差这一项依据我们暂时放在一边。看看自相关性,对于间隔为3的自相关系数超过了95%的置信区间,但其它都在区间内。

不管怎样,我们说上述对数收益率序列近似为一个白噪声。

3、随机游走

随机游走 random walk是对白噪声的简单延伸。

对于时间序列 { x t } \{x_t\} {xt​},如果满足如下条件,该时间序列是一个随机游走:

x t = w t + w t − 1 + . . . + w 0 x_t=w_t+w_{t-1}+...+w_0 xt​=wt​+wt−1​+...+w0​

其中, w t w_t wt​是一个均值为0,方差为 σ 2 \sigma^2 σ2的白噪声。

所以随机游走是白噪声的一个累积。比如,非严格地说,如果把股价看成随机游走,它其实就是每日收益率(如果看成白噪声)的不断累积。

根据均值和方差的可加性可以求得随机游走的的均值和方差:

μ x t = 0 ; V a r ( x t ) = t σ 2 \mu_{x_t}=0; Var(x_t)=t\sigma^2 μxt​​=0;Var(xt​)=tσ2

进一步,随机游走的自协方差也可以计算出来:

C o v ( x t , x t + k ) = C o v ( x t , x t + w t + 1 + . . . + w k ) Cov(x_t,x_{t+k})=Cov(x_t,x_t+w_{t+1}+...+w_k) Cov(xt​,xt+k​)=Cov(xt​,xt​+wt+1​+...+wk​)
= C o v ( x t , x t ) + ∑ i = t + 1 k C o v ( x t , w i ) =Cov(x_t,x_t)+\sum^k_{i=t+1}Cov(x_t,w_i) =Cov(xt​,xt​)+i=t+1∑k​Cov(xt​,wi​)
= C o v ( x t , x t ) + 0 = t σ 2 =Cov(x_t,x_t)+0=t\sigma^2 =Cov(xt​,xt​)+0=tσ2

有了自协方差,自相关系数也可以算出来:

ρ k ( t ) = C o v ( x t , x t + k ) V a r ( x t ) V a r ( x t + k ) \rho_k(t)=\frac{Cov(x_t,x_{t+k})}{\sqrt{Var(x_t)}\sqrt{Var(x_{t+k})}} ρk​(t)=Var(xt​) ​Var(xt+k​) ​Cov(xt​,xt+k​)​
= t σ 2 t σ 2 ( t + k ) σ 2 =\frac{t\sigma^2}{\sqrt{t\sigma^2}\sqrt{(t+k)\sigma^2}} =tσ2 ​(t+k)σ2 ​tσ2​
= 1 1 + k t =\frac{1}{\sqrt{1+\frac{k}{t}}} =1+tk​ ​1​

显然,上面的自相关系数和时间间隔有关,所以不具有平稳性。

另外,当k很小时,自相关系数接近于1。如果把股价走势看成随机游走,那么它的当日价格和昨日价格的相关性理论上非常高。

很多人把上述结论看成是一个重要的工具,于是以今日价格作为次日价格的预测值(因为相关性很高嘛)。看似很有道理,但是策略的期望收益大概率为0。

这里要注意的是,当k很小时,自相关系数接近于1,但不是1!

4、随机游走示例

下面我们用随机游走来生成一些序列看看。就用第二节中的均值(-0.000062)和标准差(0.01315)构建一个高斯白噪声。

设定初始值为3000(昨天,上证第44次突破3000点),然后,我们生成8条随机游走曲线如下:

import numpy as np
import pandas as pd
import math

mu = 0  
sigma = 0.01315  
num = 500
offsets = [i for i in range(500)]
fig = plt.figure(figsize=(10, 6))
ax = fig.add_axes([0.2, 0.2, 1.2, 1.2])
colors = ['grey', 'brown', 'red', 'sienna', 'olive', 'green', 'blue', 'purple']

for i in range(0, 8):
    rand_returns = np.random.normal(mu, sigma, num)
    prices = []
    for j in range(500):
        if j == 0:
            current_price = 3000
        else:
            last_price = prices[j-1]
            current_return = rand_returns[j]
            current_price = math.pow(math.e, math.log(last_price)+current_return)
        prices.append(current_price)
    ax.plot(offsets, prices, color=colors[i], linewidth=1.5, linestyle="-", label=r'random walk %d' % i)

plt.legend(loc='upper left', frameon=False)

时间序列学习(2):白噪声、随机游走

可以看到,这些数值走势毫无相关性和规律性,在时间推进过程中,波动由于单点白噪声的累积在远端越来越大,但是没有明显的方向性。

上一篇:【原创】modb 功能设计之“支持多消费者单生产者”


下一篇:PyTorch中FLOPs计算问题