Ejemplo n.º 1
0
def cci_metrics(position: pd.DataFrame, cci: dict, **kwargs) -> list:

    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    view = kwargs.get('view', '')

    metrics = [0.0] * len(position['Close'])
    features = cci['signals']
    signals = cci['tabular']
    periods = cci['periods']

    for feat in features:
        if 'zero' in feat['value']:
            if feat['type'] == 'bullish':
                metrics[feat['index']] += 0.6
            else:
                metrics[feat['index']] -= 0.6

        elif '100' in feat['value']:
            if feat['type'] == 'bullish':
                metrics[feat['index']] += 1.0
            else:
                metrics[feat['index']] -= 1.0

    for period in signals:
        if period == str(periods['short']):
            point = 0.2
        elif period == str(periods['medium']):
            point = 0.2
        else:
            point = 0.2

        for i, value in enumerate(signals[period]):
            if value > 100.0:
                metrics[i] += point
            if value < 100.0:
                metrics[i] -= point

    metrics = exponential_moving_avg(metrics, 7, data_type='list')
    norm = normalize_signals([metrics])
    metrics = norm[0]

    name2 = INDEXES.get(name, name)
    title = f"{name2} - Commodity Channel Index Metrics"

    if plot_output:
        dual_plotting(position['Close'], metrics,
                      'Price', 'Metrics', title=title)

    else:
        filename = filename = os.path.join(
            name, view, f"commodity_metrics_{name}.png")
        dual_plotting(position['Close'], metrics, 'Price',
                      'Metrics', title=title, saveFig=True, filename=filename)

    return metrics
def kst_metrics(fund: pd.DataFrame, kst_dict: dict, **kwargs) -> dict:
    """KST Metrics

    Arguments:
        fund {pd.DataFrame} -- fund dataset
        kst_dict {dict} -- kst data object

    Optional Args:
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        views {str} -- (default: {''})

    Returns:
        dict -- kst data object
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    views = kwargs.get('views', '')

    metrics = [0.0] * len(kst_dict['tabular']['signal'])

    for sig in kst_dict['signals']:
        if sig['type'] == 'bullish':
            multiply = 1.0
        else:
            multiply = -1.0

        if 'crossover' in sig['value']:
            metrics[sig['index']] += 0.2 * multiply

        if 'crossed' in sig['value']:
            metrics[sig['index']] += 1.0 * multiply

    metrics = exponential_moving_avg(metrics, 7, data_type='list')
    metrics = normalize_signals([metrics])[0]

    kst_dict['metrics'] = metrics

    name2 = INDEXES.get(name, name)
    title = f"{name2} - KST Metrics"

    if plot_output:
        dual_plotting(fund['Close'], kst_dict['metrics'],
                      'Price', 'Metrics', title=title)
    else:
        filename = os.path.join(name, views, f"kst_metrics_{name}")
        dual_plotting(fund['Close'], kst_dict['metrics'], 'Price',
                      'Metrics', title=title, saveFig=True, filename=filename)

    return kst_dict
Ejemplo n.º 3
0
def adx_metrics(fund: pd.DataFrame, adx: dict, **kwargs) -> dict:
    """ADX Metricx

    Arguments:
        fund {pd.DataFrame} -- fund dataset
        adx {dict} -- adx data object

    Optional Args:
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        view {str} -- (default: {''})
        pbar {ProgressBar} -- (default: {None})

    Returns:
        dict -- adx data object
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    view = kwargs.get('view', '')
    pbar = kwargs.get('pbar')

    adx['metrics'] = [0.0] * len(fund['Close'])
    adx['signals'] = []

    auto = autotrend(fund['Close'], periods=[14])

    no_trend = adx['tabular']['no_trend'][0]
    strong_trend = adx['tabular']['strong_trend'][0]
    over_trend = adx['tabular']['high_trend'][0]

    signal = adx['tabular']['adx']
    for i in range(1, len(signal)):
        data = None
        date = fund.index[i].strftime("%Y-%m-%d")

        trend = 0.0
        state = 'none'
        if auto[i] > 0.0:
            trend = 1.0
            state = 'bull'
        elif auto[i] < 0.0:
            trend = -1.0
            state = 'bear'

        if signal[i - 1] < no_trend and signal[i] > no_trend:
            adx['metrics'][i] += 1.0 * trend
            if state != 'none':
                data = {
                    "type": state,
                    "value": '20-crossover: trend start',
                    "index": i,
                    "date": date
                }

        if signal[i - 1] < strong_trend and signal[i] > strong_trend:
            adx['metrics'][i] += 0.6 * trend
            if state != 'none':
                data = {
                    "type": state,
                    "value": '25-crossover: STRONG trend',
                    "index": i,
                    "date": date
                }

        if signal[i] > strong_trend:
            adx['metrics'][i] += 0.2 * trend

        if signal[i - 1] > over_trend and signal[i] < over_trend:
            adx['metrics'][i] += -1.0 * trend
            if state != 'none':
                if state == 'bull':
                    state = 'bear'
                else:
                    state = 'bull'
                data = {
                    "type": state,
                    "value": '40-crossunder: weakening trend',
                    "index": i,
                    "date": date
                }

        if signal[i - 1] > no_trend and signal[i] < no_trend:
            adx['metrics'][i] += 0.0
            if state != 'none':
                if state == 'bull':
                    state = 'bear'
                else:
                    state = 'bull'
                data = {
                    "type": state,
                    "value": '20-crossunder: WEAK/NO trend',
                    "index": i,
                    "date": date
                }

        if data is not None:
            adx['signals'].append(data)

    if pbar is not None:
        pbar.uptick(increment=0.1)

    metrics = exponential_moving_avg(adx['metrics'], 7, data_type='list')
    if pbar is not None:
        pbar.uptick(increment=0.1)

    adx['metrics'] = normalize_signals([metrics])[0]

    name2 = INDEXES.get(name, name)
    title = f"{name2} - ADX Metrics"

    if plot_output:
        dual_plotting(fund['Close'],
                      adx['metrics'],
                      'Price',
                      'Metrics',
                      title=title)
    else:
        filename = os.path.join(name, view, f"adx_metrics_{name}.png")
        dual_plotting(fund['Close'],
                      adx['metrics'],
                      'Price',
                      'Metrics',
                      title=title,
                      saveFig=True,
                      filename=filename)

    if pbar is not None:
        pbar.uptick(increment=0.2)

    return adx
