Example #1
0
def ark_orders(l_args):
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="ARK Orders",
        description="""
            Orders by ARK Investment Management LLC - https://ark-funds.com/. [Source: https://cathiesark.com]
        """,
    )

    parser.add_argument(
        "-n",
        "--num",
        action="store",
        dest="n_num",
        type=check_positive,
        default=20,
        help="Last N orders.",
    )

    ns_parser = parse_known_args_and_warn(parser, l_args)
    if not ns_parser:
        return

    df_orders = get_ark_orders()

    if df_orders.empty:
        print("The ARK orders aren't anavilable at the moment.\n")
        return

    pd.set_option("mode.chained_assignment", None)
    df_orders = add_order_total(df_orders.head(ns_parser.n_num))

    if gtff.USE_COLOR:
        df_orders["direction"] = df_orders["direction"].apply(
            direction_color_red_green)

        patch_pandas_text_adjustment()

    df_orders[
        "link"] = "https://finviz.com/quote.ashx?t=" + df_orders["ticker"]

    pd.set_option("display.max_colwidth", None)
    pd.set_option("display.max_rows", None)
    pd.set_option("display.float_format", "{:,.2f}".format)
    print("")
    print("Orders by ARK Investment Management LLC")
    print("")
    print(df_orders.to_string(index=False))
    print("")
def display_cashflow_comparison(
    similar: List[str],
    timeframe: str,
    quarter: bool = False,
    export: str = "",
):
    """Compare cashflow between companies. [Source: Marketwatch]

    Parameters
    ----------
    ticker : str
        Main ticker to compare income
    similar : List[str]
        Similar companies to compare income with
    timeframe : str
        Whether to use quarterly or annual
    quarter : bool, optional
        Whether to use quarterly statements, by default False
    export : str, optional
        Format to export data
    """
    df_financials_compared = marketwatch_model.get_financial_comparisons(
        similar, "cashflow", timeframe, quarter)

    # Export data before the color
    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)),
        "cashflow",
        df_financials_compared,
    )

    if gtff.USE_COLOR:
        df_financials_compared = df_financials_compared.applymap(
            financials_colored_values)
        patch_pandas_text_adjustment()

    if not quarter:
        df_financials_compared.index.name = timeframe

    print_rich_table(
        df_financials_compared,
        headers=list(df_financials_compared.columns),
        show_index=True,
        title="Cashflow Comparison",
    )
    console.print("")
def display_income_comparison(
    similar: List[str],
    timeframe: str,
    quarter: bool = False,
    export: str = "",
):
    """Display income data. [Source: Marketwatch]

    Parameters
    ----------
    similar : List[str]
        List of tickers to compare
    timeframe : str
        Whether to use quarterly or annual
    quarter : bool, optional
        Whether to use quarterly statements, by default False
    export : str, optional
        Format to export data
    """
    df_financials_compared = marketwatch_model.get_financial_comparisons(
        similar, "income", timeframe, quarter
    )
    # Export data before the color
    export_data(
        export,
        os.path.dirname(os.path.abspath(__file__)),
        "income",
        df_financials_compared,
    )

    if rich_config.USE_COLOR:
        df_financials_compared = df_financials_compared.applymap(
            lambda_financials_colored_values
        )
        patch_pandas_text_adjustment()

    if not quarter:
        df_financials_compared.index.name = timeframe

    print_rich_table(
        df_financials_compared,
        headers=list(df_financials_compared.columns),
        show_index=True,
        title="Income Data",
    )
    console.print("")
Example #4
0
def analyst(l_args, s_ticker):
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="analyst",
        description="""
            Print analyst prices and ratings of the company. The following fields are expected:
            date, analyst, category, price from, price to, and rating. [Source: Finviz]
        """,
    )

    parser.add_argument(
        "-c",
        "--color",
        action="store",
        dest="n_color",
        type=int,
        choices=[0, 1],
        default=1,
        help="Add / remove color",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, l_args)
        if not ns_parser:
            return

        df_fa = analyst_df(s_ticker)

        if ns_parser.n_color == 1:
            df_fa["category"] = df_fa["category"].apply(
                category_color_red_green)

            patch_pandas_text_adjustment()

        print(df_fa)
        print("")

    except Exception as e:
        print(e)
        print("")
        return
Example #5
0
def k_nearest_neighbors(l_args, s_ticker, df_stock):
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="knn",
        description="""
            K nearest neighbors is a simple algorithm that stores all
            available cases and predict the numerical target based on a similarity measure
            (e.g. distance functions).
        """,
    )

    parser.add_argument(
        "-i",
        "--input",
        action="store",
        dest="n_inputs",
        type=check_positive,
        default=40,
        help="number of days to use for prediction.",
    )
    parser.add_argument(
        "-d",
        "--days",
        action="store",
        dest="n_days",
        type=check_positive,
        default=5,
        help="prediction days.",
    )
    parser.add_argument(
        "-j",
        "--jumps",
        action="store",
        dest="n_jumps",
        type=check_positive,
        default=1,
        help="number of jumps in training data.",
    )
    parser.add_argument(
        "-n",
        "--neighbors",
        action="store",
        dest="n_neighbors",
        type=check_positive,
        default=20,
        help="number of neighbors to use on the algorithm.",
    )
    parser.add_argument(
        "-e",
        "--end",
        action="store",
        type=valid_date,
        dest="s_end_date",
        default=None,
        help="The end date (format YYYY-MM-DD) to select - Backtesting",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, l_args)
        if not ns_parser:
            return

        # BACKTESTING
        if ns_parser.s_end_date:
            if ns_parser.s_end_date < df_stock.index[0]:
                print(
                    "Backtesting not allowed, since End Date is older than Start Date of historical data\n"
                )
                return

            if ns_parser.s_end_date < get_next_stock_market_days(
                    last_stock_day=df_stock.index[0],
                    n_next_days=ns_parser.n_inputs + ns_parser.n_days,
            )[-1]:
                print(
                    "Backtesting not allowed, since End Date is too close to Start Date to train model\n"
                )
                return

            future_index = get_next_stock_market_days(
                last_stock_day=ns_parser.s_end_date,
                n_next_days=ns_parser.n_days)

            if future_index[-1] > datetime.datetime.now():
                print(
                    "Backtesting not allowed, since End Date + Prediction days is in the future\n"
                )
                return

            df_future = df_stock[future_index[0]:future_index[-1]]
            df_stock = df_stock[:ns_parser.s_end_date]

        # Split training data
        stock_x, stock_y = splitTrain.split_train(
            df_stock["5. adjusted close"].values,
            ns_parser.n_inputs,
            ns_parser.n_days,
            ns_parser.n_jumps,
        )

        if not stock_x:
            print("Given the model parameters more training data is needed.\n")
            return

        # Machine Learning model
        knn = neighbors.KNeighborsRegressor(n_neighbors=ns_parser.n_neighbors)
        knn.fit(stock_x, stock_y)

        # Prediction data
        l_predictions = knn.predict(
            df_stock["5. adjusted close"].values[-ns_parser.n_inputs:].reshape(
                1, -1))[0]
        l_pred_days = get_next_stock_market_days(
            last_stock_day=df_stock["5. adjusted close"].index[-1],
            n_next_days=ns_parser.n_days,
        )
        df_pred = pd.Series(l_predictions, index=l_pred_days, name="Price")

        # Plotting
        plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
        plt.plot(df_stock.index, df_stock["5. adjusted close"], lw=2)
        s_knn = f"{ns_parser.n_neighbors}-Nearest Neighbors on {s_ticker}"
        # BACKTESTING
        if ns_parser.s_end_date:
            plt.title(
                f"BACKTESTING: {s_knn} - {ns_parser.n_days} days prediction")
        else:
            plt.title(f"{s_knn} - {ns_parser.n_days} days prediction")
        plt.xlim(df_stock.index[0],
                 get_next_stock_market_days(df_pred.index[-1], 1)[-1])
        plt.xlabel("Time")
        plt.ylabel("Share Price ($)")
        plt.grid(b=True, which="major", color="#666666", linestyle="-")
        plt.minorticks_on()
        plt.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)
        plt.plot(
            [df_stock.index[-1], df_pred.index[0]],
            [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
            lw=1,
            c="tab:green",
            linestyle="--",
        )
        plt.plot(df_pred.index, df_pred, lw=2, c="tab:green")
        plt.axvspan(df_stock.index[-1],
                    df_pred.index[-1],
                    facecolor="tab:orange",
                    alpha=0.2)
        _, _, ymin, ymax = plt.axis()
        plt.vlines(df_stock.index[-1],
                   ymin,
                   ymax,
                   linewidth=1,
                   linestyle="--",
                   color="k")

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=1,
                c="tab:blue",
                linestyle="--",
            )

        if gtff.USE_ION:
            plt.ion()

        plt.show()

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
            plt.subplot(211)
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(df_pred.index, df_pred, lw=2, c="green")
            plt.scatter(df_future.index,
                        df_future["5. adjusted close"],
                        c="tab:blue",
                        lw=3)
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.scatter(df_pred.index, df_pred, c="green", lw=3)
            plt.plot(
                [df_stock.index[-1], df_pred.index[0]],
                [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
                lw=2,
                c="green",
                ls="--",
            )
            plt.title("BACKTESTING: Real data price versus Prediction")
            plt.xlim(df_stock.index[-1],
                     df_pred.index[-1] + datetime.timedelta(days=1))
            plt.xticks([
                df_stock.index[-1],
                df_pred.index[-1] + datetime.timedelta(days=1)
            ])
            plt.ylabel("Share Price ($)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True,
                     which="minor",
                     color="#999999",
                     linestyle="-",
                     alpha=0.2)
            plt.legend(["Real data", "Prediction data"])
            plt.xticks([])

            plt.subplot(212)
            plt.axhline(y=0, color="k", linestyle="--", linewidth=2)
            plt.plot(
                df_future.index,
                100 *
                (df_pred.values - df_future["5. adjusted close"].values) /
                df_future["5. adjusted close"].values,
                lw=2,
                c="red",
            )
            plt.scatter(
                df_future.index,
                100 *
                (df_pred.values - df_future["5. adjusted close"].values) /
                df_future["5. adjusted close"].values,
                c="red",
                lw=5,
            )
            plt.title(
                "BACKTESTING: Error between Real data and Prediction [%]")
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    0,
                    100 * (df_pred.values[0] -
                           df_future["5. adjusted close"].values[0]) /
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                ls="--",
                c="red",
            )
            plt.xlim(df_stock.index[-1],
                     df_pred.index[-1] + datetime.timedelta(days=1))
            plt.xticks([
                df_stock.index[-1],
                df_pred.index[-1] + datetime.timedelta(days=1)
            ])
            plt.xlabel("Time")
            plt.ylabel("Prediction Error (%)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True,
                     which="minor",
                     color="#999999",
                     linestyle="-",
                     alpha=0.2)
            plt.legend(["Real data", "Prediction data"])

            if gtff.USE_ION:
                plt.ion()

            plt.show()

            # Refactor prediction dataframe for backtesting print
            df_pred.name = "Prediction"
            df_pred = df_pred.to_frame()
            df_pred["Real"] = df_future["5. adjusted close"]

            if gtff.USE_COLOR:
                patch_pandas_text_adjustment()

                print("Time         Real [$]  x  Prediction [$]")
                print(
                    df_pred.apply(price_prediction_backtesting_color,
                                  axis=1).to_string())
            else:
                print(df_pred[["Real", "Prediction"]].round(2).to_string())

            print("")
            print_prediction_kpis(df_pred["Real"].values,
                                  df_pred["Prediction"].values)

        else:
            # Print prediction data
            print_pretty_prediction(df_pred,
                                    df_stock["5. adjusted close"].values[-1])
        print("")

    except Exception as e:
        print(e)
        print("")
Example #6
0
def display_chains(
    ticker: str,
    expiry: str,
    to_display: List[str],
    min_sp: float,
    max_sp: float,
    calls_only: bool,
    puts_only: bool,
    export: str = "",
):
    """Display option chain

    Parameters
    ----------
    ticker: str
        Stock ticker
    expiry: str
        Expiration date of option
    to_display: List[str]
        List of columns to display
    min_sp: float
        Min strike price to display
    max_sp: float
        Max strike price to display
    calls_only: bool
        Only display calls
    puts_only: bool
        Only display puts
    export: str
        Format to  export file
    """

    chains_df = tradier_model.get_option_chains(ticker, expiry)
    columns = to_display + ["strike", "option_type"]
    chains_df = chains_df[columns].rename(columns=column_map)

    if min_sp == -1:
        min_strike = np.percentile(chains_df["strike"], 25)
    else:
        min_strike = min_sp

    if max_sp == -1:
        max_strike = np.percentile(chains_df["strike"], 75)
    else:
        max_strike = max_sp

    chains_df = chains_df[chains_df["strike"] >= min_strike]
    chains_df = chains_df[chains_df["strike"] <= max_strike]

    calls_df = chains_df[chains_df.option_type == "call"].drop(columns=["option_type"])
    puts_df = chains_df[chains_df.option_type == "put"].drop(columns=["option_type"])

    df = calls_df if calls_only else puts_df

    if calls_only or puts_only:
        print_rich_table(
            df,
            headers=[x.title() for x in df.columns],
            show_index=False,
            title=f"The strike prices are displayed between {min_strike} and {max_strike}",
        )

    else:
        puts_df = puts_df[puts_df.columns[::-1]]
        chain_table = calls_df.merge(puts_df, on="strike")

        if gtff.USE_COLOR:
            call_cols = [col for col in chain_table if col.endswith("_x")]
            put_cols = [col for col in chain_table if col.endswith("_y")]
            patch_pandas_text_adjustment()
            pd.set_option("display.max_colwidth", 0)
            pd.set_option("display.max_rows", None)
            for cc in call_cols:
                chain_table[cc] = chain_table[cc].astype(str).apply(green_highlight)
            for pc in put_cols:
                chain_table[pc] = chain_table[pc].astype(str).apply(red_highlight)
        headers = [
            col.strip("_x")
            if col.endswith("_x")
            else col.strip("_y")
            if col.endswith("_y")
            else col
            for col in chain_table.columns
        ]
        print_rich_table(
            chain_table, headers=headers, show_index=False, title="Option chain"
        )

    export_data(
        export,
        os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
        "chains",
        chains_df,
    )
