コード例 #1
0
def triple_moving_average(fund: pd.DataFrame, **kwargs) -> dict:
    """Triple Moving Average

    3 simple moving averages of "config" length

    Arguments:
        fund {pd.DataFrame} -- fund historical data

    Optional Args:
        name {list} -- name of fund, primarily for plotting (default: {''})
        plot_output {bool} -- True to render plot in realtime (default: {True})
        config {list of ints} -- list of moving average time periods (default: {[12, 50, 200]})
        progress_bar {ProgressBar} -- (default: {None})
        view {str} -- directory of plots (default: {''})

    Returns:
        tma {dict} -- contains all ma information in "short", "medium", and "long" keys
    """
    name = kwargs.get('name', '')
    config = kwargs.get('config', [12, 50, 200])
    plot_output = kwargs.get('plot_output', True)
    out_suppress = kwargs.get('out_suppress', False)
    progress_bar = kwargs.get('progress_bar', None)
    view = kwargs.get('view', '')

    tshort = simple_moving_avg(fund, config[0])
    if progress_bar is not None:
        progress_bar.uptick(increment=0.2)

    tmed = simple_moving_avg(fund, config[1])
    if progress_bar is not None:
        progress_bar.uptick(increment=0.2)

    tlong = simple_moving_avg(fund, config[2])
    if progress_bar is not None:
        progress_bar.uptick(increment=0.2)

    mshort = []
    mmed = []
    mlong = []
    for i, close in enumerate(fund['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))

    triple_exp_mov_average(fund,
                           config=[9, 21, 50],
                           plot_output=plot_output,
                           name=name,
                           view=view)

    tshort_x, tshort2 = adjust_signals(fund, tshort, offset=config[0])
    tmed_x, tmed2 = adjust_signals(fund, tmed, offset=config[1])
    tlong_x, tlong2 = adjust_signals(fund, tlong, offset=config[2])

    plot_short = {
        "plot": tshort2,
        "color": "blue",
        "legend": f"{config[0]}-day MA",
        "x": tshort_x
    }
    plot_med = {
        "plot": tmed2,
        "color": "orange",
        "legend": f"{config[1]}-day MA",
        "x": tmed_x
    }
    plot_long = {
        "plot": tlong2,
        "color": "black",
        "legend": f"{config[2]}-day MA",
        "x": tlong_x
    }

    if not out_suppress:
        name3 = INDEXES.get(name, name)
        name2 = name3 + \
            ' - Simple Moving Averages [{}, {}, {}]'.format(
                config[0], config[1], config[2])
        # legend = ['Price', f'{config[0]}-SMA',
        #           f'{config[1]}-SMA', f'{config[2]}-SMA']

        # plots = [fund['Close'], tshort2, tmed2, tlong2]
        # x_vals = [fund.index, tshort_x, tmed_x, tlong_x]

        if plot_output:
            candlestick_plot(fund,
                             title=name2,
                             additional_plts=[plot_short, plot_med, plot_long])
            # generic_plotting(plots, x=x_vals,
            #                  legend=legend, title=name2)

        else:
            filename = os.path.join(name, view,
                                    f"simple_moving_averages_{name}.png")
            candlestick_plot(fund,
                             title=name2,
                             filename=filename,
                             saveFig=True,
                             additional_plts=[plot_short, plot_med, plot_long])
            # generic_plotting(plots, x=x_vals,
            #                  legend=legend, title=name2, saveFig=True, filename=filename)

    tma = dict()
    tma['short'] = {'period': config[0]}
    tma['medium'] = {'period': config[1]}
    tma['long'] = {'period': config[2]}
    tma['tabular'] = {'short': tshort, 'medium': tmed, 'long': tlong}
    tma['metrics'] = {
        f'{config[0]}-d': mshort,
        f'{config[1]}-d': mmed,
        f'{config[2]}-d': mlong
    }

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

    tma['type'] = 'trend'
    tma['length_of_data'] = len(tma['tabular']['short'])
    tma['signals'] = find_crossovers(tma, fund)

    return tma
コード例 #2
0
def triple_exp_mov_average(fund: pd.DataFrame,
                           config=[9, 20, 50],
                           **kwargs) -> list:
    """Triple Exponential Moving Average

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

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

    Keyword Arguments:
        config {list} -- look back period (default: {[9, 13, 50]})

    Returns:
        list -- plots and signals
    """
    plot_output = kwargs.get('plot_output', True)
    name = kwargs.get('name', '')
    view = kwargs.get('view', '')
    p_bar = kwargs.get('progress_bar')
    out_suppress = kwargs.get('out_suppress', False)

    tema = dict()

    tshort = exponential_moving_avg(fund, config[0])
    if p_bar is not None:
        p_bar.uptick(increment=0.2)

    tmed = exponential_moving_avg(fund, config[1])
    if p_bar is not None:
        p_bar.uptick(increment=0.2)

    tlong = exponential_moving_avg(fund, config[2])
    if p_bar is not None:
        p_bar.uptick(increment=0.2)

    tema['tabular'] = {'short': tshort, 'medium': tmed, 'long': tlong}
    tema['short'] = {"period": config[0]}
    tema['medium'] = {"period": config[1]}
    tema['long'] = {"period": config[2]}

    tshort_x, tshort2 = adjust_signals(fund, tshort, offset=config[0])
    tmed_x, tmed2 = adjust_signals(fund, tmed, offset=config[1])
    tlong_x, tlong2 = adjust_signals(fund, tlong, offset=config[2])

    plot_short = {
        "plot": tshort2,
        "color": "blue",
        "legend": f"{config[0]}-day MA",
        "x": tshort_x
    }
    plot_med = {
        "plot": tmed2,
        "color": "orange",
        "legend": f"{config[1]}-day MA",
        "x": tmed_x
    }
    plot_long = {
        "plot": tlong2,
        "color": "black",
        "legend": f"{config[2]}-day MA",
        "x": tlong_x
    }

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

    for i, close in enumerate(fund['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))

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

    tema['metrics'] = {
        f'{config[0]}-d': mshort,
        f'{config[1]}-d': mmed,
        f'{config[2]}-d': mlong
    }

    if not out_suppress:
        name3 = INDEXES.get(name, name)
        name2 = name3 + \
            ' - Exp Moving Averages [{}, {}, {}]'.format(
                config[0], config[1], config[2])
        # legend = ['Price', f'{config[0]}-EMA',
        #           f'{config[1]}-EMA', f'{config[2]}-EMA']

        # plots = [fund['Close'], tshort2, tmed2, tlong2]
        # x_vals = [fund.index, tshort_x, tmed_x, tlong_x]

        if plot_output:
            candlestick_plot(fund,
                             title=name2,
                             additional_plts=[plot_short, plot_med, plot_long])
            # generic_plotting(plots, x=x_vals,
            #                  legend=legend, title=name2)

        else:
            filename = os.path.join(name, view,
                                    f"exp_moving_averages_{name}.png")
            candlestick_plot(fund,
                             title=name2,
                             filename=filename,
                             saveFig=True,
                             additional_plts=[plot_short, plot_med, plot_long])
            # generic_plotting(plots, x=x_vals,
            #                  legend=legend, title=name2, saveFig=True, filename=filename)

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

    tema['type'] = 'trend'
    tema['length_of_data'] = len(tema['tabular']['short'])
    tema['signals'] = find_crossovers(tema, fund)

    return tema
コード例 #3
0
def generate_sar(fund: pd.DataFrame, **kwargs) -> dict:
    """Generate Stop and Reverse (SAR) Signal

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

    Optional Args:
        af {list} -- acceleration factor (default: {[0.02, 0.01]})
        max_factor {float} -- max acceleration factor (default: {0.2})
        period_offset {int} -- lookback period to establish a trend in starting
                                (default: {5})
        plot_output {bool} -- (default: {True})
        name {str} -- (default: {''})
        view {str} -- (default: {''})
        p_bar {ProgressBar} -- (default: {None})

    Returns:
        dict -- sar data object; signals (different AFs)
    """
    # Note, higher/faster AF should be first of 2
    ACC_FACTOR = kwargs.get('af', [0.02, 0.01])
    MAX_FACTOR = kwargs.get('max_factor', 0.2)
    period_offset = kwargs.get('period_offset', 5)

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

    sar_dict = dict()

    signals = {"fast": [], "slow": []}
    sig_names = ["fast", "slow"]
    colors = ["blue", "black"]
    indicators = []

    signal = [0.0] * len(fund['Close'])
    auto = autotrend(fund['Close'], periods=[4])

    # Observe for an 'offset' amount of time before starting
    ep_high = 0.0
    ep_low = float('inf')
    for i in range(period_offset):
        signal[i] = fund['Close'][i]

        if fund['Low'][i] < ep_low:
            ep_low = fund['Low'][i]

        if fund['High'][i] > ep_high:
            ep_high = fund['High'][i]

    # Determine an initial trend to start
    trend = 'down'
    e_p = ep_low
    signal[period_offset - 1] = ep_high

    if auto[period_offset - 1] > 0.0:
        trend = 'up'
        e_p = ep_high
        signal[period_offset - 1] = ep_low

    add_plts = []

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

    # Begin generating SAR signal, number of signals determined by number of AFs
    for k, afx in enumerate(ACC_FACTOR):
        a_f = afx

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

            if trend == 'down':
                sar_i = signal[i - 1] - a_f * (signal[i - 1] - e_p)
                if fund['High'][i] > sar_i:
                    # Broken downward trend. Stop and reverse!
                    a_f = afx
                    sar_i = e_p
                    e_p = fund['High'][i]
                    trend = 'up'
                    data = {
                        "type": 'bullish',
                        "value": f'downtrend broken-{sig_names[k]}',
                        "index": i,
                        "date": date
                    }

                else:
                    if fund['Low'][i] < e_p:
                        e_p = fund['Low'][i]
                        a_f += afx
                        if a_f > MAX_FACTOR:
                            a_f = MAX_FACTOR

            else:
                sar_i = signal[i - 1] + a_f * (e_p - signal[i - 1])
                if fund['Low'][i] < sar_i:
                    # Broken upward trend.  Stop and reverse!
                    a_f = afx
                    sar_i = e_p
                    e_p = fund['Low'][i]
                    trend = 'down'
                    data = {
                        "type": 'bearish',
                        "value": f'upward broken-{sig_names[k]}',
                        "index": i,
                        "date": date
                    }

                else:
                    if fund['High'][i] > e_p:
                        e_p = fund['High'][i]
                        a_f += afx
                        if a_f > MAX_FACTOR:
                            a_f = MAX_FACTOR

            signal[i] = sar_i

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

        signals[sig_names[k]] = signal.copy()
        add_plts.append({
            "plot": signals[sig_names[k]],
            "style": 'scatter',
            "legend": f'Parabolic SAR-{sig_names[k]}',
            "color": colors[k]
        })

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

    name2 = INDEXES.get(name, name)
    title = f"{name2} - Parabolic SAR"

    if plot_output:
        candlestick_plot(fund, additional_plts=add_plts, title=title)
    else:
        filename = os.path.join(name, view, f"parabolic_sar_{name}")
        candlestick_plot(fund,
                         additional_plts=add_plts,
                         title=title,
                         saveFig=True,
                         filename=filename)

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

    sar_dict['tabular'] = signals
    sar_dict['signals'] = indicators

    return sar_dict