avatarCris Velasquez

Summary

The provided content offers an in-depth exploration of advanced moving average methods for stock price analysis in Python, detailing their theoretical backgrounds, practical implementations, and applications in trading strategies.

Abstract

The article delves into sophisticated moving average techniques, such as FRAMA, ZLEMA, VIDYA, ALMA, MAMA, FAMA, APMA, Rainbow Moving Average, Wilders Moving Average, and Smoothed Moving Average (SMMA). It explains the mathematical underpinnings of each method, demonstrates how to implement them in Python, and provides visual examples using stock market data. The author emphasizes the adaptability of these methods to market volatility and their utility in identifying trends, generating trading signals, and managing risk. The article also discusses the limitations and complexities of these advanced techniques, while advocating for their rewards when used effectively by informed traders.

Opinions

  • The author suggests that advanced moving averages like FRAMA and ZLEMA are superior to traditional moving averages due to their adaptive nature and responsiveness to market dynamics.
  • There is an opinion that the complexity of calculating and interpreting advanced moving averages is justified by the precision and insight they offer into market trends.
  • The article implies that traders willing to invest time in understanding these methods will be better equipped to make informed decisions and develop robust trading strategies.
  • It is conveyed that while these moving averages have limitations, their ability to capture specific market dynamics provides a competitive edge in trading.
  • The author encourages clapping to support the content, indicating a belief in the value and educational impact of the article for the trading community.
  • The article promotes the use of a recommended AI service, ZAI.chat, as a cost-effective alternative to ChatGPT Plus (GPT-4), suggesting confidence in the service's performance and functionality.

Top 36 Moving Average Methods For Stock Prices in Python [2/4]

Adaptive and Dynamic — FRAMA, ZLEMA, Rainbow, and Beyond

1. Introduction

We now transition from the foundational moving averages discussed in Part 1 to more sophisticated and dynamic techniques. These are not mere adaptations of the basic forms, but rather, ingenious tools crafted to capture specific market dynamics. This is article two of a four-part series on moving averages. The complete list can be seen below:

  • Part 1 — Fundamental Techniques: Simple Moving Average (SMA), Exponential Moving Average (EMA), Weighted Moving Average (WMA), Double Exponential Moving Average (DEMA), Triple Exponential Moving Average (TEMA), Volume Adjusted Moving Average (VAMA), Adaptive Moving Average (AMA or KAMA), Triangular Moving Average (TMA), Hull Moving Average (HMA)
  • Part 2 — Adaptive and Dynamic: Fractal Adaptive Moving Average (FRAMA), Zero Lag Exponential Moving Average (ZLEMA), Variable Index Dynamic Average (VIDYA), Arnaud Legoux Moving Average (ALMA), MESA Adaptive Moving Average (MAMA), Following Adaptive Moving Average (FAMA) , Adaptive Period Moving Average, Rainbow Moving Average, Wilders Moving Average, Smoothed Moving Average (SMMA)
  • Part 3 — Advanced Weighting: Guppy Multiple Moving Average (GMMA), Least Squares Moving Average (LSMA), Welch’s Moving Average or Modified Moving Average, Sin-weighted Moving Average, Median Moving Average, Geometric Moving Average, Elastic Volume Weighted Moving Average (eVWMA), Regularized Exponential Moving Average (REMA), Parabolic Weighted Moving Average
  • Part 4From Niche to Noteworthy: Jurik Moving Average (JMA), End Point Moving Average (EPMA), Chande Moving Average (CMA), Harmonic Moving Average, McGinley Dynamic, Anchored Moving Average, Holt-Winters Moving Average, Filtered Moving Average, Kijun Sen (Base Line)

2. Background and Python Implementation

This section explores the methodologies from both theoretical and practical standpoints. The ultimate goal is to offer a Python-based implementation to put them all to work.

2.1 Fractal Adaptive Moving Average (FRAMA)

FRAMA (Fractal Adaptive Moving Average) is a moving average that takes into account market volatility and adapts its speed accordingly. The core idea behind FRAMA is that markets, like fractals, have similar patterns on both small and large scales.

By determining the fractal dimension of a price series, the FRAMA adjusts its sensitivity, becoming faster during trending periods and slower during sideways movements.

