# -*- coding: utf-8 -*-
from pandas import concat, DataFrame
from pandas_ta import Imports
from pandas_ta.overlap import ema
from pandas_ta.utils import get_offset, verify_series, signals
[docs]def macd(close, fast=None, slow=None, signal=None, talib=None, offset=None, **kwargs):
"""Indicator: Moving Average, Convergence/Divergence (MACD)"""
# Validate arguments
fast = int(fast) if fast and fast > 0 else 12
slow = int(slow) if slow and slow > 0 else 26
signal = int(signal) if signal and signal > 0 else 9
if slow < fast:
fast, slow = slow, fast
close = verify_series(close, max(fast, slow, signal))
offset = get_offset(offset)
mode_tal = bool(talib) if isinstance(talib, bool) else True
if close is None: return
as_mode = kwargs.setdefault("asmode", False)
# Calculate Result
if Imports["talib"] and mode_tal:
from talib import MACD
macd, signalma, histogram = MACD(close, fast, slow, signal)
else:
fastma = ema(close, length=fast)
slowma = ema(close, length=slow)
macd = fastma - slowma
signalma = ema(close=macd.loc[macd.first_valid_index():,], length=signal)
histogram = macd - signalma
if as_mode:
macd = macd - signalma
signalma = ema(close=macd.loc[macd.first_valid_index():,], length=signal)
histogram = macd - signalma
# Offset
if offset != 0:
macd = macd.shift(offset)
histogram = histogram.shift(offset)
signalma = signalma.shift(offset)
# Handle fills
if "fillna" in kwargs:
macd.fillna(kwargs["fillna"], inplace=True)
histogram.fillna(kwargs["fillna"], inplace=True)
signalma.fillna(kwargs["fillna"], inplace=True)
if "fill_method" in kwargs:
macd.fillna(method=kwargs["fill_method"], inplace=True)
histogram.fillna(method=kwargs["fill_method"], inplace=True)
signalma.fillna(method=kwargs["fill_method"], inplace=True)
# Name and Categorize it
_asmode = "AS" if as_mode else ""
_props = f"_{fast}_{slow}_{signal}"
macd.name = f"MACD{_asmode}{_props}"
histogram.name = f"MACD{_asmode}h{_props}"
signalma.name = f"MACD{_asmode}s{_props}"
macd.category = histogram.category = signalma.category = "momentum"
# Prepare DataFrame to return
data = {macd.name: macd, histogram.name: histogram, signalma.name: signalma}
df = DataFrame(data)
df.name = f"MACD{_asmode}{_props}"
df.category = macd.category
signal_indicators = kwargs.pop("signal_indicators", False)
if signal_indicators:
signalsdf = concat(
[
df,
signals(
indicator=histogram,
xa=kwargs.pop("xa", 0),
xb=kwargs.pop("xb", None),
xserie=kwargs.pop("xserie", None),
xserie_a=kwargs.pop("xserie_a", None),
xserie_b=kwargs.pop("xserie_b", None),
cross_values=kwargs.pop("cross_values", True),
cross_series=kwargs.pop("cross_series", True),
offset=offset,
),
signals(
indicator=macd,
xa=kwargs.pop("xa", 0),
xb=kwargs.pop("xb", None),
xserie=kwargs.pop("xserie", None),
xserie_a=kwargs.pop("xserie_a", None),
xserie_b=kwargs.pop("xserie_b", None),
cross_values=kwargs.pop("cross_values", False),
cross_series=kwargs.pop("cross_series", True),
offset=offset,
),
],
axis=1,
)
return signalsdf
else:
return df
macd.__doc__ = \
"""Moving Average Convergence Divergence (MACD)
The MACD is a popular indicator to that is used to identify a security's trend.
While APO and MACD are the same calculation, MACD also returns two more series
called Signal and Histogram. The Signal is an EMA of MACD and the Histogram is
the difference of MACD and Signal.
Sources:
https://www.tradingview.com/wiki/MACD_(Moving_Average_Convergence/Divergence)
AS Mode: https://tr.tradingview.com/script/YFlKXHnP/
Calculation:
Default Inputs:
fast=12, slow=26, signal=9
EMA = Exponential Moving Average
MACD = EMA(close, fast) - EMA(close, slow)
Signal = EMA(MACD, signal)
Histogram = MACD - Signal
if asmode:
MACD = MACD - Signal
Signal = EMA(MACD, signal)
Histogram = MACD - Signal
Args:
close (pd.Series): Series of 'close's
fast (int): The short period. Default: 12
slow (int): The long period. Default: 26
signal (int): The signal period. Default: 9
talib (bool): If TA Lib is installed and talib is True, Returns the TA Lib
version. Default: True
offset (int): How many periods to offset the result. Default: 0
Kwargs:
asmode (value, optional): When True, enables AS version of MACD.
Default: False
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.DataFrame: macd, histogram, signal columns.
"""