예제 #1
0
def view_ma(
    series: pd.Series,
    length: List[int] = None,
    offset: int = 0,
    ma_type: str = "EMA",
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
) -> None:
    """Plots MA technical indicator

    Parameters
    ----------
    series : pd.Series
        Series of prices
    length : List[int]
        Length of EMA window
    ma_type: str
        Type of moving average.  Either "EMA" "ZLMA" or "SMA"
    s_ticker : str
        Ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (1 axis is expected in the list), by default None
    """
    # Define a dataframe for adding EMA series to it
    price_df = pd.DataFrame(series)

    l_legend = [s_ticker]
    if not length:
        length = [20, 50]

    for win in length:
        if ma_type == "EMA":
            df_ta = overlap_model.ema(series, win, offset)
            l_legend.append(f"EMA {win}")
        elif ma_type == "SMA":
            df_ta = overlap_model.sma(series, win, offset)
            l_legend.append(f"SMA {win}")
        elif ma_type == "WMA":
            df_ta = overlap_model.wma(series, win, offset)
            l_legend.append(f"WMA {win}")
        elif ma_type == "HMA":
            df_ta = overlap_model.hma(series, win, offset)
            l_legend.append(f"HMA {win}")
        elif ma_type == "ZLMA":
            df_ta = overlap_model.zlma(series, win, offset)
            l_legend.append(f"ZLMA {win}")
        price_df = price_df.join(df_ta)

    plot_data = reindex_dates(price_df)

    # This plot has 1 axis
    if external_axes is None:
        _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    else:
        if len(external_axes) != 1:
            console.print("[red]Expected list of one axis item./n[/red]")
            return
        (ax, ) = external_axes

    ax.plot(plot_data.index, plot_data.iloc[:, 1].values)
    ax.set_xlim([plot_data.index[0], plot_data.index[-1]])
    ax.set_ylabel(f"{s_ticker} Price")
    for idx in range(2, plot_data.shape[1]):
        ax.plot(plot_data.iloc[:, idx])

    ax.set_title(f"{s_ticker} {ma_type.upper()}")
    ax.legend(l_legend)
    theme.style_primary_axis(
        ax,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        f"{ma_type.lower()}{'_'.join([str(win) for win in length])}",
        price_df,
    )