The metdholody for FRAMA is slightly more complex for as it involves computing the fractal dimension. But at high-level, FRAMA is calculated using the following steps:

  1. Split the data into two batches.
  2. Calculate the ’N’ value (difference between the maximum and minimum) for both batches.
  3. Determine the combined ’N’ value for the two batches.
  4. Compute the fractal dimension using the ’N’ values.
  5. Calculate the adaptive filter factor (alpha) using the fractal dimension.
  6. Compute the FRAMA value using the alpha value and the price data.

The basic structure of the mathemtical representation is the following:

Equation 2.1.1. N(t) determines the adaptive window length of the FRAMA based on the price series’ fractal nature.
Equation 2.1.2. α(t) defines the FRAMA’s sensitivity by adjusting its response to recent price changes.
Equation 2.1.3. FRAMA(t) calculates the adaptive moving average value using the fractal dimension of the market.

Where:

  • D(t) is the fractal dimension.
  • N(t) is the adjusted dimension.
  • α(t) is the weighting multiplier.
  • P(t) is the price at time t.

The key aspect of FRAMA is the adaptive filter factor, which determines the sensitivity of the moving average. A higher fractal dimension leads to a more reactive moving average, while a lower dimension results in a smoother curve.

FRAMA can be used similarly to other moving averages, such as identifying trends and generating buy/sell signals. A notable advantage of FRAMA over traditional moving averages is its adaptive nature, which can be more responsive to significant price changes.

When the price is trending, FRAMA can shorten its period, making it more responsive to price changes. Conversely, during sideways or non-trending periods, FRAMA can lengthen its period, providing a smoother line that’s less prone to false signals.

import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt

def fetch_data(ticker_symbol, start_date, end_date):
    data = yf.download(ticker_symbol, start=start_date, end=end_date)
    return data

def calculate_FRAMA(data, batch=10):
    # Input
    InputPrice = data['Close'].values
    
    Length = len(InputPrice)
    Filt = np.array(InputPrice)

    # Sequentially calculate all variables and the output
    for i in range(2 * batch, Length):

        # Take 2 batches of the input  
        v1 = InputPrice[i-2*batch:i - batch]  
        v2 = InputPrice[i - batch:i]

        # For the 1st batch calculate N1  
        H1 = np.max(v1)  
        L1 = np.min(v1)  
        N1 = (H1 - L1) / batch

        # For the 2nd batch calculate N2  
        H2 = np.max(v2)  
        L2 = np.min(v2)  
        N2 = (H2 - L2) / batch

        # For both batches calculate N3  
        H = np.max([H1, H2])  
        L = np.min([L1, L2])  
        N3 = (H - L) / (2 * batch)

        # Calculate fractal dimension  
        Dimen = 0  
        if N1 > 0 and N2 > 0 and N3 > 0:  
            Dimen = (np.log(N1 + N2) - np.log(N3)) / np.log(2)

        # Calculate lowpass filter factor  
        alpha = np.exp(-4.6 * (Dimen) - 1)  
        alpha = np.clip(alpha, 0.1, 1)  # Ensuring alpha stays between 0.1 and 1

        # Filter the input data  
        Filt[i] = alpha * InputPrice[i] + (1 - alpha) * Filt[i-1]

    data['FRAMA'] = Filt
    return data

# Fetching data
ticker_symbol = "AMZN"
start_date = "2020-01-01"
end_date = "2024-01-01"
data = fetch_data(ticker_symbol, start_date, end_date)

# Calculating FRAMA
data = calculate_FRAMA(data)

# Plotting
plt.figure(figsize=(20,7))
data['Close'].plot(label="Close Price", color="blue")
data['FRAMA'].plot(label="FRAMA", color="green", alpha=0.7)
plt.title(f"{ticker_symbol} Stock Price and FRAMA")
plt.legend()
plt.grid(True)
plt.show()
Figure 1. Visualization of AMZN Stock Price with its FRAMA from 2020 to 2023: The blue line represents the closing price of Amazon (AMZN) stock, while the green line denotes the Fractal Adaptive Moving Average (FRAMA). The FRAMA adapts to market volatility, adjusting its sensitivity to capture price trends and movements.

2.2 Zero Lag Exponential Moving Average (ZLEMA)

The Zero Lag Exponential Moving Average (ZLEMA) is a type of exponential moving average that aims to eliminate the lag associated with traditional EMAs.

The primary goal of ZLEMA is to adjust recent prices to react faster to price changes. It does this by subtracting a lagged EMA from the current price, aiming to provide a faster-moving line with virtually zero lag.

