Пример #1
0
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
Пример #2
0
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
Пример #4
0
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