def compute_macd(
        df, column_source, column_target_ema,
        column_target_macd, column_target_macd_signal, column_target_macd_histogram,
        time_period_fast, time_period_slow, time_period_macd):
    """
    Compute Moving Average Convergence Divergence (MACD).

    When fast ema crosses above slow ema, it indicates a reversal from downtrend to uptrend.
    When fast ema crosses below slow ema, it indicates a reversal from uptrend to downtrend.

    When macd crosses above ema_macd (signal), it indicates a reversal from downtrend to uptrend.
    When macd crosses below ema_macd (signal), it indicates a reversal from uptrend to downtrend.

    :param df: dataframe (sorted in ascending time order)
    :param column_source: name of source column in dataframe  with values to compute MACD (e.g. close price)
    :param column_target_ema: prefix of target column in dataframe for EMA results
    :param column_target_macd: name of target column in dataframe for MACD results
    :param column_target_macd_signal: name of target column in dataframe for MACD signal results
    :param column_target_macd_histogram: name of target column in dataframe for MACD histogram results
    :param time_period_fast: number of days over which to average for fast EMA
    :param time_period_slow: number of days over which to average for slow EMA
    :param time_period_macd: number of days over which to average for MACD EMA
    :return: modified dataframe
    """
    time_fast_slow_macd = "{:d}-{:d}-{:d}".format(time_period_fast, time_period_slow, time_period_macd)
    key_ema_fast = column_target_ema + "-{:d}".format(time_period_fast)
    key_ema_slow = column_target_ema + "-{:d}".format(time_period_slow)
    key_macd = column_target_macd + "-" + time_fast_slow_macd
    key_macd_signal = column_target_macd_signal + "-" + time_fast_slow_macd
    key_macd_histogram = column_target_macd_histogram + "-" + time_fast_slow_macd

    # compute EMA and add results back to dataframe
    df[key_ema_fast] = df[column_source].ewm(span=time_period_fast, adjust=False).mean()
    df[key_ema_slow] = df[column_source].ewm(span=time_period_slow, adjust=False).mean()

    # compute MACD and add results back to dataframe
    df[key_macd] = df[key_ema_fast] - df[key_ema_slow]
    df[key_macd_signal] = df[key_macd].ewm(span=time_period_macd, adjust=False).mean()
    df[key_macd_histogram] = df[key_macd] - df[key_macd_signal]

    return df