The formula for ZLEMA involves a few steps:

  1. Calculate the lag: Lag = n / 2​, where n is the ZLEMA period.
  2. Create a new series, Adjusted Close, by subtracting the Lag-day EMA from the close: Adjusted Close = Close − EMA_Lag​ (Close)
  3. Calculate ZLEMA: ZLEMA = EMA_n​ (Adjusted Close).

The ZLEMA’s strength lies in its quest for real-time market reactions. Traditional EMAs, by nature, have an inherent delay; ZLEMA seeks to sidestep this by recalibrating recent prices. By subtracting a lagged EMA, it projects an accelerated response curve that closely trails live price action.

For traders, this offers a distinct advantage: capturing rapid price shifts as they unfold, rather than playing catch-up. This nimbleness can be pivotal in fast-paced markets. Yet, its aggressive responsiveness warrants caution. A keen trader often contrasts ZLEMA’s insights with other indicators to discern genuine trends from fleeting fluctuations.

import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt

def calculate_EMA(prices, period):
    alpha = 2 / (period + 1)
    EMA = [prices[0]]
    for price in prices[1:]:
        EMA.append((price - EMA[-1]) * alpha + EMA[-1])
    return EMA

def calculate_ZLEMA(prices, period):
    lag = period // 2
    adjusted_prices = [2*prices[i] - (prices[i - lag] if i >= lag else prices[0]) for i in range(len(prices))]
    ZLEMA = calculate_EMA(adjusted_prices, period)
    return ZLEMA

# Fetching data
ticker_symbol = "AAPL"
data = yf.download(ticker_symbol, start="2020-01-01", end="2023-01-01")

close_prices = data['Close'].tolist()

# Calculate ZLEMA
zlema_period = 28
data['ZLEMA'] = calculate_ZLEMA(close_prices, zlema_period)

# Plotting
plt.figure(figsize=(20,7))
plt.plot(data.index, data['Close'], label='Price', color='black')
plt.plot(data.index, data['ZLEMA'], label=f'ZLEMA {zlema_period}', color='red')
plt.title(f'Zero Lag Exponential Moving Average (ZLEMA) of {ticker_symbol} (n = {zlema_period})')
plt.legend()
plt.grid()
plt.show()
Figure 2. Zero Lag Exponential Moving Average (ZLEMA) Analysis of AAPL from 2020 to 2023: The graph presents Apple Inc. (AAPL) stock price depicted in black, contrasted with its 28-period ZLEMA in red. The ZLEMA aims to eliminate the lag associated with traditional EMAs, providing a potentially more timely representation of the stock’s trend.

2.3 Variable Index Dynamic Average (VIDYA)

VIDYA, or Variable Index Dynamic Average, is an adaptive moving average introduced by Tushar Chande in the early 1990s. The fundamental idea behind VIDYA is to adjust the smoothing constant dynamically based on the volatility of the price series.

By doing so, VIDYA can respond faster in volatile markets and slow down in trending markets. The rate of adjustment is governed by a volatility index, with the Chande Momentum Oscillator (CMO) often being the chosen index for this purpose.

The VIDYA is calculated as:

Equation 2.3.1. VIDYA(t), an adaptive moving average that adjusts its smoothing constant based on price volatility, using the Chande Momentum Oscillator (CMO) as its volatility index

Where:

  • VIDYAt​ is the VIDYA at time t.
  • VIDYA_t−1​ is the VIDYA at time t−1.
  • ABS(CMO_t​) is the absolute value of the Chande Momentum Oscillator at time t, scaled between 0 and 1.
  • Close_t​ is the close price at time t.

VIDYA is an adaptive moving average tailored for fluctuating markets. It dynamically adjusts its sensitivity based on market volatility, quickening during turbulence and slowing in steadier periods.

import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt

def calculate_CMO(prices, period):
    """ Calculate Chande Momentum Oscillator (CMO) """
    deltas = np.diff(prices)
    sum_gains = np.cumsum(np.where(deltas >= 0, deltas, 0))
    sum_losses = np.abs(np.cumsum(np.where(deltas < 0, deltas, 0)))

    cmo = 100 * (sum_gains - sum_losses) / (sum_gains + sum_losses)
    return np.insert(cmo, 0, 0)  # Add a zero at the beginning for alignment

