Skip to content
All library documents

Computing MACD with Recursive Exponential Moving Averages

Article Quant Q&A · Author: dev0419

Summary

The document describes a manual method for calculating the moving average convergence divergence indicator without relying on a library’s exponential moving average function. It explains the recursive EMA setup: begin with a simple moving average, calculate the smoothing multiplier from the chosen period, and update each later value from the current input and previous EMA. MACD is formed by subtracting a longer-period EMA from a shorter-period EMA, then smoothing the MACD line to obtain its signal line.

The reported error occurs because the EMA helper expects a data frame with a close-price column, but the signal calculation passes only the MACD series. The answer separates signal-line calculation from price EMA calculation and uses MACD values as its input. The example illustrates the conceptual distinction between the price EMAs and the signal EMA, but its implementation is not a complete reusable recipe: it mutates and drops rows from the input frame, and the shown initialization and indexing choices warrant care when matching a particular platform’s EMA convention.

Key ideas

  • An EMA can be calculated recursively using a period-based smoothing multiplier.
  • MACD is the difference between a shorter-period price EMA and a longer-period price EMA.
  • The signal line is an EMA applied to the MACD series itself.
  • A helper that expects a close-price column cannot directly process a standalone MACD series.
  • Initialization, index handling, and in-place row removal can affect implementation behavior.

Tags

Full text
# How to compute moving average convergence divergence without using pandas ewm function?


# How to compute moving average convergence divergence without using pandas ewm function?












I'm trying to compute the moving average divergence convergence (MACD) which is a technical indicator in trading. To compute MACD we have to find out exponential moving average over a certain period or a time window n(I will be providing the procedure, code on how the moving average and a sample input before the signal column is computed). The signal values range from -10 to 10. I kept getting KeyError: 'close'. I could not understand how to proceed further please do let me know how I can correct this.

```
     # How to compute ema ?
    
    # 1. Calculate the SMA
    
    # (Period Values / Number of Periods)
    # 2. Calculate the Multiplier
    
    # (2 / (Number of Periods + 1) therefore (2 / (5+1) = 33.333%
    # 3. Calculate the EMA
    # For the first EMA, we use the SMA(previous day) instead of EMA(previous day).
    
    # EMA = {Close - EMA(previous day)} x multiplier + EMA(previous day)
    
    
    # How to compute macd ?
    
    # Calculate the short-term EMA (Exponential Moving Average): This is often based on a 12-period EMA.
    # Calculate the long-term EMA: This is often based on a 26-period EMA.
    # Calculate the MACD Line: Subtract the long-term EMA from the short-term EMA.
    # Calculate the Signal Line: Calculate a 9-period EMA of the MACD Line to create the Signal Line.
    
    
    def compute_ema(df,n):
        df['sma'] = df['close'].rolling(n).mean()
        multiplier = 2/(n + 1)
        df.dropna(inplace=True)
        df['ema'] = np.nan
        for i in range(len(df)):
            if i == 1:
                df.loc[df.index[i], 'ema'] =  (df.loc[df.index[i],'close'] - df.loc[df.index[i - 1],'sma']) * multiplier + df.loc[df.index[i - 1], 'sma']
                # df['ema'].iloc[i] = (df['close'].iloc[i] - df['sma'].iloc[i-1]) + df['sma'].iloc[i-1]
            else:
                df.loc[df.index[i], 'ema'] =  (df.loc[df.index[i],'close'] - df.loc[df.index[i - 1],'ema']) * multiplier + df.loc[df.index[i - 1], 'ema']
        return df
df['fast'] = compute_ema(df, n=12)
df['slow'] = compute_ema(df, n=26)
df['macd'] = df['fast'] - df['slow']
df['signal'] = compute_ema(df['macd'],n)
KeyError: 'close'

The above exception was the direct cause of the following exception:

KeyError                                  Traceback (most recent call last)
Cell In[41], line 1
----> 1 df['signal'] = compute_ema(df['macd'],n)

Cell In[21], line 24
     23 def compute_ema(df,n):
...
   3815     #  InvalidIndexError. Otherwise we fall through and re-raise
   3816     #  the TypeError.
   3817     self._check_indexing_error(key)
```

## Answer by dev0419 (score 0)

https://quant.stackexchange.com/a/79624

I managed to fix the code it provides the values accurately.

```
def compute_ema(df,n,column_name):
    df['sma'] = df['close'].rolling(n).mean()
    multiplier = 2 / (n + 1)
    df.dropna(inplace=True)
    for i in range(1,len(df)):
        if i == 1:
            df.loc[df.index[i],column_name] = df.loc[df.index[i - 1],'sma']
        else:
            df.loc[df.index[i],column_name] = (df.loc[df.index[i],'close'] - df.loc[df.index[i - 1],column_name]) * multiplier + df.loc[df.index[i - 1],column_name]
    return df

def compute_signal(df,n):
    df['signal_sma'] = df['macd'].rolling(n).mean()
    multiplier = 2 / (n + 1)
    df.dropna(inplace=True)
    for i in range(1,len(df)):
        if i == 1:
            df.loc[df.index[i],'signal_ma'] = df.loc[df.index[i - 1],'signal_sma']
        else:
            df.loc[df.index[i],'signal_ma'] = (df.loc[df.index[i],'macd'] - df.loc[df.index[i - 1],'signal_ma']) * multiplier + df.loc[df.index[i - 1],'signal_ma']
    return df
```

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.