Ejemplo n.º 4
0
def clustered_metrics(position: pd.DataFrame, cluster_oscs: dict,
                      **kwargs) -> dict:
    """Clustered Metrics

    Arguments:
        position {pd.DataFrame} -- dataset
        cluster_oscs {dict} -- clustered osc data object

    Optional Args:
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        view {str} -- file directory of plots (default: {''})

    Returns:
        dict -- clustered osc data object
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    view = kwargs.get('view')

    ults = cluster_oscs['tabular']

    # Take indicator set: weight, filter, normalize
    weights = [1.0, 0.85, 0.55, 0.1]
    state2 = [0.0] * len(ults)

    for ind, s in enumerate(ults):
        if s != 0.0:
            state2[ind] += s

            # Smooth the curves
            if ind - 1 >= 0:
                state2[ind - 1] += s * weights[1]
            if ind + 1 < len(ults):
                state2[ind + 1] += s * weights[1]
            if ind - 2 >= 0:
                state2[ind - 2] += s * weights[2]
            if ind + 2 < len(ults):
                state2[ind + 2] += s * weights[2]
            if ind - 3 >= 0:
                state2[ind - 3] += s * weights[3]
            if ind + 3 < len(ults):
                state2[ind + 3] += s * weights[3]

    metrics = exponential_moving_avg(state2, 7, data_type='list')
    norm = normalize_signals([metrics])
    metrics = norm[0]

    cluster_oscs['metrics'] = metrics

    name3 = INDEXES.get(name, name)
    name2 = name3 + " - Clustered Oscillator Metrics"
    if plot_output:
        dual_plotting(position['Close'],
                      metrics,
                      'Price',
                      'Metrics',
                      title=name2)
    else:
        filename = os.path.join(name, view,
                                f"clustered_osc_metrics_{name}.png")
        dual_plotting(position['Close'],
                      metrics,
                      'Price',
                      'Metrics',
                      title=name2,
                      filename=filename,
                      saveFig=True)

    return cluster_oscs
Ejemplo n.º 5
0
def bear_bull_feature_detection(bear_bull: dict, position: pd.DataFrame, **kwargs) -> dict:
    """Bear Bull Feature Detection

    Arguments:
        bear_bull {dict} -- bull bear data object
        position {pd.DataFrame} -- dataset

    Optional Args:
        interval {int} -- size of exponential moving average window (default: {13})
        bb_interval {list} -- list of sizes of bear and bull windows (default: {[4, 5, 6, 7, 8]})
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        p_bar {ProgressBar} -- (default {None})
        view {str} -- (default: {''})

    Returns:
        dict -- [description]
    """
    interval = kwargs.get('interval', 13)
    bb_interval = kwargs.get('bb_interval', [4, 5, 6, 7, 8])
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    p_bar = kwargs.get('p_bar')
    view = kwargs.get('view')

    # Determine the slope of the ema at given points
    ema = exponential_moving_avg(position, interval)

    ema_slopes = [0.0] * (interval-1)
    for i in range(interval-1, len(ema)):
        x = list(range(i-(interval-1), i))
        y = ema[i-(interval-1): i]
        reg = linregress(x, y=y)
        ema_slopes.append(reg[0])

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    incr = 0.6 / float(len(bb_interval))

    state = [0.0] * len(ema)
    features = []

    for bb in bb_interval:
        # Determine the slope of the bear power signal at given points
        bear_slopes = [0.0] * (bb-1)
        for i in range(bb-1, len(ema)):
            x = list(range(i-(bb-1), i))
            y = bear_bull['tabular']['bears'][i-(bb-1): i]
            reg = linregress(x, y=y)
            bear_slopes.append(reg[0])

        # Determine the slope of the bull power signal at given points
        bull_slopes = [0.0] * (bb-1)
        for i in range(bb-1, len(ema)):
            x = list(range(i-(bb-1), i))
            y = bear_bull['tabular']['bulls'][i-(bb-1): i]
            reg = linregress(x, y=y)
            bull_slopes.append(reg[0])

        for i in range(1, len(ema)):
            data = None
            date = position.index[i].strftime("%Y-%m-%d")

            if ema_slopes[i] > 0.0:
                if bear_bull['tabular']['bears'][i] < 0.0:
                    if bear_slopes[i] > 0.0:
                        # Determine the basic (first 2 conditions) bullish state (+1)
                        state[i] += 1.0
                        if bear_bull['tabular']['bulls'][i] > bear_bull['tabular']['bulls'][i-1]:
                            state[i] += 0.5
                            if position['Close'][i] < position['Close'][i-1]:
                                # Need to find bullish divergence!
                                state[i] += 1.0
                                data = {
                                    "type": 'bullish',
                                    "value": f'bullish divergence: {bb}d interval',
                                    "index": i,
                                    "date": date
                                }

            if ema_slopes[i] < 0.0:
                if bear_bull['tabular']['bulls'][i] > 0.0:
                    if bull_slopes[i] < 0.0:
                        # Determine the basic (first 2 conditions) bearish state (+1)
                        state[i] += -1.0
                        if bear_bull['tabular']['bears'][i] < bear_bull['tabular']['bears'][i-1]:
                            state[i] += -0.5
                            if position['Close'][i] > position['Close'][i-1]:
                                # Need to find bearish divergence!
                                state[i] += -1.0
                                data = {
                                    "type": 'bearish',
                                    "value": f'bearish divergence: {bb}d interval',
                                    "index": i,
                                    "date": date
                                }

            if data is not None:
                features.append(data)

        if p_bar is not None:
            p_bar.uptick(increment=incr)

    bear_bull['signals'] = filter_features(features, plot_output=plot_output)
    bear_bull['length_of_data'] = len(bear_bull['tabular']['bears'])

    weights = [1.0, 0.75, 0.45, 0.1]

    state2 = [0.0] * len(state)
    for ind, s in enumerate(state):
        if s != 0.0:
            state2[ind] += s

            # Smooth the curves
            if ind - 1 >= 0:
                state2[ind-1] += s * weights[1]
            if ind + 1 < len(state):
                state2[ind+1] += s * weights[1]
            if ind - 2 >= 0:
                state2[ind-2] += s * weights[2]
            if ind + 2 < len(state):
                state2[ind+2] += s * weights[2]
            if ind - 3 >= 0:
                state2[ind-3] += s * weights[3]
            if ind + 3 < len(state):
                state2[ind+3] += s * weights[3]

    state3 = exponential_moving_avg(state2, 7, data_type='list')
    norm = normalize_signals([state3])
    state4 = norm[0]

    title = 'Bear Bull Power Metrics'
    if plot_output:
        dual_plotting(position['Close'], state4, 'Price',
                      'Bear Bull Power', title=title)
    else:
        filename = os.path.join(name, view, f"bear_bull_power_{name}.png")
        dual_plotting(position['Close'], state4, 'Price', 'Metrics', title=title,
                      saveFig=True, filename=filename)

    bear_bull['metrics'] = state4

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    return bear_bull
Ejemplo n.º 6
0
def demand_index_metrics(fund: pd.DataFrame, dmx: dict, **kwargs) -> list:
    """Demand Index Metrics

    Arguments:
        fund {pd.DataFrame} -- fund dataset
        dmx {dict} -- demand index data object

    Optional Args:
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        view {str} -- (default: {''})
        progress_bar {ProgressBar} -- (default: {None})

    Returns:
        list -- demand index data object
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    view = kwargs.get('view', '')
    pbar = kwargs.get('pbar')

    metrics = [0.0] * len(dmx['tabular'])

    weight_map = {
        "zero crossover": [1.2, 0.95, 0.6, 0.1],
        "dual-signal-line": [1.0, 0.85, 0.55, 0.1],
        "signal-line zone": [0.8, 0.65, 0.4, 0.1]
    }

    for sig in dmx['signals']:
        ind = sig['index']
        s = 1.0
        if sig['type'] == 'bearish':
            s = -1.0

        if 'dual-signal-line' in sig['value']:
            weights = weight_map['dual-signal-line']
        elif 'signal-line zone' in sig['value']:
            weights = weight_map['signal-line zone']
        else:
            weights = weight_map['zero crossover']
        
        metrics[ind] = s

        # Smooth the curves
        if ind - 1 >= 0:
            metrics[ind-1] += s * weights[1]
        if ind + 1 < len(metrics):
            metrics[ind+1] += s * weights[1]
        if ind - 2 >= 0:
            metrics[ind-2] += s * weights[2]
        if ind + 2 < len(metrics):
            metrics[ind+2] += s * weights[2]
        if ind - 3 >= 0:
            metrics[ind-3] += s * weights[3]
        if ind + 3 < len(metrics):
            metrics[ind+3] += s * weights[3]

    if pbar is not None:
        pbar.uptick(increment=0.1)

    metrics = exponential_moving_avg(metrics, 7, data_type='list')
    norm = normalize_signals([metrics])
    metrics = norm[0]

    if pbar is not None:
        pbar.uptick(increment=0.1)

    name2 = INDEXES.get(name, name)
    title = f"{name2} - Demand Index"
    if plot_output:
        dual_plotting(fund['Close'], metrics, 'Price', 'Demand Index Metrics')
    else:
        filename = os.path.join(name, view, f"di_metrics_{name}")
        dual_plotting(fund['Close'], metrics, 'Price', 'Demand Index Metrics',
                      title=title, saveFig=True, filename=filename)

    return metrics