def calculate_VIDYA(prices, period):
    cmo_values = calculate_CMO(prices, period)
    vidya = [prices[0]]

    for i in range(1, len(prices)):
        alpha = abs(cmo_values[i]) / 100  # Normalize CMO to [0, 1]
        vidya.append((1 - alpha) * vidya[-1] + alpha * prices[i])
       
    return vidya

# Fetching data
ticker_symbol = "V"
data = yf.download(ticker_symbol, start="2020-01-01", end="2024-01-01")
close_prices = data['Close'].tolist()

# Calculate VIDYA
vidya_period = 14
data['VIDYA'] = calculate_VIDYA(close_prices, vidya_period)

# Plotting
plt.figure(figsize=(20,7))
plt.plot(data.index, data['Close'], label='Price', color='black')
plt.plot(data.index, data['VIDYA'], label=f'VIDYA {vidya_period}', color='blue')
plt.title(f'Variable Index Dynamic Average (VIDYA) of {ticker_symbol} (n = {vidya_period})')
plt.legend()
plt.grid()
plt.show()
Figure 3. Variable Index Dynamic Average (VIDYA) Analysis of Visa Inc. (V) from 2020 to 2023: The graph showcases Visa Inc.’s (V) stock price illustrated in black, with its 14-period VIDYA depicted in blue. VIDYA, a dynamic exponential moving average, adjusts its sensitivity based on the Chande Momentum Oscillator (CMO) to better capture volatile market conditions and provide timely insights.

2.4 Arnaud Legoux Moving Average (ALMA)

The Arnaud Legoux Moving Average (ALMA) was developed by Arnaud Legoux and Dimitris Kouzis-Loukas to try to minimize the lag associated with traditional moving averages and make the moving average more responsive to recent price changes while also remaining smooth.

The ALMA uses a sliding window approach and weights the data with a Gaussian function, ensuring the most recent prices have a higher weight.

To calculate the ALMA for a period n, we can use the following formula:

Equation 2.4.1. The Arnaud Legoux Moving Average (ALMA): A responsive moving average that leverages a Gaussian weighting scheme to give more significance to recent prices.

Where:

  • Price_tn+i+1​ is the price at the time tn+i+1.
  • wi​ is the weight of the ith data point in the window and is calculated as:
Equation 2.4.2. weight in ALMA: Uses the Gaussian function to determine the weight for each data point based on its position in the window, emphasizing recent prices.

Where:

  • moff is n−1​/2 offset by the parameter offset.
  • σ is n / 6 which defines the width of the Gaussian window.

By harnessesing the power of a Gaussian function within a sliding window ensures that recent prices command higher significance, resulting in a moving average that swiftly acknowledges contemporary price shifts, all while maintaining a commendable smoothness.

For traders on the hunt for a finely-tuned blend of immediacy and clarity, the ALMA offers a compelling proposition. However, as always, it’s prudent to use ALMA readings with other technical metrics for a holistic market analysis.

import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt

def calculate_ALMA(prices, period, offset=0.85, sigma=6):
    m = np.floor(offset * (period - 1))
    s = period / sigma
    alma = []
    
    for i in range(period - 1, len(prices)):
        weights = [np.exp(- (j - m)**2 / (2 * s * s)) for j in range(period)]
        sum_weights = sum(weights)
        normalized_weights = [w/sum_weights for w in weights]
        
        window = prices[i-period+1:i+1]
        alma_value = sum([normalized_weights[j] * window[j] for j in range(period)])
        alma.append(alma_value)
        
    return [None]*(period-1) + alma  # Pad the beginning with None for alignment

# Fetching data
ticker_symbol = "BABA"
data = yf.download(ticker_symbol, start="2020-01-01", end="2024-01-01")
close_prices = data['Close'].tolist()

# Calculate ALMA
alma_period = 36
data['ALMA'] = calculate_ALMA(close_prices, alma_period)

# Plotting
plt.figure(figsize=(20,7))
plt.plot(data.index, data['Close'], label=f'{ticker_symbol} Price', color='black')
plt.plot(data.index, data['ALMA'], label=f'ALMA {alma_period}', color='purple')
plt.title(f'Arnaud Legoux Moving Average of {ticker_symbol} (n = {alma_period})')
plt.legend()
plt.grid()
plt.show()
Figure 4. Arnaud Legoux Moving Average (ALMA) of Alibaba Group (BABA) from 2020 to 2023: The chart displays BABA’s stock price (black line) alongside its 14-day ALMA (purple line), highlighting the trend and smoothing out price fluctuations.

