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
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
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
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
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
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
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
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
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
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
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
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
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
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