def compute_macd_custom(
        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
    """
    k_fast = 2 / (time_period_fast + 1)  # fast EMA smoothing factor
    ema_fast = 0
    k_slow = 2 / (time_period_slow + 1)  # slow EMA smoothing factor
    ema_slow = 0
    k_macd = 2 / (time_period_macd + 1)  # MACD EMA smoothing factor
    ema_macd = 0
    ema_fast_values = []
    ema_slow_values = []
    macd_values = []
    macd_signal_values = []  # EMA of MACD values
    macd_histogram_values = []  # MACD - MACD-EMA
    for value in df[column_source]:
        # compute MACD
        if ema_fast == 0:  # first observation
            ema_fast = value
            ema_slow = value
        else:
            ema_fast = (value - ema_fast) * k_fast + ema_fast
            ema_slow = (value - ema_slow) * k_slow + ema_slow
        ema_fast_values.append(ema_fast)
        ema_slow_values.append(ema_slow)
        macd = ema_fast - ema_slow
        macd_values.append(macd)

        # compute MACD signal and histogram
        if ema_macd == 0:  # first observation
            ema_macd = macd
        else:
            ema_macd = (macd - ema_macd) * k_macd + ema_macd  # signal is EMA of MACD values
        macd_signal_values.append(ema_macd)
        macd_histogram_values.append(macd - ema_macd)

    # add computed results back to dataframe
    time_fast = str(time_period_fast)
    time_slow = str(time_period_slow)
    time_fast_slow_macd = time_fast + "-" + time_slow + "-" + str(time_period_macd)
    key_ema_fast = column_target_ema + "-" + time_fast
    key_ema_slow = column_target_ema + "-" + time_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
    df[key_ema_fast] = ema_fast_values
    df[key_ema_slow] = ema_slow_values
    df[key_macd] = macd_values
    df[key_macd_signal] = macd_signal_values
    df[key_macd_histogram] = macd_histogram_values

    return df