2.5 MESA Adaptive Moving Average (MAMA) and Following Adaptive Moving Average (FAMA)

The MESA Adaptive Moving Average (MAMA) emerged from the forward-thinking of John Ehlers, spotlighted in his work “Cybernetic Analysis for Stocks and Futures.” Rooted in the Maximum Entropy Spectral Analysis (MESA) approach, MAMA was conceived to dynamically tackle non-stationary data, like fluctuating stock prices, which might possess evolving statistical properties.

Traditional averages, no matter their typology, often lag during periods of heightened volatility. MAMA’s hallmark is its adaptability to price volatility. During abrupt price variations, MAMA springs into action, offering near-instantaneous reflections of market movements. Conversely, in periods of stable price trends, its adaptability moderates its pace, curating a clearer depiction of genuine price trends by filtering out market noise.

Complementing MAMA is the Following Adaptive Moving Average (FAMA), which magnifies changing market trends. As a derivative of MAMA, FAMA illuminates areas prone to price corrections within trending markets. Such insights are pivotal for demarcating the culmination of correction phases and the likely resurgence of the prevailing trend.

Formulas and Derivations are as follows:

MESA Adaptive Moving Average (MAMA):

Deriving from MESA and the Hilbert Transform, MAMA’s adjustability is anchored to the calculation of the dominant cycle period. At its core:

  • The raw price phase is ascertained using the Hilbert Transform.
  • An instantaneous period is deduced, which inversely relates to the instantaneous frequency.
  • This instantaneous period is smoothed to unveil the dominant cycle period.
  • The dominant cycle period is then leveraged to compute the smooth price.

The ensuing MAMA value mirrors an adaptive average resonating with recent price dynamics.

Following Adaptive Moving Average (FAMA):

FAMA underscores trend inflection points. Its essence can be captured by:

Equation 2.5.1: Formula for the Following Adaptive Moving Average (FAMA). The equation describes how FAMA at any given time (FAMAt​) is computed based on its previous value (FAMAt−1​), the current price, and an adaptive smoothing constant (α), which is derived from MAMA.

Where:

  • α is the adaptive smoothing constant, a byproduct of MAMA.

Consider a stock price demonstrating a consistent uptrend interspersed with minor fluctuations. Here, MAMA traces this ascent smoothly, adeptly filtering minor noise. Simultaneously, FAMA, with its heightened sensitivity, mirrors the short-term deviations around MAMA, hinting at possible correction points.

Suddenly, a market-altering news event precipitates a sharp price drop. MAMA, with its adaptive nature, aligns quickly with this price transformation. The more reactive FAMA might cross MAMA, a potential bearish signal for traders.

Post this upheaval, if the stock price finds its footing and commences recovery, MAMA will gracefully track this new trajectory. Concurrently, FAMA will offer granular insights into trend continuities and minor corrections.

import yfinance as yf
import talib
import matplotlib.pyplot as plt

# Fetching data
ticker_symbol = "GOOGL"
data = yf.download(ticker_symbol, start="2020-01-01", end="2024-01-01")

# Calculating MAMA and FAMA
data['MAMA'], data['FAMA'] = talib.MAMA(data['Close'].values)

# Plotting both MAMA and FAMA
plt.figure(figsize=(20,7))
plt.plot(data.index, data['Close'], label='Price', color='black')
plt.plot(data.index, data['MAMA'], label='MAMA', color='blue')
plt.plot(data.index, data['FAMA'], label='FAMA', color='red')
plt.title(f'MESA Adaptive Moving Average (MAMA) & Following Adaptive Moving Average (FAMA) of {ticker_symbol}')
plt.legend()
plt.grid()
plt.show()
Figure 4. MESA Adaptive Moving Average (MAMA) and Following Adaptive Moving Average (FAMA) of GOOGL (2020–2023): The combined chart illustrates the relationship between Apple’s stock price, MAMA, and FAMA. By studying the interactions between the stock price and these indicators, traders can discern potential market trend shifts and trading opportunities.

2.6 Adaptive Period Moving Average

The Adaptive Period Moving Average (APMA) adjusts the period of the moving average dynamically based on recent market volatility. When prices are volatile, the APMA shortens its period to be more sensitive to recent price changes.