Ejemplo n.º 7
0
def momentum_metrics(position: pd.DataFrame, mo_dict: dict, **kwargs) -> dict:
    """Momentum Oscillator Metrics 

    Combination of pure oscillator signal + weighted features

    Arguments:
        position {pd.DataFrame} -- fund
        mo_dict {dict} -- momentum oscillator dict

    Optional Args:
        plot_output {bool} -- plots in real time if True (default: {True})
        name {str} -- name of fund (default: {''})
        progress_bar {ProgressBar} -- (default: {None})
        view {str} -- (default: {''})

    Returns:
        dict -- mo_dict w/ updated keys and data
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    period_change = kwargs.get('period_change', 5)
    view = kwargs.get('view', '')

    weights = [1.3, 0.85, 0.55, 0.1]

    # Convert features to a "tabular" array
    tot_len = len(position['Close'])
    metrics = [0.0] * tot_len
    mo_features = mo_dict['signals']
    signal = mo_dict['tabular']

    for feat in mo_features:
        ind = feat['index']
        if feat['type'] == 'bullish':
            val = 1.0
        else:
            val = -1.0

        metrics[ind] += val * weights[0]

        # Smooth the curves
        if ind - 1 >= 0:
            metrics[ind - 1] += val * weights[1]
        if ind + 1 < tot_len:
            metrics[ind + 1] += val * weights[1]
        if ind - 2 >= 0:
            metrics[ind - 2] += val * weights[2]
        if ind + 2 < tot_len:
            metrics[ind + 2] += val * weights[2]
        if ind - 3 >= 0:
            metrics[ind - 3] += val * weights[3]
        if ind + 3 < tot_len:
            metrics[ind + 3] += val * weights[3]

    norm_signal = normalize_signals([signal])[0]

    metrics4 = []
    changes = []
    for i, met in enumerate(metrics):
        metrics4.append(met + norm_signal[i])

    min_ = np.abs(min(metrics4)) + 1.0
    for _ in range(period_change):
        changes.append(0.0)
    for i in range(period_change, len(metrics4)):
        c = (((metrics4[i] + min_) /
              (metrics4[i - period_change] + min_)) - 1.0) * 100.0
        changes.append(c)

    mo_dict['metrics'] = metrics4
    mo_dict['changes'] = changes

    title = '(Chande) Momentum Oscillator Metrics'
    if plot_output:
        dual_plotting(position['Close'],
                      metrics4,
                      'Price',
                      'Metrics',
                      title=title)
    else:
        filename = os.path.join(name, view, f"momentum_metrics_{name}.png")
        dual_plotting(position['Close'],
                      metrics4,
                      'Price',
                      'Metrics',
                      title=title,
                      saveFig=True,
                      filename=filename)

    return mo_dict
def get_ao_signal(position: pd.DataFrame, **kwargs) -> list:
    """Get Awesome Oscillator Signal

    Arguments:
        position {pd.DataFrame} -- dataset of fund

    Optional Args:
        short_period {int} -- moving average period (default: {5})
        long_period {int} -- moving average period (default: {34})
        filter_style {str} -- moving average type, 'sma' or 'ema' (default: {'sma'})
        plot_output {bool} -- True plots in realtime (default: {True})
        p_bar {ProgressBar} -- (default: {None})
        name {str} -- name of fund (default: {''})

    Returns:
        list -- awesome signal
    """
    short_period = kwargs.get('short_period', 5)
    long_period = kwargs.get('long_period', 34)
    filter_style = kwargs.get('filter_style', 'sma')
    plot_output = kwargs.get('plot_output', True)
    p_bar = kwargs.get('progress_bar')
    name = kwargs.get('name', '')
    view = kwargs.get('view')

    signal = []
    mid_points = []
    for i, high in enumerate(position['High']):
        mid = (high + position['Low'][i]) / 2
        mid_points.append(mid)

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    if filter_style == 'sma':
        short_signal = simple_moving_avg(mid_points,
                                         short_period,
                                         data_type='list')
        long_signal = simple_moving_avg(mid_points,
                                        long_period,
                                        data_type='list')

    elif filter_style == 'ema':
        short_signal = exponential_moving_avg(mid_points,
                                              short_period,
                                              data_type='list')
        long_signal = exponential_moving_avg(mid_points,
                                             long_period,
                                             data_type='list')

    else:
        short_signal = []
        long_signal = []

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    for i in range(long_period):
        signal.append(0.0)
    for i in range(long_period, len(long_signal)):
        diff = short_signal[i] - long_signal[i]
        signal.append(diff)

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    med_term = simple_moving_avg(signal, 14, data_type='list')
    long_term = simple_moving_avg(signal, long_period, data_type='list')

    signal, med_term, long_term = normalize_signals(
        [signal, med_term, long_term])

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    triggers = ao_signal_trigger(signal, med_term, long_term)

    x = dates_extractor_list(position)
    name3 = INDEXES.get(name, name)
    name2 = name3 + ' - Awesome Oscillator'

    if plot_output:
        dual_plotting([signal, med_term, long_term], position['Close'],
                      ['Awesome', 'Medium', 'Long'], 'Price')
        dual_plotting([signal, triggers], position['Close'],
                      ['Awesome', 'Triggers'], 'Price')
        bar_chart(signal, position=position, x=x, title=name2, bar_delta=True)
    else:
        filename = os.path.join(name, view, f"awesome_bar_{name}")
        bar_chart(signal,
                  position=position,
                  x=x,
                  saveFig=True,
                  filename=filename,
                  title=name2,
                  bar_delta=True)

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    return signal
Ejemplo n.º 9
0
def rsi_metrics(position: pd.DataFrame, rsi: dict, **kwargs) -> dict:
    """RSI Metrics

    Arguments:
        position {pd.DataFrame} -- dataset
        rsi {dict} -- rsi data object

    Optional Args:
        p_bar {ProgressBar} -- (default: {None})

    Returns:
        dict -- rsi data object
    """
    p_bar = kwargs.get('p_bar')

    swings = rsi['indicator']
    divs = rsi['divergence']

    # Take indicator sets: weight, combine, filter, normalize
    weights = [1.0, 0.85, 0.55, 0.1]
    state2 = [0.0] * len(divs)

    for ind, s in enumerate(divs):
        if s != 0.0:
            state2[ind] += s

            # Smooth the curves
            if ind - 1 >= 0:
                state2[ind - 1] += s * weights[1]
            if ind + 1 < len(divs):
                state2[ind + 1] += s * weights[1]
            if ind - 2 >= 0:
                state2[ind - 2] += s * weights[2]
            if ind + 2 < len(divs):
                state2[ind + 2] += s * weights[2]
            if ind - 3 >= 0:
                state2[ind - 3] += s * weights[3]
            if ind + 3 < len(divs):
                state2[ind + 3] += s * weights[3]

    if p_bar is not None:
        p_bar.uptick(increment=0.05)

    for ind, s in enumerate(swings):
        if s != 0.0:
            state2[ind] += s

            # Smooth the curves
            if ind - 1 >= 0:
                state2[ind - 1] += s * weights[1]
            if ind + 1 < len(swings):
                state2[ind + 1] += s * weights[1]
            if ind - 2 >= 0:
                state2[ind - 2] += s * weights[2]
            if ind + 2 < len(swings):
                state2[ind + 2] += s * weights[2]
            if ind - 3 >= 0:
                state2[ind - 3] += s * weights[3]
            if ind + 3 < len(swings):
                state2[ind + 3] += s * weights[3]

    if p_bar is not None:
        p_bar.uptick(increment=0.05)

    metrics = exponential_moving_avg(state2, 7, data_type='list')
    norm = normalize_signals([metrics])
    metrics = norm[0]

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    rsi['metrics'] = metrics

    return rsi
Ejemplo n.º 10
0
def macd_metrics(position: pd.DataFrame, macd: dict, **kwargs) -> dict:
    """MACD Metrics

    Arguments:
        position {pd.DataFrame} -- fund dataset
        macd {dict} -- macd data object

    Optional Args:
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        p_bar {ProgressBar} -- (default: {None})
        view {str} -- directory of plots (default: {''})

    Returns:
        dict -- macd data object
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    p_bar = kwargs.get('p_bar')
    view = kwargs.get('view')

    m_bar = macd['tabular']['bar']

    max_m = max(m_bar)
    min_m = min(m_bar)
    div = max_m
    if np.abs(min_m) > max_m:
        div = min_m

    macd = macd_divergences(position, macd, omit=26)

    weights = [1.0, 0.85, 0.55, 0.2]
    for mac in macd['indicators']:

        if mac['type'] == 'bearish':
            s = -1.0 * div / 2.0
        else:
            s = 1.0 * div / 2.0

        ind = mac['index']
        m_bar[ind] += s * weights[0]

        # Smooth the curves
        if ind - 1 >= 0:
            m_bar[ind - 1] += s * weights[1]
        if ind + 1 < len(m_bar):
            m_bar[ind + 1] += s * weights[1]
        if ind - 2 >= 0:
            m_bar[ind - 2] += s * weights[2]
        if ind + 2 < len(m_bar):
            m_bar[ind + 2] += s * weights[2]
        if ind - 3 >= 0:
            m_bar[ind - 3] += s * weights[3]
        if ind + 3 < len(m_bar):
            m_bar[ind + 3] += s * weights[3]

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    metrics = exponential_moving_avg(m_bar, 7, data_type='list')
    norm = normalize_signals([metrics])
    metrics = norm[0]

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    macd['metrics'] = metrics

    name3 = INDEXES.get(name, name)
    name2 = name3 + ' - MACD Metrics'
    if plot_output:
        dual_plotting(position['Close'],
                      metrics,
                      'Price',
                      'Metrics',
                      title=name2)
    else:
        filename = os.path.join(name, view, f"macd_metrics_{name}.png")
        dual_plotting(position['Close'],
                      metrics,
                      'Price',
                      'Metrics',
                      title=name2,
                      saveFig=True,
                      filename=filename)

    return macd
