def generate_macd_signal(fund: pd.DataFrame, **kwargs) -> dict: """Generate MACD Signal macd = ema(12) - ema(26) 'signal' = macd(ema(9)) Arguments: fund {pd.DataFrame} -- fund dataset Keyword Arguments: plotting {bool} -- (default: {True}) name {str} -- (default: {''}) view {str} -- directory of plots (default: {''}) Returns: dict -- macd data object """ plotting = kwargs.get('plot_output', True) name = kwargs.get('name', '') view = kwargs.get('view') macd = dict() emaTw = exponential_moving_avg(fund, interval=12) emaTs = exponential_moving_avg(fund, interval=26) macd_val = [] for i in range(len(emaTw)): if i < 26: macd_val.append(0.0) else: macd_val.append(emaTw[i] - emaTs[i]) macd_sig = exponential_moving_avg(macd_val, interval=9, data_type='list') # Actual MACD vs. its signal line m_bar = [] for i, sig in enumerate(macd_sig): m_bar.append(macd_val[i] - sig) macd['tabular'] = {'macd': macd_val, 'signal_line': macd_sig, 'bar': m_bar} x = dates_extractor_list(fund) name3 = INDEXES.get(name, name) name2 = name3 + ' - MACD' if plotting: bar_chart(m_bar, position=fund, x=x, title=name2) else: filename = os.path.join(name, view, f"macd_bar_{name}.png") bar_chart(m_bar, position=fund, x=x, title=name2, saveFig=True, filename=filename) return macd
def generate_bear_bull_signal(position: pd.DataFrame, **kwargs) -> dict: """Generate Bear Bull Signal Arguments: position {pd.DataFrame} -- dataset Optional Args: interval {int} -- size of exponential moving average window (default: {13}) plot_output {bool} -- (default: {True}) name {str} -- (default: {''}) p_bar {ProgressBar} -- (default: {None}) Returns: dict -- [description] """ interval = kwargs.get('interval', 13) plot_output = kwargs.get('plot_output', True) name = kwargs.get('name', '') p_bar = kwargs.get('p_bar') bb_signal = {'bulls': [], 'bears': []} ema = exponential_moving_avg(position, interval) for i, high in enumerate(position['High']): bb_signal['bulls'].append(high - ema[i]) if p_bar is not None: p_bar.uptick(increment=0.1) for i, low in enumerate(position['Low']): bb_signal['bears'].append(low - ema[i]) if p_bar is not None: p_bar.uptick(increment=0.1) x = dates_extractor_list(position) if plot_output: name3 = INDEXES.get(name, name) name2 = name3 + ' - Bull Power' bar_chart(bb_signal['bulls'], position=position, title=name2, x=x) name2 = name3 + ' - Bear Power' bar_chart(bb_signal['bears'], position=position, title=name2, x=x) return bb_signal
def generate_obv_content(fund: pd.DataFrame, **kwargs) -> dict: """Generate On Balance Signal Content Arguments: fund {pd.DataFrame} Optional Args: plot_output {bool} -- (default: {True}) filter_factor {float} -- threshold divisor (x/filter_factor) for "significant" OBVs (default: {2.5}) sma_interval {int} -- interval for simple moving average (default: {20}) name {str} -- (default: {''}) progress_bar {ProgressBar} -- (default: {None}) view {'str'} -- period (default: {None}) Returns: dict -- obv data object """ plot_output = kwargs.get('plot_output', True) filter_factor = kwargs.get('filter_factor', 2.5) sma_interval = kwargs.get('sma_interval', 20) name = kwargs.get('name', '') progress_bar = kwargs.get('progress_bar') view = kwargs.get('view') obv_dict = dict() obv = generate_obv_signal(fund) obv_dict['obv'] = obv if progress_bar is not None: progress_bar.uptick(increment=0.125) ofilter, features = obv_feature_detection(obv, fund, sma_interval=sma_interval, filter_factor=filter_factor, progress_bar=progress_bar, plot_output=plot_output) obv_dict['tabular'] = ofilter obv_dict['signals'] = features if progress_bar is not None: progress_bar.uptick(increment=0.125) volume = [] volume.append(fund['Volume'][0]) for i in range(1, len(fund['Volume'])): if fund['Close'][i] - fund['Close'][i - 1] < 0: volume.append(-1.0 * fund['Volume'][i]) else: volume.append(fund['Volume'][i]) x = dates_extractor_list(fund) name3 = INDEXES.get(name, name) name2 = name3 + ' - On Balance Volume (OBV)' name4 = name3 + ' - Significant OBV Changes' name5 = name3 + ' - Volume' if plot_output: dual_plotting(fund['Close'], obv, x=x, y1_label='Position Price', y2_label='On Balance Volume', x_label='Trading Days', title=name2, subplot=True) dual_plotting(fund['Close'], ofilter, x=x, y1_label='Position Price', y2_label='OBV-DIFF', x_label='Trading Days', title=name4, subplot=True) bar_chart(volume, x=x, position=fund, title=name5, all_positive=True) else: filename = os.path.join(name, view, f"obv_diff_{name}.png") filename2 = os.path.join(name, view, f"obv_standard_{name}.png") filename3 = os.path.join(name, view, f"volume_{name}.png") bar_chart(volume, x=x, position=fund, title=name5, saveFig=True, filename=filename3, all_positive=True) bar_chart(ofilter, x=x, position=fund, title=name4, saveFig=True, filename=filename) dual_plotting(fund['Close'], obv, x=x, y1_label='Position Price', y2_label='On Balance Volume', x_label='Trading Days', title=name2, saveFig=True, filename=filename2) if progress_bar is not None: progress_bar.uptick(increment=0.125) obv_dict['length_of_data'] = len(obv_dict['tabular']) return obv_dict
def relative_strength(primary_name: str, full_data_dict: dict, **kwargs) -> list: """Relative Strength Compare a fund vs. market, sector, and/or other fund Arguments: primary_name {str} -- primary fund to compare against full_data_dict {dict} -- all retrieved funds by fund name Optional Args: secondary_fund_names {list} -- fund names to compare against (default: {[]}) meta {dict} -- "metadata" from api calls (default: {None}) config {dict} -- control config dictionary of software package (default: {None}) sector {str} -- sector fund (if in full_data_dict) for comparison (default: {''}) plot_output {bool} -- True to render plot in realtime (default: {True}) progress_bar {ProgressBar} -- (default: {None}) view {str} -- Directory of plots (default: {''}) Returns: list -- dict containing all relative strength information, sector match data """ secondary_fund_names = kwargs.get('secondary_fund_names', []) config = kwargs.get('config', None) sector = kwargs.get('sector', '') plot_output = kwargs.get('plot_output', True) progress_bar = kwargs.get('progress_bar', None) meta = kwargs.get('meta', None) sector_data = kwargs.get('sector_data', {}) view = kwargs.get('view', '') period = kwargs.get('period', '2y') interval = kwargs.get('interval', '1d') sector_bench = None comp_funds = [] comp_data = {} if meta is not None: match = meta.get('info', {}).get('sector') if match is not None: fund_len = { 'length': len(full_data_dict[primary_name]['Close']), 'start': full_data_dict[primary_name].index[0], 'end': full_data_dict[primary_name].index[ len(full_data_dict[primary_name]['Close']) - 1], 'dates': full_data_dict[primary_name].index } match_fund, match_data = api_sector_match(match, config, fund_len=fund_len, period=period, interval=interval) if match_fund is not None: comp_funds, comp_data = api_sector_funds(match_fund, config, fund_len=fund_len, period=period, interval=interval) if match_data is None: match_data = full_data_dict sector = match_fund sector_data = match_data sector_bench = match_data[match_fund] if progress_bar is not None: progress_bar.uptick(increment=0.3) r_strength = dict() rat_sp = [] rat_sector = [] rat_secondaries = [] secondary_names = [] secondary_fund_names.extend(comp_funds) for key in comp_data: if sector_data.get(key) is None: sector_data[key] = comp_data[key] sp = get_SP500_df(full_data_dict) if sp is not None: rat_sp = normalized_ratio(full_data_dict[primary_name], sp) if progress_bar is not None: progress_bar.uptick(increment=0.1) if len(sector_data) > 0: rat_sector = normalized_ratio(full_data_dict[primary_name], sector_data[sector]) if progress_bar is not None: progress_bar.uptick(increment=0.1) if len(secondary_fund_names) > 0: for sfund in secondary_fund_names: if full_data_dict.get(sfund) is not None: rat_secondaries.append( normalized_ratio(full_data_dict[primary_name], full_data_dict[sfund])) secondary_names.append(sfund) elif sector_data.get(sfund) is not None: rat_secondaries.append( normalized_ratio(full_data_dict[primary_name], sector_data[sfund])) secondary_names.append(sfund) if progress_bar is not None: progress_bar.uptick(increment=0.2) st = period_strength(primary_name, full_data_dict, config=config, periods=[20, 50, 100], sector=sector, sector_data=sector_data.get(sector, None)) r_strength['market'] = {'tabular': rat_sp, 'comparison': 'S&P500'} r_strength['sector'] = {'tabular': rat_sector, 'comparison': sector} r_strength['period'] = st r_strength['secondary'] = [{ 'tabular': second, 'comparison': secondary_names[i] } for i, second in enumerate(rat_secondaries)] dates = dates_extractor_list(full_data_dict[list( full_data_dict.keys())[0]]) if len(rat_sp) < len(dates): dates = dates[0:len(rat_sp)] output_data = [] legend = [] if len(rat_sp) > 0: output_data.append(rat_sp) legend.append("vs. S&P 500") if len(rat_sector) > 0: output_data.append(rat_sector) legend.append(f"vs. Sector ({sector})") if len(rat_secondaries) > 0: for i, rat in enumerate(rat_secondaries): output_data.append(rat) legend.append(f"vs. {secondary_names[i]}") r_strength['tabular'] = {} for i, out_data in enumerate(output_data): r_strength['tabular'][str(legend[i])] = out_data primary_name2 = INDEXES.get(primary_name, primary_name) title = f"Relative Strength of {primary_name2}" if progress_bar is not None: progress_bar.uptick(increment=0.1) if plot_output: generic_plotting(output_data, x=dates, title=title, legend=legend, ylabel='Difference Ratio') else: filename = os.path.join(primary_name, view, f"relative_strength_{primary_name}.png") generic_plotting(output_data, x=dates, title=title, saveFig=True, filename=filename, legend=legend, ylabel='Difference Ratio') if progress_bar is not None: progress_bar.uptick(increment=0.2) return r_strength, sector_bench
def composite_index(data: dict, sectors: list, index_dict: dict, plot_output=True, bond_type='Treasury', index_type='BND', **kwargs): """Composite Index Arguments: data {dict} -- Data of composites sectors {list} -- sector list index_dict {dict} -- data pulled from sectors.json file (can be None) Keyword Arguments: plot_output {bool} -- (default: {True}) bond_type {str} -- (default: {'Treasury'}) index_type {str} -- (default: {'BND'}) Optional Args: clock {uint64_t} -- timekeeping for prog_bar (default: {None}) Returns: list -- composite signal, plots, dates """ clock = kwargs.get('clock') progress = len(sectors) + 2 p = ProgressBar( progress, name=f'{bond_type} Bond Composite Index', offset=clock) p.start() composite = [] for tick in sectors: if tick != index_type: cluster = cluster_oscs( data[tick], plot_output=False, function='market', wma=False) graph = cluster['tabular'] p.uptick() composite.append(graph) composite2 = [] for i in range(len(composite[0])): s = 0.0 for j in range(len(composite)): s += float(composite[j][i]) composite2.append(s) p.uptick() composite2 = windowed_moving_avg(composite2, 3, data_type='list') max_ = np.max(np.abs(composite2)) composite2 = [x / max_ for x in composite2] key = list(data.keys())[0] data_to_plot = bond_type_index_generator( data, index_dict, bond_type=bond_type) dates = dates_extractor_list(data[key]) if plot_output: dual_plotting(data_to_plot, composite2, y1_label=index_type, y2_label='BCI', title=f'{bond_type} Bond Composite Index') else: dual_plotting(data_to_plot, composite2, y1_label=index_type, y2_label='BCI', title=f'{bond_type} Bond Composite Index', x=dates, saveFig=True, filename=f'{bond_type}_BCI.png') p.uptick() return composite2, data_to_plot, dates
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