赫尔挪动平均线(Hull Moving Average,简称 HMA)是一种技术指标,于 2005 年由 Alan Hull 开发。它是一种挪动平均线,利用加权计算来缩小滞后并进步准确性。
HMA 对价格变动十分敏感,同时最大水平地缩小短期稳定可能产生的乐音。它通过应用加权计算来强调更近期的价格,同时平滑数据。
计算 HMA 的公式波及三个步骤。首先,应用价格数据计算加权挪动平均线。而后,应用第一步的后果计算第二个加权挪动平均线。最初,应用第二步的后果计算第三个加权挪动平均线。最终计算的后果就是挪动赫尔平均线。
WMA_1 = 一段期间内价格的加权挪动平均值 (WMA) /2
WMA_2 = 价格在一段时间内的 WMA
HMA_non_smooth = 2 * WMA_1 – WMA_2
HMA = HMA_non_smooth 的 WMA 除以根号 (周期)
在上面的文章中,咱们将介绍如何应用 Python 实现 HMA。本文将对计算 WMA 的两种办法进行具体比拟。而后介绍它在工夫序列建模中的作用。
Python 实现 HMA
办法 1:将 WMA 计算为按期间加权的挪动平均价格:
defhma(period):
wma_1=df['Adj Close'].rolling(period//2).apply(lambdax: \
np.sum(x*np.arange(1, period//2+1)) /np.sum(np.arange(1, period//2+1)), raw=True)
wma_2=df['Adj Close'].rolling(period).apply(lambdax: \
np.sum(x*np.arange(1, period+1)) /np.sum(np.arange(1, period+1)), raw=True)
diff=2*wma_1-wma_2
hma=diff.rolling(int(np.sqrt(period))).mean()
returnhma
period=20
df['hma'] =hma(period)
df['sma_20days'] =df['Adj Close'].rolling(period).mean()
figsize= (10,6)
df[['Adj Close','hma','sma_20days']].plot(figsize=figsize)
plt.title('Hull Moving Average {0} days'.format(period))
plt.show()
如图所示,HMA 比通常的 SMA 反馈更快:
还能够尝试更短的工夫框架,看看 HMA 与价格曲线的关系有多亲密。
df['hma_short']=hma(14)
df['hma_long']=hma(30)
figsize= (12,6)
df[['Adj Close','hma_short','hma_long']].plot(figsize=figsize)
plt.title('Hull Moving Average')
plt.show()
办法 2,应用体量计算加权平均值:
defhma_volume(period):
wma_1=df['nominal'].rolling(period//2).sum()/df['Volume'].rolling(period//2).sum()
wma_2=df['nominal'].rolling(period).sum()/df['Volume'].rolling(period).sum()
diff=2*wma_1-wma_2
hma=diff.rolling(int(np.sqrt(period))).mean()
returnhma
df['nominal'] =df['Adj Close'] *df['Volume']
period=20
df['hma_volume']=hma_volume(period)
figsize=(12,8)
fig, (ax0,ax1) =plt.subplots(nrows=2, sharex=True, subplot_kw=dict(frameon=True),figsize=figsize)
df[['Adj Close','hma_volume','hma']].plot(ax=ax0)
ax0.set_title('HMA Volume vs HMA period')
df[['Volume']].plot(ax=ax1)
ax1.set_title('Hull Moving Average')
plt.show()
体量的 HMA 比第一种办法计算的 HMA 稍滞后:
策略的回溯测试
为了回测每种策略 (办法 1 和 2),咱们将计算一个短期和一个长期的 HMA:
当短线超过长线时,能够触发买入指令。当短线低于长线时,就会触发卖出指令。
而后咱们计算每个信号产生的 pnl。
办法 1:
#SIGNAL
df['hma_short']=hma(20)
df['hma_long']=hma(30)
df['signal'] =np.where(df['hma_short'] >df['hma_long'],1,-1)
#RETURN
df['signal_shifted']=df['signal'].shift()
## Calculate the returns on the days we trigger a signal
df['returns'] =df['Adj Close'].pct_change()
## Calculate the strategy returns
df['strategy_returns'] =df['signal_shifted'] *df['returns']
## Calculate the cumulative returns
df1=df.dropna()
df1['cumulative_returns'] = (1+df1['strategy_returns']).cumprod()
#PLOT
figsize=(12,8)
fig, (ax0,ax1) =plt.subplots(nrows=2, sharex=True, subplot_kw=dict(frameon=True),figsize=figsize)
df[['Adj Close','hma_long','hma_short']].plot(ax=ax0)
ax0.set_title("HMA: Short vs Long")
df[['signal']].plot(ax=ax1,style='-.',alpha=0.4)
ax1.legend()
ax1.set_title("HMA - Signals")
plt.show()
df1['cumulative_returns'].plot(figsize=(10,4))
plt.title("Cumulative Return")
plt.show()
你能够看到每次产生的信号都有一条穿插线:
在数据集的整个时间段内产生的总体回报是正的,即便在某些期间它是负的:
回报率:
df1['cumulative_returns'].tail()[-1]
#1.0229750801053696
办法 2:
#SIGNAL
df['hma_volume_short']=hma_volume(20)
df['hma_volume_long']=hma_volume(30)
df['signal'] =np.where(df['hma_volume_short'] >df['hma_volume_long'],1,-1)
#RETURN
df['returns'] =df['Adj Close'].pct_change()
## Calculate the strategy returns
df['strategy_returns'] =df['signal'].shift() *df['returns']
## Calculate the cumulative returns
df2=df.dropna()
df2['cumulative_returns_volume'] = (1+df2['strategy_returns']).cumprod()
# PLOT
figsize=(12,8)
fig, (ax0,ax1) =plt.subplots(nrows=2, sharex=True, subplot_kw=dict(frameon=True),figsize=figsize)
df[['Adj Close','hma_volume_short','hma_volume_long']].plot(ax=ax0)
df[['signal']].plot(ax=ax1,style='-.',alpha=0.4)
ax0.set_title("HMA - Volume: Short vs Long")
ax1.legend()
plt.title("HMA - Signals")
plt.show()
figs= (10,4)
df2['cumulative_returns_volume'].plot(figsize=figs)
plt.title("Cumulative Return")
plt.show()
看起来比第一种办法中的 HMA 更平滑,能够触发的信号更少 (在咱们的例子中只有 1 个):
这种策略产生的回报不是很好:0.75(0.775-1⇒-24%)
df2['cumulative_returns_volume'].tail()[-1]
#0.7555329108482581
咱们来比拟两种策略的信号:
df['signal'] =np.where(df['hma_short'] >df['hma_long'],1,-1)
df['signal_volume'] =np.where(df['hma_volume_short'] >df['hma_volume_long'],1,-1)
figsize=(12,8)
df[['signal','signal_volume']].plot(figsize=figsize)
plt.show()
空头头寸的信号比多头头寸更多:
所以仅应用 HMA 还不足以产生有利可图的策略。咱们能够应用绝对强弱指数(RSI)和随机指数(Stochastic Oscillator 等其余指标来确认交易信号。然而对于工夫序列来说,HMA 是一个很好的特色工程的办法。
HMA 信号的一些解释
🎯穿插信号: 当价格越过 HMA 上方时,能够解释为看涨信号,当价格越过 HMA 下方时,能够解释为看空信号。它也能够触发买入和卖出信号,正如咱们之前曾经看到的。(上图点 1)。
🎯趋势跟踪信号:HMA 也可用于辨认趋势并生成趋势跟踪信号。当 HMA 歪斜向上时,它示意回升趋势,当它歪斜向下时,它示意降落趋势 (上图点 2)。
🎯反转信号: 当价格从下方靠近 HMA 时,看涨反转趋势可能在不久的未来产生 (上图点 3)。
HMA 在工夫序列建模的作用
HMA 在工夫序列建模中的作用次要是作为一个平滑滤波器,能够在肯定水平上缩小噪声并进步工夫序列预测的准确性。在工夫序列建模中,常常须要对数据进行平滑解决,以打消异样值和噪声,同时保留趋势和季节性变动的信号。HMA 是一种无效的平滑滤波器,它通过加权均匀的形式来计算平均值,并对较早的数据施加更大的权重,从而能够更精确地捕获趋势性信号。
除了作为一个平滑滤波器,HMA 还能够作为一个特征提取器来提取工夫序列中的特色,并用于建设预测模型。例如,能够应用 HMA 计算工夫序列中的趋势和季节性变动,并将其作为输出特色用于构建 ARIMA、VAR 或 LSTM 等预测模型。
总结
HMA 不仅在交易中有宽泛的利用,也是一种有用的工夫序列剖析工具。HMA 作为一种挪动平均线,能够缩小工夫序列中的噪声和突发性变动,从而更精确地捕获数据的趋势性和周期性变动。在工夫序列剖析中,HMA 通常用于平滑解决数据,以进步预测的准确性。在理论利用中,HMA 经常与其余技术指标和工夫序列分析方法相结合,在各种数据分析和预测工作中获取更好的预测后果。
https://avoid.overfit.cn/post/3c5f6027e1914676ad0f32c477c743c7
作者:Hanane D.