社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

用 Python 计算 Hurst 指数并预测市场趋势

Python中文社区 • 2 年前 • 471 次点击  


建造水库是一个高风险的问题。如果计算错误,成千上万的人可能会失去他们的家园。在20世纪中期,英国水文学家埃德温-哈罗德-赫斯特在解决这类问题方面取得了重大突破。他开发了后来被称为Hurst指数的东西,这是一个衡量时间序列中自动相关的指标。虽然它是为了估计河流中的水量而开发,但正如我们所期望的那样,对于涉及时间序列的数学计算,Hurst指数在金融市场研究中得到了有趣的应用。

下面将展示如何计算Hurst指数,并使用它来评估标准普尔500指数、比特币和美元/瑞士法郎交易对的特性,看看我们是否能理解这些金融序列的交易趋势。

什么是Hurst指数?

Hurst指数可以用来确定一个时间序列是否倾向于向单一方向移动(H>0.5),振荡(H<0.5),或随机(H=0.5)。

虽然赫斯特发现这种关系在各种自然现象中很有用,如洪水、河流排放和树木年轮,但我们也可以用它来将一个市场归类为趋势性或均值回归性。如果我们知道一个市场倾向于以某种方式行事,我们可以尝试用适当的均值回归或趋势跟踪策略来捕捉这一点,或者在你的算法交易系统中使用它作为一个过滤器。

如何计算Hurst指数?计算Hurst指数需要估计多个不同时间段的R/S统计量,然后将其与各时间段绘制成对数图,并找出斜率。这条线的斜率就是Hurst指数 —— H。

有多种方法来估计Hurst指数。就我所知,重新标定的范围分析方法是最古老的,但使用去趋势波动分析(DFA)是最常见的。我们将使用后者,因为尽管它听起来很复杂,但它只需要3-4行代码就能运行,而且比我的重标范围分析实现快一个数量级。这两种方法都是可行的,但它们略有不同。

假设我们有一个价格序列,我们称之为x。然后我们可以看一下x在不同时间t的差异,并取其差值。这个时间差将被称为lag(滞后)。我们想得到这些滞后差值的标准差的关系。

我们可以按以下步骤写出我们的计算结果。

1、选择一个滞后期的范围(如2到100)。

2、计算x中所有点的滞后差值。

3、计算每个lag的标准差。

4、将标准差的对数与lag的对数作图,以估计H。

数学上的公式为:

将所有的数据插入最后一个方程,我们可以找到最佳拟合线,我们就得到了H的值。让我们来看看如何用Python来做这件事!

用Python中计算Hurst指数

首先导入几个包: 

  1. import numpy as np

  2. import matplotib.pyplot as plt

然后定义我们的 hurst()函数。

  1. def hurst(price, min_lag=2, max_lag=100):

  2. lags = np.arange(min_lag, max_lag + 1)

  3. tau = [np.std(np.subtract(price[lag:], price[:-lag]))

  4. for lag in lags]

  5. m = np.polyfit(np.log10(lags), np.log10(tau), 1)

  6. return m, lags, tau

我们可以通过使用一个计算所有滞后差值的标准差的列表来理解,将所有的东西整合在几行紧凑的线条中。

接下来,让我们在一些我们知道答案的序列上测试这个函数。这将有助于确保我们的计算是正确的。

  1. N = 10000

  2. rand = np.cumsum(np.random.randn(N) + 0.01)

  3. mr = np.cumsum(np.sin(np.linspace(0, N/3*np.pi, N))/2 + 1)

  4. tr = np. cumsum(np.arange(N)/N)


  5. m_rand, lag_rand, rs_rand = hurst(rand)

  6. m_mr, lag_mr, rs_mr = hurst(mr)

  7. m_tr, lag_tr, rs_tr = hurst(tr)


  8. print(f "Hurst(Random):\t{m_rand[0]:.3f}")

  9. print(f"Hurst(MR):\t{m_mr[0]:.3f}")

  10. print(f"Hurst(TR):\t{m_tr[0]:.3f}")

  1. Hurst(Random): 0.499

  2. Hurst(MR): 0.075

  3. Hurst(TR): 0.997

此外,我们可以将这些系列与我们的lag值和统计数据的对数图一起绘制。

左栏中的图是对数图。你可以看到我们试图在Y轴上拟合标准差统计数字。对于随机和趋势的时间序列,它们匹配得很好。均值回归的是一个快速振荡的正弦波——完全不一致,但斜率仍然是正的,并且小于0.5。在你的生活中,你永远不会看到这样的金融时间序列,但它应该给你信心,我们的函数是有效的!

金融时间序列的Hurst指数

将Hurst应用于金融数据也同样简单明了。我们可以把它应用于一些常见的时间序列,看看我们得到什么。

我们将使用美元/瑞士法郎交易对、BTC和SPY来感受一下这些数据。

用yfinance软件包抓取数据。

  1. import pandas as pd

  2. import yfinance as yf


  3. tickers = ['CHF=X', 'BTC-USD', 'SPY', 'GLD', 'USO']

  4. start = '2010-01-01'

  5. end = '2021-12-31'

  6. yfObj = yf.Tickers(tickers)

  7. df = yfObj.history(start=start, end=end)

  8. df.drop(['Stock Splits', 'Dividends', 'Volume',

  9. 'Open', 'High', 'Low'], axis=1, inplace=True)

  10. df.columns = df.columns.swaplevel()

我们在这里只对收盘价感兴趣,所以我们可以放弃所有其他的列,并在这些列上运行swaplevel(),这样我们就可以按股票代码进行索引。