Example #7
0
def fbprophet(l_args, s_ticker, df_stock):
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="fbprophet",
        description="""
            Facebook Prophet is a forecasting procedure that is fast and provides
            completely automated forecasts that can be tuned by hand by data scientists
            and analysts. It was developed by Facebook's data science team and is open
            source.
        """,
    )

    parser.add_argument(
        "-d",
        "--days",
        action="store",
        dest="n_days",
        type=check_positive,
        default=5,
        help="prediction days",
    )
    parser.add_argument(
        "-e",
        "--end",
        action="store",
        type=valid_date,
        dest="s_end_date",
        default=None,
        help="The end date (format YYYY-MM-DD) to select - Backtesting",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, l_args)
        if not ns_parser:
            return

        # BACKTESTING
        if ns_parser.s_end_date:

            if ns_parser.s_end_date < df_stock.index[0]:
                print(
                    "Backtesting not allowed, since End Date is older than Start Date of historical data\n"
                )
                return

            if (ns_parser.s_end_date < get_next_stock_market_days(
                    last_stock_day=df_stock.index[0],
                    n_next_days=5 + ns_parser.n_days)[-1]):
                print(
                    "Backtesting not allowed, since End Date is too close to Start Date to train model\n"
                )
                return

            future_index = get_next_stock_market_days(
                last_stock_day=ns_parser.s_end_date,
                n_next_days=ns_parser.n_days)

            if future_index[-1] > datetime.datetime.now():
                print(
                    "Backtesting not allowed, since End Date + Prediction days is in the future\n"
                )
                return

            df_future = df_stock[future_index[0]:future_index[-1]]
            df_stock = df_stock[:ns_parser.s_end_date]

        df_stock = df_stock.sort_index(ascending=True)
        df_stock.reset_index(level=0, inplace=True)
        df_stock = df_stock[["date", "5. adjusted close"]]
        df_stock = df_stock.rename(columns={
            "date": "ds",
            "5. adjusted close": "y"
        })
        df_stock["ds"] = pd.to_datetime(df_stock["ds"])

        model = Prophet(yearly_seasonality=False, daily_seasonality=False)
        model.fit(df_stock)

        l_pred_days = get_next_stock_market_days(
            last_stock_day=pd.to_datetime(df_stock["ds"].values[-1]),
            n_next_days=ns_parser.n_days,
        )
        close_prices = model.make_future_dataframe(periods=ns_parser.n_days)
        forecast = model.predict(close_prices)

        df_pred = forecast["yhat"][
            -ns_parser.n_days:]  # .apply(lambda x: f"{x:.2f} $")
        df_pred.index = l_pred_days

        _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
        model.plot(
            forecast[:-ns_parser.n_days],
            ax=ax,
            xlabel="Time",
            ylabel="Share Price ($)",
        )
        _, _, ymin, ymax = ax.axis()
        ax.vlines(
            df_stock["ds"].values[-1],
            ymin,
            ymax,
            linewidth=2,
            linestyle="--",
            color="k",
        )
        plt.axvspan(
            df_stock["ds"].values[-1],
            l_pred_days[-1],
            facecolor="tab:orange",
            alpha=0.2,
        )
        plt.ylim(ymin, ymax)
        plt.xlim(df_stock["ds"].values[0],
                 get_next_stock_market_days(l_pred_days[-1], 1)[-1])
        # BACKTESTING
        if ns_parser.s_end_date:
            plt.title(
                f"BACKTESTING: Fb Prophet on {s_ticker} - {ns_parser.n_days} days prediction"
            )
        else:
            plt.title(
                f"Fb Prophet on {s_ticker} - {ns_parser.n_days} days prediction"
            )

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(
                [df_stock["ds"].values[-1], df_future.index[0]],
                [
                    df_stock["y"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=1,
                c="tab:blue",
                linestyle="--",
            )

        plt.plot(df_pred.index, df_pred.values, lw=2, c="green")

        if gtff.USE_ION:
            plt.ion()

        plt.show()

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
            plt.subplot(211)
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(df_pred.index, df_pred, lw=2, c="green")
            plt.scatter(
                df_future.index,
                df_future["5. adjusted close"],
                c="tab:blue",
                lw=3,
            )
            plt.plot(
                [df_stock["ds"].values[-1], df_future.index[0]],
                [
                    df_stock["y"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.scatter(df_pred.index, df_pred, c="green", lw=3)
            plt.plot(
                [df_stock["ds"].values[-1], df_pred.index[0]],
                [df_stock["y"].values[-1], df_pred.values[0]],
                lw=2,
                c="green",
                ls="--",
            )
            plt.title("BACKTESTING: Real data price versus Prediction")
            plt.xlim(
                df_stock["ds"].values[-1],
                df_pred.index[-1] + datetime.timedelta(days=1),
            )
            plt.ylabel("Share Price ($)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True,
                     which="minor",
                     color="#999999",
                     linestyle="-",
                     alpha=0.2)
            plt.legend(["Real data", "Prediction data"])
            plt.xticks([])

            plt.subplot(212)
            plt.axhline(y=0, color="k", linestyle="--", linewidth=2)

            plt.plot(
                df_future.index,
                100 *
                (df_pred.values - df_future["5. adjusted close"].values) /
                df_future["5. adjusted close"].values,
                lw=2,
                c="red",
            )
            plt.scatter(
                df_future.index,
                100 *
                (df_pred.values - df_future["5. adjusted close"].values) /
                df_future["5. adjusted close"].values,
                c="red",
                lw=5,
            )
            plt.title(
                "BACKTESTING: Error between Real data and Prediction [%]")
            plt.plot(
                [df_stock["ds"].values[-1], df_future.index[0]],
                [
                    0,
                    100 * (df_pred.values[0] -
                           df_future["5. adjusted close"].values[0]) /
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                ls="--",
                c="red",
            )
            plt.xlim(
                df_stock["ds"].values[-1],
                df_pred.index[-1] + datetime.timedelta(days=1),
            )
            plt.xlabel("Time")
            plt.ylabel("Prediction Error (%)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True,
                     which="minor",
                     color="#999999",
                     linestyle="-",
                     alpha=0.2)
            plt.legend(["Real data", "Prediction data"])

            if gtff.USE_ION:
                plt.ion()

            plt.show()

            # Refactor prediction dataframe for backtesting print
            df_pred.name = "Prediction"
            df_pred = df_pred.to_frame()
            df_pred["Real"] = df_future["5. adjusted close"]

            if gtff.USE_COLOR:

                patch_pandas_text_adjustment()

                print("Time         Real [$]  x  Prediction [$]")
                print(
                    df_pred.apply(price_prediction_backtesting_color,
                                  axis=1).to_string())
            else:
                print(df_pred[["Real", "Prediction"]].round(2).to_string())

            print("")
            print_prediction_kpis(df_pred["Real"].values,
                                  df_pred["Prediction"].values)
        else:
            print("")
            print("Predicted share price:")
            print(df_pred.to_string())
        print("")

    except Exception as e:
        print(e)
        print("")
Example #8
0
def _plot_and_print_results(
    df_stock, ns_parser, df_future, df_pred, model_name, s_ticker
):
    """Plot and print the results. """
    # Plotting
    plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
    plt.plot(df_stock.index, df_stock["5. adjusted close"], lw=3)

    # BACKTESTING
    if ns_parser.n_loops == 1:
        if ns_parser.s_end_date:
            plt.title(
                f"BACKTESTING: {model_name} on {s_ticker} - {ns_parser.n_days} days prediction"
            )
        else:
            plt.title(
                f"{model_name} on {s_ticker} - {ns_parser.n_days} days prediction"
            )
    else:
        if ns_parser.s_end_date:
            plt.title(
                f"{ns_parser.n_loops} loops - BACKTESTING: {model_name} on {s_ticker}"
                f" - {ns_parser.n_days} days prediction"
            )
        else:
            plt.title(
                f"{ns_parser.n_loops} loops - {model_name} on {s_ticker} - {ns_parser.n_days} days prediction"
            )

    plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1])
    plt.xlabel("Time")
    plt.ylabel("Share Price ($)")
    plt.grid(b=True, which="major", color="#666666", linestyle="-")
    plt.minorticks_on()
    plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)

    if ns_parser.n_loops == 1:
        plt.plot(
            [df_stock.index[-1], df_pred.index[0]],
            [
                df_stock["5. adjusted close"].values[-1],
                df_pred[df_pred.columns[0]].values[0],
            ],
            lw=1,
            c="tab:green",
            linestyle="--",
        )
        plt.plot(df_pred.index, df_pred[df_pred.columns[0]], lw=2, c="tab:green")
    else:
        df_quantiles = pd.DataFrame()
        df_quantiles["Quantile 10%"] = df_pred.quantile(0.1, axis=1)
        df_quantiles["Median"] = df_pred.quantile(0.5, axis=1)
        df_quantiles["Quantile 90%"] = df_pred.quantile(0.9, axis=1)

        plt.plot(df_pred.index, df_quantiles["Median"], lw=2, c="tab:green")
        plt.fill_between(
            df_pred.index,
            df_quantiles["Quantile 10%"],
            df_quantiles["Quantile 90%"],
            alpha=0.30,
            color="tab:green",
            interpolate=True,
        )
        plt.fill_between(
            [df_stock.index[-1], df_pred.index[0]],
            [
                df_stock["5. adjusted close"].values[-1],
                df_quantiles["Quantile 10%"].values[0],
            ],
            [
                df_stock["5. adjusted close"].values[-1],
                df_quantiles["Quantile 90%"].values[0],
            ],
            alpha=0.30,
            color="tab:green",
            interpolate=True,
        )

    plt.axvspan(
        df_stock.index[-1], df_pred.index[-1], facecolor="tab:orange", alpha=0.2
    )
    _, _, ymin, ymax = plt.axis()
    plt.vlines(
        df_stock.index[-1],
        ymin,
        ymax,
        colors="k",
        linewidth=3,
        linestyle="--",
        color="k",
    )

    # BACKTESTING
    if ns_parser.s_end_date:
        plt.plot(
            df_future.index,
            df_future["5. adjusted close"],
            lw=2,
            c="tab:blue",
            ls="--",
        )
        plt.plot(
            [df_stock.index[-1], df_future.index[0]],
            [
                df_stock["5. adjusted close"].values[-1],
                df_future["5. adjusted close"].values[0],
            ],
            lw=1,
            c="tab:blue",
            linestyle="--",
        )

    if gtff.USE_ION:
        plt.ion()

    plt.show()

    # BACKTESTING
    if ns_parser.s_end_date:
        plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
        plt.subplot(211)
        plt.plot(
            df_future.index,
            df_future["5. adjusted close"],
            lw=2,
            c="tab:blue",
            ls="--",
        )
        if ns_parser.n_loops == 1:
            plt.plot(df_pred.index, df_pred, lw=2, c="green")
        else:
            plt.plot(
                df_quantiles["Median"].index, df_quantiles["Median"], lw=2, c="green"
            )

        plt.scatter(df_future.index, df_future["5. adjusted close"], c="tab:blue", lw=3)
        plt.plot(
            [df_stock.index[-1], df_future.index[0]],
            [
                df_stock["5. adjusted close"].values[-1],
                df_future["5. adjusted close"].values[0],
            ],
            lw=2,
            c="tab:blue",
            ls="--",
        )
        if ns_parser.n_loops == 1:
            plt.scatter(df_pred.index, df_pred, c="green", lw=3)
            plt.plot(
                [df_stock.index[-1], df_pred.index[0]],
                [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
                lw=2,
                c="green",
                ls="--",
            )
        else:
            plt.scatter(
                df_quantiles["Median"].index, df_quantiles["Median"], lw=3, c="green"
            )
            plt.plot(
                [df_stock.index[-1], df_quantiles["Median"].index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_quantiles["Median"].values[0],
                ],
                lw=2,
                c="green",
                ls="--",
            )
            plt.fill_between(
                df_pred.index,
                df_quantiles["Quantile 10%"],
                df_quantiles["Quantile 90%"],
                alpha=0.30,
                color="tab:green",
                interpolate=True,
            )

        plt.title("BACKTESTING: Real data price versus Prediction")
        plt.xlim(df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1))
        plt.xticks(
            [df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1)],
            visible=True,
        )
        plt.ylabel("Share Price ($)")
        plt.grid(b=True, which="major", color="#666666", linestyle="-")
        plt.minorticks_on()
        plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
        plt.legend(["Real data", "Prediction data"])
        plt.xticks([])

        plt.subplot(212)
        plt.axhline(y=0, color="k", linestyle="--", linewidth=2)
        if ns_parser.n_loops == 1:
            plt.plot(
                df_future.index,
                100
                * (
                    df_pred[df_pred.columns[0]].values
                    - df_future["5. adjusted close"].values
                )
                / df_future["5. adjusted close"].values,
                lw=2,
                c="red",
            )
            plt.scatter(
                df_future.index,
                100
                * (
                    df_pred[df_pred.columns[0]].values
                    - df_future["5. adjusted close"].values
                )
                / df_future["5. adjusted close"].values,
                c="red",
                lw=5,
            )
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    0,
                    100
                    * (
                        df_pred[df_pred.columns[0]].values[0]
                        - df_future["5. adjusted close"].values[0]
                    )
                    / df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                ls="--",
                c="red",
            )
        else:
            plt.plot(
                df_future.index,
                100
                * (
                    df_quantiles["Median"].values
                    - df_future["5. adjusted close"].values
                )
                / df_future["5. adjusted close"].values,
                lw=2,
                c="red",
            )
            plt.scatter(
                df_future.index,
                100
                * (
                    df_quantiles["Median"].values
                    - df_future["5. adjusted close"].values
                )
                / df_future["5. adjusted close"].values,
                c="red",
                lw=5,
            )
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    0,
                    100
                    * (
                        df_quantiles["Median"].values[0]
                        - df_future["5. adjusted close"].values[0]
                    )
                    / df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                ls="--",
                c="red",
            )
            plt.fill_between(
                df_pred.index,
                100
                * (
                    df_quantiles["Quantile 10%"].values
                    - df_future["5. adjusted close"].values
                )
                / df_future["5. adjusted close"].values,
                100
                * (
                    df_quantiles["Quantile 90%"].values
                    - df_future["5. adjusted close"].values
                )
                / df_future["5. adjusted close"].values,
                alpha=0.30,
                color="red",
                interpolate=True,
            )
        plt.title("BACKTESTING: Error between Real data and Prediction [%]")

        plt.xlim(df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1))
        plt.xticks(
            [df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1)],
            visible=True,
        )
        plt.xlabel("Time")
        plt.ylabel("Prediction Error (%)")
        plt.grid(b=True, which="major", color="#666666", linestyle="-")
        plt.minorticks_on()
        plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
        plt.legend(["Real data", "Prediction data"])

        if gtff.USE_ION:
            plt.ion()

        plt.show()

        # Refactor prediction dataframe for backtesting print
        if ns_parser.n_loops == 1:
            df_pred.rename(columns={df_pred.columns[0]: "Prediction"}, inplace=True)

        else:
            df_pred = pd.DataFrame()
            df_pred["Prediction"] = df_quantiles["Median"]

        df_pred["Real"] = df_future["5. adjusted close"]

        if gtff.USE_COLOR:
            patch_pandas_text_adjustment()

            print("Time         Real [$]  x  Prediction [$]")
            print(df_pred.apply(price_prediction_backtesting_color, axis=1).to_string())
        else:
            print(df_pred[["Real", "Prediction"]].round(2).to_string())

        print("")
        print_prediction_kpis(df_pred["Real"].values, df_pred["Prediction"].values)
        print("")

    else:
        patch_pandas_text_adjustment()
        # Print prediction data
        print_pretty_prediction_nn(df_pred, df_stock["5. adjusted close"].values[-1])
        print("")

        if ns_parser.n_loops > 1:
            print("Prediction Stats:")
            print(df_quantiles.round(2).to_string())
            print("")