def awesome_metrics(position: pd.DataFrame, ao_dict: dict, **kwargs) -> dict:
    """Awesome Oscillator Metrics 

    Combination of pure oscillator signal + weighted trigger signals

    Arguments:
        position {pd.DataFrame} -- fund
        ao_dict {dict} -- awesome oscillator dictionary

    Optional Args:
        plot_output {bool} -- plots in real time if True (default: {True})
        name {str} -- name of fund (default: {''})
        progress_bar {ProgressBar} -- (default: {None})

    Returns:
        dict -- ao_dict w/ updated keys and data
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    p_bar = kwargs.get('progress_bar')
    period_change = kwargs.get('period_change', 5)
    view = kwargs.get('view')

    weights = [1.0, 0.85, 0.5, 0.05]

    # Convert features to a "tabular" array
    tot_len = len(position['Close'])
    metrics = [0.0] * tot_len
    plus_minus = ao_dict.get('pm', {}).get('pm_data')
    indexes = ao_dict.get('pm', {}).get('indexes', [])

    for i, ind in enumerate(indexes):
        metrics[ind] += float(plus_minus[i])

        # Smooth the curves
        if ind - 1 >= 0:
            metrics[ind - 1] += float(plus_minus[i]) * weights[1]
        if ind + 1 < tot_len:
            metrics[ind + 1] += float(plus_minus[i]) * weights[1]
        if ind - 2 >= 0:
            metrics[ind - 2] += float(plus_minus[i]) * weights[2]
        if ind + 2 < tot_len:
            metrics[ind + 2] += float(plus_minus[i]) * weights[2]
        if ind - 3 >= 0:
            metrics[ind - 3] += float(plus_minus[i]) * weights[3]
        if ind + 3 < tot_len:
            metrics[ind + 3] += float(plus_minus[i]) * weights[3]

    metrics2 = exponential_moving_avg(metrics, 7, data_type='list')
    norm = normalize_signals([metrics2])
    metrics3 = norm[0]

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    ao_signal = ao_dict['tabular']

    metrics4 = []
    for i, met in enumerate(metrics3):
        metrics4.append(met + ao_signal[i])

    changes = []
    min_ = 1.0 - min(metrics4)
    for _ in range(period_change):
        changes.append(0.0)
    for i in range(period_change, len(metrics4)):
        c = (((metrics4[i] + min_) /
              (metrics4[i - period_change] + min_)) - min_) * 100.0
        changes.append(c)

    ao_dict['metrics'] = metrics4
    ao_dict['changes'] = changes

    title = 'Awesome Oscillator Metrics'
    if plot_output:
        dual_plotting(position['Close'],
                      metrics4,
                      'Price',
                      'Metrics',
                      title=title)
    else:
        filename = os.path.join(name, view, f"awesome_metrics_{name}.png")
        dual_plotting(position['Close'],
                      metrics4,
                      'Price',
                      'Metrics',
                      title=title,
                      saveFig=True,
                      filename=filename)

    ao_dict.pop('pm')

    return ao_dict
Ejemplo n.º 12
0
def get_stoch_metrics(position: pd.DataFrame, full_stoch: dict,
                      **kwargs) -> dict:
    """Get Stochastic Metrics

    Arguments:
        position {pd.DataFrame} -- dataset
        full_stoch {dict} -- stochastic data object

    Optional Args:
        plot_output {bool} -- (default: {True})
        p_bar {ProgressBar} -- {default: {None}}

    Returns:
        dict -- stochastic data object
    """
    plot_output = kwargs.get('plot_output', True)
    p_bar = kwargs.get('p_bar')

    stochs = full_stoch['indicator']

    # Take indicator set: weight, filter, normalize
    weights = [1.0, 0.85, 0.55, 0.1]
    state2 = [0.0] * len(stochs)

    for ind, s in enumerate(stochs):
        if s != 0.0:
            state2[ind] += s

            # Smooth the curves
            if ind - 1 >= 0:
                state2[ind - 1] += s * weights[1]
            if ind + 1 < len(stochs):
                state2[ind + 1] += s * weights[1]
            if ind - 2 >= 0:
                state2[ind - 2] += s * weights[2]
            if ind + 2 < len(stochs):
                state2[ind + 2] += s * weights[2]
            if ind - 3 >= 0:
                state2[ind - 3] += s * weights[3]
            if ind + 3 < len(stochs):
                state2[ind + 3] += s * weights[3]

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    metrics = exponential_moving_avg(state2, 7, data_type='list')
    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    norm = normalize_signals([metrics])
    metrics = norm[0]

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    full_stoch['metrics'] = metrics

    if plot_output:
        dual_plotting(position['Close'],
                      metrics,
                      'Price',
                      'Metrics',
                      title='Stochastic Metrics')

    return full_stoch
Ejemplo n.º 13
0
def total_power_feature_detection(tp: dict, position: pd.DataFrame, **kwargs) -> dict:
    """Total Power Feature Detection / Metrics

    Arguments:
        tp {dict} -- total power data object
        position {pd.DataFrame} -- dataset

    Optional Args:
        adj_level {float} -- threshold level of indicators (default: {72.0})
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        p_bar {ProgressBar} -- (default: {None})
        view {str} -- (default: {''})

    Returns:
        dict -- tp
    """
    adj_level = kwargs.get('adj_level', 72.0)
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    p_bar = kwargs.get('p_bar')
    view = kwargs.get('view')

    tab = tp['tabular']
    metrics = [0.0] * len(tab['total'])
    features = []

    if tab['bulls'][0] > tab['bears'][0]:
        on_top = 'bull'
    else:
        on_top = 'bear'

    tot_above = ''
    for i, tot in enumerate(tab['total']):
        date = position.index[i].strftime("%Y-%m-%d")

        if (tot >= 99.0) and (tab['bulls'][i] >= 99.0):
            metrics[i] += 3.0
            data = {
                "type": 'bullish',
                "value": 'full bullish signal: 100%',
                "index": i,
                "date": date
            }
            features.append(data)

        if (tot >= 99.0) and (tab['bears'][i] >= 99.0):
            metrics[i] += -3.0
            data = {
                "type": 'bearish',
                "value": 'full bearish signal: 100%',
                "index": i,
                "date": date
            }
            features.append(data)

        if (on_top == 'bull') and (tab['bears'][i] > tab['bulls'][i]):
            metrics[i] += -1.0
            on_top = 'bear'
            data = {
                "type": 'bearish',
                "value": 'bear-bull crossover',
                "index": i,
                "date": date
            }
            features.append(data)

        if (on_top == 'bear') and (tab['bulls'][i] > tab['bears'][i]):
            metrics[i] += -1.0
            on_top = 'bull'
            data = {
                "type": 'bullish',
                "value": 'bear-bull crossover',
                "index": i,
                "date": date
            }
            features.append(data)

        if tot > tab['bulls'][i]:
            tot_above = 'bull'

        if tot > tab['bears'][i]:
            tot_above = 'bear'

        if (tot_above == 'bull') and (tab['bulls'][i] > tot):
            tot_above = ''
            metrics[i] += 1.0
            data = {
                "type": 'bullish',
                "value": 'bull-total crossover',
                "index": i,
                "date": date
            }
            features.append(data)

        if (tot_above == 'bear') and (tab['bears'][i] > tot):
            tot_above = ''
            metrics[i] += -1.0
            data = {
                "type": 'bearish',
                "value": 'bear-total crossover',
                "index": i,
                "date": date
            }
            features.append(data)

        if i > 0:
            if (tab['bulls'][i-1] < adj_level) and (tab['bulls'][i] > adj_level):
                metrics[i] += 1.0
                data = {
                    "type": 'bullish',
                    "value": 'bull-adjustment level crossover',
                    "index": i,
                    "date": date
                }
                features.append(data)

            if (tab['bears'][i-1] < adj_level) and (tab['bears'][i] > adj_level):
                metrics[i] += -1.0
                data = {
                    "type": 'bearish',
                    "value": 'bear-adjustment level crossover',
                    "index": i,
                    "date": date
                }
                features.append(data)

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    weights = [1.0, 0.85, 0.6, 0.25]

    state2 = [0.0] * len(metrics)
    for ind, s in enumerate(metrics):
        if s != 0.0:
            state2[ind] += s

            # Smooth the curves
            if ind - 1 >= 0:
                state2[ind-1] += s * weights[1]
            if ind + 1 < len(metrics):
                state2[ind+1] += s * weights[1]
            if ind - 2 >= 0:
                state2[ind-2] += s * weights[2]
            if ind + 2 < len(metrics):
                state2[ind+2] += s * weights[2]
            if ind - 3 >= 0:
                state2[ind-3] += s * weights[3]
            if ind + 3 < len(metrics):
                state2[ind+3] += s * weights[3]

    metrics = exponential_moving_avg(state2, 7, data_type='list')
    norm = normalize_signals([metrics])
    metrics = norm[0]

    name2 = INDEXES.get(name, name)
    title = name2 + ' - Total Power Metrics'
    if plot_output:
        dual_plotting(position['Close'], metrics, 'Price', 'Metrics')
        for feat in features:
            print(f"Total Power: {feat}")

    else:
        filename = os.path.join(name, view, f"total_pwr_metrics_{name}.png")
        dual_plotting(position['Close'], metrics, 'Price',
                      'Metrics', title=title, saveFig=True, filename=filename)

    tp['metrics'] = metrics
    tp['signals'] = features
    tp['length_of_data'] = len(tp['tabular']['bears'])

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    return tp
Ejemplo n.º 14
0
def atr_indicators(fund: pd.DataFrame, atr_dict: dict, **kwargs) -> dict:
    """ATR Indicators

    Run exponential moving average periods to weed out higher volatility: 20, 40

    Arguments:
        fund {pd.DataFrame} -- fund dataset
        atr_dict {dict} -- atr data object

    Optional Args:
        periods {list} -- list of ema lookback periods (default: {[20, 40]})
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        out_suppress {bool} -- (default: {False})

    Returns:
        dict: [description]
    """
    periods = kwargs.get('periods', [50, 200])
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    out_suppress = kwargs.get('out_suppress', False)

    ema_1 = exponential_moving_avg(atr_dict['tabular'],
                                   periods[0],
                                   data_type='list')
    ema_2 = exponential_moving_avg(atr_dict['tabular'],
                                   periods[1],
                                   data_type='list')

    states = []
    for i, tab in enumerate(atr_dict['tabular']):
        if tab > ema_1[i] and ema_1[i] > ema_2[i]:
            states.append('u3')
        elif tab > ema_1[i] and tab > ema_2[i]:
            states.append('u2')
        elif tab < ema_1[i] and tab > ema_2[i]:
            states.append('u1')
        elif tab > ema_1[i] and tab < ema_2[i]:
            states.append('e1')
        elif tab < ema_1[i] and ema_1[i] < ema_2[i]:
            states.append('e3')
        elif tab < ema_1[i] and tab < ema_2[i]:
            states.append('e2')
        else:
            states.append('n')

    metrics = [0.0] * len(ema_1)
    signals = []
    for i in range(1, len(ema_1)):
        date = fund.index[i].strftime("%Y-%m-%d")
        data = None

        if states[i] == 'u3' and states[i - 1] != 'u3':
            metrics[i] += -1.0
            data = {
                "type": 'bearish',
                "value":
                f'volatility crossover: signal-{periods[0]}-{periods[1]}',
                "date": date,
                "index": i
            }

        elif states[i] == 'e3' and states[i - 1] != 'e3':
            metrics[i] += 1.0
            data = {
                "type": 'bullish',
                "value":
                f'volatility crossover: {periods[1]}-{periods[0]}-signal',
                "date": date,
                "index": i
            }

        elif states[i] == 'u2' and states[i - 1] == 'e1':
            metrics[i] += -0.6

        elif states[i] == 'e2' and states[i - 1] == 'u1':
            metrics[i] += 0.6

        elif states[i] == 'u1' and states[i - 1] == 'u3':
            metrics[i] += 0.2

        elif states[i] == 'e1' and states[i - 1] == 'e3':
            metrics[i] += -0.2

        if data is not None:
            signals.append(data)

    metrics = exponential_moving_avg(metrics, 7, data_type='list')
    metrics = normalize_signals([metrics])[0]

    atr_dict['metrics'] = metrics
    atr_dict['signals'] = signals

    if plot_output and not out_suppress:
        name2 = INDEXES.get(name, name)
        title = f"{name2} - ATR Moving Averages"
        dual_plotting(fund['Close'], [atr_dict['tabular'], ema_1, ema_2],
                      'Price',
                      'ATRs',
                      title=title)

    return atr_dict
def roc_metrics(fund: pd.DataFrame, roc_dict: dict, **kwargs) -> dict:
    """Rate of Change Metrics

    Arguments:
        fund {pd.DataFrame} -- fund dataset
        roc_dict {dict} -- roc data object

    Optional Args:
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        views {str} -- (default: {''})
        p_bar {ProgressBar} -- (default: {None})

    Returns:
        dict -- roc data object
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    views = kwargs.get('views', '')
    p_bar = kwargs.get('p_bar')

    MAP_TABULAR = {'short': 0.65, 'medium': 1.0, 'long': 0.4}

    roc_dict['metrics'] = [0.0] * len(fund['Close'])
    roc_dict['signals'] = []

    # Look at zero crossovers first
    roc_dict = roc_zero_crossovers(fund, roc_dict, MAP_TABULAR)
    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    roc_dict = roc_over_threshold_crossovers(fund, roc_dict, MAP_TABULAR)
    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    roc_dict['metrics'] = exponential_moving_avg(roc_dict['metrics'],
                                                 7,
                                                 data_type='list')

    roc_dict['metrics'] = normalize_signals([roc_dict['metrics']])[0]
    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    name2 = INDEXES.get(name, name)
    title = f"{name2} - Rate of Change Metrics"

    if plot_output:
        dual_plotting(fund['Close'],
                      roc_dict['metrics'],
                      'Price',
                      'ROC Metrics',
                      title=title)
    else:
        filename = os.path.join(name, views, f"roc_metrics_{name}")
        dual_plotting(fund['Close'],
                      roc_dict['metrics'],
                      'Price',
                      'ROC Metrics',
                      title=title,
                      saveFig=True,
                      filename=filename)

    return roc_dict