接下来,我们需要通过Hurst()函数运行每个时间序列,以获得指数和相关值。

  1. vals = {c[0]: hurst(df[c].dropna().values) for c in df.columns}

一旦完成,我有一个辅助函数来绘制结果。

  1. def plotHurst(m, x, y, series, name):

  2. fig, ax = plt.subplots(1, 2, figsize=(15, 6))

  3. ax[0].plot(np.log10(x), m[0] * np.log10 (x) + m[1])

  4. ax[0].scatter(np.log10(x), np.log10(y), c=colors[1])

  5. ax[0].set_title(f"{name} (H = {m[0]:.3f})")

  6. ax[0].set_xlabel(r"log($\tau$)" )

  7. ax[0].set_ylabel(r"log($\sigma_\tau$)")


  8. ax[1].plot(series)

  9. ax[1].set_title(f"{name}")

  10. ax[1].set_ylabel("Price ($)")

  11. ax[1].set_xlabel ("Date")


  12. return fig, ax

这使得绘制我们的数值变得更加容易。如果我们想绘制所有的数值,我们可以循环浏览我们的vals字典,并调用plt.show(),如下面的代码所示。

  1. for k, v in vals.items():

  2. fig, ax = plotHurst(*v, df[k], k)

  3. plt.show()

让我们依次看一下结果,看看我们是否能从Hurst指数告诉我们的东西中得到一些启示。

美元/瑞士法郎交易对均值回归

我们将从Hurst指标中看到的最强烈的信号开始,即美元/瑞士法郎交叉。

大多数交易员都有一种直觉,即货币对总体上是均值回归的,而对于强势货币之间的货币对,如美元和瑞士法郎,它尤其明显。

这正是我们在这里看到的情况。

不过,值得注意的是,较短的时间框架与我们在这里看到的较长的时间框架有一定的偏差。在最短的时间范围内,已实现波动率的期限结构(即蓝点所在的位置)低于红线。

出于好奇,我绘制了各种最大lag值的Hurst指数,看看这个系列是否曾经成为一个趋势系列。

并非如此。

它确实越长越平均,表明美元和瑞士法郎之间有一个相当稳定的长期关系。这是每日数据,所以它可以提供一些指导,作为你应该交易的时间框架。考虑到它在60天以上会变得更加均值化,也许在这个时间范围内(或更长)运行的均值化策略将是最有效的。

比特币是一种动量游戏

比特币暴涨暴跌的势头恰恰相反。

Hurst指数给出了一个相当明确的信号:这是一个动量交易,而已实现的波动率期限结构显示出令人惊讶的少数偏差。

但有趣的是,2021年的情况。

在比特币2020年的巨大牛市之后,它在2021年度过了一个随机/平均回归阶段。请注意,这不是那么多的数据,但有趣的是,不知道比特币是否已经进入了一个趋势变化。在2017年的大牛市之后,它在2018-2019年进入了一个类似的趋势,它有两年时间在进行均值回归,直到2020年起飞。

到目前为止,2022年已经显示出类似的模式。它能在今年剩下的时间里持续下去吗?

标准普尔500指数的均值回归

这个对我来说是最大的惊喜。Hurst指数显示,标普500指数是一个平均回归的时间序列。

看看它右边的价格图,它看起来有一个强大的上升趋势。

我们的算法揭示了我们眼睛看不到的东西。

我们可以对标准普尔500指数进行与美元/瑞士法郎汇率相同的分析,看看在不同的滞后期是否有任何拐点或赫斯特指数的变化。

当我们这样做时,我们会得到下面的图表。

在这幅图中,H值随着滞后期的变化而明显变化。在中短期内,该系列是平均回归的,但在较长的时间范围内,它变得有强烈的趋势性。在非常长的时间内(超过400天),它又回到了强烈的均值回归。

让我们看看这在不同的时间范围内是否成立。

我们将回到过去,从1993年开始到2021年,获取SPY的数据。这将产生7,284个交易日。此外,我们将把它分为四个时间段,并在这四个时间段中的每一个时间段运行相同的分析,以查看SPY的行为是否在较小的间隔内发生变化。

这就产生了下面的图表。

这表明,标准普尔500指数在不同的lag(滞后)期会经历更多的趋势和更多的均值回归时期。例如,比较2000-2007年期间。在这里,我们从互联网的繁荣和萧条到全球金融危机的高峰,几乎所有的滞后期都是趋势的。从那时起,在200-300区间内,趋势的持续程度较低,但其他地方的均值回归更为普遍。

值得注意的是,在我们看的每一个时间框架内,该系列似乎都在200-300天范围内有趋势。这似乎表明,标普500指数在这些时间范围内表现出强烈的趋势行为,可以通过趋势跟踪模型加以利用,而均值回归模型在较短的时间范围内会更有价值。

这种对200-300天范围内趋势的观察似乎与著名的海龟交易员杰里-帕克的轶事观察相吻合,即现代趋势跟踪在这些200天以上的时间范围内效果最好。

总结

一个市场是倾向于趋势、均值回归,还是随机的,这对交易者来说是有价值的信息。虽然赫斯特指数本身并不是一个入场信号,但它可以作为一个系统的过滤器。考虑到市场制度可能会随着时间的推移而发生变化,有利于一种或另一种方法,用Hurst过滤器覆盖你的模型,可以帮助防止你的算法在均值回归的市场中买入突破,或在市场走向新高时在回撤之前做空。

从本质上讲,它可以帮助你的算法与它所交易的市场相匹配。当然,这需要大量的回测。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/135337
 
471 次点击