adf机器_使用希尔伯特-黄变换(HHT)进行时间序列分析

本文介绍了如何利用希尔伯特-黄变换(HHT)对非平稳时间序列进行分析,以富时100指数为例,通过经验模态分解(EMD)和Augmented Dickey-Fuller Test(ADF测试)去除趋势,确保数据平稳。通过HHT分解,可以揭示股价波动的内在模式。
摘要由CSDN通过智能技术生成

近期原创文章:

将非平稳时间序列用经验模态分解(EMD)转为固有特征方程式并且捕获其趋势。可以尝试使用HHT,当然这只是其中的一种方法,并没有像其他方法一样存在数学证明等。

数据准备

为了方便起见,我们选取了富时100指数(FTSE100)过去10年的收盘价作为金融时间序列,只是作为我们研究,大家可以用其他指数。之后,我们会选取希尔伯特谱来分析固有特征方程式来提取即时数据信息。

富时100指数数据的提取式这样的,加载到dataframe里:

时间,   开盘价,   收盘价,   最高价,    最低价,  成交量

02-Jan-2009,4434.20,4561.80,4561.80,4430.00,407295392

05-Jan-2009,4561.80,4579.60,4618.10,4520.80,836675968

21-Dec-2018,6711.93,6721.17,6733.00,6653.65,1636792576

24-Dec-2018,6721.17,6685.99,6721.17,6661.04,173149664

import os

import pandas as pd

import matplotlib.pyplot as plt

import numpy as np

data_directory = 'some path...'

data_file = os.path.join(data_directory, 'ftse100_2009_2018.csv' )

ftseinfo = pd.read_csv(data_file)

测试数据

# convert strings to dates

ftseinfo['Date'] = pd.to_datetime(ftseinfo['Date'], format="%d-%b-%Y" )

# convenience variable for plots

date_axis = ftseinfo['Date']

# The date entries are not evenly spaced, so calculate number of days from first date for each

first_date = date_axis[0]

deltas = ftseinfo['Date'] - first_date

def getdays(delta):

return delta.days

ftseinfo['deltadays'] = deltas.apply(getdays)

# convenience variable for days

days = ftseinfo['deltadays']

# plot closing price

fig = plt.figure(figsize=(12,6))

sp1 = fig.add_subplot(111)

plt.xlabel('date')

plt.ylabel('price')

sp1.plot_date( x=date_axis, y=ftseinfo['Close Price'] )

plt.legend(loc='center right')

plt.show()

7123076c9176551281623a4160981591.png

当股价是非平稳状态并且有随机走势基础时,以上图形可以看作有线性的趋势结构,让我们加以测试。

平稳性

一组具有平稳性的时间序列不以某些时间点为依赖,并且没有趋势性或季节性。股价按理来说应该是平稳性的,可是很显然,有些走势并非如此。它可能具备一些趋势。当然我们不能肯定未来的价格依赖于过去的价格,趋势只是过去时间点已知发生的事实。所以,给出一段股价走势,这些数据可能呈现出非平稳定性。为了更好地分析,我们要去除这一非平稳状态。通常,我们通过观察数据差异(例如价格变动)而不是绝对价格。

Augmented Dickey-Fuller Test(用于测试稳态):

# Dickey-Fuller test

from statsmodels.tsa.stattools import adfuller

def adf_test(timeseries):

dftest = adfuller(timeseries, autolag='AIC')

print('ADF Statistic: %f' % dftest[0])

print('p-value: %f' % dftest[1])

print('Critical Values:')

for key, value in dftest[4].items():

print('\t%s: %.3f' % (key, value))

结果显示于下方:

adf_test( ftseinfo['Close Price'] )

ADF Statistic: -2.129286

p-value: 0.232903

Critical Values:

1%: -3.433

5%: -2.863

10%: -2.567

我们用一个0.05的p-value作为阀值,很显然这里的p-value大于0.05,所以我们认为这组时间序列是非平稳的,需要改进。

分解与残差(趋势)

在下面的例子里,用pyhtt包来处理HHT分解:

from pyhht.utils import inst_freq

from pyhht import EMD

def decompose( x, y ):

decomposer = EMD( y )

imfs = decomposer.decompose()

return imfs

def emd_analysis( days, data_values ):

# decompose time series into intrinsic mode functions

imfs = decompose(days, data_values)

# extract the residue (overall trend)

imf_residue = imfs[len(imfs)-1]

return (imfs, imf_residue )

# Do the decomposition on the closing price time series

( imfs, imf_residue ) = emd_analysis( days, ftseinfo['Close Price'])

# plot the residue to see if a clear trend in there

fig = plt.figure(figsize=(12,6))

sp1 = fig.add_subplot(111)

plt.xlabel('date')