예제 #2
0
def display_adosc(
    ohlc: pd.DataFrame,
    fast: int = 3,
    slow: int = 10,
    use_open: bool = False,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Display AD Osc Indicator

    Parameters
    ----------
    ohlc : pd.DataFrame
        Dataframe of prices
    use_open : bool
        Whether to use open prices in calculation
    fast: int
         Length of fast window
    slow : int
        Length of slow window
    s_ticker : str
        Stock ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (3 axes is expected in the list), by default None
    """
    divisor = 1_000_000
    df_vol = ohlc["Volume"] / divisor
    df_vol.name = "Adj Volume"
    df_ta = volume_model.adosc(ohlc, use_open, fast, slow)
    df_cal = df_ta[df_ta.columns[0]] / divisor
    df_cal.name = "Adj ADOSC"

    plot_data = pd.merge(ohlc,
                         df_vol,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = pd.merge(plot_data,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = pd.merge(plot_data,
                         df_cal,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 3 axes
    if external_axes is None:
        _, axes = plt.subplots(
            3,
            1,
            sharex=True,
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
        ax1, ax2, ax3 = axes
    else:
        if len(external_axes) != 3:
            console.print("[red]Expected list of 3 axis items./n[/red]")
            return
        (ax1, ax2, ax3) = external_axes

    ax1.set_title(f"{s_ticker} AD Oscillator")
    ax1.plot(plot_data.index, plot_data["Adj Close"].values)
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Price")
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.set_ylabel("Volume [M]")
    bar_colors = [
        theme.down_color if x[1].Open < x[1].Close else theme.up_color
        for x in plot_data.iterrows()
    ]
    ax2.bar(
        plot_data.index,
        plot_data["Adj Volume"],
        color=bar_colors,
        width=theme.volume_bar_width,
    )
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax3.set_ylabel("AD Osc [M]")
    ax3.plot(plot_data.index, plot_data["Adj ADOSC"], label="AD Osc")
    ax3.set_xlim(plot_data.index[0], plot_data.index[-1])
    theme.style_primary_axis(
        ax3,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "adosc",
        df_ta,
    )
예제 #3
0
def display_aroon(
    ohlc: pd.DataFrame,
    length: int = 25,
    scalar: int = 100,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Plot Aroon indicator

    Parameters
    ----------
    ohlc : pd.DataFrame
        Dataframe with OHLC price data
    length:int
        Length of window
    s_ticker : str
        Ticker
    scalar : int
        Scalar variable
    export: str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (3 axes are expected in the list), by default None
    """
    df_ta = trend_indicators_model.aroon(
        high_values=ohlc["High"],
        low_values=ohlc["Low"],
        length=length,
        scalar=scalar,
    )
    plot_data = pd.merge(ohlc,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 3 axes
    if not external_axes:
        _, axes = plt.subplots(3,
                               1,
                               sharex=True,
                               figsize=plot_autoscale(),
                               dpi=PLOT_DPI)
        ax1, ax2, ax3 = axes
    else:
        if len(external_axes) != 3:
            console.print("[red]Expected list of 3 axis items./n[/red]")
            return
        ax1, ax2, ax3 = external_axes

    ax1.plot(plot_data.index, plot_data["Adj Close"].values)
    ax1.set_title(f"Aroon on {s_ticker}")
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Share Price ($)")
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.plot(plot_data.index, plot_data[df_ta.columns[0]].values,
             theme.down_color)
    ax2.plot(plot_data.index, plot_data[df_ta.columns[1]].values,
             theme.up_color)
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax2.axhline(50, ls="--")
    ax2.legend(
        [f"Aroon DOWN ({df_ta.columns[0]})", f"Aroon UP ({df_ta.columns[1]})"])
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax3.plot(plot_data.index, plot_data[df_ta.columns[2]].values)
    ax3.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax3.legend([f"Aroon OSC ({df_ta.columns[2]})"])
    ax3.set_ylim([-100, 100])
    theme.style_primary_axis(
        ax3,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "aroon",
        df_ta,
    )
예제 #4
0
def fibonacci_retracement(
    ohlc: pd.DataFrame,
    period: int = 120,
    start_date: Optional[Union[str, None]] = None,
    end_date: Optional[Union[str, None]] = None,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Calculate fibonacci retracement levels

    Parameters
    ----------
    ohlc: pd.DataFrame
        Stock data
    period: int
        Days to lookback
    start_date: Optional[str, None]
        User picked date for starting retracement
    end_date: Optional[str, None]
        User picked date for ending retracement
    s_ticker:str
        Stock ticker
    export: str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axis is expected in the list), by default None
    """
    (
        df_fib,
        min_date,
        max_date,
        min_pr,
        max_pr,
    ) = custom_indicators_model.calculate_fib_levels(ohlc, period, start_date,
                                                     end_date)

    levels = df_fib.Price

    plot_data = reindex_dates(ohlc)

    # This plot has 1 axes
    if external_axes is None:
        _, ax1 = plt.subplots(
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
        ax2 = ax1.twinx()
    else:
        if len(external_axes) != 1:
            logger.error("Expected list of one axis item.")
            console.print("[red]Expected list of 1 axis item./n[/red]")
            return
        ax1, ax2 = external_axes

    ax1.plot(plot_data["Adj Close"])

    if is_intraday(ohlc):
        date_format = "%b %d %H:%M"
    else:
        date_format = "%Y-%m-%d"
    min_date_index = plot_data[plot_data["date"] == min_date.strftime(
        date_format)].index
    max_date_index = plot_data[plot_data["date"] == max_date.strftime(
        date_format)].index
    ax1.plot(
        [min_date_index, max_date_index],
        [min_pr, max_pr],
    )

    for i in levels:
        ax1.axhline(y=i, alpha=0.5)

    for i in range(5):
        ax1.fill_between(plot_data.index, levels[i], levels[i + 1], alpha=0.15)

    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_title(f"Fibonacci Support for {s_ticker.upper()}")
    ax1.set_yticks(levels)
    ax1.set_yticklabels([0, 0.235, 0.382, 0.5, 0.618, 1])
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.set_ylim(ax1.get_ylim())
    ax2.set_ylabel("Price")
    theme.style_primary_axis(ax2)

    if external_axes is None:
        theme.visualize_output()
        print_rich_table(
            df_fib,
            headers=["Fib Level", "Price"],
            show_index=False,
            title="Fibonacci retracement levels",
        )
        console.print("")

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "fib",
        df_fib,
    )
예제 #5
0
def view_kc(
    ohlc: pd.DataFrame,
    length: int = 20,
    scalar: float = 2,
    mamode: str = "ema",
    offset: int = 0,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """View Keltner Channels Indicator

    Parameters
    ----------

    ohlc : pd.DataFrame
        Dataframe of stock prices
    length : int
        Length of window
    mamode: str
        Type of filter
    offset : int
        Offset value
    s_ticker : str
        Ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axes are expected in the list), by default None
    """
    df_ta = volatility_model.kc(
        ohlc["High"],
        ohlc["Low"],
        ohlc["Adj Close"],
        length,
        scalar,
        mamode,
        offset,
    )
    plot_data = pd.merge(ohlc,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 1 axis
    if external_axes is None:
        _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    else:
        if len(external_axes) != 1:
            console.print("[red]Expected list of 1 axis item./n[/red]")
            return
        (ax, ) = external_axes

    ax.plot(plot_data.index, plot_data["Adj Close"].values)
    ax.plot(
        plot_data.index,
        plot_data[df_ta.columns[0]].values,
        linewidth=0.7,
        label="Upper",
    )
    ax.plot(plot_data.index,
            plot_data[df_ta.columns[1]].values,
            linewidth=0.7,
            ls="--")
    ax.plot(
        plot_data.index,
        plot_data[df_ta.columns[2]].values,
        linewidth=0.7,
        label="Lower",
    )
    ax.fill_between(
        plot_data.index,
        plot_data[df_ta.columns[0]].values,
        plot_data[df_ta.columns[2]].values,
        alpha=0.1,
    )
    ax.set_title(f"{s_ticker} Keltner Channels")
    ax.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax.set_ylabel("Price")
    ax.legend([s_ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
    theme.style_primary_axis(
        ax,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "kc",
        df_ta,
    )
예제 #6
0
def display_spread(
    name: str,
    df: pd.DataFrame,
    target: str,
    window: int,
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """View rolling spread

    Parameters
    ----------
    name : str
        Stock ticker
    df : pd.DataFrame
        Dataframe
    target: str
        Column in data to look at
    window : int
        Length of window
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (3 axes are expected in the list), by default None
    """
    data = df[target]
    df_sd, df_var = rolling_model.get_spread(data, window)

    plot_data = pd.merge(
        data,
        df_sd,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_sd"),
    )
    plot_data = pd.merge(
        plot_data,
        df_var,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_var"),
    )
    plot_data = reindex_dates(plot_data)

    # This plot has 1 axis
    if external_axes is None:
        _, axes = plt.subplots(
            3,
            1,
            sharex=True,
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
        (ax1, ax2, ax3) = axes
    else:
        if len(external_axes) != 3:
            logger.error("Expected list of one axis item.")
            console.print("[red]Expected list of 1 axis items./n[/red]")
            return
        (ax1, ax2, ax3) = external_axes

    ax1.plot(plot_data.index, plot_data[target].values)
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Value")
    ax1.set_title(f"Spread of {name} {target}")

    ax2.plot(
        plot_data[f"STDEV_{window}"].index,
        plot_data[f"STDEV_{window}"].values,
        label="Stdev",
    )
    ax2.set_ylabel("Stdev")

    ax3.plot(
        plot_data[f"VAR_{window}"].index,
        plot_data[f"VAR_{window}"].values,
        label="Variance",
    )
    ax3.set_ylabel("Variance")

    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )
    theme.style_primary_axis(
        ax3,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "spread",
        df_sd.join(df_var, lsuffix="_sd", rsuffix="_var"),
    )
예제 #7
0
def display_cci(
    ohlc: pd.DataFrame,
    length: int = 14,
    scalar: float = 0.0015,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Display CCI Indicator

    Parameters
    ----------

    ohlc : pd.DataFrame
        Dataframe of OHLC
    length : int
        Length of window
    scalar : float
        Scalar variable
    s_ticker : str
        Stock ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axes are expected in the list), by default None
    """
    df_ta = momentum_model.cci(ohlc["High"], ohlc["Low"], ohlc["Adj Close"],
                               length, scalar)
    plot_data = pd.merge(ohlc,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 2 axes
    if external_axes is None:
        _, (ax1, ax2) = plt.subplots(2,
                                     1,
                                     figsize=plot_autoscale(),
                                     sharex=True,
                                     dpi=PLOT_DPI)
    else:
        if len(external_axes) != 2:
            logger.error("Expected list of two axis items.")
            console.print("[red]Expected list of 2 axis items./n[/red]")
            return
        ax1, ax2 = external_axes

    ax1.set_title(f"{s_ticker} CCI")
    ax1.plot(
        plot_data.index,
        plot_data["Adj Close"].values,
    )
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Share Price ($)")

    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.plot(plot_data.index, plot_data[df_ta.columns[0]].values)
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax2.axhspan(100, ax2.get_ylim()[1], facecolor=theme.down_color, alpha=0.2)
    ax2.axhspan(ax2.get_ylim()[0], -100, facecolor=theme.up_color, alpha=0.2)

    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax3 = ax2.twinx()
    ax3.set_ylim(ax2.get_ylim())
    ax3.axhline(100, color=theme.down_color, ls="--")
    ax3.axhline(-100, color=theme.up_color, ls="--")

    theme.style_twin_axis(ax3)

    ax2.set_yticks([-100, 100])
    ax2.set_yticklabels(["OVERSOLD", "OVERBOUGHT"])

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "cci",
        df_ta,
    )
def display_adx(
    ohlc: pd.DataFrame,
    length: int = 14,
    scalar: int = 100,
    drift: int = 1,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Plot ADX indicator

    Parameters
    ----------
    ohlc : pd.DataFrame
        Dataframe with OHLC price data
    length : int
        Length of window
    scalar : int
        Scalar variable
    drift : int
        Drift variable
    s_ticker : str
        Ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axes are expected in the list), by default None
    """
    df_ta = trend_indicators_model.adx(
        high_values=ohlc["High"],
        low_values=ohlc["Low"],
        close_values=ohlc["Adj Close"],
        length=length,
        scalar=scalar,
        drift=drift,
    )
    plot_data = pd.merge(ohlc, df_ta, how="outer", left_index=True, right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 2 axes
    if not external_axes:
        _, axes = plt.subplots(
            2, 1, sharex=True, figsize=plot_autoscale(), dpi=PLOT_DPI
        )
        ax1, ax2 = axes
    else:
        if len(external_axes) != 2:
            logger.error("Expected list of two axis items.")
            console.print("[red]Expected list of 2 axis items./n[/red]")
            return
        ax1, ax2 = external_axes

    ax1.plot(plot_data.index, plot_data["Close"].values)
    ax1.set_title(f"Average Directional Movement Index (ADX) on {s_ticker}")
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Share Price ($)")
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.plot(plot_data.index, plot_data[df_ta.columns[0]].values)
    ax2.plot(plot_data.index, plot_data[df_ta.columns[1]].values, color=theme.up_color)
    ax2.plot(
        plot_data.index, plot_data[df_ta.columns[2]].values, color=theme.down_color
    )
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax2.axhline(25, ls="--")
    ax2.legend(
        [
            f"ADX ({df_ta.columns[0]})",
            f"+DI ({df_ta.columns[1]})",
            f"-DI ({df_ta.columns[2]})",
        ]
    )
    ax2.set_ylim([0, 100])
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "adx",
        df_ta,
    )
예제 #9
0
def display_macd(
    series: pd.Series,
    n_fast: int = 12,
    n_slow: int = 26,
    n_signal: int = 9,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Plot MACD signal

    Parameters
    ----------
    series : pd.Series
        Values to input
    n_fast : int
        Fast period
    n_slow : int
        Slow period
    n_signal : int
        Signal period
    s_ticker : str
        Stock ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axes are expected in the list), by default None
    """
    df_ta = momentum_model.macd(series, n_fast, n_slow, n_signal)
    plot_data = pd.merge(series,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 2 axes
    if external_axes is None:
        _, (ax1, ax2) = plt.subplots(2,
                                     1,
                                     figsize=plot_autoscale(),
                                     sharex=True,
                                     dpi=PLOT_DPI)
    else:
        if len(external_axes) != 2:
            logger.error("Expected list of two axis items.")
            console.print("[red]Expected list of 2 axis items./n[/red]")
            return
        ax1, ax2 = external_axes

    ax1.set_title(f"{s_ticker} MACD")
    ax1.plot(plot_data.index, plot_data.iloc[:, 1].values)
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Share Price ($)")
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.plot(plot_data.index, plot_data.iloc[:, 2].values)
    ax2.plot(plot_data.index,
             plot_data.iloc[:, 4].values,
             color=theme.down_color)
    ax2.bar(
        plot_data.index,
        plot_data.iloc[:, 3].values,
        width=theme.volume_bar_width,
        color=theme.up_color,
    )
    ax2.legend([
        f"MACD Line {plot_data.columns[2]}",
        f"Signal Line {plot_data.columns[4]}",
        f"Histogram {plot_data.columns[3]}",
    ])
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "macd",
        df_ta,
    )
예제 #10
0
def display_rsi(
    series: pd.Series,
    length: int = 14,
    scalar: float = 100.0,
    drift: int = 1,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Display RSI Indicator

    Parameters
    ----------
    series : pd.Series
        Values to input
    length : int
        Length of window
    scalar : float
        Scalar variable
    drift : int
        Drift variable
    s_ticker : str
        Stock ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axes are expected in the list), by default None
    """
    df_ta = momentum_model.rsi(series, length, scalar, drift)

    # This plot has 2 axes
    if external_axes is None:
        _, (ax1, ax2) = plt.subplots(2,
                                     1,
                                     figsize=plot_autoscale(),
                                     sharex=True,
                                     dpi=PLOT_DPI)
    else:
        if len(external_axes) != 2:
            logger.error("Expected list of two axis items.")
            console.print("[red]Expected list of 2 axis items./n[/red]")
            return
        ax1, ax2 = external_axes

    plot_data = pd.merge(series,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    ax1.plot(plot_data.index, plot_data.iloc[:, 1].values)
    ax1.set_title(f"{s_ticker} RSI{length}")
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Share Price ($)")
    theme.style_primary_axis(
        ax=ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.plot(plot_data.index, plot_data[df_ta.columns[0]].values)
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax2.axhspan(0, 30, facecolor=theme.up_color, alpha=0.2)
    ax2.axhspan(70, 100, facecolor=theme.down_color, alpha=0.2)
    ax2.set_ylim([0, 100])

    theme.style_primary_axis(
        ax=ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax3 = ax2.twinx()
    ax3.set_ylim(ax2.get_ylim())
    ax3.axhline(30, color=theme.up_color, ls="--")
    ax3.axhline(70, color=theme.down_color, ls="--")
    ax2.set_yticks([30, 70])
    ax2.set_yticklabels(["OVERSOLD", "OVERBOUGHT"])

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "rsi",
        df_ta,
    )
예제 #11
0
def display_kurtosis(
    name: str,
    df: pd.DataFrame,
    target: str,
    window: int,
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """View rolling kurtosis

    Parameters
    ----------
    name : str
        Ticker
    df : pd.DataFrame
        Dataframe of stock prices
    window : int
        Length of window
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axes are expected in the list), by default None
    """
    data = df[target]
    df_kurt = rolling_model.get_kurtosis(data, window)

    plot_data = pd.merge(
        data,
        df_kurt,
        how="outer",
        left_index=True,
        right_index=True,
    )
    plot_data = reindex_dates(plot_data)

    # This plot has 1 axis
    if external_axes is None:
        _, axes = plt.subplots(
            2,
            1,
            sharex=True,
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
        (ax1, ax2) = axes
    else:
        if len(external_axes) != 2:
            logger.error("Expected list of two axis items.")
            console.print("[red]Expected list of 2 axis items./n[/red]")
            return
        (ax1, ax2) = external_axes

    ax1.set_title(f"{name} {target} Kurtosis Indicator (window {str(window)})")
    ax1.plot(plot_data.index, plot_data[target].values)
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel(f"{target}")

    ax2.plot(
        plot_data.index,
        plot_data[f"KURT_{window}"].values,
    )
    ax2.set_ylabel("Indicator")

    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    console.print("")
    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "kurtosis",
        df_kurt,
    )
예제 #12
0
def display_quantile(
    name: str,
    df: pd.DataFrame,
    target: str,
    window: int,
    quantile: float,
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """View rolling quantile

    Parameters
    ----------
    name : str
        Stock ticker
    df : pd.DataFrame
        Dataframe
    target : str
        Column in data to look at
    window : int
        Length of window
    quantile : float
        Quantile to get
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (1 axis is expected in the list), by default None
    """
    data = df[target]
    df_med, df_quantile = rolling_model.get_quantile(data, window, quantile)

    plot_data = pd.merge(
        data,
        df_med,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_med"),
    )
    plot_data = pd.merge(
        plot_data,
        df_quantile,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_quantile"),
    )
    plot_data = reindex_dates(plot_data)

    # This plot has 1 axis
    if external_axes is None:
        _, ax = plt.subplots(
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
    else:
        if len(external_axes) != 1:
            logger.error("Expected list of one axis item.")
            console.print("[red]Expected list of 1 axis items./n[/red]")
            return
        (ax, ) = external_axes

    ax.set_title(f"{name} {target} Median & Quantile")
    ax.plot(plot_data.index, plot_data[target].values, label=target)
    ax.plot(
        plot_data.index,
        plot_data[f"MEDIAN_{window}"].values,
        label=f"Median w={window}",
    )
    ax.plot(
        plot_data.index,
        plot_data[f"QTL_{window}_{quantile}"].values,
        label=f"Quantile q={quantile}",
        linestyle="--",
    )

    ax.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax.set_ylabel(f"{name} Value")
    ax.legend()

    theme.style_primary_axis(
        ax,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "quantile",
        df_med.join(df_quantile),
    )
예제 #13
0
def display_mean_std(
    name: str,
    df: pd.DataFrame,
    target: str,
    window: int,
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """View rolling spread

    Parameters
    ----------
    name : str
        Stock ticker
    df : pd.DataFrame
        Dataframe
    target : str
        Column in data to look at
    window : int
        Length of window
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axes are expected in the list), by default None
    """
    data = df[target]
    rolling_mean, rolling_std = rolling_model.get_rolling_avg(data, window)
    plot_data = pd.merge(
        data,
        rolling_mean,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_mean"),
    )
    plot_data = pd.merge(
        plot_data,
        rolling_std,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_std"),
    )
    plot_data = reindex_dates(plot_data)

    # This plot has 2 axes
    if external_axes is None:
        _, axes = plt.subplots(
            2,
            1,
            sharex=True,
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
        ax1, ax2 = axes
    else:
        if len(external_axes) != 2:
            logger.error("Expected list of two axis items.")
            console.print("[red]Expected list of 2 axis items./n[/red]")
            return
        (ax1, ax2) = external_axes

    ax1.plot(
        plot_data.index,
        plot_data[target].values,
        label=name,
    )
    ax1.plot(
        plot_data.index,
        plot_data[target + "_mean"].values,
    )
    ax1.set_ylabel("Values", )
    ax1.legend(["Real Values", "Rolling Mean"])
    ax1.set_title(
        f"Rolling mean and std (window {str(window)}) of {name} {target}")
    ax1.set_xlim([plot_data.index[0], plot_data.index[-1]])

    ax2.plot(
        plot_data.index,
        plot_data[target + "_std"].values,
        label="Rolling std",
    )
    ax2.legend(["Rolling std"])
    ax2.set_ylabel(f"{target} Std Deviation", )

    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "rolling",
        rolling_mean.join(rolling_std, lsuffix="_mean", rsuffix="_std"),
    )
예제 #14
0
def display_obv(
    ohlc: pd.DataFrame,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Plot OBV technical indicator

    Parameters
    ----------
    ohlc : pd.DataFrame
        Dataframe of prices
    s_ticker : str
        Ticker
    export: str
        Format to export data as
    external_axes : Optional[List[plt.Axes]], optional
        External axes (1 axis is expected in the list), by default None
    """
    divisor = 1_000_000
    df_vol = ohlc["Volume"] / divisor
    df_vol.name = "Adj Volume"
    df_ta = volume_model.obv(ohlc)
    df_cal = df_ta[df_ta.columns[0]] / divisor
    df_cal.name = "Adj OBV"

    plot_data = pd.merge(ohlc,
                         df_vol,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = pd.merge(plot_data,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = pd.merge(plot_data,
                         df_cal,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 3 axes
    if external_axes is None:
        _, axes = plt.subplots(
            3,
            1,
            sharex=True,
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
        ax1, ax2, ax3 = axes
    else:
        if len(external_axes) != 3:
            console.print("[red]Expected list of 3 axis items./n[/red]")
            return
        (ax1, ax2, ax3) = external_axes

    ax1.plot(plot_data.index, plot_data["Adj Close"].values)
    ax1.set_title(f"{s_ticker} OBV")
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Price")
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax2.set_ylabel("Volume [M]")
    bar_colors = [
        theme.down_color if x[1].Open < x[1].Close else theme.up_color
        for x in plot_data.iterrows()
    ]
    ax2.bar(
        plot_data.index,
        plot_data["Adj Volume"],
        color=bar_colors,
        alpha=0.8,
        width=theme.volume_bar_width,
    )
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax3.set_ylabel("OBV [M]")
    ax3.plot(plot_data.index, plot_data["Adj OBV"])
    ax3.set_xlim(plot_data.index[0], plot_data.index[-1])
    theme.style_primary_axis(
        ax3,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "obv",
        df_ta,
    )
예제 #15
0
def display_stoch(
    ohlc: pd.DataFrame,
    fastkperiod: int = 14,
    slowdperiod: int = 3,
    slowkperiod: int = 3,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
) -> None:
    """Plot stochastic oscillator signal

    Parameters
    ----------
    ohlc : pd.DataFrame
        Dataframe of prices
    fastkperiod : int
        Fast k period
    slowdperiod : int
        Slow d period
    slowkperiod : int
        Slow k period
    s_ticker : str
        Stock ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (3 axes are expected in the list), by default None
    """
    df_ta = momentum_model.stoch(
        ohlc["High"],
        ohlc["Low"],
        ohlc["Adj Close"],
        fastkperiod,
        slowdperiod,
        slowkperiod,
    )
    # This plot has 3 axes
    if not external_axes:
        _, axes = plt.subplots(2,
                               1,
                               sharex=True,
                               figsize=plot_autoscale(),
                               dpi=PLOT_DPI)
        ax1, ax2 = axes
        ax3 = ax2.twinx()
    else:
        if len(external_axes) != 3:
            logger.error("Expected list of three axis items.")
            console.print("[red]Expected list of 3 axis items./n[/red]")
            return
        ax1, ax2, ax3 = external_axes

    plot_data = pd.merge(ohlc,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    ax1.plot(plot_data.index, plot_data["Adj Close"].values)

    ax1.set_title(
        f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}")
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Share Price ($)")
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.plot(plot_data.index, plot_data[df_ta.columns[0]].values)
    ax2.plot(plot_data.index, plot_data[df_ta.columns[1]].values, ls="--")
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax3.set_ylim(ax2.get_ylim())
    ax3.axhspan(80, 100, facecolor=theme.down_color, alpha=0.2)
    ax3.axhspan(0, 20, facecolor=theme.up_color, alpha=0.2)
    ax3.axhline(80, color=theme.down_color, ls="--")
    ax3.axhline(20, color=theme.up_color, ls="--")
    theme.style_twin_axis(ax3)

    ax2.set_yticks([20, 80])
    ax2.set_yticklabels(["OVERSOLD", "OVERBOUGHT"])
    ax2.legend([f"%K {df_ta.columns[0]}", f"%D {df_ta.columns[1]}"])

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "stoch",
        df_ta,
    )
예제 #16
0
def display_seasonal(
    name: str,
    df: pd.DataFrame,
    target: str,
    multiplicative: bool = False,
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Display seasonal decomposition data

    Parameters
    ----------
    name : str
        Name of dataset
    df : pd.DataFrame
        DataFrame
    target : str
        Column of data to look at
    multiplicative : bool
        Boolean to indicate multiplication instead of addition
    export : str
        Format to export trend and cycle df
    external_axes : Optional[List[plt.Axes]], optional
        External axes (6 axes are expected in the list), by default None
    """
    data = df[target]
    result, cycle, trend = qa_model.get_seasonal_decomposition(
        data, multiplicative)

    plot_data = pd.merge(
        data,
        result.trend,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_result.trend"),
    )
    plot_data = pd.merge(
        plot_data,
        result.seasonal,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_result.seasonal"),
    )
    plot_data = pd.merge(
        plot_data,
        result.resid,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_result.resid"),
    )
    plot_data = pd.merge(
        plot_data,
        cycle,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_cycle"),
    )
    plot_data = pd.merge(
        plot_data,
        trend,
        how="outer",
        left_index=True,
        right_index=True,
        suffixes=("", "_trend"),
    )
    plot_data = reindex_dates(plot_data)

    # This plot has 1 axis
    if external_axes is None:
        fig, axes = plt.subplots(
            4,
            1,
            sharex=True,
            figsize=plot_autoscale(),
            dpi=PLOT_DPI,
        )
        (ax1, ax2, ax3, ax4) = axes
    else:
        if len(external_axes) != 4:
            logger.error("Expected list of four axis items.")
            console.print("[red]Expected list of 4 axis items./n[/red]")
            return
        (ax1, ax2, ax3, ax4) = external_axes

    colors = iter(theme.get_colors())

    ax1.set_title(f"{name} (Time-Series) {target} seasonal decomposition")
    ax1.plot(plot_data.index,
             plot_data[target].values,
             color=next(colors),
             label="Values")
    ax1.set_xlim([plot_data.index[0], plot_data.index[-1]])
    ax1.legend()

    # Multiplicative model
    ax2.plot(plot_data["trend"], color=theme.down_color, label="Cyclic-Trend")
    ax2.plot(
        plot_data["trend_cycle"],
        color=theme.up_color,
        linestyle="--",
        label="Cycle component",
    )
    ax2.legend()

    ax3.plot(plot_data["trend_trend"],
             color=next(colors),
             label="Trend component")
    ax3.plot(plot_data["seasonal"],
             color=next(colors),
             label="Seasonal effect")
    ax3.legend()

    ax4.plot(plot_data["resid"], color=next(colors), label="Residuals")
    ax4.legend()

    theme.style_primary_axis(ax1)
    theme.style_primary_axis(ax2)
    theme.style_primary_axis(ax3)
    theme.style_primary_axis(
        ax4,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        fig.tight_layout(pad=theme.tight_layout_padding)
        fig.subplots_adjust(hspace=0.1, )
        theme.visualize_output(force_tight_layout=False)

    # From  # https://otexts.com/fpp2/seasonal-strength.html
    console.print("Time-Series Level is " + str(round(data.mean(), 2)))

    Ft = max(0, 1 - np.var(result.resid)) / np.var(result.trend + result.resid)
    console.print(f"Strength of Trend: {Ft:.4f}")

    Fs = max(
        0,
        1 - np.var(result.resid) / np.var(result.seasonal + result.resid),
    )
    console.print(f"Strength of Seasonality: {Fs:.4f}\n")

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "summary",
        cycle.join(trend),
    )
예제 #17
0
def display_fisher(
    ohlc: pd.DataFrame,
    length: int = 14,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Display Fisher Indicator

    Parameters
    ----------
    ohlc : pd.DataFrame
        Dataframe of prices
    length : int
        Length of window
    s_ticker : str
        Ticker string
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (3 axes are expected in the list), by default None
    """
    df_ta = momentum_model.fisher(ohlc["High"], ohlc["Low"], length)
    plot_data = pd.merge(ohlc,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 3 axes
    if not external_axes:
        _, axes = plt.subplots(2,
                               1,
                               sharex=True,
                               figsize=plot_autoscale(),
                               dpi=PLOT_DPI)
        ax1, ax2 = axes
        ax3 = ax2.twinx()
    else:
        if len(external_axes) != 3:
            logger.error("Expected list of three axis items.")
            console.print("[red]Expected list of 3 axis items./n[/red]")
            return
        ax1, ax2, ax3 = external_axes

    ax1.set_title(f"{s_ticker} Fisher Transform")
    ax1.plot(plot_data.index, plot_data["Adj Close"].values)
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Price")
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.plot(
        plot_data.index,
        plot_data[df_ta.columns[0]].values,
        label="Fisher",
    )
    ax2.plot(
        plot_data.index,
        plot_data[df_ta.columns[1]].values,
        label="Signal",
    )
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax3.set_ylim(ax2.get_ylim())
    ax3.axhspan(2, ax2.get_ylim()[1], facecolor=theme.down_color, alpha=0.2)
    ax3.axhspan(ax2.get_ylim()[0], -2, facecolor=theme.up_color, alpha=0.2)
    ax3.axhline(2, color=theme.down_color, ls="--")
    ax3.axhline(-2, color=theme.up_color, ls="--")
    theme.style_twin_axis(ax3)

    ax2.set_yticks([-2, 0, 2])
    ax2.set_yticklabels(["-2 STDEV", "0", "+2 STDEV"])
    ax2.legend()

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "fisher",
        df_ta,
    )
예제 #18
0
def display_donchian(
    ohlc: pd.DataFrame,
    ticker: str = "",
    upper_length: int = 20,
    lower_length: int = 20,
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Show donchian channels

    Parameters
    ----------
    ohlc : pd.DataFrame
        Dataframe of stock prices
    ticker : str
        Ticker
    upper_length : int
        Length of window to calculate upper channel
    lower_length : int
        Length of window to calculate lower channel
    export : str
        Format of export file
    external_axes : Optional[List[plt.Axes]], optional
        External axes (1 axis is expected in the list), by default None
    """
    df_ta = volatility_model.donchian(ohlc["High"], ohlc["Low"], upper_length,
                                      lower_length)
    plot_data = pd.merge(ohlc,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 1 axis
    if external_axes is None:
        _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    else:
        if len(external_axes) != 1:
            console.print("[red]Expected list of 1 axis item./n[/red]")
            return
        (ax, ) = external_axes

    ax.plot(plot_data.index, plot_data["Adj Close"].values)
    ax.plot(
        plot_data.index,
        plot_data[df_ta.columns[0]].values,
        linewidth=0.7,
        label="Upper",
    )
    ax.plot(plot_data.index,
            plot_data[df_ta.columns[1]].values,
            linewidth=0.7,
            ls="--")
    ax.plot(
        plot_data.index,
        plot_data[df_ta.columns[2]].values,
        linewidth=0.7,
        label="Lower",
    )
    ax.fill_between(
        plot_data.index,
        plot_data[df_ta.columns[0]].values,
        plot_data[df_ta.columns[2]].values,
        alpha=0.1,
    )
    ax.set_title(f"{ticker} donchian")
    ax.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax.set_ylabel("Price ($)")
    ax.legend([ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
    theme.style_primary_axis(
        ax,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "donchian",
        df_ta,
    )
예제 #19
0
def display_cg(
    series: pd.Series,
    length: int = 14,
    s_ticker: str = "",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Display center of gravity Indicator

    Parameters
    ----------
    series : pd.Series
        Series of values
    length : int
        Length of window
    s_ticker : str
        Stock ticker
    export : str
        Format to export data
    external_axes : Optional[List[plt.Axes]], optional
        External axes (2 axes are expected in the list), by default None
    """
    df_ta = momentum_model.cg(series, length)
    plot_data = pd.merge(series,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 2 axes
    if external_axes is None:
        _, (ax1, ax2) = plt.subplots(2,
                                     1,
                                     figsize=plot_autoscale(),
                                     sharex=True,
                                     dpi=PLOT_DPI)
    else:
        if len(external_axes) != 2:
            logger.error("Expected list of two axis items.")
            console.print("[red]Expected list of 2 axis items./n[/red]")
            return
        ax1, ax2 = external_axes

    ax1.set_title(f"{s_ticker} Centre of Gravity")
    ax1.plot(plot_data.index, plot_data[series.name].values)
    ax1.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax1.set_ylabel("Share Price ($)")
    theme.style_primary_axis(
        ax1,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    ax2.plot(plot_data.index, plot_data[df_ta.columns[0]].values, label="CG")
    # shift cg 1 bar forward for signal
    signal = np.roll(plot_data[df_ta.columns[0]].values, 1)
    ax2.plot(plot_data.index, signal, label="Signal")
    ax2.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax2.legend()
    theme.style_primary_axis(
        ax2,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "cg",
        df_ta,
    )
예제 #20
0
def display_bbands(
    ohlc: pd.DataFrame,
    ticker: str = "",
    length: int = 15,
    n_std: float = 2,
    mamode: str = "sma",
    export: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Show bollinger bands

    Parameters
    ----------
    ohlc : pd.DataFrame
        Dataframe of stock prices
    ticker : str
        Ticker
    length : int
        Length of window to calculate BB
    n_std : float
        Number of standard deviations to show
    mamode : str
        Method of calculating average
    export : str
        Format of export file
    external_axes : Optional[List[plt.Axes]], optional
        External axes (1 axis is expected in the list), by default None
    """
    df_ta = volatility_model.bbands(ohlc["Adj Close"], length, n_std, mamode)
    plot_data = pd.merge(ohlc,
                         df_ta,
                         how="outer",
                         left_index=True,
                         right_index=True)
    plot_data = reindex_dates(plot_data)

    # This plot has 2 axes
    if not external_axes:
        _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    else:
        if len(external_axes) != 1:
            console.print("[red]Expected list of 2 axis items./n[/red]")
            return
        (ax, ) = external_axes

    ax.plot(
        plot_data.index,
        plot_data["Adj Close"].values,
    )
    ax.plot(
        plot_data.index,
        plot_data[df_ta.columns[0]].values,
        theme.down_color,
        linewidth=0.7,
    )
    ax.plot(plot_data.index,
            plot_data[df_ta.columns[1]].values,
            ls="--",
            linewidth=0.7)
    ax.plot(
        plot_data.index,
        plot_data[df_ta.columns[2]].values,
        theme.up_color,
        linewidth=0.7,
    )
    ax.set_title(f"{ticker} Bollinger Bands")
    ax.set_xlim(plot_data.index[0], plot_data.index[-1])
    ax.set_ylabel("Share Price ($)")
    ax.legend([ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]])
    ax.fill_between(df_ta.index,
                    df_ta.iloc[:, 0].values,
                    df_ta.iloc[:, 2].values,
                    alpha=0.1)
    theme.style_primary_axis(
        ax,
        data_index=plot_data.index.to_list(),
        tick_labels=plot_data["date"].to_list(),
    )

    if external_axes is None:
        theme.visualize_output()

    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
        "bbands",
        df_ta,
    )
예제 #21
0
def show_indices(
    indices: list,
    interval: str = "1d",
    start_date: int = None,
    end_date: int = None,
    column: str = "Adj Close",
    returns: bool = False,
    store: bool = False,
    raw: bool = False,
    external_axes: Optional[List[plt.axes]] = None,
    export: str = "",
):
    """Load (and show) the selected indices over time [Source: Yahoo Finance]

    Parameters
    ----------
    indices: list
        A list of indices you wish to load (and plot).
    interval: str
        Valid intervals: 1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo
        Intraday data cannot extend last 60 days
    start_date : str
        The starting date, format "YEAR-MONTH-DAY", i.e. 2010-12-31.
    end_date : str
        The end date, format "YEAR-MONTH-DAY", i.e. 2020-06-05.
    column : str
        Which column to load in, by default this is the Adjusted Close.
    returns: bool
        Flag to show cumulative returns on index
    store : bool
        Whether to prevent plotting the data.
    raw : bool
        Whether to display the raw output.
    external_axes: Optional[List[plt.axes]]
        External axes to plot on
    export : str
        Export data to csv,json,xlsx or png,jpg,pdf,svg file

    Returns
    ----------
    Plots the Series.
    """
    indices_data: pd.DataFrame = pd.DataFrame()

    for index in indices:
        indices_data[index] = get_index(index, interval, start_date, end_date,
                                        column)

    if returns:
        indices_data = indices_data.pct_change().dropna()
        indices_data = indices_data + 1
        indices_data = indices_data.cumprod()

    if not store:
        if external_axes is None:
            _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
        else:
            ax = external_axes[0]

        for index in indices:
            if index.lower() in INDICES:
                label = INDICES[index.lower()]["name"]
            else:
                label = index

            if not indices_data[index].empty:
                data_to_percent = 100 * (indices_data[index].values - 1)
                ax.plot(data_to_percent, label=label)

        ax.set_title("Indices")
        if returns:
            ax.set_ylabel("Performance (%)")
        ax.legend(
            bbox_to_anchor=(0, 0.40, 1, -0.52),
            loc="upper right",
            mode="expand",
            borderaxespad=0,
            prop={"size": 9},
            ncol=2,
        )

        if returns:
            indices_data.index.name = "date"
            plot_data = reindex_dates(indices_data)
            theme.style_primary_axis(
                ax,
                data_index=plot_data.index.to_list(),
                tick_labels=plot_data["date"].to_list(),
            )
            ax.set_xlim(plot_data.index[0], plot_data.index[-1])
        else:
            theme.style_primary_axis(ax)
        if external_axes is None:
            theme.visualize_output()

    if raw:
        print_rich_table(
            indices_data.fillna("-").iloc[-10:],
            headers=list(indices_data.columns),
            show_index=True,
            title=f"Indices [column: {column}]",
        )

    if export:
        export_data(
            export,
            os.path.dirname(os.path.abspath(__file__)),
            "index_data",
            indices_data,
        )

    return indices_data