白噪声是非常简单的一种建模时间序列的模型。
对于时间序列 { w t } \{w_t\} {wt},若满足下面三个条件,该序列为一个离散的白噪声(white noise):
前两个条件并没有规定 w t w_t wt一定是正态分布。如果是正态分布,那么这个时间序列又叫高斯白噪声(Gaussian white noise)。
回顾上一篇笔记中的平稳性要求,显然一个白噪声序列是符合弱平稳性的(其均值和自相关系数均为固定值,比弱平稳性更加严格一些)。
上一篇笔记中的日收益率序列,不严格地说,其实是一个差分序列。也就是每一个时间点的价格减去前一个时间点的价格(当然,还除以了前一时间点的价格)。
现在我们利用对数收益率处理成纯的差分序列,即每一个时间点价格的对数减去前一个时间点价格的对数。
对于价格的时间序列 { 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)
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()
可以看到,上述收益率序列的均值-0.000062,非常接近于0;样本方差不能代表时间序列的方差,所以方差这一项依据我们暂时放在一边。看看自相关性,对于间隔为3的自相关系数超过了95%的置信区间,但其它都在区间内。
不管怎样,我们说上述对数收益率序列近似为一个白噪声。
随机游走 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∑kCov(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!
下面我们用随机游走来生成一些序列看看。就用第二节中的均值(-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)
可以看到,这些数值走势毫无相关性和规律性,在时间推进过程中,波动由于单点白噪声的累积在远端越来越大,但是没有明显的方向性。