When prices are less volatile, the APMA lengthens its period to reduce noise and generate smoother signals. The APMA may employ different metrics to measure volatility, like standard deviation or the Average True Range (ATR).

The general idea behind the APMA is to adjust the period of the moving average based on a measure of volatility. The formula can be expressed as:

Equation 2.6.1. Formula for the Adaptive Period Moving Average (APMA). The formula dynamically adjusts the moving average period based on recent market volatility. The Adjusted Period is determined by current volatility in relation to observed maximum and minimum volatilities.

Where:

  • Adjusted Period is the calculated period for the moving average based on current volatility.
  • Maximum Period and Minimum Period are user-defined constants specifying the bounds of the possible period adjustments.
  • Max Volatility and Min Volatility are the maximum and minimum observed volatilities, respectively.
  • Current Volatility is the measure of recent volatility, typically calculated using ATR or standard deviation

Note: The above formula is just a possible approach to adjust the moving average period. There can be other methods or variations.

APMA stands out by dynamically calibrating its sensitivity based on market volatility, offering traders a real-time edge. In volatile conditions, its shorter period captures swift price changes, ensuring timely responses.

During stable phases, its lengthened period filters out market noise, yielding cleaner signals. This adaptability not only aids precise trend identification but also enhances risk assessment.

import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt

def adaptive_period_moving_average(prices, min_period=5, max_period=30):
    atr = np.zeros_like(prices)
    adjusted_periods = np.zeros_like(prices)
    moving_averages = np.full_like(prices, np.nan)  # Initialize with NaN values

    for i in range(1, len(prices)):
        atr[i] = atr[i-1] + (abs(prices[i] - prices[i-1]) - atr[i-1]) / 14

        min_volatility = atr[1:i+1].min()
        max_volatility = atr[1:i+1].max()

        if max_volatility == min_volatility:
            adjusted_period = min_period
        else:
            adjusted_period = int(((max_period - min_period) / (max_volatility - min_volatility)) * (atr[i] - min_volatility) + min_period)
        
        adjusted_periods[i] = adjusted_period

        if i >= adjusted_period:
            moving_averages[i] = np.mean(prices[i-adjusted_period+1:i+1])

    return moving_averages

# Fetching data
ticker_symbol = "MA"
data = yf.download(ticker_symbol, start="2020-01-01", end="2024-01-01")

data['APMA'] = adaptive_period_moving_average(data['Close'].values)

# Plotting
plt.figure(figsize=(20,7))
plt.plot(data.index, data['Close'], label='Price', color='black')
plt.plot(data.index, data['APMA'], label='Adaptive Period MA', color='red')
plt.title(f'Adaptive Period Moving Average (APMA) of {ticker_symbol}')
plt.legend()
plt.grid()
plt.show()
Figure 6. APMA of MA (2020–2023): The APMA (red) adjusts its period based on price volatility, ranging between a minimum and maximum period. For Mastercard’s stock (black), this technique dynamically alters its sensitivity, providing a flexible smoothing of price trends influenced by the observed volatility.

2.7 Rainbow Moving Average

The Rainbow Moving Average is a collection of exponential moving averages (EMAs) with different periods. It is called “Rainbow” because when plotted, the collection of EMAs resembles the colors of a rainbow, especially when you color-code them in a spectrum.

The Rainbow Moving Average helps to visualize the convergence and divergence of short-term and long-term trends. When the EMAs are intertwined or braided, it indicates a lack of trend or a weak trend. When the EMAs separate, with shorter periods on top and longer periods at the bottom (or vice versa), it indicates a stronger trend.

Equation 2.7.1: Computational Formula for the Exponential Moving Average (EMA) with Smoothing Factor.
  • EMAt​ is the Exponential Moving Average for the current time t
  • Pt​ is the price for the current time t
  • α is the smoothing factor, calculated as α = 2 / (N+1)​
  • N is the period of the EMA
  • EMAt−1​ is the Exponential Moving Average for the previous time t−1

Given its layered structure, traders can easily gauge the relative strength of different timeframes at a glance. For instance, if longer-term EMAs shift above shorter ones, it could signify a potential reversal, moving from a bullish to bearish sentiment. Additionally, the RMA acts as a dynamic support and resistance mechanism; prices may often rebound or face resistance around these moving average lines.