plt.ylabel('residue')

sp1.plot_date( x=date_axis, y=imf_residue, color='red' )

plt.show()

8d6eabdecfc0fd245622e7caec4e88ce.png

残差显示了非常明显的趋势性,从分解结果可以看出一条十分明显的趋势线,因此需要去除。 之后我们在用ADF(Augmented Dickey-Fuller Test)来测试是否稳态。

趋势去除第一步

ftseinfo['trend_adjusted_1'] = ftseinfo['Close Price'] - imf_residue

# Let's look at adjusted prices

fig = plt.figure(figsize=(12,6))

sp1 = fig.add_subplot(111)

plt.xlabel('date')

plt.ylabel('trend adjusted price')

sp1.plot_date( x=date_axis, y=ftseinfo['trend_adjusted_1'], color='green' )

plt.axhline(0, color='black')

plt.legend(loc='lower right')

plt.show()

4d5434cfc24de3a0ccbc941c0d45ad0b.png

再用ADF测试:

# Dickey-Fuller test for stationary or not

adf_test( ftseinfo['trend_adjusted_1'] )

ADF Statistic: -3.329548

p-value: 0.013608

Critical Values:

1%: -3.433

5%: -2.863

10%: -2.567

发现p-value小于0.05,表明已经是平稳时间序列了。

分解步骤2

# Do the decomposition on the price movement series

( imfs, imf_residue ) = emd_analysis( days, ftseinfo['trend_adjusted_1'])

现在测试剩余残差:

# Check residue to ensure no significant trend information remains

fig = plt.figure(figsize=(12,6))

sp1 = fig.add_subplot(111)

plt.xlabel('date')

plt.ylabel('residue')

sp1.plot_date( x=date_axis, y=imf_residue, color='red' )

plt.axhline(0, color='black')

plt.show()

看起来也是需要去除的。

趋势去除第二步

ftseinfo['trend_adjusted_2'] = ftseinfo['trend_adjusted_1'] - imf_residue

# Dickey-Fuller test for stationary or not

adf_test( ftseinfo['trend_adjusted_2'] )

ADF Statistic: -3.343714

p-value: 0.013034

Critical Values:

1%: -3.433

5%: -2.863

10%: -2.567

1841e046caf270d973b4e1bbcce54ff6.png我们再分解一次。

( imfs, imf_residue ) = emd_analysis( days, ftseinfo['trend_adjusted_2'])

# Check residue to ensure no significant trend information remains

fig = plt.figure(figsize=(12,6))

sp1 = fig.add_subplot(111)

plt.xlabel('date')

plt.ylabel('residue')

sp1.plot_date( x=date_axis, y=imf_residue, color='red' )

plt.axhline(0, color='black')

plt.show()

b45228d86cbf49afb33f29b323c38abb.png

从图形看还是剩余了一些趋势,但是在十年中的增长很少,可以认为趋势基本不存在了。

复权价格EMD

从以上看来,HHT/EMD方法找到了两个趋势, 我们都已经将他们去除了,剩余的数据已经没有了趋势。因此我们可以开始测试固有特征方程了。

# Plot each IMF in turn; the highest frequency IMFS are first and lowest are last

for i in range(0,len(imfs)-1):

fig = plt.figure(figsize=(12,6))

sp1 = fig.add_subplot(111)

plt.xlabel('date')

plt.ylabel('imf %d'%i)

sp1.plot_date( x=date_axis, y=imfs[i], color='green' )

plt.axhline(0, color='black')

plt.show()

随着分解过程的进行,先去掉最高频率的函数,然后识别出频率越来越低的函数。

155201640776dfbf7cf78d882c032e7b.png

IMF 0

cde1a84c44a3559fba4ef96cccfd00d5.png

IMF 1

a7fcd0ec9bbf70e32bdf099bf8a388e2.png

IMF 2

6c28a10324cf15606aa146260ad42814.png

IMF 3

fd260930bf12e1fb7c147f39fbeee128.png

IMF 4

1d3f1e4fe2f2b1d6aa36060773cd15d2.png

IMF 5

30dcaeeaf9585fdffdacd1e20a6986f5.png

IMF 6

17c86133c24438f44e91309447fab70d.png

IMF 7

IMF 8

理论上讲,这其中任何IMF曲线均可用希尔伯特时频谱分析来得到其频率的数据。这些曲线可以给长期的价格波动提供可靠依据。

总结

所以我们看到了HHT可以用在非平稳时间序列上来分析残差的趋势问题。

例子里运用富时100的数据只是为了探索这一理论,并不具有实战性。

当趋势的信息被去除后, 时间序列经过固有特征IMF方程的处理分解,即可展现出股价波动的一些信息。我们的想法得以达成。

推荐阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值