def compare_cashflow(other_args: List[str], ticker: str, similar: List[str]):
    """Compare balance between companies

    Parameters
    ----------
    other_args : List[str]
        Command line arguments to be processed with argparse
    ticker : str
        Main ticker to compare income
    similar : List[str]
        Similar companies to compare income with
    """
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="compare_cashflow",
        description="""
            Prints either yearly or quarterly cash statement the company, and compares
            it against similar companies. [Source: Market Watch]
        """,
    )
    parser.add_argument(
        "-s",
        "--similar",
        dest="l_similar",
        type=lambda s: [str(item).upper() for item in s.split(",")],
        default=similar,
        help="similar companies to compare with.",
    )
    parser.add_argument(
        "-a",
        "--also",
        dest="l_also",
        type=lambda s: [str(item).upper() for item in s.split(",")],
        default=[],
        help="apart from loaded similar companies also compare with.",
    )
    parser.add_argument(
        "-q",
        "--quarter",
        action="store_true",
        default=False,
        dest="b_quarter",
        help="Quarter financial data flag.",
    )
    parser.add_argument(
        "-t",
        "--timeframe",
        dest="s_timeframe",
        type=str,
        default=None,
        help="Specify yearly/quarterly timeframe. Default is last.",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return

        l_similar = ns_parser.l_similar
        l_similar += ns_parser.l_also

        # Add main ticker to similar list of companies
        l_similar.insert(0, ticker)

        l_timeframes, ddf_financials = prepare_comparison_financials(
            l_similar, "cashflow", ns_parser.b_quarter)

        if ns_parser.s_timeframe:
            if ns_parser.s_timeframe not in l_timeframes:
                raise ValueError(
                    f"Timeframe selected should be one of {', '.join(l_timeframes)}"
                )
            s_timeframe = ns_parser.s_timeframe
        else:
            s_timeframe = l_timeframes[-1]

        print(
            f"Other available {('yearly', 'quarterly')[ns_parser.b_quarter]} timeframes are: {', '.join(l_timeframes)}\n"
        )

        df_financials_compared = combine_similar_financials(
            ddf_financials, l_similar, s_timeframe, ns_parser.b_quarter)

        if gtff.USE_COLOR:
            df_financials_compared = df_financials_compared.applymap(
                financials_colored_values)

            patch_pandas_text_adjustment()
            pd.set_option("display.max_colwidth", None)
            pd.set_option("display.max_rows", None)

        if not ns_parser.b_quarter:
            df_financials_compared.index.name = s_timeframe

        print(df_financials_compared.to_string())
        print("")

    except Exception as e:
        print(e, "\n")
        return
Example #10
0
def balance(other_args: List[str], ticker: str):
    """Market Watch ticker balance statement

    Parameters
    ----------
    other_args : List[str]
        argparse other args
    ticker : str
        Fundamental analysis ticker symbol
    """
    parser = argparse.ArgumentParser(
        add_help=False,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        prog="balance",
        description="""
            Prints either yearly or quarterly assets from balance sheet of the company.
            The following fields are expected: Cash & Short Term Investments, Cash & Short Term
            Investments Growth, Cash Only, Short-Term Investments, Cash & ST Investments / Total
            Assets, Total Accounts Receivable, Total Accounts Receivable Growth, Accounts
            Receivables, Net, Accounts Receivables, Gross, Bad Debt/Doubtful Accounts, Other
            Receivable, Accounts Receivable Turnover, Inventories, Finished Goods, Work in
            Progress, Raw Materials, Progress Payments & Other, Other Current Assets,
            Miscellaneous Current Assets, Net Property, Plant & Equipment, Property, Plant &
            Equipment - Gross, Buildings, Land & Improvements, Computer Software and Equipment,
            Other Property, Plant & Equipment, Accumulated Depreciation, Total Investments and
            Advances, Other Long-Term Investments, Long-Term Note Receivables, Intangible Assets,
            Net Goodwill, Net Other Intangibles, Other Assets.

            Prints either yearly or quarterly liabilities and shareholders' equity from balance
            sheet of the company. The following fields are expected: ST Debt & Current Portion LT
            Debt, Short Term Debt, Current Portion of Long Term Debt, Accounts Payable, Accounts
            Payable Growth, Income Tax Payable, Other Current Liabilities, Dividends Payable,
            Accrued Payroll, Miscellaneous Current Liabilities, Long-Term Debt, Long-Term Debt
            excl. Capitalized Leases, Non-Convertible Debt, Convertible Debt, Capitalized Lease
            Obligations, Provision for Risks & Charges, Deferred Taxes, Deferred Taxes - Credits,
            Deferred Taxes - Debit, Other Liabilities, Other Liabilities (excl. Deferred Income),
            Deferred Income, Non-Equity Reserves, Total Liabilities / Total Assets, Preferred Stock
            (Carrying Value), Redeemable Preferred Stock, Non-Redeemable Preferred Stock, Common
            Equity (Total), Common Equity/Total Assets, Common Stock Par/Carry Value, Retained
            Earnings, ESOP Debt Guarantee, Cumulative Translation Adjustment/Unrealized For. Exch.
            Gain, Unrealized Gain/Loss Marketable Securities, Revaluation Reserves, Treasury Stock,
            Total Shareholders' Equity, Total Shareholders' Equity / Total Assets, Accumulated
            Minority Interest, Total Equity, Total Current Assets, Total Assets, Total Current
            Liabilities, Total Liabilities, and Liabilities & Shareholders' Equity.
            [Source: Market Watch]
        """,
    )
    parser.add_argument(
        "-q",
        "--quarter",
        action="store_true",
        default=False,
        dest="b_quarter",
        help="Quarter fundamental data flag.",
    )

    ns_parser = parse_known_args_and_warn(parser, other_args)
    if not ns_parser:
        return

    df_financials = mwm.prepare_df_financials(ticker, "balance",
                                              ns_parser.b_quarter)

    if gtff.USE_COLOR:
        df_financials = df_financials.applymap(financials_colored_values)

        patch_pandas_text_adjustment()
        pd.set_option("display.max_colwidth", None)
        pd.set_option("display.max_rows", None)

    if df_financials.empty:
        print("Marketwatch does not yet provide financials for this ticker")
    else:
        print(df_financials.to_string(index=False))
    print("")
Example #11
0
def regression(l_args, s_ticker, df_stock, polynomial):
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="regression",
        description="""
            Regression attempts to model the relationship between
            two variables by fitting a linear/quadratic/cubic/other equation to
            observed data. One variable is considered to be an explanatory variable,
            and the other is considered to be a dependent variable.
        """,
    )

    parser.add_argument(
        "-i",
        "--input",
        action="store",
        dest="n_inputs",
        type=check_positive,
        default=40,
        help="number of days to use for prediction.",
    )
    parser.add_argument(
        "-d",
        "--days",
        action="store",
        dest="n_days",
        type=check_positive,
        default=5,
        help="prediction days.",
    )
    parser.add_argument(
        "-j",
        "--jumps",
        action="store",
        dest="n_jumps",
        type=check_positive,
        default=1,
        help="number of jumps in training data.",
    )
    parser.add_argument(
        "-e",
        "--end",
        action="store",
        type=valid_date,
        dest="s_end_date",
        default=None,
        help="The end date (format YYYY-MM-DD) to select - Backtesting",
    )

    if polynomial == USER_INPUT:
        parser.add_argument(
            "-p",
            "--polynomial",
            action="store",
            dest="n_polynomial",
            type=check_positive,
            required=True,
            help="polynomial associated with regression.",
        )

    try:
        ns_parser = parse_known_args_and_warn(parser, l_args)
        if not ns_parser:
            return

        # BACKTESTING
        if ns_parser.s_end_date:
            if ns_parser.s_end_date < df_stock.index[0]:
                print(
                    "Backtesting not allowed, since End Date is older than Start Date of historical data\n"
                )
                return

            if ns_parser.s_end_date < get_next_stock_market_days(
                    last_stock_day=df_stock.index[0],
                    n_next_days=ns_parser.n_inputs + ns_parser.n_days,
            )[-1]:
                print(
                    "Backtesting not allowed, since End Date is too close to Start Date to train model\n"
                )
                return

            future_index = get_next_stock_market_days(
                last_stock_day=ns_parser.s_end_date,
                n_next_days=ns_parser.n_days)

            if future_index[-1] > datetime.datetime.now():
                print(
                    "Backtesting not allowed, since End Date + Prediction days is in the future\n"
                )
                return

            df_future = df_stock[future_index[0]:future_index[-1]]
            df_stock = df_stock[:ns_parser.s_end_date]

        # Split training data
        stock_x, stock_y = splitTrain.split_train(
            df_stock["5. adjusted close"].values,
            ns_parser.n_inputs,
            ns_parser.n_days,
            ns_parser.n_jumps,
        )

        if not stock_x:
            print("Given the model parameters more training data is needed.\n")
            return

        # Machine Learning model
        if polynomial == LINEAR:
            model = linear_model.LinearRegression(n_jobs=-1)
        else:
            if polynomial == USER_INPUT:
                polynomial = ns_parser.n_polynomial
            model = pipeline.make_pipeline(
                preprocessing.PolynomialFeatures(polynomial),
                linear_model.Ridge())

        model.fit(stock_x, stock_y)
        l_predictions = model.predict(
            df_stock["5. adjusted close"].values[-ns_parser.n_inputs:].reshape(
                1, -1))[0]

        # Prediction data
        l_pred_days = get_next_stock_market_days(
            last_stock_day=df_stock["5. adjusted close"].index[-1],
            n_next_days=ns_parser.n_days,
        )
        df_pred = pd.Series(l_predictions, index=l_pred_days, name="Price")

        # Plotting
        plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
        plt.plot(df_stock.index, df_stock["5. adjusted close"], lw=2)
        # BACKTESTING
        if ns_parser.s_end_date:
            plt.title(
                f"BACKTESTING: Regression (polynomial {polynomial}) on {s_ticker} - {ns_parser.n_days} days prediction"
            )
        else:
            plt.title(
                f"Regression (polynomial {polynomial}) on {s_ticker} - {ns_parser.n_days} days prediction"
            )
        plt.xlim(df_stock.index[0],
                 get_next_stock_market_days(df_pred.index[-1], 1)[-1])
        plt.xlabel("Time")
        plt.ylabel("Share Price ($)")
        plt.grid(b=True, which="major", color="#666666", linestyle="-")
        plt.minorticks_on()
        plt.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)
        plt.plot(
            [df_stock.index[-1], df_pred.index[0]],
            [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
            lw=1,
            c="tab:green",
            linestyle="--",
        )
        plt.plot(df_pred.index, df_pred, lw=2, c="tab:green")
        plt.axvspan(df_stock.index[-1],
                    df_pred.index[-1],
                    facecolor="tab:orange",
                    alpha=0.2)
        _, _, ymin, ymax = plt.axis()
        plt.vlines(df_stock.index[-1],
                   ymin,
                   ymax,
                   linewidth=1,
                   linestyle="--",
                   color="k")

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=1,
                c="tab:blue",
                linestyle="--",
            )

        if gtff.USE_ION:
            plt.ion()

        plt.show()

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
            plt.subplot(211)
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(df_pred.index, df_pred, lw=2, c="green")
            plt.scatter(df_future.index,
                        df_future["5. adjusted close"],
                        c="tab:blue",
                        lw=3)
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.scatter(df_pred.index, df_pred, c="green", lw=3)
            plt.plot(
                [df_stock.index[-1], df_pred.index[0]],
                [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
                lw=2,
                c="green",
                ls="--",
            )
            plt.title("BACKTESTING: Real data price versus Prediction")
            plt.xlim(df_stock.index[-1],
                     df_pred.index[-1] + datetime.timedelta(days=1))
            plt.xticks(
                [
                    df_stock.index[-1],
                    df_pred.index[-1] + datetime.timedelta(days=1)
                ],
                visible=True,
            )
            plt.ylabel("Share Price ($)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True,
                     which="minor",
                     color="#999999",
                     linestyle="-",
                     alpha=0.2)
            plt.legend(["Real data", "Prediction data"])
            plt.xticks([])

            plt.subplot(212)
            plt.axhline(y=0, color="k", linestyle="--", linewidth=2)
            plt.plot(
                df_future.index,
                100 *
                (df_pred.values - df_future["5. adjusted close"].values) /
                df_future["5. adjusted close"].values,
                lw=2,
                c="red",
            )
            plt.scatter(
                df_future.index,
                100 *
                (df_pred.values - df_future["5. adjusted close"].values) /
                df_future["5. adjusted close"].values,
                c="red",
                lw=5,
            )
            plt.title(
                "BACKTESTING: Error between Real data and Prediction [%]")
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    0,
                    100 * (df_pred.values[0] -
                           df_future["5. adjusted close"].values[0]) /
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                ls="--",
                c="red",
            )
            plt.xlim(df_stock.index[-1],
                     df_pred.index[-1] + datetime.timedelta(days=1))
            plt.xticks(
                [
                    df_stock.index[-1],
                    df_pred.index[-1] + datetime.timedelta(days=1)
                ],
                visible=True,
            )
            plt.xlabel("Time")
            plt.ylabel("Prediction Error (%)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True,
                     which="minor",
                     color="#999999",
                     linestyle="-",
                     alpha=0.2)
            plt.legend(["Real data", "Prediction data"])

            if gtff.USE_ION:
                plt.ion()

            plt.show()

            # Refactor prediction dataframe for backtesting print
            df_pred.name = "Prediction"
            df_pred = df_pred.to_frame()
            df_pred["Real"] = df_future["5. adjusted close"]

            if gtff.USE_COLOR:

                patch_pandas_text_adjustment()

                print("Time         Real [$]  x  Prediction [$]")
                print(
                    df_pred.apply(price_prediction_backtesting_color,
                                  axis=1).to_string())
            else:
                print(df_pred[["Real", "Prediction"]].round(2).to_string())

            print("")
            print_prediction_kpis(df_pred["Real"].values,
                                  df_pred["Prediction"].values)

        else:
            # Print prediction data
            print_pretty_prediction(df_pred,
                                    df_stock["5. adjusted close"].values[-1])
        print("")

    except SystemExit:
        print("")
    except Exception as e:
        print(e)
        print("")
