A Hull moving average (HMA) smooths price data while reducing the lag associated with moving averages. It belongs to the weighted-average family alongside SMA, EMA, and WMA, but targets faster trend identification with smoothness. section 10.2.2 section 10.4
For a chosen window, calculate a WMA over half the window and another over the full window. Double the half-window WMA, subtract the full-window WMA, then apply a WMA with a window equal to the square root of the original window. section 10.2.2
Comparing moving averages on historical prices
With Python, pandas, NumPy, and yfinance, add SMA, EMA, WMA, and HMA columns to NVIDIA closing prices. For one reported day, a three-day HMA is 67.96 while the corresponding SMA is 63.55; with a 20-day window, HMA is 64.19 versus SMA at 58.33. These differences show that window choice materially changes the resulting trend measure. section 10.2.2
def weighted_moving_average(prices, window):
weights = np.arange(1, window + 1)
return prices.rolling(window).apply(
lambda x: np.dot(x, weights) / weights.sum(), raw=True)
def hull_moving_average(prices, window):
half_window = int(window / 2)
sqrt_window = int(np.sqrt(window))
wma_half = weighted_moving_average(prices, half_window)
wma_full = weighted_moving_average(prices, window)
hma = weighted_moving_average(2 * wma_half - wma_full, sqrt_window)
return hma
Use the implementation listing to inspect the WMA helper and the HMA construction step by step. section 10.2.2