By assessing the distance between individual EMAs in the RMA, traders can also gauge market volatility. A wider spread might indicate heightened volatility, while a narrower spread can suggest a more stable environment. In essence, the RMA provides a consolidated lens through which traders can evaluate multiple market dimensions simultaneously.

import yfinance as yf
import matplotlib.pyplot as plt

# Download stock data
ticker = "NVDA"
data = yf.download(ticker, start="2020-01-01", end="2023-12-26")
# Calculate EMAs with different lookback periods
lookback_periods = [2, 4, 8, 16, 32, 64, 128, 192, 320, 512]
colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', 'black','gray','brown']
for i, lookback in enumerate(lookback_periods):
    data[f'EMA{lookback}'] = data['Close'].ewm(span=lookback).mean()
# Plot the results
plt.figure(figsize=(20,7))
plt.plot(data['Close'], label='Close', linewidth=2, alpha=0.8, color='black')
for i, lookback in enumerate(lookback_periods):
    plt.plot(data[f'EMA{lookback}'], label=f'EMA {lookback}', linewidth=1.5, alpha=0.8, color=colors[i])
plt.title(f'{ticker} Rainbow Moving Average')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.grid()
plt.show()
Figure 7. Rainbow Moving Average for NVIDIA (NVDA) (2020–2023): The graph displays NVDA’s stock price alongside EMAs with varying lookback periods. Each EMA is depicted in a distinct color, from short (red) to long-term (brown) trends, offering a multi-layered view of price movements.

2.8 Wilders Moving Average

The Wilders Moving Average is a special type of exponential moving average developed by J. Welles Wilder, the author of the book “New Concepts in Technical Trading Systems.” This average was primarily designed for commodity and stock markets to measure the volatility of price movements.

The Wilders Moving Average places more weight on past prices compared to the regular exponential moving average, making it react more slowly to recent price changes. This characteristic of the Wilders MA makes it particularly useful for trending markets, as it reduces the noise of minor price fluctuations.

The Wilders Moving Average is calculated using the following formula:

Equation 2.8.1. Formula for the Wilders Moving Average (WMA). Developed by J. Welles Wilder, this unique exponential moving average emphasizes past prices more than traditional EMAs. WMAt represents the Wilders Moving Average at time t, calculated based on the close price (Ct) and a specified lookback period (N).

Where:

  • WMAt​ is the Wilders Moving Average at time t.
  • Ct​ is the close price at time t.
  • N is the lookback period.

This formula is similar to the EMA, but the weighting is different. By prioritizing past prices, it provides a steady and less volatile representation of market sentiment, reducing susceptibility to short-term price shocks.

This focus enhances interpretability, allowing traders to discern more sustained market trends and minimize the influence of transient fluctuations.

import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt

def wilders_moving_average(prices, period):
    wilder = [prices[0]]
    for price in prices[1:]:
        wilder_value = ((wilder[-1] * (period - 1)) + price) / period
        wilder.append(wilder_value)
    return wilder

# Fetching data
ticker_symbol = "AAPL"
data = yf.download(ticker_symbol, start="2020-01-01", end="2024-01-01")

# Calculate Wilders Moving Average
period = 14
data['Wilders_MA'] = wilders_moving_average(data['Close'].tolist(), period)

# Plotting
plt.figure(figsize=(20,7))
plt.plot(data.index, data['Close'], label='Price', color='black')
plt.plot(data.index, data['Wilders_MA'], label=f'Wilders MA {period}', color='red')
plt.title(f'Wilders Moving Average of {ticker_symbol} (n = {14})')
plt.legend()
plt.grid()
plt.show()
Figure 8. Wilder’s Moving Average of AAPL (2020–2023): This chart displays Apple’s stock price alongside Wilder’s Moving Average, a method emphasizing earlier price data. The comparison offers insights into potential market trends.

2.9 Smoothed Moving Average (SMMA)

The Smoothed Moving Average (SMMA) is a type of moving average that takes into account a vast amount of data points, smoothing out fluctuations in the data to provide a clearer view of the underlying trend.

Unlike the Simple Moving Average (SMA) and the Exponential Moving Average (EMA), the SMMA gives equal weight to all prices in its series.

The SMMA is calculated as follows:

For the first period:

Equation 2.9.1. Initial calculation for the Smoothed Moving Average (SMMA). This equation outlines the method for determining the initial value of the SMMA, providing the foundation for subsequent computations. Unlike other moving averages, SMMA assigns equal significance to all prices within its series.