Example #12
0
def exponential_smoothing(l_args, s_ticker, df_stock):
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="ets",
        description="""
            Exponential Smoothing, see https://otexts.com/fpp2/taxonomy.html

            Trend='N',  Seasonal='N': Simple Exponential Smoothing
            Trend='N',  Seasonal='A': Exponential Smoothing
            Trend='N',  Seasonal='M': Exponential Smoothing
            Trend='A',  Seasonal='N': Holt’s linear method
            Trend='A',  Seasonal='A': Additive Holt-Winters’ method
            Trend='A',  Seasonal='M': Multiplicative Holt-Winters’ method
            Trend='Ad', Seasonal='N': Additive damped trend method
            Trend='Ad', Seasonal='A': Exponential Smoothing
            Trend='Ad', Seasonal='M': Holt-Winters’ damped method

            Trend component: N: None, A: Additive, Ad: Additive Damped
            Seasonality component: N: None, A: Additive, M: Multiplicative
        """,
    )

    parser.add_argument(
        "-d",
        "--days",
        action="store",
        dest="n_days",
        type=check_positive,
        default=5,
        help="prediction days.",
    )
    parser.add_argument(
        "-t",
        "--trend",
        action="store",
        dest="trend",
        type=check_valid_trend,
        default="N",
        help="Trend component: N: None, A: Additive, Ad: Additive Damped.",
    )
    parser.add_argument(
        "-s",
        "--seasonal",
        action="store",
        dest="seasonal",
        type=check_valid_seasonal,
        default="N",
        help="Seasonality component: N: None, A: Additive, M: Multiplicative.",
    )
    parser.add_argument(
        "-p",
        "--periods",
        action="store",
        dest="seasonal_periods",
        type=check_positive,
        default=5,
        help="Seasonal periods.",
    )
    parser.add_argument(
        "-e",
        "--end",
        action="store",
        type=valid_date,
        dest="s_end_date",
        default=None,
        help="The end date (format YYYY-MM-DD) to select - Backtesting",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, l_args)
        if not ns_parser:
            return

        # BACKTESTING
        if ns_parser.s_end_date:

            if ns_parser.s_end_date < df_stock.index[0]:
                print(
                    "Backtesting not allowed, since End Date is older than Start Date of historical data\n"
                )
                return

            if (ns_parser.s_end_date < get_next_stock_market_days(
                    last_stock_day=df_stock.index[0],
                    n_next_days=5 + ns_parser.n_days)[-1]):
                print(
                    "Backtesting not allowed, since End Date is too close to Start Date to train model\n"
                )
                return

            future_index = get_next_stock_market_days(
                last_stock_day=ns_parser.s_end_date,
                n_next_days=ns_parser.n_days)

            if future_index[-1] > datetime.datetime.now():
                print(
                    "Backtesting not allowed, since End Date + Prediction days is in the future\n"
                )
                return

            df_future = df_stock[future_index[0]:future_index[-1]]
            df_stock = df_stock[:ns_parser.s_end_date]

        # Get ETS model
        model, title = get_exponential_smoothing_model(
            df_stock["5. adjusted close"].values,
            ns_parser.trend,
            ns_parser.seasonal,
            ns_parser.seasonal_periods,
        )

        if model.mle_retvals.success:
            forecast = model.forecast(ns_parser.n_days)

            l_pred_days = get_next_stock_market_days(
                last_stock_day=df_stock["5. adjusted close"].index[-1],
                n_next_days=ns_parser.n_days,
            )
            df_pred = pd.Series(forecast, index=l_pred_days, name="Price")

            if ~np.isnan(forecast).any():

                print(f"\n{title}")
                print("\nFit model parameters:")
                for key, value in model.params.items():
                    print(f"{key} {' '*(18-len(key))}: {value}")

                print("\nAssess fit model:")
                print(f"AIC: {round(model.aic, 2)}")
                print(f"BIC: {round(model.bic, 2)}")
                print(f"SSE: {round(model.sse, 2)}\n")

                # Plotting
                plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
                plt.plot(df_stock.index, df_stock["5. adjusted close"], lw=2)
                # BACKTESTING
                if ns_parser.s_end_date:
                    plt.title(f"BACKTESTING: {title} on {s_ticker}")
                else:
                    plt.title(f"{title} on {s_ticker}")

                plt.xlim(
                    df_stock.index[0],
                    get_next_stock_market_days(df_pred.index[-1], 1)[-1],
                )
                plt.xlabel("Time")
                plt.ylabel("Share Price ($)")
                plt.grid(b=True, which="major", color="#666666", linestyle="-")
                plt.minorticks_on()
                plt.grid(b=True,
                         which="minor",
                         color="#999999",
                         linestyle="-",
                         alpha=0.2)
                plt.plot(
                    [df_stock.index[-1], df_pred.index[0]],
                    [
                        df_stock["5. adjusted close"].values[-1],
                        df_pred.values[0]
                    ],
                    lw=1,
                    c="tab:green",
                    linestyle="--",
                )
                plt.plot(df_pred.index, df_pred, lw=2, c="tab:green")
                plt.axvspan(
                    df_stock.index[-1],
                    df_pred.index[-1],
                    facecolor="tab:orange",
                    alpha=0.2,
                )
                _, _, ymin, ymax = plt.axis()
                plt.vlines(
                    df_stock.index[-1],
                    ymin,
                    ymax,
                    linewidth=1,
                    linestyle="--",
                    color="k",
                )

                # BACKTESTING
                if ns_parser.s_end_date:
                    plt.plot(
                        df_future.index,
                        df_future["5. adjusted close"],
                        lw=2,
                        c="tab:blue",
                        ls="--",
                    )
                    plt.plot(
                        [df_stock.index[-1], df_future.index[0]],
                        [
                            df_stock["5. adjusted close"].values[-1],
                            df_future["5. adjusted close"].values[0],
                        ],
                        lw=1,
                        c="tab:blue",
                        linestyle="--",
                    )

                if gtff.USE_ION:
                    plt.ion()

                plt.show()

                # BACKTESTING
                if ns_parser.s_end_date:
                    plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
                    plt.subplot(211)
                    plt.plot(
                        df_future.index,
                        df_future["5. adjusted close"],
                        lw=2,
                        c="tab:blue",
                        ls="--",
                    )
                    plt.plot(df_pred.index, df_pred, lw=2, c="green")
                    plt.scatter(
                        df_future.index,
                        df_future["5. adjusted close"],
                        c="tab:blue",
                        lw=3,
                    )
                    plt.plot(
                        [df_stock.index[-1], df_future.index[0]],
                        [
                            df_stock["5. adjusted close"].values[-1],
                            df_future["5. adjusted close"].values[0],
                        ],
                        lw=2,
                        c="tab:blue",
                        ls="--",
                    )
                    plt.scatter(df_pred.index, df_pred, c="green", lw=3)
                    plt.plot(
                        [df_stock.index[-1], df_pred.index[0]],
                        [
                            df_stock["5. adjusted close"].values[-1],
                            df_pred.values[0]
                        ],
                        lw=2,
                        c="green",
                        ls="--",
                    )
                    plt.title("BACKTESTING: Real data price versus Prediction")
                    plt.xlim(
                        df_stock.index[-1],
                        df_pred.index[-1] + datetime.timedelta(days=1),
                    )
                    plt.ylabel("Share Price ($)")
                    plt.grid(b=True,
                             which="major",
                             color="#666666",
                             linestyle="-")
                    plt.minorticks_on()
                    plt.grid(b=True,
                             which="minor",
                             color="#999999",
                             linestyle="-",
                             alpha=0.2)
                    plt.legend(["Real data", "Prediction data"])
                    plt.xticks([])

                    plt.subplot(212)
                    plt.axhline(y=0, color="k", linestyle="--", linewidth=2)
                    plt.plot(
                        df_future.index,
                        100 * (df_pred.values -
                               df_future["5. adjusted close"].values) /
                        df_future["5. adjusted close"].values,
                        lw=2,
                        c="red",
                    )
                    plt.scatter(
                        df_future.index,
                        100 * (df_pred.values -
                               df_future["5. adjusted close"].values) /
                        df_future["5. adjusted close"].values,
                        c="red",
                        lw=5,
                    )
                    plt.title(
                        "BACKTESTING: Error between Real data and Prediction [%]"
                    )
                    plt.plot(
                        [df_stock.index[-1], df_future.index[0]],
                        [
                            0,
                            100 * (df_pred.values[0] -
                                   df_future["5. adjusted close"].values[0]) /
                            df_future["5. adjusted close"].values[0],
                        ],
                        lw=2,
                        ls="--",
                        c="red",
                    )
                    plt.xlim(
                        df_stock.index[-1],
                        df_pred.index[-1] + datetime.timedelta(days=1),
                    )
                    plt.xlabel("Time")
                    plt.ylabel("Prediction Error (%)")
                    plt.grid(b=True,
                             which="major",
                             color="#666666",
                             linestyle="-")
                    plt.minorticks_on()
                    plt.grid(b=True,
                             which="minor",
                             color="#999999",
                             linestyle="-",
                             alpha=0.2)
                    plt.legend(["Real data", "Prediction data"])

                    if gtff.USE_ION:
                        plt.ion()

                    plt.show()

                    # Refactor prediction dataframe for backtesting print
                    df_pred.name = "Prediction"
                    df_pred = df_pred.to_frame()
                    df_pred["Real"] = df_future["5. adjusted close"]

                    if gtff.USE_COLOR:

                        patch_pandas_text_adjustment()

                        print("Time         Real [$]  x  Prediction [$]")
                        print(
                            df_pred.apply(price_prediction_backtesting_color,
                                          axis=1).to_string())
                    else:
                        print(df_pred[["Real",
                                       "Prediction"]].round(2).to_string())

                    print("")
                    print_prediction_kpis(df_pred["Real"].values,
                                          df_pred["Prediction"].values)

                else:
                    # Print prediction data
                    print_pretty_prediction(
                        df_pred, df_stock["5. adjusted close"].values[-1])
                print("")

            else:
                print(
                    "RuntimeWarning: invalid value encountered in double_scalars."
                )
        else:
            print("ConvergenceWarning: Optimization failed to converge.")

    except Exception as e:
        print(e)
        print("")