Ejemplo n.º 16
0
def swing_trade_metrics(position: pd.DataFrame, swings: dict, **kwargs) -> dict:
    """Swing Trade Metrics

    Arguments:
        position {pd.DataFrame} -- fund dataset
        swings {dict} -- hull data object

    Optional Args:
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        p_bar {ProgressBar} -- (default: {None})
        view {str} -- directory of plots (default: {''})

    Returns:
        dict -- hull data object
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    p_bar = kwargs.get('p_bar')
    view = kwargs.get('view')

    weights = [1.0, 0.55, 0.25, 0.1]

    # Convert features to a "tabular" array
    tot_len = len(position['Close'])
    metrics = [0.0] * tot_len

    for i, val in enumerate(swings['tabular']['swing']):

        metrics[i] += val * weights[0]

        # Smooth the curves
        if i - 1 >= 0:
            metrics[i-1] += val * weights[1]
        if i + 1 < tot_len:
            metrics[i+1] += val * weights[1]
        if i - 2 >= 0:
            metrics[i-2] += val * weights[2]
        if i + 2 < tot_len:
            metrics[i+2] += val * weights[2]
        if i - 3 >= 0:
            metrics[i-3] += val * weights[3]
        if i + 3 < tot_len:
            metrics[i+3] += val * weights[3]

    norm_signal = normalize_signals([metrics])[0]
    metrics = simple_moving_avg(norm_signal, 7, data_type='list')
    swings['metrics'] = {'metrics': metrics}

    tshort = swings['tabular']['short']
    tmed = swings['tabular']['medium']
    tlong = swings['tabular']['long']

    mshort = []
    mmed = []
    mlong = []

    for i, close in enumerate(position['Close']):
        mshort.append(np.round((close - tshort[i]) / tshort[i] * 100.0, 3))
        mmed.append(np.round((close - tmed[i]) / tmed[i] * 100.0, 3))
        mlong.append(np.round((close - tlong[i]) / tlong[i] * 100.0, 3))

    shp = swings['short']['period']
    mdp = swings['medium']['period']
    lgp = swings['long']['period']

    swings['metrics'][f'{shp}-d'] = mshort
    swings['metrics'][f'{mdp}-d'] = mmed
    swings['metrics'][f'{lgp}-d'] = mlong

    name3 = INDEXES.get(name, name)
    name2 = name3 + ' - Hull Moving Average Metrics'

    if plot_output:
        dual_plotting(position['Close'], swings['metrics']['metrics'],
                      'Price', 'Metrics', title='Hull Moving Average Metrics')
    else:
        filename2 = os.path.join(name, view, f"hull_metrics_{name}.png")
        dual_plotting(position['Close'], swings['metrics']['metrics'],
                      'Price', 'Metrics', title=name2, saveFig=True, filename=filename2)

    if p_bar is not None:
        p_bar.uptick(increment=0.2)

    return swings
Ejemplo n.º 17
0
def bollinger_metrics(position: pd.DataFrame, bol_bands: dict,
                      **kwargs) -> dict:
    """Bollinger Metrics

    Arguments:
        position {pd.DataFrame} -- dataset of fund
        bol_bands {dict} -- bollinger band data object

    Optional Args:
        period {int} -- look back period for Stdev (default: {20})
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        view {str} -- (default: {''})

    Returns:
        dict -- bollinger band data object
    """
    period = kwargs.get('period', 20)
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    view = kwargs.get('view')

    weights = [1.0, 0.6, 0.25, 0.0]
    tot_len = len(position['Close'])

    metrics = [0.0] * tot_len
    for feat in bol_bands['indicators']:
        ind = feat['index']
        if feat['type'] == 'bullish':
            val = 1.0
        else:
            val = -1.0

        metrics[ind] += val * weights[0]

        # Smooth the curves
        if ind - 1 >= 0:
            metrics[ind - 1] += val * weights[1]
        if ind + 1 < tot_len:
            metrics[ind + 1] += val * weights[1]
        if ind - 2 >= 0:
            metrics[ind - 2] += val * weights[2]
        if ind + 2 < tot_len:
            metrics[ind + 2] += val * weights[2]
        if ind - 3 >= 0:
            metrics[ind - 3] += val * weights[3]
        if ind + 3 < tot_len:
            metrics[ind + 3] += val * weights[3]

    close = position['Close']
    bb = bol_bands['tabular']
    for i in range(period, len(close)):
        s_range = bb['middle_band'][i] - bb['lower_band'][i]
        if metrics[i] <= 0.6 and metrics[i] >= -0.6:
            c = close[i] - bb['middle_band'][i]
            c = np.round(c / s_range, 4)
            metrics[i] = c

    metrics = exponential_moving_avg(metrics, 7, data_type='list')
    norm_signal = normalize_signals([metrics])[0]

    bol_bands['metrics'] = norm_signal

    name3 = INDEXES.get(name, name)
    name2 = name3 + f" - Bollinger Band Metrics"
    if plot_output:
        dual_plotting(position['Close'],
                      norm_signal,
                      'Price',
                      'Indicators',
                      title=name2)
    else:
        filename = os.path.join(name, view,
                                f"bollinger_band_metrics_{name}.png")
        # filename = name + f"/{view}" + f"/bollinger_band_metrics_{name}.png"
        dual_plotting(position['Close'],
                      norm_signal,
                      'Price',
                      'Metrics',
                      title=name2,
                      saveFig=True,
                      filename=filename)

    return bol_bands
Ejemplo n.º 18
0
def ultimate_osc_metrics(position: pd.DataFrame, ultimate: dict,
                         **kwargs) -> dict:
    """Ultimate Oscillator Metrics

    Arguments:
        position {pd.DataFrame} -- fund dataset
        ultimate {dict} -- ultimate osc data object

    Optional Args:
        p_bar {ProgressBar} -- (default: {None})
        plot_output {bool} -- (default: {True})
        out_suppress {bool} -- (default: {True})
        name {str} -- (default: {''})
        view {str} -- (default: {''})

    Returns:
        dict -- ultimate osc data object
    """
    p_bar = kwargs.get('p_bar')
    plot_output = kwargs.get('plot_output', True)
    out_suppress = kwargs.get('out_suppress', True)
    name = kwargs.get('name', '')
    view = kwargs.get('view', '')

    ults = ultimate['plots']

    # Take indicator set: weight, filter, normalize
    weights = [1.0, 0.9, 0.75, 0.45]
    state2 = [0.0] * len(ults)

    for ind, s in enumerate(ults):
        if s != 0.0:
            state2[ind] += s

            # Smooth the curves
            if ind - 1 >= 0:
                state2[ind - 1] += s * weights[1]
            if ind + 1 < len(ults):
                state2[ind + 1] += s * weights[1]
            if ind - 2 >= 0:
                state2[ind - 2] += s * weights[2]
            if ind + 2 < len(ults):
                state2[ind + 2] += s * weights[2]
            if ind - 3 >= 0:
                state2[ind - 3] += s * weights[3]
            if ind + 3 < len(ults):
                state2[ind + 3] += s * weights[3]

    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    metrics = exponential_moving_avg(state2, 7, data_type='list')
    if p_bar is not None:
        p_bar.uptick(increment=0.1)

    norm = normalize_signals([metrics])
    metrics = norm[0]

    if not out_suppress:
        name3 = INDEXES.get(name, name)
        name2 = name3 + ' - Ultimate Oscillator Metrics'

        if plot_output:
            dual_plotting(position['Close'],
                          metrics,
                          'Price',
                          'Metrics',
                          title='Ultimate Oscillator Metrics')

        else:
            filename = os.path.join(name, view,
                                    f"ultimate_osc_metrics_{name}.png")
            dual_plotting(position['Close'],
                          metrics,
                          'Price',
                          'Metrics',
                          title=name2,
                          filename=filename,
                          saveFig=True)

    ultimate['metrics'] = metrics

    return ultimate