For subsequent periods:

Equation 2.9.2. Subsequent calculation for the Smoothed Moving Average (SMMA) for periods after the first. SMMAi denotes the Smoothed Moving Average for the current period, and Pricei is the asset’s price at that period. The period of the SMMA is represented by n.
  • SMMAi​ is the Smoothed Moving Average for the current period.
  • Pricei​ is the price of the asset at the current period.
  • n is the period of the SMMA.

When the price hovers around the SMMA, it can signify a consolidative or range-bound market, where neither the bulls nor the bears have definitive control.

Sudden departures from the SMMA can also signify breakout moments, either upward or downward. By analyzing the proximity and movement of the price relative to the SMMA, traders can deduce potential future price directions and adjust their strategies accordingly.

import yfinance as yf
import matplotlib.pyplot as plt

def calculate_SMMA(prices, n):
    SMMA = [np.nan] * (n-1)  # Fill the initial n-1 values with NaN
    SMMA.append(sum(prices[:n]) / n)
    for i in range(n, len(prices)):
        smma_value = (SMMA[-1] * (n - 1) + prices[i]) / n
        SMMA.append(smma_value)
    return SMMA

# Fetching data
ticker_symbol = "VOW.DE"
data = yf.download(ticker_symbol, start="2020-01-01", end="2024-01-01")

# Calculate SMMA
n = 28
data['SMMA'] = calculate_SMMA(data['Close'].tolist(), n)

# Plotting
plt.figure(figsize=(20,7))
plt.plot(data.index, data['Close'], label='Price', color='black')
plt.plot(data.index, data['SMMA'], label=f'SMMA {n}', color='red')
plt.title(f'Smoothed Moving Average (SMMA) of {ticker_symbol} (n ={n})')
plt.legend()
plt.grid()
plt.show()
Figure 1. Smoothed Moving Average (SMMA) of VOW.DE (2020–2023): The SMMA provides a smoothing effect by placing equal weight on every price, thus minimizing volatility. Over a 14-day period, the chart contrasts Volkswagen’s stock price (black) with its 28-day SMMA (red), highlighting a gentler curve that offers a clearer picture of price trends.

3. Applications & Insights

Moving Average techniques such as FRAMA is designed to resonate with traders who understand that markets move in cycles of volatility. The ZLEMA is a response to the urgency of real-time decision-making in trading. Advanced moving averages are not without their limitations. They can be more complex to calculate than basic moving averages, and they may require additional parameters to be set.

However, for traders who are willing to invest the time and effort to learn how to use them effectively, advanced moving averages can be a powerful tool for identifying trading opportunities and making informed trading decisions. Here are a few examples of how advanced moving averages can be used in trading:

  • FRAMA: The FRAMA can be used to identify trending markets and potential support and resistance levels. It can also be used to generate entry and exit signals. For example, a trader may buy a stock when it crosses above its FRAMA and sell it when it crosses below its FRAMA.
  • ZLEMA: The ZLEMA can be used to identify trend changes and momentum shifts. It can also be used to generate entry and exit signals. For example, a trader may buy a stock when its price crosses above its ZLEMA and sell it when its price crosses below its ZLEMA.

4. Concluding Thoughts

Sophisticated moving average techniques are essential for traders who seek to gain a deeper understanding of the market and make more informed decisions. These tools are designed to capture specific market dynamics that may be missed by basic moving averages, providing traders with gateways to precision in a noisy and complex environment.

While sophisticated moving averages can be more complex to calculate and interpret, they offer significant rewards to traders who are willing to invest the time and effort to learn how to use them effectively. By embracing the nuances and complexities of these techniques, traders can develop more robust trading strategies and manage risk more effectively.

Thank you for taking the time to read. If you found the content insightful, please consider clapping to support future content.👏

Related articles:

Subscribe to DDIntel Here.

DDIntel captures the more notable pieces from our main site and our popular DDI Medium publication. Check us out for more insightful work from our community.

Register on AItoolverse (alpha) to get 50 DDINs

Join our network here: https://datadriveninvestor.com/collaborate

DDI Official Telegram Channel: https://t.me/+tafUp6ecEys4YjQ1

Follow us on LinkedIn, Twitter, YouTube, and Facebook.

Data Science
Python
Finance
Trading
Statistics
Recommended from ReadMedium