Example #13
0
def display_exponential_smoothing(
    ticker: str,
    values: Union[pd.DataFrame, pd.Series],
    n_predict: int,
    trend: str = "N",
    seasonal: str = "N",
    seasonal_periods: int = 5,
    s_end_date: str = "",
    export: str = "",
    time_res: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Perform exponential smoothing

    Parameters
    ----------
    ticker : str
        Dataset being smoothed
    values : Union[pd.DataFrame, pd.Series]
        Raw data
    n_predict : int
        Days to predict
    trend : str, optional
        Trend variable, by default "N"
    seasonal : str, optional
        Seasonal variable, by default "N"
    seasonal_periods : int, optional
        Number of seasonal periods, by default 5
    s_end_date : str, optional
        End date for backtesting, by default ""
    export : str, optional
        Format to export data, by default ""
    time_res : str
        Resolution for data, allowing for predicting outside of standard market days
    external_axes : Optional[List[plt.Axes]], optional
        External axes (1 axis is expected in the list), by default None
    """
    if s_end_date:
        if not time_res:
            future_index = get_next_stock_market_days(
                last_stock_day=s_end_date, n_next_days=n_predict
            )
        else:
            future_index = pd.date_range(
                s_end_date, periods=n_predict + 1, freq=time_res
            )[1:]

        if future_index[-1] > datetime.datetime.now():
            console.print(
                "Backtesting not allowed,"
                + " since End Date + Prediction days is in the future\n"
            )
            return

        df_future = values[future_index[0] : future_index[-1]]  # noqa: E203
        values = values[:s_end_date]  # type: ignore

    # Get ETS model
    model, title, forecast = ets_model.get_exponential_smoothing_model(
        values, trend, seasonal, seasonal_periods, n_predict
    )

    if not forecast:
        console.print("No forecast made.  Model did not converge.\n")
        return

    if np.isnan(forecast).any():
        console.print("Model predicted NaN values.  Runtime Error.\n")
        return

    if not time_res:
        l_pred_days = get_next_stock_market_days(
            last_stock_day=values.index[-1],
            n_next_days=n_predict,
        )
    else:
        l_pred_days = pd.date_range(
            values.index[-1], periods=n_predict + 1, freq=time_res
        )[1:]

    df_pred = pd.Series(forecast, index=l_pred_days, name="Price")

    console.print(f"\n{title}")
    console.print("\nFit model parameters:")
    for key, value in model.params.items():
        console.print(f"{key} {' '*(18-len(key))}: {value}")

    console.print("\nAssess fit model:")
    console.print(f"AIC: {round(model.aic, 2)}")
    console.print(f"BIC: {round(model.bic, 2)}")
    console.print(f"SSE: {round(model.sse, 2)}\n")

    # Plotting

    # This plot has 1 axes
    if external_axes is None:
        _, ax1 = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    else:
        if (not s_end_date and len(external_axes) != 1) or (
            s_end_date and len(external_axes) != 3
        ):
            console.print(
                "[red]Expected list of 1 axis item "
                + "or 3 axis items when backtesting./n[/red]"
            )
            return
        ax1 = external_axes[0]

    ax1.plot(values.index, values.values)

    # BACKTESTING
    if s_end_date:
        ax1.set_title(f"BACKTESTING: {title} on {ticker}", fontsize=12)
    else:
        ax1.set_title(f"{title} on {ticker}", fontsize=12)

    ax1.set_xlim(
        values.index[0],
        get_next_stock_market_days(df_pred.index[-1], 1)[-1],
    )
    ax1.set_ylabel("Value")
    ax1.plot(
        [values.index[-1], df_pred.index[0]],
        [values.values[-1], df_pred.values[0]],
        color=theme.down_color,
        linestyle="--",
    )
    ax1.plot(df_pred.index, df_pred, color=theme.down_color)
    ax1.axvspan(
        values.index[-1],
        df_pred.index[-1],
        facecolor=theme.down_color,
        alpha=0.2,
    )
    _, _, ymin, ymax = plt.axis()
    ax1.vlines(
        values.index[-1],
        ymin,
        ymax,
        linestyle="--",
        color=theme.get_colors(reverse=True)[0],
    )

    # BACKTESTING
    if s_end_date:
        ax1.plot(
            df_future.index,
            df_future,
            color=theme.up_color,
            linestyle="--",
        )
        ax1.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            color=theme.up_color,
            linestyle="--",
        )

    theme.style_primary_axis(ax1)

    if external_axes is None:
        theme.visualize_output()

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

        ax2.plot(
            df_future.index,
            df_future,
            color=theme.up_color,
            linestyle="--",
        )
        ax2.plot(df_pred.index, df_pred)
        ax2.scatter(
            df_future.index,
            df_future,
            color=theme.up_color,
        )
        ax2.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            color=theme.up_color,
            linestyle="--",
        )
        ax2.scatter(df_pred.index, df_pred)
        ax2.plot(
            [values.index[-1], df_pred.index[0]],
            [values.values[-1], df_pred.values[0]],
            linestyle="--",
        )
        ax2.set_title("BACKTESTING: Values")
        ax2.set_xlim(
            values.index[-1],
            df_pred.index[-1] + datetime.timedelta(days=1),
        )
        ax2.set_ylabel("Value")
        ax2.legend(["Real data", "Prediction data"])
        theme.style_primary_axis(ax2)

        ax3.axhline(y=0, linestyle="--")
        ax3.plot(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            color=theme.down_color,
        )
        ax3.scatter(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            color=theme.down_color,
        )
        ax3.set_title("BACKTESTING: % Error")
        ax3.plot(
            [values.index[-1], df_future.index[0]],
            [
                0,
                100 * (df_pred.values[0] - df_future.values[0]) / df_future.values[0],
            ],
            ls="--",
            color=theme.down_color,
        )
        ax3.set_xlim(
            values.index[-1],
            df_pred.index[-1] + datetime.timedelta(days=1),
        )
        ax3.set_ylabel("Prediction Error (%)")
        theme.style_primary_axis(ax3)

        if external_axes is None:
            theme.visualize_output()

        # Refactor prediction dataframe for backtesting print
        df_pred.name = "Prediction"
        df_pred = df_pred.to_frame()
        df_pred["Real"] = df_future

        if gtff.USE_COLOR:

            patch_pandas_text_adjustment()

            console.print("Time         Real [$]  x  Prediction [$]")
            console.print(
                df_pred.apply(
                    lambda_price_prediction_backtesting_color, axis=1
                ).to_string()
            )
        else:
            console.print(df_pred[["Real", "Prediction"]].round(2).to_string())

        console.print("")
        print_prediction_kpis(df_pred["Real"].values, df_pred["Prediction"].values)

    else:
        # Print prediction data
        print_pretty_prediction(df_pred, values.values[-1])
    export_data(export, os.path.dirname(os.path.abspath(__file__)), "ets")
Example #14
0
def simple_moving_average(l_args, s_ticker, df_stock):
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="sma",
        description="""
            Moving Averages are used to smooth the data in an array to
            help eliminate noise and identify trends. The Simple Moving Average is literally
            the simplest form of a moving average. Each output value is the average of the
            previous n values. In a Simple Moving Average, each value in the time period carries
            equal weight, and values outside of the time period are not included in the average.
            This makes it less responsive to recent changes in the data, which can be useful for
            filtering out those changes.
        """,
    )

    parser.add_argument(
        "-l",
        "--length",
        action="store",
        dest="n_length",
        type=check_positive,
        default=20,
        help="length of SMA window.",
    )
    parser.add_argument(
        "-d",
        "--days",
        action="store",
        dest="n_days",
        type=check_positive,
        default=5,
        help="prediction days.",
    )
    parser.add_argument(
        "-e",
        "--end",
        action="store",
        type=valid_date,
        dest="s_end_date",
        default=None,
        help="The end date (format YYYY-MM-DD) to select - Backtesting",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, l_args)
        if not ns_parser:
            return

        # BACKTESTING
        if ns_parser.s_end_date:

            if ns_parser.s_end_date < df_stock.index[0]:
                print(
                    "Backtesting not allowed, since End Date is older than Start Date of historical data\n"
                )
                return

            if (
                ns_parser.s_end_date
                < get_next_stock_market_days(
                    last_stock_day=df_stock.index[0], n_next_days=5 + ns_parser.n_days
                )[-1]
            ):
                print(
                    "Backtesting not allowed, since End Date is too close to Start Date to train model\n"
                )
                return

            future_index = get_next_stock_market_days(
                last_stock_day=ns_parser.s_end_date, n_next_days=ns_parser.n_days
            )

            if future_index[-1] > datetime.datetime.now():
                print(
                    "Backtesting not allowed, since End Date + Prediction days is in the future\n"
                )
                return

            df_future = df_stock[future_index[0] : future_index[-1]]
            df_stock = df_stock[: ns_parser.s_end_date]

        # Prediction data
        l_predictions = list()
        for pred_day in range(ns_parser.n_days):
            if pred_day < ns_parser.n_length:
                l_ma_stock = df_stock["5. adjusted close"].values[
                    -ns_parser.n_length + pred_day :
                ]
            else:
                l_ma_stock = list()
            l_predictions.append(np.mean(np.append(l_ma_stock, l_predictions)))

        l_pred_days = get_next_stock_market_days(
            last_stock_day=df_stock["5. adjusted close"].index[-1],
            n_next_days=ns_parser.n_days,
        )
        df_pred = pd.Series(l_predictions, index=l_pred_days, name="Price")

        # Plotting
        plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
        plt.plot(df_stock.index, df_stock["5. adjusted close"], lw=2)
        # BACKTESTING
        if ns_parser.s_end_date:
            plt.title(
                f"BACKTESTING: {ns_parser.n_length} Moving Average on {s_ticker} - {ns_parser.n_days} days prediction"
            )
        else:
            plt.title(
                f"{ns_parser.n_length} Moving Average on {s_ticker} - {ns_parser.n_days} days prediction"
            )
        plt.xlim(
            df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]
        )
        plt.xlabel("Time")
        plt.ylabel("Share Price ($)")
        plt.grid(b=True, which="major", color="#666666", linestyle="-")
        plt.minorticks_on()
        plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
        df_ma = df_stock["5. adjusted close"].rolling(window=ns_parser.n_length).mean()
        plt.plot(df_ma.index, df_ma, lw=2, linestyle="--", c="tab:orange")
        plt.plot(
            [df_stock.index[-1], df_pred.index[0]],
            [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
            lw=1,
            c="tab:green",
            linestyle="--",
        )
        plt.plot(df_pred.index, df_pred, lw=2, c="tab:green")
        plt.axvspan(
            df_stock.index[-1], df_pred.index[-1], facecolor="tab:orange", alpha=0.2
        )
        _, _, ymin, ymax = plt.axis()
        plt.vlines(
            df_stock.index[-1], ymin, ymax, linewidth=1, linestyle="--", color="k"
        )

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=1,
                c="tab:blue",
                linestyle="--",
            )

        if gtff.USE_ION:
            plt.ion()

        plt.show()

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
            plt.subplot(211)
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(df_pred.index, df_pred, lw=2, c="green")
            plt.scatter(
                df_future.index, df_future["5. adjusted close"], c="tab:blue", lw=3
            )
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.scatter(df_pred.index, df_pred, c="green", lw=3)
            plt.plot(
                [df_stock.index[-1], df_pred.index[0]],
                [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
                lw=2,
                c="green",
                ls="--",
            )
            plt.title("BACKTESTING: Real data price versus Prediction")
            plt.xlim(df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1))
            plt.xticks(
                [df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1)],
                visible=True,
            )
            plt.ylabel("Share Price ($)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
            plt.legend(["Real data", "Prediction data"])
            plt.xticks([])

            plt.subplot(212)
            plt.axhline(y=0, color="k", linestyle="--", linewidth=2)
            plt.plot(
                df_future.index,
                100
                * (df_pred.values - df_future["5. adjusted close"].values)
                / df_future["5. adjusted close"].values,
                lw=2,
                c="red",
            )
            plt.scatter(
                df_future.index,
                100
                * (df_pred.values - df_future["5. adjusted close"].values)
                / df_future["5. adjusted close"].values,
                c="red",
                lw=5,
            )
            plt.title("BACKTESTING: Error between Real data and Prediction [%]")
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    0,
                    100
                    * (df_pred.values[0] - df_future["5. adjusted close"].values[0])
                    / df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                ls="--",
                c="red",
            )
            plt.xlim(df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1))
            plt.xticks(
                [df_stock.index[-1], df_pred.index[-1] + datetime.timedelta(days=1)],
                visible=True,
            )
            plt.xlabel("Time")
            plt.ylabel("Prediction Error (%)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
            plt.legend(["Real data", "Prediction data"])

            if gtff.USE_ION:
                plt.ion()

            plt.show()

            # Refactor prediction dataframe for backtesting print
            df_pred.name = "Prediction"
            df_pred = df_pred.to_frame()
            df_pred["Real"] = df_future["5. adjusted close"]

            if gtff.USE_COLOR:

                patch_pandas_text_adjustment()

                print("Time         Real [$]  x  Prediction [$]")
                print(
                    df_pred.apply(
                        price_prediction_backtesting_color, axis=1
                    ).to_string()
                )
            else:
                print(df_pred[["Real", "Prediction"]].round(2).to_string())

            print("")
            print_prediction_kpis(df_pred["Real"].values, df_pred["Prediction"].values)

        else:
            # Print prediction data
            print_pretty_prediction(df_pred, df_stock["5. adjusted close"].values[-1])
        print("")

    except Exception as e:
        print(e)
        print("")
def print_insider_filter(
    preset_loaded: str,
    ticker: str,
    limit: int = 10,
    links: bool = False,
    export: str = "",
):
    """Print insider filter based on loaded preset. [Source: OpenInsider]

    Parameters
    ----------
    preset_loaded : str
        Loaded preset filter
    ticker : str
        Stock ticker
    limit : int
        Limit of rows of data to display
    links : bool
        Flag to show hyperlinks
    export : str
        Format to export data
    """
    if ticker:
        link = f"http://openinsider.com/screener?s={ticker}"
    else:
        link = get_open_insider_link(preset_loaded)

    if not link:
        console.print("")
        return

    df_insider = get_open_insider_data(link, has_company_name=bool(not ticker))
    df_insider_orig = df_insider.copy()

    if df_insider.empty:
        console.print("No insider data found\n")
        return

    if links:
        df_insider = df_insider[["Ticker Link", "Insider Link",
                                 "Filing Link"]].head(limit)
    else:
        df_insider = df_insider.drop(
            columns=["Filing Link", "Ticker Link", "Insider Link"]).head(limit)

    if rich_config.USE_COLOR and not links:
        if not df_insider[df_insider["Trade Type"] == "S - Sale"].empty:
            df_insider[df_insider["Trade Type"] == "S - Sale"] = df_insider[
                df_insider["Trade Type"] == "S - Sale"].apply(
                    lambda_red_highlight)
        if not df_insider[df_insider["Trade Type"] == "S - Sale+OE"].empty:
            df_insider[df_insider["Trade Type"] == "S - Sale+OE"] = df_insider[
                df_insider["Trade Type"] == "S - Sale+OE"].apply(
                    lambda_yellow_highlight)
        if not df_insider[df_insider["Trade Type"] == "F - Tax"].empty:
            df_insider[df_insider["Trade Type"] == "F - Tax"] = df_insider[
                df_insider["Trade Type"] == "F - Tax"].apply(
                    lambda_magenta_highlight)
        if not df_insider[df_insider["Trade Type"] == "P - Purchase"].empty:
            df_insider[df_insider["Trade Type"] ==
                       "P - Purchase"] = df_insider[df_insider["Trade Type"] ==
                                                    "P - Purchase"].apply(
                                                        lambda_green_highlight)

        patch_pandas_text_adjustment()
        pd.set_option("display.max_colwidth", 0)
        pd.set_option("display.max_rows", None)

        # needs to be done because table is too large :(
        df_insider = df_insider.drop(columns=["Filing Date", "Trade Type"])

    else:
        # needs to be done because table is too large :(
        df_insider = df_insider.drop(columns=["Filing Date"])

    console.print("")
    print_rich_table(
        df_insider,
        headers=[x.title() for x in df_insider.columns],
        title="Insider filtered",
    )

    if export:
        if preset_loaded:
            cmd = "filter"
        if ticker:
            cmd = "lis"

        export_data(export, os.path.dirname(os.path.abspath(__file__)), cmd,
                    df_insider)

    if not links:
        l_chars = [list(chars) for chars in df_insider_orig["X"].values]
        l_uchars = np.unique(list(itertools.chain(*l_chars)))
        console.print("")
        for char in l_uchars:
            console.print(d_notes[char])

        l_tradetype = df_insider_orig["Trade Type"].values
        l_utradetype = np.unique(l_tradetype)
        console.print("")
        for tradetype in l_utradetype:
            console.print(d_trade_types[tradetype])

    console.print("")
Example #16
0
def cash(other_args: List[str], ticker: str):
    """Market Watch ticker cash flow statement

    Parameters
    ----------
    other_args : List[str]
        argparse other args
    ticker : str
        Fundamental analysis ticker symbol
    """
    parser = argparse.ArgumentParser(
        add_help=False,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        prog="cash_flow",
        description="""
            Prints either yearly or quarterly cash flow operating activities of the company.
            The following fields are expected: Net Income before Extraordinaries, Net Income
            Growth, Depreciation, Depletion & Amortization, Depreciation and Depletion,
            Amortization of Intangible Assets, Deferred Taxes & Investment Tax Credit, Deferred
            Taxes, Investment Tax Credit, Other Funds, Funds from Operations, Extraordinaries,
            Changes in Working Capital, Receivables, Accounts Payable, Other Assets/Liabilities,
            and Net Operating Cash Flow Growth.

            Prints either yearly or quarterly cash flow investing activities of the company.
            The following fields are expected: Capital Expenditures, Capital Expenditures Growth,
            Capital Expenditures/Sales, Capital Expenditures (Fixed Assets), Capital Expenditures
            (Other Assets), Net Assets from Acquisitions, Sale of Fixed Assets & Businesses,
            Purchase/Sale of Investments, Purchase of Investments, Sale/Maturity of Investments,
            Other Uses, Other Sources, Net Investing Cash Flow Growth.

            Prints either yearly or quarterly cash flow financing activities of the company.
            The following fields are expected: Cash Dividends Paid - Total, Common Dividends,
            Preferred Dividends, Change in Capital Stock, Repurchase of Common & Preferred Stk.,
            Sale of Common & Preferred Stock, Proceeds from Stock Options, Other Proceeds from Sale
            of Stock, Issuance/Reduction of Debt, Net, Change in Current Debt, Change in Long-Term
            Debt, Issuance of Long-Term Debt, Reduction in Long-Term Debt, Other Funds, Other Uses,
            Other Sources, Net Financing Cash Flow Growth, Net Financing Cash Flow/Sales, Exchange
            Rate Effect, Miscellaneous Funds, Net Change in Cash, Free Cash Flow, Free Cash Flow
            Growth, Free Cash Flow Yield, Net Operating Cash Flow, Net Investing Cash Flow, Net
            Financing Cash Flow.
            [Source: Market Watch]
        """,
    )
    parser.add_argument(
        "-q",
        "--quarter",
        action="store_true",
        default=False,
        dest="b_quarter",
        help="Quarter fundamental data flag.",
    )

    ns_parser = parse_known_args_and_warn(parser, other_args)
    if not ns_parser:
        return

    df_financials = mwm.prepare_df_financials(ticker, "cashflow",
                                              ns_parser.b_quarter)

    if gtff.USE_COLOR:
        df_financials = df_financials.applymap(financials_colored_values)

        patch_pandas_text_adjustment()
        pd.set_option("display.max_colwidth", None)
        pd.set_option("display.max_rows", None)

    if df_financials.empty:
        print("Marketwatch does not yet provide financials for this ticker")
    else:
        print(df_financials.to_string(index=False))
    print("")
Example #17
0
def income(other_args: List[str], ticker: str):
    """Market Watch ticker income statement

    Parameters
    ----------
    other_args : List[str]
        argparse other args
    ticker : str
        Fundamental analysis ticker symbol
    """
    parser = argparse.ArgumentParser(
        add_help=False,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        prog="income",
        description="""
            Prints either yearly or quarterly income statement the company. The following fields
            are expected: Sales Growth, Cost of Goods Sold (COGS) incl. D&A, COGS Growth, COGS
            excluding D&A, Depreciation & Amortization Expense, Depreciation, Amortization of
            Intangibles, Gross Income, Gross Income Growth, Gross Profit Margin, SG&A Expense, SGA
            Growth, Research & Development, Other SG&A, Other Operating Expense, Unusual Expense,
            EBIT after Unusual Expense, Non Operating Income/Expense, Non-Operating Interest
            Income, Equity in Affiliates (Pretax), Interest Expense, Interest Expense Growth,
            Gross Interest Expense, Interest Capitalized, Pretax Income, Pretax Income Growth,
            Pretax Margin, Income Tax, Income Tax - Current Domestic, Income Tax - Current Foreign,
            Income Tax - Deferred Domestic, Income Tax - Deferred Foreign, Income Tax Credits,
            Equity in Affiliates, Other After Tax Income (Expense), Consolidated Net Income,
            Minority Interest Expense, Net Income Growth, Net Margin Growth, Extraordinaries &
            Discontinued Operations, Extra Items & Gain/Loss Sale Of Assets, Cumulative Effect -
            Accounting Chg, Discontinued Operations, Net Income After Extraordinaries,
            Preferred Dividends, Net Income Available to Common, EPS (Basic), EPS (Basic) Growth,
            Basic Shares Outstanding, EPS (Diluted), EPS (Diluted) Growth, Diluted Shares
            Outstanding, EBITDA, EBITDA Growth, EBITDA Margin, Sales/Revenue, and Net Income.
            [Source: Market Watch]
        """,
    )
    parser.add_argument(
        "-q",
        "--quarter",
        action="store_true",
        default=False,
        dest="b_quarter",
        help="Quarter fundamental data flag.",
    )

    ns_parser = parse_known_args_and_warn(parser, other_args)
    if not ns_parser:
        return

    df_financials = mwm.prepare_df_financials(ticker, "income",
                                              ns_parser.b_quarter)

    if gtff.USE_COLOR:
        df_financials = df_financials.applymap(financials_colored_values)

        patch_pandas_text_adjustment()
        pd.set_option("display.max_colwidth", None)
        pd.set_option("display.max_rows", None)

    if df_financials.empty:
        print("Marketwatch does not yet provide financials for this ticker")
    else:
        print(df_financials.to_string(index=False))
    print("")
Example #18
0
def print_insider_filter(other_args: List[str], preset_loaded: str):
    """Print insider filter based on loaded preset

    Parameters
    ----------
    other_args : List[str]
        Command line arguments to be processed with argparse
    preset_loaded: str
        Loaded preset filter
    """
    parser = argparse.ArgumentParser(
        add_help=False,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        prog="filter",
        description=
        "Print open insider filtered data using loaded preset, or selected ticker. [Source: OpenInsider]",
    )
    parser.add_argument(
        "-n",
        "--num",
        action="store",
        dest="num",
        type=check_positive,
        default=20,
        help="Number of datarows to display",
    )
    parser.add_argument(
        "-t",
        "--ticker",
        action="store",
        dest="ticker",
        type=str,
        default="",
        help="Filter latest insiders from this ticker",
    )
    parser.add_argument(
        "-l",
        "--links",
        action="store_true",
        default=False,
        help="Flag to show hyperlinks",
        dest="links",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return

        if ns_parser.ticker:
            link = f"http://openinsider.com/screener?s={ns_parser.ticker}"
        else:
            link = get_open_insider_link(preset_loaded)

        if not link:
            print("")
            return

        df_insider = get_open_insider_data(
            link, has_company_name=bool(not ns_parser.ticker))
        df_insider_orig = df_insider.copy()

        if df_insider.empty:
            print("")
            return

        if ns_parser.links:
            df_insider = df_insider[[
                "Ticker Link", "Insider Link", "Filing Link"
            ]].head(ns_parser.num)
        else:
            df_insider = df_insider.drop(
                columns=["Filing Link", "Ticker Link", "Insider Link"]).head(
                    ns_parser.num)

        if gtff.USE_COLOR and not ns_parser.links:
            if not df_insider[df_insider["Trade Type"] == "S - Sale"].empty:
                df_insider[df_insider["Trade Type"] ==
                           "S - Sale"] = df_insider[df_insider["Trade Type"] ==
                                                    "S - Sale"].apply(
                                                        red_highlight)
            if not df_insider[df_insider["Trade Type"] == "S - Sale+OE"].empty:
                df_insider[df_insider["Trade Type"] ==
                           "S - Sale+OE"] = df_insider[df_insider["Trade Type"]
                                                       == "S - Sale+OE"].apply(
                                                           yellow_highlight)
            if not df_insider[df_insider["Trade Type"] == "F - Tax"].empty:
                df_insider[df_insider["Trade Type"] == "F - Tax"] = df_insider[
                    df_insider["Trade Type"] == "F - Tax"].apply(
                        magenta_highlight)
            if not df_insider[df_insider["Trade Type"] ==
                              "P - Purchase"].empty:
                df_insider[
                    df_insider["Trade Type"] == "P - Purchase"] = df_insider[
                        df_insider["Trade Type"] == "P - Purchase"].apply(
                            green_highlight)

            patch_pandas_text_adjustment()
            pd.set_option("display.max_colwidth", 0)
            pd.set_option("display.max_rows", None)

            # needs to be done because table is too large :(
            df_insider = df_insider.drop(columns=["Filing Date", "Trade Type"])

        else:
            # needs to be done because table is too large :(
            df_insider = df_insider.drop(columns=["Filing Date"])

        print("")
        print(df_insider.to_string(index=False))

        if not ns_parser.links:
            l_chars = [list(chars) for chars in df_insider_orig["X"].values]
            l_uchars = np.unique(list(itertools.chain(*l_chars)))
            print("")
            for char in l_uchars:
                print(d_notes[char])

            l_tradetype = df_insider_orig["Trade Type"].values
            l_utradetype = np.unique(l_tradetype)
            print("")
            for tradetype in l_utradetype:
                print(d_trade_types[tradetype])

        print("")

    except Exception as e:
        print(e, "\n")
Example #19
0
def display_exponential_smoothing(
    ticker: str,
    values: Union[pd.DataFrame, pd.Series],
    n_predict: int,
    trend: str = "N",
    seasonal: str = "N",
    seasonal_periods: int = 5,
    s_end_date: str = "",
    export: str = "",
    time_res: str = "",
):
    """Perform exponential smoothing

    Parameters
    ----------
    ticker : str
        Dataset being smoothed
    values : Union[pd.DataFrame, pd.Series]
        Raw data
    n_predict : int
        Days to predict
    trend : str, optional
        Trend variable, by default "N"
    seasonal : str, optional
        Seasonal variable, by default "N"
    seasonal_periods : int, optional
        Number of seasonal periods, by default 5
    s_end_date : str, optional
        End date for backtesting, by default ""
    export : str, optional
        Format to export data, by default ""
    time_res : str
        Resolution for data, allowing for predicting outside of standard market days
    """
    if s_end_date:
        if not time_res:
            future_index = get_next_stock_market_days(
                last_stock_day=s_end_date, n_next_days=n_predict)
        else:
            future_index = pd.date_range(s_end_date,
                                         periods=n_predict + 1,
                                         freq=time_res)[1:]

        if future_index[-1] > datetime.datetime.now():
            console.print(
                "Backtesting not allowed, since End Date + Prediction days is in the future\n"
            )
            return

        df_future = values[future_index[0]:future_index[-1]]
        values = values[:s_end_date]  # type: ignore

    # Get ETS model
    model, title, forecast = ets_model.get_exponential_smoothing_model(
        values, trend, seasonal, seasonal_periods, n_predict)

    if not forecast:
        console.print("No forecast made.  Model did not converge.\n")
        return

    if np.isnan(forecast).any():
        console.print("Model predicted NaN values.  Runtime Error.\n")
        return

    if not time_res:
        l_pred_days = get_next_stock_market_days(
            last_stock_day=values.index[-1],
            n_next_days=n_predict,
        )
    else:
        l_pred_days = pd.date_range(values.index[-1],
                                    periods=n_predict + 1,
                                    freq=time_res)[1:]

    df_pred = pd.Series(forecast, index=l_pred_days, name="Price")

    console.print(f"\n{title}")
    console.print("\nFit model parameters:")
    for key, value in model.params.items():
        console.print(f"{key} {' '*(18-len(key))}: {value}")

    console.print("\nAssess fit model:")
    console.print(f"AIC: {round(model.aic, 2)}")
    console.print(f"BIC: {round(model.bic, 2)}")
    console.print(f"SSE: {round(model.sse, 2)}\n")

    # Plotting
    fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    ax.plot(values.index, values.values, lw=2)
    # BACKTESTING
    if s_end_date:
        ax.set_title(f"BACKTESTING: {title} on {ticker}")
    else:
        ax.set_title(f"{title} on {ticker}")

    ax.set_xlim(
        values.index[0],
        get_next_stock_market_days(df_pred.index[-1], 1)[-1],
    )
    ax.set_xlabel("Time")
    ax.set_ylabel("Share Price ($)")
    ax.grid(b=True, which="major", color="#666666", linestyle="-")
    ax.minorticks_on()
    ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
    ax.plot(
        [values.index[-1], df_pred.index[0]],
        [values.values[-1], df_pred.values[0]],
        lw=1,
        c="tab:green",
        linestyle="--",
    )
    ax.plot(df_pred.index, df_pred, lw=2, c="tab:green")
    ax.axvspan(
        values.index[-1],
        df_pred.index[-1],
        facecolor="tab:orange",
        alpha=0.2,
    )
    _, _, ymin, ymax = plt.axis()
    ax.vlines(
        values.index[-1],
        ymin,
        ymax,
        linewidth=1,
        linestyle="--",
        color="k",
    )
    dateFmt = mdates.DateFormatter("%m/%d/%Y")
    ax.xaxis.set_major_formatter(dateFmt)
    ax.tick_params(axis="x", labelrotation=45)

    # BACKTESTING
    if s_end_date:
        ax.plot(
            df_future.index,
            df_future,
            lw=2,
            c="tab:blue",
            ls="--",
        )
        ax.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            lw=1,
            c="tab:blue",
            linestyle="--",
        )

    if gtff.USE_ION:
        plt.ion()

    fig.tight_layout()
    plt.show()

    # BACKTESTING
    if s_end_date:
        dateFmt = mdates.DateFormatter("%m-%d")
        fig, ax = plt.subplots(1, 2, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax0 = ax[0]
        ax0.plot(
            df_future.index,
            df_future,
            lw=2,
            c="tab:blue",
            ls="--",
        )
        ax0.plot(df_pred.index, df_pred, lw=2, c="green")
        ax0.scatter(
            df_future.index,
            df_future,
            c="tab:blue",
            lw=3,
        )
        ax0.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            lw=2,
            c="tab:blue",
            ls="--",
        )
        ax0.scatter(df_pred.index, df_pred, c="green", lw=3)
        ax0.plot(
            [values.index[-1], df_pred.index[0]],
            [values.values[-1], df_pred.values[0]],
            lw=2,
            c="green",
            ls="--",
        )
        ax0.set_title("BACKTESTING: Prices")
        ax0.set_xlim(
            values.index[-1],
            df_pred.index[-1] + datetime.timedelta(days=1),
        )
        ax0.set_ylabel("Share Price ($)")
        ax0.grid(b=True, which="major", color="#666666", linestyle="-")
        ax0.legend(["Real data", "Prediction data"])

        ax1 = ax[1]
        ax1.axhline(y=0, color="k", linestyle="--", linewidth=2)
        ax1.plot(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            lw=2,
            c="red",
        )
        ax1.scatter(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            c="red",
            lw=5,
        )
        ax1.set_title("BACKTESTING: % Error")
        ax1.plot(
            [values.index[-1], df_future.index[0]],
            [
                0,
                100 * (df_pred.values[0] - df_future.values[0]) /
                df_future.values[0],
            ],
            lw=2,
            ls="--",
            c="red",
        )
        ax1.set_xlim(
            values.index[-1],
            df_pred.index[-1] + datetime.timedelta(days=1),
        )
        ax1.set_xlabel("Time")
        ax1.set_ylabel("Prediction Error (%)")
        ax1.grid(b=True, which="major", color="#666666", linestyle="-")
        ax1.legend(["Real data", "Prediction data"])

        ax0.xaxis.set_major_formatter(dateFmt)
        ax0.tick_params(axis="x", labelrotation=45)
        ax1.xaxis.set_major_formatter(dateFmt)
        ax1.tick_params(axis="x", labelrotation=45)

        if gtff.USE_ION:
            plt.ion()
        fig.tight_layout()
        plt.show()

        # Refactor prediction dataframe for backtesting print
        df_pred.name = "Prediction"
        df_pred = df_pred.to_frame()
        df_pred["Real"] = df_future

        if gtff.USE_COLOR:

            patch_pandas_text_adjustment()

            console.print("Time         Real [$]  x  Prediction [$]")
            console.print(
                df_pred.apply(price_prediction_backtesting_color,
                              axis=1).to_string())
        else:
            console.print(df_pred[["Real", "Prediction"]].round(2).to_string())

        console.print("")
        print_prediction_kpis(df_pred["Real"].values,
                              df_pred["Prediction"].values)

    else:
        # Print prediction data
        print_pretty_prediction(df_pred, values.values[-1])
    export_data(export, os.path.dirname(os.path.abspath(__file__)), "ets")

    console.print("")
Example #20
0
def display_regression(
    dataset: str,
    values: Union[pd.Series, pd.DataFrame],
    poly_order: int,
    n_input: int,
    n_predict: int,
    n_jumps: int,
    s_end_date: str = "",
    export: str = "",
    time_res: str = "",
):
    """Display predications for regression models

    Parameters
    ----------
    dataset : str
        Title for data
    values : Union[pd.Series, pd.DataFrame]
        Data to fit
    poly_order : int
        Order of polynomial to fit
    n_input : int
        Length of input sequence
    n_predict : int
        Length of prediction sequence
    n_jumps : int
        Number of jumps in data
    s_end_date : str, optional
        Start date for backtesting
    export : str, optional
        Format for exporting figures
    time_res : str
        Resolution for data, allowing for predicting outside of standard market days
    """
    # BACKTESTING
    if s_end_date:
        if not time_res:
            future_index = get_next_stock_market_days(
                last_stock_day=s_end_date, n_next_days=n_predict)
        else:
            future_index = pd.date_range(s_end_date,
                                         periods=n_predict + 1,
                                         freq=time_res)[1:]

        df_future = values[future_index[0]:future_index[-1]]
        values = values[:s_end_date]  # type: ignore

    l_predictions, _ = regression_model.get_regression_model(
        values, poly_order, n_input, n_predict, n_jumps)

    # Prediction data
    if not time_res:
        l_pred_days = get_next_stock_market_days(
            last_stock_day=values.index[-1],
            n_next_days=n_predict,
        )
    else:
        l_pred_days = pd.date_range(values.index[-1],
                                    periods=n_predict + 1,
                                    freq=time_res)[1:]
    df_pred = pd.Series(l_predictions, index=l_pred_days, name="Price")

    # Plotting
    fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    ax.plot(values.index, values, lw=2)
    # BACKTESTING
    if s_end_date:
        ax.set_title(
            f"BACKTESTING: Regression (polynomial {poly_order}) on {dataset} - {n_predict} step prediction"
        )
    else:
        ax.set_title(
            f"Regression (polynomial {poly_order}) on {dataset} - {n_predict} step prediction"
        )
    ax.set_xlim(values.index[0], l_pred_days[-1])
    ax.set_xlabel("Time")
    ax.set_ylabel("Value")
    ax.grid(b=True, which="major", color="#666666", linestyle="-")
    ax.minorticks_on()
    ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
    ax.plot(
        [values.index[-1], df_pred.index[0]],
        [values.values[-1], df_pred.values[0]],
        lw=1,
        c="tab:green",
        linestyle="--",
    )
    ax.plot(df_pred.index, df_pred, lw=2, c="tab:green")
    ax.axvspan(values.index[-1],
               df_pred.index[-1],
               facecolor="tab:orange",
               alpha=0.2)
    _, _, ymin, ymax = plt.axis()
    ax.vlines(values.index[-1],
              ymin,
              ymax,
              linewidth=1,
              linestyle="--",
              color="k")

    # BACKTESTING
    if s_end_date:
        ax.plot(
            df_future.index,
            df_future,
            lw=2,
            c="tab:blue",
            ls="--",
        )
        ax.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            lw=1,
            c="tab:blue",
            linestyle="--",
        )
    fig.tight_layout()
    if gtff.USE_ION:
        plt.ion()

    plt.show()

    export_data(export, os.path.dirname(os.path.abspath(__file__)),
                "regression")
    console.print("")

    # BACKTESTING
    if s_end_date:
        fig, ax = plt.subplots(1, 2, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax0 = ax[0]
        ax0.plot(
            df_future.index,
            df_future,
            lw=2,
            c="tab:blue",
            ls="--",
        )
        ax0.plot(df_pred.index, df_pred, lw=2, c="green")
        ax0.scatter(df_future.index, df_future, c="tab:blue", lw=3)
        ax0.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            lw=2,
            c="tab:blue",
            ls="--",
        )
        ax0.scatter(df_pred.index, df_pred, c="green", lw=3)
        ax0.plot(
            [values.index[-1], df_pred.index[0]],
            [values.values[-1], df_pred.values[0]],
            lw=2,
            c="green",
            ls="--",
        )
        ax0.set_title("BACKTESTING: Real data vs Prediction")
        ax0.set_xlim(values.index[-1], df_pred.index[-1])
        ax0.set_xticks([values.index[-1], df_pred.index[-1]])
        ax0.set_ylabel("Value")
        ax0.grid(b=True, which="major", color="#666666", linestyle="-")
        ax0.minorticks_on()
        ax0.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)
        ax0.legend(["Real data", "Prediction data"])
        ax0.set_xticks([])

        ax1 = ax[1]
        ax1.axhline(y=0, color="k", linestyle="--", linewidth=2)
        ax1.plot(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            lw=2,
            c="red",
        )
        ax1.scatter(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            c="red",
            lw=5,
        )
        ax1.set_title(
            "BACKTESTING: Error between Real data and Prediction [%]")
        ax1.plot(
            [values.index[-1], df_future.index[0]],
            [
                0,
                100 * (df_pred.values[0] - df_future.values[0]) /
                df_future.values[0],
            ],
            lw=2,
            ls="--",
            c="red",
        )
        ax1.set_xlim(values.index[-1], df_pred.index[-1])
        ax1.set_xticks([values.index[-1], df_pred.index[-1]])
        ax1.set_xlabel("Time")
        ax1.set_ylabel("Prediction Error (%)")
        ax1.grid(b=True, which="major", color="#666666", linestyle="-")
        ax1.minorticks_on()
        ax1.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)
        ax1.legend(["Real data", "Prediction data"])
        fig.tight_layout()
        if gtff.USE_ION:
            plt.ion()

        plt.show()

        # Refactor prediction dataframe for backtesting print
        df_pred.name = "Prediction"
        df_pred = df_pred.to_frame()
        df_pred["Real"] = df_future

        if gtff.USE_COLOR:

            patch_pandas_text_adjustment()

            console.print("Time         Real [$]  x  Prediction [$]")
            console.print(
                df_pred.apply(price_prediction_backtesting_color,
                              axis=1).to_string())
        else:
            console.print(df_pred[["Real", "Prediction"]].round(2).to_string())

        console.print("")
        print_prediction_kpis(df_pred["Real"].values,
                              df_pred["Prediction"].values)

    else:
        # Print prediction data
        print_pretty_prediction(df_pred, values.values[-1])
    console.print("")
def orders(l_args):
    parser = argparse.ArgumentParser(
        prog="orders",
        description="""
            Orders by Fidelity customers. Information shown in the table below
            is based on the volume of orders entered on the "as of" date shown. Securities
            identified are not recommended or endorsed by Fidelity and are displayed for
            informational purposes only. [Source: Fidelity]
        """,
    )

    parser.add_argument(
        "-n",
        "--num",
        action="store",
        dest="n_num",
        type=check_positive,
        default=10,
        help="Number of top ordered stocks to be printed.",
    )

    ns_parser = parse_known_args_and_warn(parser, l_args)

    url_orders = (
        "https://eresearch.fidelity.com/eresearch/gotoBL/fidelityTopOrders.jhtml"
    )

    text_soup_url_orders = BeautifulSoup(
        requests.get(url_orders, headers={
            "User-Agent": get_user_agent()
        }).text, "lxml")

    l_orders = list()
    l_orders_vals = list()
    idx = 0
    order_list = text_soup_url_orders.findAll(
        "td",
        {
            "class": [
                "second", "third", "fourth", "fifth", "sixth", "seventh",
                "eight"
            ]
        },
    )
    for an_order in order_list:
        if ((idx + 1) % 3 == 0) or ((idx + 1) % 4 == 0) or ((idx + 1) % 6
                                                            == 0):
            if not an_order:
                l_orders_vals.append("")
            else:
                l_orders_vals.append(an_order.contents[1])
        elif (idx + 1) % 5 == 0:
            s_orders = str(an_order)
            l_orders_vals.append(s_orders[s_orders.find('title="') +
                                          len('title="'):s_orders.find('"/>')])
        else:
            l_orders_vals.append(an_order.text.strip())

        idx += 1

        # Add value to dictionary
        if (idx + 1) % 8 == 0:
            l_orders.append(l_orders_vals)
            l_orders_vals = list()
            idx = 0

    df_orders = pd.DataFrame(
        l_orders,
        columns=[
            "Symbol",
            "Company",
            "Price Change",
            "# Buy Orders",
            "Buy / Sell Ratio",
            "# Sell Orders",
            "Latest News",
        ],
    )

    df_orders = df_orders[[
        "Symbol",
        "Buy / Sell Ratio",
        "Price Change",
        "Company",
        "# Buy Orders",
        "# Sell Orders",
        "Latest News",
    ]]

    print(
        text_soup_url_orders.findAll("span", {"class": "source"})
        [0].text.capitalize() + ":")

    pd.set_option("display.max_colwidth", -1)

    if USE_COLOR:
        df_orders["Buy / Sell Ratio"] = df_orders["Buy / Sell Ratio"].apply(
            buy_sell_ratio_color_red_green)
        df_orders["Price Change"] = df_orders["Price Change"].apply(
            price_change_color_red_green)

        patch_pandas_text_adjustment()

    print(
        df_orders.head(n=ns_parser.n_num).iloc[:, :-1].to_string(index=False))
    print("")
Example #22
0
def display_regression(
    dataset: str,
    values: Union[pd.Series, pd.DataFrame],
    poly_order: int,
    n_input: int,
    n_predict: int,
    n_jumps: int,
    s_end_date: str = "",
    export: str = "",
    time_res: str = "",
    external_axes: Optional[List[plt.Axes]] = None,
):
    """Display predications for regression models

    Parameters
    ----------
    dataset : str
        Title for data
    values : Union[pd.Series, pd.DataFrame]
        Data to fit
    poly_order : int
        Order of polynomial to fit
    n_input : int
        Length of input sequence
    n_predict : int
        Length of prediction sequence
    n_jumps : int
        Number of jumps in data
    s_end_date : str, optional
        Start date for backtesting
    export : str, optional
        Format for exporting figures
    time_res : str
        Resolution for data, allowing for predicting outside of standard market days
    external_axes : Optional[List[plt.Axes]], optional
        External axes (1 axis is expected in the list), by default None
    """
    # BACKTESTING
    if s_end_date:
        if not time_res:
            future_index = get_next_stock_market_days(
                last_stock_day=s_end_date, n_next_days=n_predict
            )
        else:
            future_index = pd.date_range(
                s_end_date, periods=n_predict + 1, freq=time_res
            )[1:]

        df_future = values[future_index[0] : future_index[-1]]  # noqa: E203
        values = values[:s_end_date]  # type: ignore

    l_predictions, _ = regression_model.get_regression_model(
        list(values.values), poly_order, n_input, n_predict, n_jumps
    )

    # Prediction data
    if not time_res:
        l_pred_days = get_next_stock_market_days(
            last_stock_day=values.index[-1],
            n_next_days=n_predict,
        )
    else:
        l_pred_days = pd.date_range(
            values.index[-1], periods=n_predict + 1, freq=time_res
        )[1:]
    df_pred = pd.Series(l_predictions, index=l_pred_days, name="Price")

    # Plotting

    # This plot has 1 axes
    if external_axes is None:
        _, ax1 = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    else:
        if (not s_end_date and len(external_axes) != 1) or (
            s_end_date and len(external_axes) != 3
        ):
            logger.error("Expected list of 1 axis or 3 axes when backtesting.")
            console.print(
                "[red]Expected list of 1 axis or 3 axes when backtesting./n[/red]"
            )
            return
        ax1 = external_axes[0]

    ax1.plot(values.index, values)
    # BACKTESTING
    if s_end_date:
        ax1.set_title(
            f"BACKTESTING: Regression (polynomial {poly_order}) on {dataset} - {n_predict} step prediction",
            fontsize=12,
        )
    else:
        ax1.set_title(
            f"Regression (polynomial {poly_order}) on {dataset} - {n_predict} step prediction"
        )
    ax1.set_xlim(values.index[0], l_pred_days[-1])
    ax1.set_ylabel("Value")
    ax1.plot(
        [values.index[-1], df_pred.index[0]],
        [values.values[-1], df_pred.values[0]],
        color=theme.down_color,
        linestyle="--",
    )
    ax1.plot(df_pred.index, df_pred, color=theme.down_color)
    ax1.axvspan(values.index[-1], df_pred.index[-1], alpha=0.2)
    _, _, ymin, ymax = plt.axis()
    ax1.vlines(values.index[-1], ymin, ymax, linestyle="--")

    # BACKTESTING
    if s_end_date:
        ax1.plot(
            df_future.index,
            df_future,
            color=theme.up_color,
            linestyle="--",
        )
        ax1.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            color=theme.up_color,
            linestyle="--",
        )

    theme.style_primary_axis(ax1)

    if external_axes is None:
        theme.visualize_output()

    export_data(export, os.path.dirname(os.path.abspath(__file__)), "regression")
    console.print("")

    # BACKTESTING
    if s_end_date:
        # This plot has 1 axes
        if external_axes is None:
            _, axes = plt.subplots(
                2, 1, sharex=True, figsize=plot_autoscale(), dpi=PLOT_DPI
            )
            (ax2, ax3) = axes
        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
            (_, ax2, ax3) = external_axes

        ax2.plot(
            df_future.index,
            df_future,
            color=theme.up_color,
            linestyle="--",
        )
        ax2.plot(df_pred.index, df_pred, color=theme.down_color, marker="o")
        ax2.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            color=theme.up_color,
            linestyle="--",
        )
        ax2.plot(
            [values.index[-1], df_pred.index[0]],
            [values.values[-1], df_pred.values[0]],
            color=theme.down_color,
            linestyle="--",
            marker="o",
        )
        ax2.set_title("BACKTESTING: Real data vs Prediction", fontsize=12)
        ax2.set_xlim(values.index[-1], df_pred.index[-1])
        ax2.set_ylabel("Value")
        ax2.legend(["Real data", "Prediction data"])

        ax3.axhline(y=0, linestyle="--", color=theme.up_color)
        ax3.plot(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            color=theme.down_color,
            marker="o",
        )
        ax3.set_title(
            "BACKTESTING: Error between Real data and Prediction [%]", fontsize=12
        )
        ax3.plot(
            [values.index[-1], df_future.index[0]],
            [
                0,
                100 * (df_pred.values[0] - df_future.values[0]) / df_future.values[0],
            ],
            linestyle="--",
            color=theme.down_color,
        )
        ax3.set_xlim(values.index[-1], df_pred.index[-1])
        ax3.set_xlabel("Time")
        ax3.set_ylabel("Error (%)")
        ax3.legend(["Real data", "Prediction data"])

        theme.style_primary_axis(ax2)
        theme.style_primary_axis(ax3)

        if external_axes is None:
            theme.visualize_output()

        # Refactor prediction dataframe for backtesting print
        df_pred.name = "Prediction"
        df_pred = df_pred.to_frame()
        df_pred["Real"] = df_future

        if rich_config.USE_COLOR:

            patch_pandas_text_adjustment()

            console.print("Time         Real [$]  x  Prediction [$]")
            console.print(
                df_pred.apply(
                    lambda_price_prediction_backtesting_color, axis=1
                ).to_string()
            )
        else:
            console.print(df_pred[["Real", "Prediction"]].round(2).to_string())

        console.print("")
        print_prediction_kpis(df_pred["Real"].values, df_pred["Prediction"].values)

    else:
        # Print prediction data
        print_pretty_prediction(df_pred, values.values[-1])
    console.print("")
Example #23
0
def arima(other_args: List[str], s_ticker: str, df_stock: pd.DataFrame):
    """
    ARIMA prediction
    Parameters
    ----------
    other_args: List[str]
        Argparse arguments
    s_ticker: str
        ticker
    df_stock: pd.DataFrame
        Dataframe of prices

    """
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="arima",
        description="""
            In statistics and econometrics, and in particular in time series analysis, an
            autoregressive integrated moving average (ARIMA) model is a generalization of an
            autoregressive moving average (ARMA) model. Both of these models are fitted to time
            series data either to better understand the data or to predict future points in the
            series (forecasting). ARIMA(p,d,q) where parameters p, d, and q are non-negative
            integers, p is the order (number of time lags) of the autoregressive model, d is the
            degree of differencing (the number of times the data have had past values subtracted),
            and q is the order of the moving-average model.
        """,
    )

    parser.add_argument(
        "-d",
        "--days",
        action="store",
        dest="n_days",
        type=check_positive,
        default=5,
        help="prediction days.",
    )
    parser.add_argument(
        "-i",
        "--ic",
        action="store",
        dest="s_ic",
        type=str,
        default="aic",
        choices=["aic", "aicc", "bic", "hqic", "oob"],
        help="information criteria.",
    )
    parser.add_argument(
        "-s",
        "--seasonal",
        action="store_true",
        default=False,
        dest="b_seasonal",
        help="Use weekly seasonal data.",
    )
    parser.add_argument(
        "-o",
        "--order",
        action="store",
        dest="s_order",
        type=str,
        help="arima model order (p,d,q) in format: p,d,q.",
    )
    parser.add_argument(
        "-r",
        "--results",
        action="store_true",
        dest="b_results",
        default=False,
        help="results about ARIMA summary flag.",
    )
    parser.add_argument(
        "-e",
        "--end",
        action="store",
        type=valid_date,
        dest="s_end_date",
        default=None,
        help="The end date (format YYYY-MM-DD) to select - Backtesting",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return

        # BACKTESTING
        if ns_parser.s_end_date:

            if ns_parser.s_end_date < df_stock.index[0]:
                print(
                    "Backtesting not allowed, since End Date is older than Start Date of historical data\n"
                )
                return

            if (ns_parser.s_end_date < get_next_stock_market_days(
                    last_stock_day=df_stock.index[0],
                    n_next_days=5 + ns_parser.n_days)[-1]):
                print(
                    "Backtesting not allowed, since End Date is too close to Start Date to train model\n"
                )
                return

            future_index = get_next_stock_market_days(
                last_stock_day=ns_parser.s_end_date,
                n_next_days=ns_parser.n_days)

            if future_index[-1] > datetime.datetime.now():
                print(
                    "Backtesting not allowed, since End Date + Prediction days is in the future\n"
                )
                return

            df_future = df_stock[future_index[0]:future_index[-1]]
            df_stock = df_stock[:ns_parser.s_end_date]

        # Machine Learning model
        if ns_parser.s_order:
            t_order = tuple(int(ord) for ord in ns_parser.s_order.split(","))
            model = ARIMA(df_stock["5. adjusted close"].values,
                          order=t_order).fit()
            l_predictions = model.predict(
                start=len(df_stock["5. adjusted close"]) + 1,
                end=len(df_stock["5. adjusted close"]) + ns_parser.n_days,
            )
        else:
            if ns_parser.b_seasonal:
                model = pmdarima.auto_arima(
                    df_stock["5. adjusted close"].values,
                    error_action="ignore",
                    seasonal=True,
                    m=5,
                    information_criteria=ns_parser.s_ic,
                )
            else:
                model = pmdarima.auto_arima(
                    df_stock["5. adjusted close"].values,
                    error_action="ignore",
                    seasonal=False,
                    information_criteria=ns_parser.s_ic,
                )
            l_predictions = [
                i if i > 0 else 0
                for i in model.predict(n_periods=ns_parser.n_days)
            ]

        # Prediction data
        l_pred_days = get_next_stock_market_days(
            last_stock_day=df_stock["5. adjusted close"].index[-1],
            n_next_days=ns_parser.n_days,
        )
        df_pred = pd.Series(l_predictions, index=l_pred_days, name="Price")

        if ns_parser.b_results:
            print(model.summary())
            print("")

        # Plotting
        plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
        plt.plot(df_stock.index, df_stock["5. adjusted close"], lw=2)
        if ns_parser.s_order:
            # BACKTESTING
            if ns_parser.s_end_date:
                plt.title(
                    f"BACKTESTING: ARIMA {str(t_order)} on {s_ticker} - {ns_parser.n_days} days prediction"
                )
            else:
                plt.title(
                    f"ARIMA {str(t_order)} on {s_ticker} - {ns_parser.n_days} days prediction"
                )
        else:
            # BACKTESTING
            if ns_parser.s_end_date:
                plt.title(
                    f"BACKTESTING: ARIMA {model.order} on {s_ticker} - {ns_parser.n_days} days prediction"
                )
            else:
                plt.title(
                    f"ARIMA {model.order} on {s_ticker} - {ns_parser.n_days} days prediction"
                )
        plt.xlim(df_stock.index[0],
                 get_next_stock_market_days(df_pred.index[-1], 1)[-1])
        plt.xlabel("Time")
        plt.ylabel("Share Price ($)")
        plt.grid(b=True, which="major", color="#666666", linestyle="-")
        plt.minorticks_on()
        plt.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)
        plt.plot(
            [df_stock.index[-1], df_pred.index[0]],
            [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
            lw=1,
            c="tab:green",
            linestyle="--",
        )
        plt.plot(df_pred.index, df_pred, lw=2, c="tab:green")
        plt.axvspan(df_stock.index[-1],
                    df_pred.index[-1],
                    facecolor="tab:orange",
                    alpha=0.2)
        _, _, ymin, ymax = plt.axis()
        plt.vlines(df_stock.index[-1],
                   ymin,
                   ymax,
                   linewidth=1,
                   linestyle="--",
                   color="k")

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=1,
                c="tab:blue",
                linestyle="--",
            )

        if gtff.USE_ION:
            plt.ion()

        plt.show()

        # BACKTESTING
        if ns_parser.s_end_date:
            plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
            plt.subplot(211)
            plt.plot(
                df_future.index,
                df_future["5. adjusted close"],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.plot(df_pred.index, df_pred, lw=2, c="green")
            plt.scatter(df_future.index,
                        df_future["5. adjusted close"],
                        c="tab:blue",
                        lw=3)
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    df_stock["5. adjusted close"].values[-1],
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                c="tab:blue",
                ls="--",
            )
            plt.scatter(df_pred.index, df_pred, c="green", lw=3)
            plt.plot(
                [df_stock.index[-1], df_pred.index[0]],
                [df_stock["5. adjusted close"].values[-1], df_pred.values[0]],
                lw=2,
                c="green",
                ls="--",
            )
            plt.title("BACKTESTING: Real data price versus Prediction")
            plt.xlim(df_stock.index[-1],
                     df_pred.index[-1] + datetime.timedelta(days=1))
            plt.xticks(
                [
                    df_stock.index[-1],
                    df_pred.index[-1] + datetime.timedelta(days=1)
                ],
                visible=True,
            )
            plt.ylabel("Share Price ($)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True,
                     which="minor",
                     color="#999999",
                     linestyle="-",
                     alpha=0.2)
            plt.legend(["Real data", "Prediction data"])
            plt.xticks([])

            plt.subplot(212)
            plt.axhline(y=0, color="k", linestyle="--", linewidth=2)
            plt.plot(
                df_future.index,
                100 *
                (df_pred.values - df_future["5. adjusted close"].values) /
                df_future["5. adjusted close"].values,
                lw=2,
                c="red",
            )
            plt.scatter(
                df_future.index,
                100 *
                (df_pred.values - df_future["5. adjusted close"].values) /
                df_future["5. adjusted close"].values,
                c="red",
                lw=5,
            )
            plt.title(
                "BACKTESTING: Error between Real data and Prediction [%]")
            plt.plot(
                [df_stock.index[-1], df_future.index[0]],
                [
                    0,
                    100 * (df_pred.values[0] -
                           df_future["5. adjusted close"].values[0]) /
                    df_future["5. adjusted close"].values[0],
                ],
                lw=2,
                ls="--",
                c="red",
            )
            plt.xlim(df_stock.index[-1],
                     df_pred.index[-1] + datetime.timedelta(days=1))
            plt.xticks(
                [
                    df_stock.index[-1],
                    df_pred.index[-1] + datetime.timedelta(days=1)
                ],
                visible=True,
            )
            plt.xlabel("Time")
            plt.ylabel("Prediction Error (%)")
            plt.grid(b=True, which="major", color="#666666", linestyle="-")
            plt.minorticks_on()
            plt.grid(b=True,
                     which="minor",
                     color="#999999",
                     linestyle="-",
                     alpha=0.2)
            plt.legend(["Real data", "Prediction data"])

            if gtff.USE_ION:
                plt.ion()

            plt.show()

            # Refactor prediction dataframe for backtesting print
            df_pred.name = "Prediction"
            df_pred = df_pred.to_frame()
            df_pred["Real"] = df_future["5. adjusted close"]

            if gtff.USE_COLOR:

                patch_pandas_text_adjustment()

                print("Time         Real [$]  x  Prediction [$]")
                print(
                    df_pred.apply(price_prediction_backtesting_color,
                                  axis=1).to_string())
            else:
                print(df_pred[["Real", "Prediction"]].round(2).to_string())

            print("")
            print_prediction_kpis(df_pred["Real"].values,
                                  df_pred["Prediction"].values)

        else:
            # Print prediction data
            print_pretty_prediction(df_pred,
                                    df_stock["5. adjusted close"].values[-1])
        print("")

    except Exception as e:
        print(e, "\n")
def display_arima(
    dataset: str,
    values: Union[pd.DataFrame, pd.Series],
    arima_order: str,
    n_predict: int,
    seasonal: bool,
    ic: str,
    results: bool,
    s_end_date: str = "",
    export: str = "",
):
    """View fit ARIMA model

    Parameters
    ----------
    dataset : str
        String indicating dataset (for plot title)
    values : Union[pd.DataFrame, pd.Series]
        Data to fit
    arima_order : str
        String of ARIMA params in form "p,q,d"
    n_predict : int
        Days to predict
    seasonal : bool
        Flag to use seasonal model
    ic : str
        Information Criteria for model evaluation
    results : bool
        Flag to display model summary
    s_end_date : str, optional
        Specified end date for backtesting comparisons
    export : str, optional
        Format to export image
    """

    if arima_order:
        t_order = tuple(int(ord) for ord in arima_order.split(","))
    if s_end_date:
        future_index = get_next_stock_market_days(last_stock_day=s_end_date,
                                                  n_next_days=n_predict)

        if future_index[-1] > datetime.datetime.now():
            print(
                "Backtesting not allowed, since End Date + Prediction days is in the future\n"
            )
            return

        df_future = values[future_index[0]:future_index[-1]]
        values = values[:s_end_date]  # type: ignore

    l_predictions, model = arima_model.get_arima_model(values, arima_order,
                                                       n_predict, seasonal, ic)

    # Prediction data
    l_pred_days = get_next_stock_market_days(
        last_stock_day=values.index[-1],
        n_next_days=n_predict,
    )
    df_pred = pd.Series(l_predictions, index=l_pred_days, name="Price")

    if results:
        print(model.summary())
        print("")

    # Plotting
    fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
    ax.plot(values.index, values, lw=2)

    # pylint:disable=no-member

    if arima_order:
        # BACKTESTING
        if s_end_date:
            ax.set_title(
                f"BACKTESTING: ARIMA {str(t_order)} on {dataset} - {n_predict} days prediction"
            )
        else:
            ax.set_title(
                f"ARIMA {str(t_order)} on {dataset} - {n_predict} days prediction"
            )
    else:
        # BACKTESTING
        if s_end_date:
            ax.set_title(
                f"BACKTESTING: ARIMA {model.order} on {dataset} - {n_predict} days prediction"
            )
        else:
            plt.title(
                f"ARIMA {model.order} on {dataset} - {n_predict} days prediction"
            )
    ax.set_xlim(values.index[0],
                get_next_stock_market_days(df_pred.index[-1], 1)[-1])
    ax.set_xlabel("Time")
    ax.set_ylabel("Value")
    ax.grid(b=True, which="major", color="#666666", linestyle="-")
    ax.minorticks_on()
    ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
    ax.plot(
        [values.index[-1], df_pred.index[0]],
        [values.values[-1], df_pred.values[0]],
        lw=1,
        c="tab:green",
        linestyle="--",
    )
    ax.plot(df_pred.index, df_pred, lw=2, c="tab:green")
    ax.axvspan(values.index[-1],
               df_pred.index[-1],
               facecolor="tab:orange",
               alpha=0.2)
    _, _, ymin, ymax = plt.axis()
    ax.vlines(values.index[-1],
              ymin,
              ymax,
              linewidth=1,
              linestyle="--",
              color="k")

    # BACKTESTING
    if s_end_date:
        ax.plot(
            df_future.index,
            df_future.values,
            lw=2,
            c="tab:blue",
            ls="--",
        )
        plt.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            lw=1,
            c="tab:blue",
            linestyle="--",
        )

    fig.tight_layout()
    if gtff.USE_ION:
        plt.ion()

    plt.show()

    # BACKTESTING
    if s_end_date:
        fig, ax = plt.subplots(1, 2, figsize=plot_autoscale(), dpi=PLOT_DPI)
        ax0 = ax[0]
        ax0.plot(
            df_future.index,
            df_future.values,
            lw=2,
            c="tab:blue",
            ls="--",
        )
        ax0.plot(df_pred.index, df_pred, lw=2, c="green")
        ax0.scatter(df_future.index, df_future, c="tab:blue", lw=3)
        ax0.plot(
            [values.index[-1], df_future.index[0]],
            [
                values.values[-1],
                df_future.values[0],
            ],
            lw=2,
            c="tab:blue",
            ls="--",
        )
        ax0.scatter(df_pred.index, df_pred, c="green", lw=3)
        ax0.plot(
            [values.index[-1], df_pred.index[0]],
            [values.values[-1], df_pred.values[0]],
            lw=2,
            c="green",
            ls="--",
        )
        ax0.set_title("BACKTESTING: Real data Prediction")
        ax0.set_xlim(values.index[-1],
                     df_pred.index[-1] + datetime.timedelta(days=1))
        ax0.set_xticks(
            [values.index[-1], df_pred.index[-1] + datetime.timedelta(days=1)])
        ax0.set_ylabel("Value")
        ax0.grid(b=True, which="major", color="#666666", linestyle="-")
        ax0.minorticks_on()
        ax0.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)
        ax0.legend(["Real data", "Prediction data"])
        ax0.set_xticks([])

        ax1 = ax[1]
        ax1.axhline(y=0, color="k", linestyle="--", linewidth=2)
        ax1.plot(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            lw=2,
            c="red",
        )
        ax1.scatter(
            df_future.index,
            100 * (df_pred.values - df_future.values) / df_future.values,
            c="red",
            lw=5,
        )
        ax1.set_title(
            "BACKTESTING: Error between Real data and Prediction [%]")
        ax1.plot(
            [values.index[-1], df_future.index[0]],
            [
                0,
                100 * (df_pred.values[0] - df_future.values[0]) /
                df_future.values[0],
            ],
            lw=2,
            ls="--",
            c="red",
        )
        ax1.set_xlim(values.index[-1],
                     df_pred.index[-1] + datetime.timedelta(days=1))
        ax1.set_xticks(
            [values.index[-1], df_pred.index[-1] + datetime.timedelta(days=1)])
        ax1.set_xlabel("Time")
        ax1.set_ylabel("Prediction Error (%)")
        ax1.grid(b=True, which="major", color="#666666", linestyle="-")
        ax1.minorticks_on()
        ax1.grid(b=True,
                 which="minor",
                 color="#999999",
                 linestyle="-",
                 alpha=0.2)
        ax1.legend(["Real data", "Prediction data"])
        fig.tight_layout()
        if gtff.USE_ION:
            plt.ion()

        plt.show()

        # Refactor prediction dataframe for backtesting print
        df_pred.name = "Prediction"
        df_pred = df_pred.to_frame()
        df_pred["Real"] = df_future.values

        if gtff.USE_COLOR:
            if gtff.USE_TABULATE_DF:
                df_pred["Real"] = df_pred["Real"].astype(float)
                df_pred["Prediction"] = df_pred["Prediction"].astype(float)
                df_pred["Dif"] = (100 * (df_pred.Prediction - df_pred.Real) /
                                  df_pred.Real)
                print(
                    tabulate(
                        df_pred,
                        headers=[
                            "Date", "Predicted", "Actual", "% Difference"
                        ],
                        showindex=True,
                        floatfmt=".2f",
                        tablefmt="fancy_grid",
                    ))
            else:
                patch_pandas_text_adjustment()
                print("Time         Real [$]  x  Prediction [$]")
                print(
                    df_pred.apply(price_prediction_backtesting_color,
                                  axis=1).to_string())
        else:
            if gtff.USE_TABULATE_DF:
                df_pred["Real"] = df_pred["Real"].astype(float)
                df_pred["Prediction"] = df_pred["Predicted"].astype(float)
                df_pred["Dif"] = (100 * (df_pred.Prediction - df_pred.Real) /
                                  df_pred.Real)
                print(
                    tabulate(
                        df_pred,
                        headers=[
                            "Date", "Predicted", "Actual", "% Difference"
                        ],
                        showindex=True,
                        floatfmt=".2f",
                        tablefmt="fancy_grid",
                    ))
            else:
                print(df_pred[["Real", "Prediction"]].round(2).to_string())

        print("")
        print_prediction_kpis(df_pred["Real"].values,
                              df_pred["Prediction"].values)

    else:
        # Print prediction data
        print_pretty_prediction(df_pred, values.values[-1])
    export_data(export, os.path.dirname(os.path.abspath(__file__)), "arima")
    print("")