From d56eedc58bbdafa65438b6967b3e07578e354ef4 Mon Sep 17 00:00:00 2001 From: fede Date: Sat, 12 Nov 2022 21:42:32 -0600 Subject: [PATCH] [FEAT] Automatic Statistical Forecasting (#3317) * feat: add autostatsforecast * feat: update autostatsforecast description * feat: improve print results * fix: update autostatsforecat docs (sorted results) * fix: rename autostatsforecast -> beststatsmodel * feat: try-except statsforecast imports * fix: update beststatsmodel example * fix: delete unused file * fix: rename beststatsmodel -> autoselect command * fix: update autoselect command description * SDK : Fetch `trail_map_forecasting.csv` * SDK : add `forecast.autoselect` * SDK : update `sdk.py` * feat: add pylint exep to preserve informative warning Co-authored-by: martinb-bb <105685594+martinb-bb@users.noreply.github.com> Co-authored-by: Chavithra PARANA --- openbb_terminal/forecast/autoselect_model.py | 214 ++++++++++++++++++ openbb_terminal/forecast/autoselect_view.py | 118 ++++++++++ .../forecast/forecast_controller.py | 58 +++++ openbb_terminal/miscellaneous/i18n/en.yml | 1 + .../library/trail_map_forecasting.csv | 1 + .../forecast/test_autoselect_model.py | 11 + .../forecast/test_autoselect_view.py | 18 ++ .../terminal/forecast/autoselect/_index.md | 80 +++++++ website/data/menu/main.yml | 2 + 9 files changed, 503 insertions(+) create mode 100644 openbb_terminal/forecast/autoselect_model.py create mode 100644 openbb_terminal/forecast/autoselect_view.py create mode 100644 tests/openbb_terminal/forecast/test_autoselect_model.py create mode 100644 tests/openbb_terminal/forecast/test_autoselect_view.py create mode 100644 website/content/terminal/forecast/autoselect/_index.md diff --git a/openbb_terminal/forecast/autoselect_model.py b/openbb_terminal/forecast/autoselect_model.py new file mode 100644 index 00000000000..81f7eff21ec --- /dev/null +++ b/openbb_terminal/forecast/autoselect_model.py @@ -0,0 +1,214 @@ +# pylint: disable=too-many-arguments +"""Automatic Statistical Forecast""" +__docformat__ = "numpy" + +import logging +from typing import Any, Union, Optional, List, Tuple + +import warnings +import numpy as np +import pandas as pd +from statsforecast.core import StatsForecast + +from openbb_terminal.decorators import log_start_end +from openbb_terminal.rich_config import console, USE_COLOR +from openbb_terminal.forecast import helpers + + +warnings.simplefilter("ignore") + +logger = logging.getLogger(__name__) + +# pylint: disable=E1123 + + +def precision_format(best_model: str, index: str, val: float) -> str: + if index == best_model and USE_COLOR: + return f"[#00AAFF]{val:.2f}% [/#00AAFF]" + return f"{val:.2f}%" + + +@log_start_end(log=logger) +def get_autoselect_data( + data: Union[pd.Series, pd.DataFrame], + target_column: str = "close", + seasonal_periods: int = 7, + n_predict: int = 5, + start_window: float = 0.85, + forecast_horizon: int = 5, +) -> Tuple[ + list[np.ndarray], List[np.ndarray], List[np.ndarray], Optional[float], Any, Any +]: + + """Performs Automatic Statistical forecasting + This is a wrapper around StatsForecast models; + we refer to this link for the original and more complete documentation of the parameters. + + + https://nixtla.github.io/statsforecast/models.html + + Parameters + ---------- + data : Union[pd.Series, np.ndarray] + Input data. + target_column (str, optional): + Target column to forecast. Defaults to "close". + seasonal_periods: int + Number of seasonal periods in a year (7 for daily data) + If not set, inferred from frequency of the series. + n_predict: int + Number of days to forecast + start_window: float + Size of sliding window from start of timeseries and onwards + forecast_horizon: int + Number of days to forecast when backtesting and retraining historical + + Returns + ------- + list[float] + Adjusted Data series + list[float] + List of historical fcast values + list[float] + List of predicted fcast values + Optional[float] + precision + Any + Fit ETS model object. + """ + + use_scalers = False + # statsforecast preprocessing + # when including more time series + # the preprocessing is similar + _, ticker_series = helpers.get_series(data, target_column, is_scaler=use_scalers) + freq = ticker_series.freq_str + ticker_series = ticker_series.pd_dataframe().reset_index() + ticker_series.columns = ["ds", "y"] + ticker_series.insert(0, "unique_id", target_column) + + # check statsforecast dependency + try: + from statsforecast.models import ( # pylint: disable=import-outside-toplevel + AutoARIMA, + ETS, + AutoCES, + MSTL, + Naive, + SeasonalNaive, + SeasonalWindowAverage, + RandomWalkWithDrift, + ) + except Exception as e: + error = str(e) + if "cannot import name" in error: + console.print( + "[red]Please update statsforecast to version 1.2.0 or higher.[/red]" + ) + else: + console.print(f"[red]{error}[/red]") + return [], [], [], None, None, None + + try: + # Model Init + season_length = int(seasonal_periods) + models = [ + AutoARIMA(season_length=season_length), + ETS(season_length=season_length), + AutoCES(season_length=season_length), + MSTL(season_length=season_length), + SeasonalNaive(season_length=season_length), + SeasonalWindowAverage( + season_length=season_length, window_size=season_length + ), + RandomWalkWithDrift(), + ] + fcst = StatsForecast( + df=ticker_series, + models=models, + freq=freq, + verbose=True, + fallback_model=Naive(), + ) + except Exception as e: # noqa + error = str(e) + if "got an unexpected keyword argument" in error: + console.print( + "[red]Please update statsforecast to version 1.1.3 or higher.[/red]" + ) + else: + console.print(f"[red]{error}[/red]") + return [], [], [], None, None, None + + # Historical backtesting + last_training_point = int((len(ticker_series) - 1) * start_window) + historical_fcast = fcst.cross_validation( + h=int(forecast_horizon), + test_size=len(ticker_series) - last_training_point, + n_windows=None, + input_size=min(10 * forecast_horizon, len(ticker_series)), + ) + # change name to AutoETS and AutoCES + cols = [ + c if (c not in ["ETS", "CES"]) else f"Auto{c}" for c in historical_fcast.columns + ] + historical_fcast.columns = cols + + # train new model on entire timeseries to provide best current forecast + # we have the historical fcast, now lets predict. + forecast = fcst.forecast(int(n_predict)) + # change name to AutoETS and AutoCES + cols = [c if (c not in ["ETS", "CES"]) else f"Auto{c}" for c in forecast.columns] + forecast.columns = cols + # Backtesting evaluation + y_true = historical_fcast["y"].values + model_names = historical_fcast.drop(columns=["ds", "cutoff", "y"]).columns + precision_per_model = [ + helpers.mean_absolute_percentage_error(y_true, historical_fcast[model].values) + for model in model_names + ] + precision = pd.DataFrame({"precision": precision_per_model}, index=model_names) + precision = precision.sort_values(by="precision") + # select best model + best_precision = precision["precision"].min() + best_model = precision["precision"].idxmin() + + # print results + precision["precision"] = [ + precision_format(best_model, index, val) + for index, val in precision["precision"].iteritems() + ] + console.print("\n") + helpers.print_rich_table( + precision, + show_index=True, + index_name="Model", + headers=["MAPE"], + title=f"Performance per model.\nBest model: [#00AAFF]{best_model}[/#00AAFF]", + ) + + # transform outputs to make them compatible with + # plots + use_scalers = False + _, ticker_series = helpers.get_series( + ticker_series.rename(columns={"y": target_column}), + target_column, + is_scaler=use_scalers, + time_col="ds", + ) + _, forecast = helpers.get_series( + forecast.rename(columns={best_model: target_column}), + target_column, + is_scaler=use_scalers, + time_col="ds", + ) + _, historical_fcast = helpers.get_series( + historical_fcast.groupby("ds") + .head(1) + .rename(columns={best_model: target_column}), + target_column, + is_scaler=use_scalers, + time_col="ds", + ) + + return (ticker_series, historical_fcast, forecast, best_precision, fcst, best_model) diff --git a/openbb_terminal/forecast/autoselect_view.py b/openbb_terminal/forecast/autoselect_view.py new file mode 100644 index 00000000000..bc862b26fd1 --- /dev/null +++ b/openbb_terminal/forecast/autoselect_view.py @@ -0,0 +1,118 @@ +"""Automatic Statistical Forecasting View""" +__docformat__ = "numpy" + +import logging +from typing import Union, Optional, List +from datetime import datetime + +import pandas as pd +import matplotlib.pyplot as plt + +from openbb_terminal.forecast import autoselect_model +from openbb_terminal.decorators import log_start_end +from openbb_terminal.forecast import helpers + +logger = logging.getLogger(__name__) +# pylint: disable=too-many-arguments + + +@log_start_end(log=logger) +def display_autoselect_forecast( + data: Union[pd.DataFrame, pd.Series], + target_column: str = "close", + dataset_name: str = "", + seasonal_periods: int = 7, + n_predict: int = 5, + start_window: float = 0.85, + forecast_horizon: int = 5, + export: str = "", + residuals: bool = False, + forecast_only: bool = False, + start_date: Optional[datetime] = None, + end_date: Optional[datetime] = None, + naive: bool = False, + export_pred_raw: bool = False, + external_axes: Optional[List[plt.axes]] = None, +): + """Display Automatic Statistical Forecasting Model + + Parameters + ---------- + data : Union[pd.Series, np.array] + Data to forecast + dataset_name str + The name of the ticker to be predicted + target_column (str, optional): + Target column to forecast. Defaults to "close". + seasonal_periods: int + Number of seasonal periods in a year + If not set, inferred from frequency of the series. + n_predict: int + Number of days to forecast + start_window: float + Size of sliding window from start of timeseries and onwards + forecast_horizon: int + Number of days to forecast when backtesting and retraining historical + export: str + Format to export data + residuals: bool + Whether to show residuals for the model. Defaults to False. + forecast_only: bool + Whether to only show dates in the forecasting range. Defaults to False. + start_date: Optional[datetime] + The starting date to perform analysis, data before this is trimmed. Defaults to None. + end_date: Optional[datetime] + The ending date to perform analysis, data after this is trimmed. Defaults to None. + naive: bool + Whether to show the naive baseline. This just assumes the closing price will be the same + as the previous day's closing price. Defaults to False. + external_axes:Optional[List[plt.axes]] + External axes to plot on + """ + data = helpers.clean_data(data, start_date, end_date, target_column, None) + if not helpers.check_data(data, target_column, None): + return + + ( + ticker_series, + historical_fcast, + predicted_values, + precision, + _model, + best_model, + ) = autoselect_model.get_autoselect_data( + data=data, + target_column=target_column, + seasonal_periods=seasonal_periods, + n_predict=n_predict, + start_window=start_window, + forecast_horizon=forecast_horizon, + ) + + if ticker_series == []: + return + + probabilistic = False + helpers.plot_forecast( + name=f"Best Model: {best_model}", + target_col=target_column, + historical_fcast=historical_fcast, + predicted_values=predicted_values, + ticker_series=ticker_series, + ticker_name=dataset_name, + data=data, + n_predict=n_predict, + forecast_horizon=forecast_horizon, + past_covariates=None, + precision=precision, + probabilistic=probabilistic, + export=export, + forecast_only=forecast_only, + naive=naive, + export_pred_raw=export_pred_raw, + external_axes=external_axes, + ) + if residuals: + helpers.plot_residuals( + _model, None, ticker_series, forecast_horizon=forecast_horizon + ) diff --git a/openbb_terminal/forecast/forecast_controller.py b/openbb_terminal/forecast/forecast_controller.py index f1b216be6f2..42256e201d6 100644 --- a/openbb_terminal/forecast/forecast_controller.py +++ b/openbb_terminal/forecast/forecast_controller.py @@ -55,6 +55,7 @@ from openbb_terminal.rich_config import console, MenuText from openbb_terminal.forecast import ( forecast_model, forecast_view, + autoselect_view, autoces_view, autoets_view, seasonalnaive_view, @@ -112,6 +113,7 @@ class ForecastController(BaseController): "delta", "atr", "signal", + "autoselect", "autoces", "autoets", "seasonalnaive", @@ -252,6 +254,7 @@ class ForecastController(BaseController): "signal", "combine", "rename", + "autoselect", "autoces", "autoets", "seasonalnaive", @@ -333,6 +336,7 @@ class ForecastController(BaseController): mt.add_cmd("signal", self.files) mt.add_raw("\n") mt.add_info("_tsforecasting_") + mt.add_cmd("autoselect", self.files) mt.add_cmd("autoces", self.files) mt.add_cmd("autoets", self.files) mt.add_cmd("seasonalnaive", self.files) @@ -1695,6 +1699,60 @@ class ForecastController(BaseController): ns_parser.target_dataset, ) + # Best Statistical Model + @log_start_end(log=logger) + def call_autoselect(self, other_args: List[str]): + """Process autoselect command""" + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + add_help=False, + prog="autoselect", + description=""" + Perform Automatic Statistical Forecast + (select best statistical model from AutoARIMA, AutoETS, AutoCES, MSTL, ...) + """, + ) + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "--target-dataset") + + ns_parser = self.parse_known_args_and_warn( + parser, + other_args, + export_allowed=EXPORT_ONLY_FIGURES_ALLOWED, + target_dataset=True, + target_column=True, + n_days=True, + seasonal="A", + periods=True, + window=True, + residuals=True, + forecast_only=True, + start=True, + end=True, + naive=True, + export_pred_raw=True, + ) + # TODO Convert this to multi series + if ns_parser: + if not helpers.check_parser_input(ns_parser, self.datasets): + return + autoselect_view.display_autoselect_forecast( + data=self.datasets[ns_parser.target_dataset], + dataset_name=ns_parser.target_dataset, + n_predict=ns_parser.n_days, + target_column=ns_parser.target_column, + seasonal_periods=ns_parser.seasonal_periods, + start_window=ns_parser.start_window, + forecast_horizon=ns_parser.n_days, + export=ns_parser.export, + residuals=ns_parser.residuals, + forecast_only=ns_parser.forecast_only, + start_date=ns_parser.s_start_date, + end_date=ns_parser.s_end_date, + naive=ns_parser.naive, + export_pred_raw=ns_parser.export_pred_raw, + ) + # AutoCES Model @log_start_end(log=logger) def call_autoces(self, other_args: List[str]): diff --git a/openbb_terminal/miscellaneous/i18n/en.yml b/openbb_terminal/miscellaneous/i18n/en.yml index 94c178c77bf..b99ab742e72 100644 --- a/openbb_terminal/miscellaneous/i18n/en.yml +++ b/openbb_terminal/miscellaneous/i18n/en.yml @@ -1042,6 +1042,7 @@ en: forecast/atr: Add Average True Range forecast/signal: Add Price Signal (short vs. long term) forecast/_tsforecasting_: TimeSeries Forecasting + forecast/autoselect: Select best statistical model from AutoARIMA, AutoETS, AutoCES, MSTL, etc. forecast/autoces: Automatic Complex Exponential Smoothing Model forecast/autoets: Automatic ETS (Error, Trend, Seasonality) Model forecast/arima: Arima (Non-darts) diff --git a/openbb_terminal/miscellaneous/library/trail_map_forecasting.csv b/openbb_terminal/miscellaneous/library/trail_map_forecasting.csv index e084161045a..4893971c4a5 100644 --- a/openbb_terminal/miscellaneous/library/trail_map_forecasting.csv +++ b/openbb_terminal/miscellaneous/library/trail_map_forecasting.csv @@ -32,3 +32,4 @@ forecast.tcn,openbb_terminal.forecast.tcn_model.get_tcn_data,openbb_terminal.for forecast.trans,openbb_terminal.forecast.trans_model.get_trans_data,openbb_terminal.forecast.trans_view.display_trans_forecast forecast.tft,openbb_terminal.forecast.tft_model.get_tft_data,openbb_terminal.forecast.tft_view.display_tft_forecast forecast.nhits,openbb_terminal.forecast.nhits_model.get_nhits_data,openbb_terminal.forecast.nhits_view.display_nhits_forecast +forecast.autoselect,openbb_terminal.forecast.autoselect_model.get_autoselect_data,openbb_terminal.forecast.autoselect_view.display_autoselect_forecast diff --git a/tests/openbb_terminal/forecast/test_autoselect_model.py b/tests/openbb_terminal/forecast/test_autoselect_model.py new file mode 100644 index 00000000000..6fcb4479558 --- /dev/null +++ b/tests/openbb_terminal/forecast/test_autoselect_model.py @@ -0,0 +1,11 @@ +import pytest +from tests.openbb_terminal.forecast import conftest + +try: + from openbb_terminal.forecast import autoselect_model +except ImportError: + pytest.skip(allow_module_level=True) + + +def test_get_autoselect_model(tsla_csv): + conftest.test_model(autoselect_model.get_autoselect_data, tsla_csv) diff --git a/tests/openbb_terminal/forecast/test_autoselect_view.py b/tests/openbb_terminal/forecast/test_autoselect_view.py new file mode 100644 index 00000000000..8045a7ef356 --- /dev/null +++ b/tests/openbb_terminal/forecast/test_autoselect_view.py @@ -0,0 +1,18 @@ +import pytest + +try: + from openbb_terminal.forecast import autoselect_view +except ImportError: + pytest.skip(allow_module_level=True) + + +def test_display_autoselect_forecast(tsla_csv): + with pytest.raises(AttributeError): + autoselect_view.display_autoselect_forecast( + tsla_csv, + target_column="close", + seasonal_periods=3, + n_predict=1, + start_window=0.5, + forecast_horizon=1, + ) diff --git a/website/content/terminal/forecast/autoselect/_index.md b/website/content/terminal/forecast/autoselect/_index.md new file mode 100644 index 00000000000..13fcfe8ea77 --- /dev/null +++ b/website/content/terminal/forecast/autoselect/_index.md @@ -0,0 +1,80 @@ +``` +usage: autoselect [--naive] [-d {AAPL}] [-c TARGET_COLUMN] [-n N_DAYS] [-s {N,A,M}] [-p SEASONAL_PERIODS] [-w START_WINDOW] [--end S_END_DATE] [--start S_START_DATE] [--residuals] [--forecast-only] + [--export-pred-raw] [-h] [--export EXPORT] + +``` + +Perform Automatic Statistical Forecast (select best statistical model from AutoARIMA, AutoETS, AutoCES, MSTL, ...) + +``` +optional arguments: + --naive Show the naive baseline for a model. (default: False) + -d {AAPL}, --target-dataset {AAPL} + The name of the dataset you want to select (default: None) + -c TARGET_COLUMN, --target-column TARGET_COLUMN + The name of the specific column you want to use (default: close) + -n N_DAYS, --n-days N_DAYS + prediction days. (default: 5) + -s {N,A,M}, --seasonal {N,A,M} + Seasonality: N: None, A: Additive, M: Multiplicative. (default: A) + -p SEASONAL_PERIODS, --periods SEASONAL_PERIODS + Seasonal periods: 4: Quarterly, 7: Daily (default: 7) + -w START_WINDOW, --window START_WINDOW + Start point for rolling training and forecast window. 0.0-1.0 (default: 0.85) + --end S_END_DATE The end date (format YYYY-MM-DD) to select for testing (default: None) + --start S_START_DATE The start date (format YYYY-MM-DD) to select for testing (default: None) + --residuals Show the residuals for the model. (default: False) + --forecast-only Do not plot the hisotorical data without forecasts. (default: False) + --export-pred-raw Export predictions to a csv file. (default: False) + -h, --help show this help message (default: False) + --export EXPORT Export figure into png, jpg, pdf, svg (default: ) + +For more information and examples, use 'about autoselect' to access the related guide. +``` + +Example: +``` +2022 Nov 09, 15:23 (๐Ÿฆ‹) /forecast/ $ load AAPL + +2022 Nov 09, 15:24 (๐Ÿฆ‹) /forecast/ $ autoselect AAPL + +Cross Validation Time Series 1: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 115/115 [00:47<00:00, 2.40it/s] +Forecast: 100%|โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 1/1 [00:01<00:00, 1.80s/it] + + + Performance per model. + Best model: AutoETS +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”“ +โ”ƒ Model โ”ƒ MAPE โ”ƒ +โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ +โ”‚ AutoETS โ”‚ 2.91% โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ AutoARIMA โ”‚ 2.93% โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ RWD โ”‚ 3.04% โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ AutoCES โ”‚ 3.15% โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ MSTL โ”‚ 3.40% โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ SeasonalNaive โ”‚ 4.32% โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ SeasWA โ”‚ 8.06% โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + + Actual price: 139.50 +โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ +โ”ƒ Datetime โ”ƒ Prediction โ”ƒ +โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ +โ”‚ 2022-11-09 โ”‚ 139.47 โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ 2022-11-10 โ”‚ 139.47 โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ 2022-11-11 โ”‚ 139.47 โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ 2022-11-14 โ”‚ 139.47 โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ 2022-11-15 โ”‚ 139.47 โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` +image diff --git a/website/data/menu/main.yml b/website/data/menu/main.yml index ef3ad06a0de..d7bde8631f2 100644 --- a/website/data/menu/main.yml +++ b/website/data/menu/main.yml @@ -749,6 +749,8 @@ main: ref: terminal/forecast/autoces - name: autoets ref: terminal/forecast/autoets + - name: autoselect + ref: terminal/forecast/autoselect - name: brnn ref: terminal/forecast/brnn - name: clean