diff --git a/python/smooth/adam_general/core/__init__.py b/python/smooth/adam_general/core/__init__.py new file mode 100644 index 00000000..72a9fe37 --- /dev/null +++ b/python/smooth/adam_general/core/__init__.py @@ -0,0 +1 @@ +# lol \ No newline at end of file diff --git a/python/smooth/adam_general/core/adam.py b/python/smooth/adam_general/core/adam.py new file mode 100644 index 00000000..165e1c59 --- /dev/null +++ b/python/smooth/adam_general/core/adam.py @@ -0,0 +1,193 @@ +import time +import warnings +from adam_profile import parameters_checker + +class Adam: + def __init__(self, model="ZXZ", lags=None, orders=None, constant=False, formula=None, + regressors=["use", "select", "adapt"], + occurrence=["none", "auto", "fixed", "general", "odds-ratio", "inverse-odds-ratio", "direct"], + distribution=["default", "dnorm", "dlaplace", "ds", "dgnorm", "dlnorm", "dinvgauss", "dgamma"], + loss=["likelihood", "MSE", "MAE", "HAM", "LASSO", "RIDGE", "MSEh", "TMSE", "GTMSE", "MSCE"], + outliers=["ignore", "use", "select"], level=0.99, + h=0, holdout=False, + persistence=None, phi=None, initial=["optimal", "backcasting", "complete"], arma=None, + ic=["AICc", "AIC", "BIC", "BICc"], bounds=["usual", "admissible", "none"], + silent=True, **kwargs): + self.model = model + self.lags = lags + self.orders = orders + self.constant = constant + self.formula = formula + self.regressors = regressors + self.occurrence = occurrence + self.distribution = distribution + self.loss = loss + self.outliers = outliers + self.level = level + self.h = h + self.holdout = holdout + self.persistence = persistence + self.phi = phi + self.initial = initial + self.arma = arma + self.ic = ic + self.bounds = bounds + self.silent = silent + self.kwargs = kwargs + + self.profiles_recent_provided = False + self.profiles_recent_table = None + self.initial_estimated = None + self.B = None + self.loss_value = None + self.other = {} + + self.elipsis = dict() + + + # If a previous model is provided as a model, write down the variables + if isinstance(self.model, (Adam, AdamSimulation)): + self._handle_previous_model() + + elif isinstance(self.model, ETS): + self._init_from_ets() + + elif isinstance(self.model, str): + pass # Everything is okay + else: + warnings.warn("A model of an unknown class was provided. Switching to 'ZZZ'.", UserWarning) + self.model = "ZZZ" + + # Check the parameters of the function and create variables based on them + checker_return = parameters_checker( + data=data, model=self.model, lags=self.lags, formula=self.formula, + orders=self.orders, constant=self.constant, arma=self.arma, + outliers=self.outliers, level=self.level, + persistence=self.persistence, phi=self.phi, initial=self.initial, + distribution=self.distribution, loss=self.loss, h=self.h, + holdout=self.holdout, occurrence=self.occurrence, ic=self.ic, + bounds=self.bounds, regressors=self.regressors, y_name=y_name, + silent=self.silent, model_do="", + parent_environment=locals(), ellipsis=ellipsis, fast=False + ) + + + #### If select was provided in the model, do auto.adam selection #### + # here I need to implement the auto.adam selection. + # Will do it in the future + # lines 690 - 700 in adam.R + + + + + def _init_from_ets(self): + self.components = self.model.components # when I do the ETS + coeffs = self.model.coef() + self.persistence = coeffs['persistence'] + self.phi = coeffs.get('phi') + self.initial = coeffs['initial'] + self.lags = [1] + + if self.components[1] != "N": + self.lags.append(1) + if self.components[2] != "N": + self.lags.append(self.model.m) + + self.model = self.model.model_type() + self.distribution = "dnorm" + self.loss = "likelihood" + + def coef(self): + if isinstance(self.model, ETS): + coefficients = { + 'persistence': self.persistence, + 'initial': self.initial + } + if self.phi is not None: + coefficients['phi'] = self.phi + + # Add level, trend, and seasonal components if present + if self.components[0] != "N": + coefficients['level'] = self.initial[0] + if self.components[1] != "N": + coefficients['trend'] = self.initial[1] + if self.components[2] != "N": + seasonal_index = 2 if self.components[1] != "N" else 1 + coefficients['seasonal'] = self.initial[seasonal_index:] + + return coefficients + return {} + + def fit(self, data): + # Start measuring the time of calculations + start_time = time.time() + + # Get the call information + ellipsis = self.kwargs + + # Is it useful? + y_name = str(data) + + + + def _handle_previous_model(self): + # If this is the simulated data, extract the parameters + # TODO: Handle simulated data case if needed + + self.initial = self.model.initial + self.initial_estimated = self.model.initial_estimated + self.distribution = self.model.distribution + self.loss = self.model.loss + self.persistence = self.model.persistence + self.phi = self.model.phi + + if self.model.initial_type != "complete": + self.initial = self.model.initial + else: + self.initial = "b" + + self.occurrence = self.model.occurrence + self.ic = self.model.ic + self.bounds = self.model.bounds + + # lambda for LASSO + self.ellipsis['lambda'] = self.model.other.get('lambda') + + # parameters for distributions + self.ellipsis['alpha'] = self.model.other.get('alpha') + self.ellipsis['shape'] = self.model.other.get('shape') + self.ellipsis['nu'] = self.model.other.get('nu') + self.B = self.model.B + + self.loss_value = self.model.loss_value + self.log_lik_adam_value = self.model.loglik() + self.lags_model_all = self.model.model_lags() + + # This needs to be fixed to align properly in case of various seasonals + self.profiles_recent_table = self.model.profile_initial + self.profiles_recent_provided = True + + self.regressors = self.model.regressors + + if self.formula is None: + self.formula = self.model.formula() + + # Parameters of the original ARIMA model + self.lags = self.model.lags() + self.orders = self.model.orders() + self.constant = self.model.constant + + if self.constant is None: + self.constant = False + + self.arma = self.model.arma + + self.model = self.model.model_type() + model_do = "use" + + # TODO: Uncomment if needed + # if "C" in self.model: + # self.initial = "o" + + # Further fitting logic goes here + # ... diff --git a/python/smooth/adam_general/core/creator.py b/python/smooth/adam_general/core/creator.py new file mode 100644 index 00000000..0ca97be1 --- /dev/null +++ b/python/smooth/adam_general/core/creator.py @@ -0,0 +1,1090 @@ +import numpy as np +from typing import List, Optional, Dict, Any +from python.smooth.adam_general.core.utils.utils import measurement_inverter, scaler, msdecompose, calculate_acf, calculate_pacf, calculate_likelihood, calculate_entropy, calculate_multistep_loss +from scipy import stats +from scipy.linalg import eigvals +from scipy.optimize import minimize +from python.smooth.adam_general.core.utils.cost_functions import logLikReturn +import pandas as pd + + +def creator(ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, + lags, lags_model, lags_model_arima, lags_model_all, lags_model_max, + profiles_recent_table, profiles_recent_provided, + obs_states, obs_in_sample, obs_all, components_number_ets, components_number_ets_seasonal, + components_names_ets, ot_logical, y_in_sample, + # Persistence and phi + persistence=None, persistence_estimate=True, + persistence_level=None, persistence_level_estimate=True, + persistence_trend=None, persistence_trend_estimate=True, + persistence_seasonal=None, persistence_seasonal_estimate=True, + persistence_xreg=None, persistence_xreg_estimate=True, persistence_xreg_provided=False, + phi=1, + # Initials + initial_type="optimal", initial_estimate=True, + initial_level=None, initial_level_estimate=True, + initial_trend=None, initial_trend_estimate=True, + initial_seasonal=None, initial_seasonal_estimate=True, + initial_arima=None, initial_arima_estimate=True, initial_arima_number=None, + initial_xreg_estimate=True, initial_xreg_provided=False, + # ARIMA elements + arima_model=False, ar_estimate=True, i_required=False, ma_estimate=True, arma_parameters=None, + ar_orders=None, i_orders=None, ma_orders=None, ar_required=False, ma_required=False, + non_zero_ari=None, non_zero_ma=None, + components_number_arima=0, components_names_arima=None, + # Explanatory variables + xreg_model=False, xreg_model_initials=None, xreg_data=None, xreg_number=0, xreg_names=None, + xreg_parameters_persistence=None, + # Constant + constant_required=False, constant_estimate=True, constant_value=None, constant_name=None): + + # Matrix of states. Time in columns, components in rows + mat_vt = np.full((components_number_ets + components_number_arima + xreg_number + constant_required, obs_states), np.nan) + + # Measurement rowvector + mat_wt = np.ones((obs_all, components_number_ets + components_number_arima + xreg_number + constant_required)) + + # If xreg are provided, then fill in the respective values in Wt vector + if xreg_model: + mat_wt[:, components_number_ets + components_number_arima:components_number_ets + components_number_arima + xreg_number] = xreg_data + + # Transition matrix + mat_f = np.eye(components_number_ets + components_number_arima + xreg_number + constant_required) + + # Persistence vector + vec_g = np.zeros((components_number_ets + components_number_arima + xreg_number + constant_required, 1)) + #vec_g_index = components_names_ets + components_names_arima + xreg_names + constant_name + + obs_nonzero = np.sum(y_in_sample != 0) + + j = 0 + # ETS model, persistence + if ets_model: + j += 1 + #vec_g_index[j-1] = "alpha" + if not persistence_level_estimate: + vec_g[j-1, 0] = persistence_level + + if model_is_trendy: + j += 1 + #vec_g_index[j-1] = "beta" + if not persistence_trend_estimate: + vec_g[j-1, 0] = persistence_trend + + if model_is_seasonal: + if not all(persistence_seasonal_estimate): + vec_g[j + np.where(np.logical_not(persistence_seasonal_estimate))[0], 0] = persistence_seasonal + + #if components_number_ets_seasonal > 1: + #vec_g_index[j:j+components_number_ets_seasonal] = [f"gamma{i}" for i in range(1, components_number_ets_seasonal+1)] + # else: + # vec_g_index[j] = "gamma" + + # ARIMA model, names for persistence + if arima_model: + # Remove diagonal from the ARIMA part of the matrix + mat_f[j:j+components_number_arima, j:j+components_number_arima] = 0 + #if components_number_arima > 1: + #vec_g_index[j:j+components_number_arima] = [f"psi{i}" for i in range(1, components_number_arima+1)] + #else: + #vec_g_index[j] = "psi" + j += components_number_arima + + # Modify transition to do drift + if not arima_model and constant_required: + mat_f[0, -1] = 1 + + # Regression, persistence + if xreg_model: + if persistence_xreg_provided and not persistence_xreg_estimate: + vec_g[j:j+xreg_number, 0] = persistence_xreg + #vec_g_index[j:j+xreg_number] = [f"delta{i}" for i in xreg_parameters_persistence] + + # Damping parameter value + if ets_model and model_is_trendy: + mat_f[0, 1] = phi + mat_f[1, 1] = phi + mat_wt[:, 1] = phi + + # If the arma parameters were provided, fill in the persistence + if arima_model and (not ar_estimate and not ma_estimate): + # Call polynomial + arima_polynomials = {key: np.array(value) for key, value in adam_polynomialiser( + 0, ar_orders, i_orders, ma_orders, + ar_estimate, ma_estimate, arma_parameters, lags + ).items()} + + # Fill in the transition matrix + if non_zero_ari.shape[0] > 0: + mat_f[components_number_ets + non_zero_ari[:, 1], components_number_ets + non_zero_ari[:, 1]] = \ + -arima_polynomials['ari_polynomial'][non_zero_ari[:, 0]] + + # Fill in the persistence vector + if non_zero_ari.shape[0] > 0: + vec_g[components_number_ets + non_zero_ari[:, 1], 0] = \ + -arima_polynomials['ari_polynomial'][non_zero_ari[:, 0]] + + if non_zero_ma.shape[0] > 0: + vec_g[components_number_ets + non_zero_ma[:, 1], 0] += \ + arima_polynomials['ma_polynomial'][non_zero_ma[:, 0]] + else: + arima_polynomials = None + + if not profiles_recent_provided: + # ETS model, initial state + # If something needs to be estimated... + if ets_model: + if initial_estimate: + # For the seasonal models + if model_is_seasonal: + if obs_nonzero >= lags_model_max * 2: + # If either e_type or s_type are multiplicative, do multiplicative decomposition + decomposition_type = "multiplicative" if any(x == "M" for x in [e_type, s_type]) else "additive" + y_decomposition = msdecompose(y_in_sample, [lag for lag in lags if lag != 1], type=decomposition_type) + j = 0 + # level + if initial_level_estimate: + mat_vt[j, 0:lags_model_max] = y_decomposition['initial'][0] + if xreg_model: + if e_type == "A": + mat_vt[j, 0:lags_model_max] -= np.dot(xreg_model_initials[0]['initial_xreg'], xreg_data[0]) + else: + mat_vt[j, 0:lags_model_max] /= np.exp(np.dot(xreg_model_initials[1]['initial_xreg'], xreg_data[0])) + else: + mat_vt[j, 0:lags_model_max] = initial_level + j += 1 + # If trend is needed + if model_is_trendy: + if initial_trend_estimate: + if t_type == "A" and s_type == "M": + mat_vt[j, 0:lags_model_max] = np.prod(y_decomposition['initial']) - y_decomposition['initial'][0] + # If the initial trend is higher than the lowest value, initialise with zero. + # This is a failsafe mechanism for the mixed models + if mat_vt[j, 0] < 0 and abs(mat_vt[j, 0]) > min(abs(y_in_sample[ot_logical])): + mat_vt[j, 0:lags_model_max] = 0 + elif t_type == "M" and s_type == "A": + mat_vt[j, 0:lags_model_max] = sum(abs(y_decomposition['initial'])) / abs(y_decomposition['initial'][0]) + elif t_type == "M": + # trend is too dangerous, make it start from 1. + mat_vt[j, 0:lags_model_max] = 1 + else: + # trend + mat_vt[j, 0:lags_model_max] = y_decomposition['initial'][1] + + # This is a failsafe for multiplicative trend models, so that the thing does not explode + if t_type == "M" and np.any(mat_vt[j, 0:lags_model_max] > 1.1): + mat_vt[j, 0:lags_model_max] = 1 + # This is a failsafe for multiplicative trend models, so that the thing does not explode + if t_type == "M" and np.any(mat_vt[0, 0:lags_model_max] < 0): + mat_vt[0, 0:lags_model_max] = y_in_sample[ot_logical][0] + else: + mat_vt[j, 0:lags_model_max] = initial_trend + j += 1 + + # Seasonal components + # For pure models use stuff as is + if all(x == "A" for x in [e_type, s_type]) or all(x == "M" for x in [e_type, s_type]) or (e_type == "A" and s_type == "M"): + for i in range(components_number_ets_seasonal): + if initial_seasonal_estimate[i]: + mat_vt[i+j-1, 0:lags_model[i+j-1]] = y_decomposition['seasonal'][i] + # Renormalise the initial seasons + if s_type == "A": + mat_vt[i+j-1, 0:lags_model[i+j-1]] -= \ + np.mean(mat_vt[i+j-1, 0:lags_model[i+j-1]]) + else: + mat_vt[i+j-1, 0:lags_model[i+j-1]] /= \ + np.exp(np.mean(np.log(mat_vt[i+j-1, 0:lags_model[i+j-1]]))) + else: + mat_vt[i+j-1, 0:lags_model[i+j-1]] = initial_seasonal[i] + + # For mixed models use a different set of initials + elif e_type == "M" and s_type == "A": + for i in range(components_number_ets_seasonal): + if initial_seasonal_estimate[i]: + mat_vt[i+j-1, 0:lags_model[i+j-1]] = np.log(y_decomposition['seasonal'][i]) * min(y_in_sample[ot_logical]) + # Renormalise the initial seasons + if s_type == "A": + mat_vt[i+j-1, 0:lags_model[i+j-1]] -= np.mean(mat_vt[i+j-1, 0:lags_model[i+j-1]]) + else: + mat_vt[i+j-1, 0:lags_model[i+j-1]] /= np.exp(np.mean(np.log(mat_vt[i+j-1, 0:lags_model[i+j-1]]))) + else: + mat_vt[i+j-1, 0:lags_model[i+j-1]] = initial_seasonal[i] + else: + # If either e_type or s_type are multiplicative, do multiplicative decomposition + j = 0 + # level + if initial_level_estimate: + mat_vt[j, 0:lags_model_max] = np.mean(y_in_sample[0:lags_model_max]) + if xreg_model: + if e_type == "A": + mat_vt[j, 0:lags_model_max] -= np.dot(xreg_model_initials[0]['initial_xreg'], xreg_data[0]) + else: + mat_vt[j, 0:lags_model_max] /= np.exp(np.dot(xreg_model_initials[1]['initial_xreg'], xreg_data[0])) + else: + mat_vt[j, 0:lags_model_max] = initial_level + j += 1 + if model_is_trendy: + if initial_trend_estimate: + if t_type == "A": + # trend + mat_vt[j, 0:lags_model_max] = y_in_sample[1] - y_in_sample[0] + elif t_type == "M": + if initial_level_estimate: + # level fix + mat_vt[j-1, 0:lags_model_max] = np.exp(np.mean(np.log(y_in_sample[ot_logical][0:lags_model_max]))) + # trend + mat_vt[j, 0:lags_model_max] = y_in_sample[1] / y_in_sample[0] + # This is a failsafe for multiplicative trend models, so that the thing does not explode + if t_type == "M" and np.any(mat_vt[j, 0:lags_model_max] > 1.1): + mat_vt[j, 0:lags_model_max] = 1 + else: + mat_vt[j, 0:lags_model_max] = initial_trend + + # Do roll back. Especially useful for backcasting and multisteps + if t_type == "A": + mat_vt[j-1, 0:lags_model_max] = mat_vt[j-1, 0] - mat_vt[j, 0] * lags_model_max + elif t_type == "M": + mat_vt[j-1, 0:lags_model_max] = mat_vt[j-1, 0] / mat_vt[j, 0]**lags_model_max + j += 1 + + # Seasonal components + if s_type == "A": + for i in range(components_number_ets_seasonal): + if initial_seasonal_estimate[i]: + mat_vt[i+j-1, 0:lags_model[i+j-1]] = y_in_sample[0:lags_model[i+j-1]] - mat_vt[0, 0] + # Renormalise the initial seasons + mat_vt[i+j-1, 0:lags_model[i+j-1]] -= np.mean(mat_vt[i+j-1, 0:lags_model[i+j-1]]) + else: + mat_vt[i+j-1, 0:lags_model[i+j-1]] = initial_seasonal[i] + # For mixed models use a different set of initials + else: + for i in range(components_number_ets_seasonal): + if initial_seasonal_estimate[i]: + # abs() is needed for mixed ETS+ARIMA + mat_vt[i+j-1, 0:lags_model[i+j-1]] = y_in_sample[0:lags_model[i+j-1]] / abs(mat_vt[0, 0]) + # Renormalise the initial seasons + mat_vt[i+j-1, 0:lags_model[i+j-1]] /= np.exp(np.mean(np.log(mat_vt[i+j-1, 0:lags_model[i+j-1]]))) + else: + mat_vt[i+j-1, 0:lags_model[i+j-1]] = initial_seasonal[i] + else: + # Non-seasonal models + # level + if initial_level_estimate: + mat_vt[0, 0:lags_model_max] = np.mean(y_in_sample[0:max(lags_model_max, int(obs_in_sample * 0.2))]) + else: + mat_vt[0, 0:lags_model_max] = initial_level + + if model_is_trendy: + if initial_trend_estimate: + if t_type == "A": + mat_vt[1, 0:lags_model_max] = np.mean(np.diff(y_in_sample[0:max(lags_model_max + 1, int(obs_in_sample * 0.2))])) + else: # t_type == "M" + mat_vt[1, 0:lags_model_max] = np.exp(np.mean(np.diff(np.log(y_in_sample[ot_logical])))) + else: + mat_vt[1, 0:lags_model_max] = initial_trend + + if initial_level_estimate and e_type == "M" and mat_vt[0, lags_model_max-1] == 0: + mat_vt[0, 0:lags_model_max] = np.mean(y_in_sample) + + # Else, insert the provided ones... make sure that this is not a backcasting + elif not initial_estimate and initial_type == "provided": + j = 0 + mat_vt[j, 0:lags_model_max] = initial_level + if model_is_trendy: + j += 1 + mat_vt[j, 0:lags_model_max] = initial_trend + if model_is_seasonal: + for i in range(components_number_ets_seasonal): + # This is misaligned, but that's okay, because this goes directly to profile_recent + mat_vt[j+i, 0:lags_model[j+i]] = initial_seasonal[i] + j += components_number_ets_seasonal + + # If ARIMA orders are specified, prepare initials + if arima_model: + if initial_arima_estimate: + mat_vt[components_number_ets:components_number_ets+components_number_arima, 0:initial_arima_number] = 0 if e_type == "A" else 1 + + if any(lag > 1 for lag in lags): + y_decomposition = msdecompose(y_in_sample, [lag for lag in lags if lag != 1], + type="additive" if e_type == "A" else "multiplicative")['seasonal'][-1][0] + else: + y_decomposition = np.mean(np.diff(y_in_sample[ot_logical])) if e_type == "A" else np.exp(np.mean(np.diff(np.log(y_in_sample[ot_logical])))) + + mat_vt[components_number_ets+components_number_arima-1, 0:initial_arima_number] = \ + np.tile(y_decomposition, int(np.ceil(initial_arima_number / max(lags))))[:initial_arima_number] + + else: + mat_vt[components_number_ets:components_number_ets+components_number_arima, 0:initial_arima_number] = 0 if e_type == "A" else 1 + mat_vt[components_number_ets+components_number_arima-1, 0:initial_arima_number] = initial_arima[:initial_arima_number] + + # Fill in the initials for xreg + if xreg_model: + if e_type == "A" or initial_xreg_provided or xreg_model_initials[1] is None: + mat_vt[components_number_ets+components_number_arima:components_number_ets+components_number_arima+xreg_number, 0:lags_model_max] = \ + xreg_model_initials[0]['initial_xreg'] + else: + mat_vt[components_number_ets+components_number_arima:components_number_ets+components_number_arima+xreg_number, 0:lags_model_max] = \ + xreg_model_initials[1]['initial_xreg'] + + # Add constant if needed + if constant_required: + if constant_estimate: + # Add the mean of data + if sum(i_orders) == 0 and not ets_model: + mat_vt[components_number_ets+components_number_arima+xreg_number, :] = np.mean(y_in_sample[ot_logical]) + # Add first differences + else: + if e_type == "A": + mat_vt[components_number_ets+components_number_arima+xreg_number, :] = np.mean(np.diff(y_in_sample[ot_logical])) + else: + mat_vt[components_number_ets+components_number_arima+xreg_number, :] = np.exp(np.mean(np.diff(np.log(y_in_sample[ot_logical])))) + else: + mat_vt[components_number_ets+components_number_arima+xreg_number, :] = constant_value + + # If ETS model is used, change the initial level + if ets_model and initial_level_estimate: + if e_type == "A": + mat_vt[0, 0:lags_model_max] -= mat_vt[components_number_ets+components_number_arima+xreg_number, 0] + else: + mat_vt[0, 0:lags_model_max] /= mat_vt[components_number_ets+components_number_arima+xreg_number, 0] + + # If ARIMA is done, debias states + if arima_model and initial_arima_estimate: + if e_type == "A": + mat_vt[components_number_ets+non_zero_ari[:, 1], 0:initial_arima_number] -= \ + mat_vt[components_number_ets+components_number_arima+xreg_number, 0] + else: + mat_vt[components_number_ets+non_zero_ari[:, 1], 0:initial_arima_number] /= \ + mat_vt[components_number_ets+components_number_arima+xreg_number, 0] + else: + mat_vt[:, 0:lags_model_max] = profiles_recent_table + + return {'mat_vt': mat_vt, 'mat_wt': mat_wt, 'mat_f': mat_f, 'vec_g': vec_g, 'arima_polynomials': arima_polynomials} + + + + +def initialiser( + ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, + components_number_ets_non_seasonal, components_number_ets_seasonal, components_number_ets, + lags, lags_model, lags_model_seasonal, lags_model_arima, lags_model_max, + mat_vt, + # Persistence values + persistence_estimate=True, + persistence_level_estimate=True, persistence_trend_estimate=True, + persistence_seasonal_estimate=True, persistence_xreg_estimate=True, + # Initials + phi_estimate=True, initial_type="optimal", initial_estimate=True, + initial_level_estimate=True, initial_trend_estimate=True, initial_seasonal_estimate=True, + initial_arima_estimate=True, initial_xreg_estimate=True, + # ARIMA elements + arima_model=False, ar_required=False, ma_required=False, + ar_estimate=True, ma_estimate=True, + ar_orders=None, ma_orders=None, i_orders=None, + components_number_arima=0, components_names_arima=None, initial_arima_number=None, + # Explanatory variables + xreg_model=False, xreg_number=0, + xreg_parameters_estimated=None, xreg_parameters_persistence=None, + # Constant and other stuff + constant_estimate=True, constant_name=None, other_parameter_estimate=False, + # Additional parameters + y_in_sample=None, ot_logical=None, bounds="usual", other=None +): + persistence_estimate_vector = [ + persistence_level_estimate, + model_is_trendy and persistence_trend_estimate, + model_is_seasonal and any(persistence_seasonal_estimate) + ] + total_params = ( + ets_model * (sum(persistence_estimate_vector) + phi_estimate) + + xreg_model * persistence_xreg_estimate * max(xreg_parameters_persistence or [0]) + + arima_model * (ar_estimate * sum(ar_orders or []) + ma_estimate * sum(ma_orders or [])) + + ets_model * (initial_type not in ["complete", "backcasting"]) * ( + initial_level_estimate + + (model_is_trendy * initial_trend_estimate) + + (model_is_seasonal * sum(initial_seasonal_estimate * (np.array(lags_model_seasonal or []) - 1))) + ) + + (initial_type not in ["complete", "backcasting"]) * arima_model * (initial_arima_number or 0) * initial_arima_estimate + + (initial_type != "complete") * xreg_model * initial_xreg_estimate * sum(xreg_parameters_estimated or []) + + constant_estimate + other_parameter_estimate + ) + + B = np.full(total_params, np.nan) + Bl = np.full(total_params, np.nan) + Bu = np.full(total_params, np.nan) + names = [] + + j = 0 + + if ets_model: + if persistence_estimate and any(persistence_estimate_vector): + if any(ptype == "M" for ptype in [e_type, t_type, s_type]): + if ((e_type == "A" and t_type == "A" and s_type == "M") or + (e_type == "A" and t_type == "M" and s_type == "A") or + (initial_type in ["complete", "backcasting"] and + ((e_type == "M" and t_type == "A" and s_type == "A") or + (e_type == "M" and t_type == "A" and s_type == "M")))): + B[j:j+sum(persistence_estimate_vector)] = [0.01, 0] + [0] * components_number_ets_seasonal + elif e_type == "M" and t_type == "M" and s_type == "A": + B[j:j+sum(persistence_estimate_vector)] = [0, 0] + [0] * components_number_ets_seasonal + elif e_type == "M" and t_type == "A": + if initial_type in ["complete", "backcasting"]: + B[j:j+sum(persistence_estimate_vector)] = [0.1, 0] + [0.01] * components_number_ets_seasonal + else: + B[j:j+sum(persistence_estimate_vector)] = [0.2, 0.01] + [0.01] * components_number_ets_seasonal + elif e_type == "M" and t_type == "M": + B[j:j+sum(persistence_estimate_vector)] = [0.1, 0.05] + [0.01] * components_number_ets_seasonal + else: + initial_values = [0.1] + if model_is_trendy: + initial_values.append(0.05) + if model_is_seasonal: + initial_values.extend([0.11] * components_number_ets_seasonal) + + B[j:j+sum(persistence_estimate_vector)] = [val for val, estimate in zip(initial_values, persistence_estimate_vector) if estimate] + else: + initial_values = [0.1] + if model_is_trendy: + initial_values.append(0.05) + if model_is_seasonal: + initial_values.extend([0.11] * components_number_ets_seasonal) + + B[j:j+sum(persistence_estimate_vector)] = [val for val, estimate in zip(initial_values, persistence_estimate_vector) if estimate] + + if bounds == "usual": + Bl[j:j+sum(persistence_estimate_vector)] = 0 + Bu[j:j+sum(persistence_estimate_vector)] = 1 + else: + Bl[j:j+sum(persistence_estimate_vector)] = -5 + Bu[j:j+sum(persistence_estimate_vector)] = 5 + + # Names for B + if persistence_level_estimate: + names.append("alpha") + j += 1 + if model_is_trendy and persistence_trend_estimate: + names.append("beta") + j += 1 + if model_is_seasonal and any(persistence_seasonal_estimate): + if components_number_ets_seasonal > 1: + names.extend([f"gamma{i}" for i in range(1, components_number_ets_seasonal+1)]) + else: + names.append("gamma") + j += sum(persistence_seasonal_estimate) + + if xreg_model and persistence_xreg_estimate: + xreg_persistence_number = max(xreg_parameters_persistence) + B[j:j+xreg_persistence_number] = 0.01 if e_type == "A" else 0 + Bl[j:j+xreg_persistence_number] = -5 + Bu[j:j+xreg_persistence_number] = 5 + names.extend([f"delta{i+1}" for i in range(xreg_persistence_number)]) + j += xreg_persistence_number + + if ets_model and phi_estimate: + B[j] = 0.95 + names.append("phi") + Bl[j] = 0 + Bu[j] = 1 + j += 1 + + if arima_model: + if any([ar_estimate, ma_estimate]): + acf_values = [-0.1] * sum(ma_orders * lags) + pacf_values = [0.1] * sum(ar_orders * lags) + + if not (ets_model or all(i_orders == 0)): + y_differenced = y_in_sample.copy() + # Implement differencing if needed + if any(i_orders > 0): + for i, order in enumerate(i_orders): + if order > 0: + y_differenced = np.diff(y_differenced, n=order, axis=0) + + # ACF/PACF calculation for non-seasonal models + if all(np.array(lags) <= 1): + if ma_required and ma_estimate: + acf_values[:min(sum(ma_orders * lags), len(y_differenced) - 1)] = calculate_acf(y_differenced, nlags=max(1, sum(ma_orders * lags)))[1:] + if ar_required and ar_estimate: + pacf_values[:min(sum(ar_orders * lags), len(y_differenced) - 1)] = calculate_pacf(y_differenced, nlags=max(1, sum(ar_orders * lags))) + + for i, lag in enumerate(lags): + if ar_required and ar_estimate and ar_orders[i] > 0: + B[j:j+ar_orders[i]] = pacf_values[i*lag:(i+1)*lag][:ar_orders[i]] + if sum(B[j:j+ar_orders[i]]) > 1: + B[j:j+ar_orders[i]] = B[j:j+ar_orders[i]] / sum(B[j:j+ar_orders[i]]) - 0.01 + Bl[j:j+ar_orders[i]] = -5 + Bu[j:j+ar_orders[i]] = 5 + names.extend([f"phi{k+1}[{lag}]" for k in range(ar_orders[i])]) + j += ar_orders[i] + + if ma_required and ma_estimate and ma_orders[i] > 0: + B[j:j+ma_orders[i]] = acf_values[i*lag:(i+1)*lag][:ma_orders[i]] + if sum(B[j:j+ma_orders[i]]) > 1: + B[j:j+ma_orders[i]] = B[j:j+ma_orders[i]] / sum(B[j:j+ma_orders[i]]) - 0.01 + Bl[j:j+ma_orders[i]] = -5 + Bu[j:j+ma_orders[i]] = 5 + names.extend([f"theta{k+1}[{lag}]" for k in range(ma_orders[i])]) + j += ma_orders[i] + + if ets_model and initial_type not in ["complete", "backcasting"] and initial_estimate: + if initial_level_estimate: + B[j] = mat_vt[0, 0] + Bl[j] = -np.inf if e_type == "A" else 0 + Bu[j] = np.inf + names.append("level") + j += 1 + if model_is_trendy and initial_trend_estimate: + B[j] = mat_vt[1, 0] + Bl[j] = -np.inf if t_type == "A" else 0 + Bu[j] = np.inf + names.append("trend") + j += 1 + if model_is_seasonal and any(initial_seasonal_estimate): + for k in range(components_number_ets_seasonal): + if initial_seasonal_estimate[k]: + B[j:j+lags_model[components_number_ets_non_seasonal+k]-1] = mat_vt[components_number_ets_non_seasonal+k, 1:lags_model[components_number_ets_non_seasonal+k]] + if s_type == "A": + Bl[j:j+lags_model[components_number_ets_non_seasonal+k]-1] = -np.inf + Bu[j:j+lags_model[components_number_ets_non_seasonal+k]-1] = np.inf + else: + Bl[j:j+lags_model[components_number_ets_non_seasonal+k]-1] = 0 + Bu[j:j+lags_model[components_number_ets_non_seasonal+k]-1] = np.inf + names.extend([f"seasonal{k+1}_{m}" for m in range(2, lags_model[components_number_ets_non_seasonal+k])]) + j += lags_model[components_number_ets_non_seasonal+k] - 1 + + if initial_type not in ["complete", "backcasting"] and arima_model and initial_arima_estimate: + B[j:j+initial_arima_number] = mat_vt[components_number_ets+components_number_arima, :initial_arima_number] + names.extend([f"ARIMAState{n}" for n in range(1, initial_arima_number+1)]) + if e_type == "A": + Bl[j:j+initial_arima_number] = -np.inf + Bu[j:j+initial_arima_number] = np.inf + else: + B[j:j+initial_arima_number] = np.abs(B[j:j+initial_arima_number]) + Bl[j:j+initial_arima_number] = 0 + Bu[j:j+initial_arima_number] = np.inf + j += initial_arima_number + + if initial_type != "complete" and initial_xreg_estimate and xreg_model: + xreg_number_to_estimate = sum(xreg_parameters_estimated or []) + if xreg_number_to_estimate > 0: + B[j:j+xreg_number_to_estimate] = mat_vt[components_number_ets+components_number_arima:components_number_ets+components_number_arima+xreg_number, 0] + names.extend([f"xreg{idx+1}" for idx in range(xreg_number_to_estimate)]) + Bl[j:j+xreg_number_to_estimate] = -np.inf + Bu[j:j+xreg_number_to_estimate] = np.inf + j += xreg_number_to_estimate + + if constant_estimate: + j += 1 + if mat_vt.shape[0] > components_number_ets + components_number_arima + xreg_number: + B[j-1] = mat_vt[components_number_ets + components_number_arima + xreg_number, 0] + else: + B[j-1] = 0 # or some other default value + names.append(constant_name or "constant") + if ets_model or (i_orders is not None and sum(i_orders) != 0): + if e_type == "A": + Bu[j-1] = np.quantile(np.diff(y_in_sample[ot_logical]), 0.6) + Bl[j-1] = -Bu[j-1] + else: + Bu[j-1] = np.exp(np.quantile(np.diff(np.log(y_in_sample[ot_logical])), 0.6)) + Bl[j-1] = np.exp(np.quantile(np.diff(np.log(y_in_sample[ot_logical])), 0.4)) + + if Bu[j-1] <= Bl[j-1]: + Bu[j-1] = np.inf + Bl[j-1] = -np.inf if e_type == "A" else 0 + + if B[j-1] <= Bl[j-1]: + Bl[j-1] = -np.inf if e_type == "A" else 0 + if B[j-1] >= Bu[j-1]: + Bu[j-1] = np.inf + else: + Bu[j-1] = max(abs(y_in_sample[ot_logical]), abs(B[j-1]) * 1.01) + Bl[j-1] = -Bu[j-1] + + if other_parameter_estimate: + j += 1 + B[j-1] = other + names.append("other") + Bl[j-1] = 1e-10 + Bu[j-1] = np.inf + + return { + "B": B[:j], + "Bl": Bl[:j], + "Bu": Bu[:j], + "names": names + } + + +def filler(B, ets_model, E_type, T_type, S_type, model_is_trendy, model_is_seasonal, + components_number_ETS, components_number_ETS_non_seasonal, + components_number_ETS_seasonal, components_number_ARIMA, + lags, lags_model, lags_model_max, + mat_Vt, mat_Wt, mat_F, vec_G, + persistence_estimate, persistence_level_estimate, persistence_trend_estimate, + persistence_seasonal_estimate, persistence_xreg_estimate, + phi_estimate, + initial_type, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, + arima_model, ar_estimate, ma_estimate, ar_orders, i_orders, ma_orders, + ar_required, ma_required, arma_parameters, + non_zero_ARI, non_zero_MA, arima_polynomials, + xreg_model, xreg_number, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_estimate): + + j = 0 + + # Fill in persistence + if persistence_estimate: + # Persistence of ETS + if ets_model: + i = 0 + # alpha + if persistence_level_estimate: + j += 1 + vec_G[i] = B[j-1] + + # beta + if model_is_trendy: + i = 1 + if persistence_trend_estimate: + j += 1 + vec_G[i] = B[j-1] + + # gamma1, gamma2, ... + if model_is_seasonal: + if any(persistence_seasonal_estimate): + vec_G[i + np.where(persistence_seasonal_estimate)[0]] = B[j:j+sum(persistence_seasonal_estimate)] + j += sum(persistence_seasonal_estimate) + i = components_number_ETS - 1 + + # Persistence of xreg + if xreg_model and persistence_xreg_estimate: + xreg_persistence_number = max(xreg_parameters_persistence) + vec_G[j + components_number_ARIMA:j + components_number_ARIMA + len(xreg_parameters_persistence)] = \ + B[j:j+xreg_persistence_number][np.array(xreg_parameters_persistence) - 1] + j += xreg_persistence_number + + # Damping parameter + if ets_model and phi_estimate: + j += 1 + mat_Wt[:, 1] = B[j-1] + mat_F[0:2, 1] = B[j-1] + + # ARMA parameters + if arima_model: + # Call the function returning ARI and MA polynomials + arima_polynomials = adam_polynomialiser( + B[j:j+sum(np.array(ar_orders)*ar_estimate + np.array(ma_orders)*ma_estimate)], + ar_orders, i_orders, ma_orders, + ar_estimate, ma_estimate, arma_parameters, lags + ) + arima_polynomials = {k: np.array(v) for k, v in arima_polynomials.items()} + + # Fill in the transition matrix + if non_zero_ARI.shape[0] > 0: + mat_F[components_number_ETS + non_zero_ARI[:, 1], + components_number_ETS:components_number_ETS + components_number_ARIMA + constant_estimate] = \ + -arima_polynomials['ariPolynomial'][non_zero_ARI[:, 0]] + + # Fill in the persistence vector + if non_zero_ARI.shape[0] > 0: + vec_G[components_number_ETS + non_zero_ARI[:, 1]] = -arima_polynomials['ariPolynomial'][non_zero_ARI[:, 0]] + if non_zero_MA.shape[0] > 0: + vec_G[components_number_ETS + non_zero_MA[:, 1]] += arima_polynomials['maPolynomial'][non_zero_MA[:, 0]] + + j += sum(np.array(ar_orders)*ar_estimate + np.array(ma_orders)*ma_estimate) + + # Initials of ETS + if ets_model and all(initial_type != ['complete', 'backcasting']) and initial_estimate: + i = 0 + if initial_level_estimate: + j += 1 + mat_Vt[i, :lags_model_max] = B[j-1] + i += 1 + if model_is_trendy and initial_trend_estimate: + j += 1 + mat_Vt[i, :lags_model_max] = B[j-1] + i += 1 + if model_is_seasonal and any(initial_seasonal_estimate): + for k in range(components_number_ETS_seasonal): + if initial_seasonal_estimate[k]: + mat_Vt[components_number_ETS_non_seasonal + k, + 1:lags_model[components_number_ETS_non_seasonal + k] - 1] = \ + B[j:j+lags_model[components_number_ETS_non_seasonal + k] - 2] + if S_type == "A": + mat_Vt[components_number_ETS_non_seasonal + k, + lags_model[components_number_ETS_non_seasonal + k] - 1] = \ + -np.sum(B[j:j+lags_model[components_number_ETS_non_seasonal + k] - 2]) + else: # "M" + mat_Vt[components_number_ETS_non_seasonal + k, + lags_model[components_number_ETS_non_seasonal + k] - 1] = \ + 1 / np.prod(B[j:j+lags_model[components_number_ETS_non_seasonal + k] - 2]) + j += lags_model[components_number_ETS_non_seasonal + k] - 1 + + # Initials of ARIMA + if arima_model: + if all(initial_type != ['complete', 'backcasting']) and initial_arima_estimate: + mat_Vt[components_number_ETS + components_number_ARIMA - 1, :initial_arima_number] = B[j:j+initial_arima_number] + if E_type == "A": + mat_Vt[components_number_ETS + non_zero_ARI[:, 1], :initial_arima_number] = \ + np.dot(arima_polynomials['ariPolynomial'][non_zero_ARI[:, 0]], + B[j:j+initial_arima_number].reshape(1, -1)) / arima_polynomials['ariPolynomial'][-1] + else: # "M" + mat_Vt[components_number_ETS + non_zero_ARI[:, 1], :initial_arima_number] = \ + np.exp(np.dot(arima_polynomials['ariPolynomial'][non_zero_ARI[:, 0]], + np.log(B[j:j+initial_arima_number]).reshape(1, -1)) / arima_polynomials['ariPolynomial'][-1]) + j += initial_arima_number + elif any([ar_estimate, ma_estimate]): + if E_type == "A": + mat_Vt[components_number_ETS + non_zero_ARI[:, 1], :initial_arima_number] = \ + np.dot(arima_polynomials['ariPolynomial'][non_zero_ARI[:, 0]], + mat_Vt[components_number_ETS + components_number_ARIMA - 1, :initial_arima_number].reshape(1, -1)) / \ + arima_polynomials['ariPolynomial'][-1] + else: # "M" + mat_Vt[components_number_ETS + non_zero_ARI[:, 1], :initial_arima_number] = \ + np.exp(np.dot(arima_polynomials['ariPolynomial'][non_zero_ARI[:, 0]], + np.log(mat_Vt[components_number_ETS + components_number_ARIMA - 1, :initial_arima_number]).reshape(1, -1)) / \ + arima_polynomials['ariPolynomial'][-1]) + + # Initials of the xreg + if xreg_model and (initial_type != "complete") and initial_estimate and initial_xreg_estimate: + xreg_number_to_estimate = sum(xreg_parameters_estimated) + mat_Vt[components_number_ETS + components_number_ARIMA + np.where(xreg_parameters_estimated == 1)[0], + :lags_model_max] = B[j:j+xreg_number_to_estimate] + j += xreg_number_to_estimate + # Normalise initials + for i in np.where(xreg_parameters_missing != 0)[0]: + mat_Vt[components_number_ETS + components_number_ARIMA + i, :lags_model_max] = \ + -np.sum(mat_Vt[components_number_ETS + components_number_ARIMA + + np.where(xreg_parameters_included == xreg_parameters_missing[i])[0], + :lags_model_max]) + + # Constant + if constant_estimate: + mat_Vt[components_number_ETS + components_number_ARIMA + xreg_number, :] = B[j] + + return { + 'mat_Vt': mat_Vt, + 'mat_Wt': mat_Wt, + 'mat_F': mat_F, + 'vec_G': vec_G, + 'arima_polynomials': arima_polynomials + } + + + + +def adam_profile_creator( + lags_model_all: List[List[int]], + lags_model_max: int, + obs_all: int, + lags: Union[List[int], None] = None, + y_index: Union[List, None] = None, + y_classes: Union[List, None] = None +) -> Dict[str, np.ndarray]: + """ + Creates recent profile and the lookup table for ADAM. + + Args: + lags_model_all: All lags used in the model for ETS + ARIMA + xreg. + lags_model_max: The maximum lag used in the model. + obs_all: Number of observations to create. + lags: The original lags provided by user (optional). + y_index: The indices needed to get the specific dates (optional). + y_classes: The class used for the actual data (optional). + + Returns: + A dictionary with 'recent' (profiles_recent_table) and 'lookup' + (index_lookup_table) as keys. + """ + # Initialize matrices + profiles_recent_table = np.zeros((len(lags_model_all), lags_model_max)) + index_lookup_table = np.ones((len(lags_model_all), obs_all + lags_model_max)) + profile_indices = ( + np.arange(1, lags_model_max * len(lags_model_all) + 1) + .reshape(-1, len(lags_model_all)) + .T + ) + + # Update matrices based on lagsModelAll + for i, lag in enumerate(lags_model_all): + # Create the matrix with profiles based on the provided lags. + # For every row, fill the first 'lag' elements from 1 to lag + profiles_recent_table[i, : lag[0]] = np.arange(1, lag[0] + 1) + + # For the i-th row in indexLookupTable, fill with a repeated sequence starting + # from lagsModelMax to the end of the row. + # The repeated sequence is the i-th row of profileIndices, repeated enough times + # to cover 'obsAll' observations. + # '- 1' at the end adjusts these values to Python's zero-based indexing. + index_lookup_table[i, lags_model_max : (lags_model_max + obs_all)] = ( + np.tile( + profile_indices[i, : lags_model_all[i][0]], + int(np.ceil(obs_all / lags_model_all[i][0])), + )[0:obs_all] + - 1 + ) + + # Extract unique values from from lagsModelMax to lagsModelMax + obsAll of + # indexLookupTable + unique_values = np.unique( + index_lookup_table[i, lags_model_max : lags_model_max + obs_all] # noqa + ) + + # fix the head of teh data before the sample starts + # Repeat the unique values lagsModelMax times and then trim the sequence to only + # keep the first lagsModelMax elements + index_lookup_table[i, :lags_model_max] = np.tile(unique_values, lags_model_max)[ + -lags_model_max: + ] + + # Convert to int! + index_lookup_table = index_lookup_table.astype(int) + + # Note: I skip andling of special cases (e.g., daylight saving time, leap years) + return { + "recent": np.array(profiles_recent_table, dtype="float64"), + "lookup": np.array(index_lookup_table, dtype="int64"), + } + +def parameters_checker(data: Union[np.ndarray, pd.Series, pd.DataFrame], + model: str = "ZXZ", + lags: Union[List[int], None] = None, + orders: Union[List[int], Dict[str, List[int]], None] = None, + formula: Union[str, None] = None, + constant: bool = True, + distribution: str = "dnorm", + loss: str = "likelihood", + h: int = 10, + holdout: bool = False, + persistence: Union[List[float], Dict[str, Union[float, List[float]]], None] = None, + phi: Union[float, None] = None, + initial: Union[str, List[float], Dict[str, Union[float, List[float]]], None] = None, + **kwargs: Any) -> Dict[str, Any]: + """ + Checks and processes input parameters for ADAM models. + + Args: + data: Input data (numpy array, pandas Series, or DataFrame). + model: Model type string. + lags: List of lag values. + orders: ARIMA orders as list [p, d, q] or dict {'ar': p, 'i': d, 'ma': q}. + formula: Formula string for regression component. + constant: Whether to include a constant term. + distribution: Error distribution type. + loss: Loss function to use. + h: Forecast horizon. + holdout: Whether to use holdout for evaluation. + persistence: Persistence parameters. + phi: Damping parameter. + initial: Initial values for model components. + **kwargs: Additional keyword arguments. + + Returns: + A dictionary of processed parameters. + + Raises: + ValueError: If any of the input parameters are invalid. + """ + # Check data + if isinstance(data, pd.DataFrame): + y = data.iloc[:, 0].values + xreg = data.iloc[:, 1:].values if data.shape[1] > 1 else None + elif isinstance(data, pd.Series): + y = data.values + xreg = None + elif isinstance(data, np.ndarray): + if data.ndim == 1: + y = data + xreg = None + elif data.ndim == 2: + y = data[:, 0] + xreg = data[:, 1:] if data.shape[1] > 1 else None + else: + raise ValueError("data must be 1D or 2D array-like") + else: + raise ValueError("data must be pandas DataFrame, Series, or numpy array") + + # Check model + if not isinstance(model, str): + raise ValueError("model must be a string") + + # Check lags + if lags is None: + lags = [1] # Default to 1 if not provided + if not isinstance(lags, list): + raise ValueError("lags must be a list of integers or None") + + # Check orders + if orders is not None: + if isinstance(orders, list): + if len(orders) != 3: + raise ValueError("orders as list must have 3 elements: [p, d, q]") + elif isinstance(orders, dict): + if not all(key in orders for key in ['ar', 'i', 'ma']): + raise ValueError("orders as dict must have keys: 'ar', 'i', 'ma'") + else: + raise ValueError("orders must be a list, dict, or None") + + # Check formula + if formula is not None and not isinstance(formula, str): + raise ValueError("formula must be a string or None") + + # Check distribution + valid_distributions = ["dnorm", "dlaplace", "ds", "dgnorm", "dlnorm", "dgamma", "dinvgauss"] + if distribution not in valid_distributions: + raise ValueError(f"distribution must be one of {valid_distributions}") + + # Check loss + valid_losses = ["likelihood", "MSE", "MAE", "HAM", "LASSO", "RIDGE", "TMSE", "GTMSE", "MSEh", "MSCE"] + if loss not in valid_losses and not callable(loss): + raise ValueError(f"loss must be one of {valid_losses} or a callable function") + + # Check h and holdout + if not isinstance(h, int) or h <= 0: + raise ValueError("h must be a positive integer") + if not isinstance(holdout, bool): + raise ValueError("holdout must be a boolean") + + # Check persistence + if persistence is not None: + if not isinstance(persistence, (list, dict)): + raise ValueError("persistence must be a list, dict, or None") + + # Check phi + if phi is not None and not isinstance(phi, (int, float)): + raise ValueError("phi must be a number or None") + + # Check initial + valid_initial_str = ["optimal", "backcasting", "complete"] + if initial is not None: + if isinstance(initial, str) and initial not in valid_initial_str: + raise ValueError(f"initial as string must be one of {valid_initial_str}") + elif not isinstance(initial, (str, list, dict)): + raise ValueError("initial must be a string, list, dict, or None") + + # Return the processed parameters + return { + "y": y, + "xreg": xreg, + "model": model, + "lags": lags, + "orders": orders, + "formula": formula, + "constant": constant, + "distribution": distribution, + "loss": loss, + "h": h, + "holdout": holdout, + "persistence": persistence, + "phi": phi, + "initial": initial, + **kwargs + } + +def architector(ets_model: bool, E_type: str, T_type: str, S_type: str, + lags: List[int], lags_model_seasonal: List[int], + xreg_number: int, obs_in_sample: int, initial_type: str, + arima_model: bool, lags_model_ARIMA: List[int], + xreg_model: bool, constant_required: bool, + profiles_recent_table: Union[np.ndarray, None] = None, + profiles_recent_provided: bool = False) -> Dict[str, Any]: + """ + Constructs the architecture for ADAM models. + + Args: + ets_model: Whether ETS model is included. + E_type, T_type, S_type: ETS model types for error, trend, and seasonality. + lags: List of lag values. + lags_model_seasonal: List of seasonal lags. + xreg_number: Number of external regressors. + obs_in_sample: Number of in-sample observations. + initial_type: Type of initial values. + arima_model: Whether ARIMA model is included. + lags_model_ARIMA: List of ARIMA lags. + xreg_model: Whether external regressors are included. + constant_required: Whether a constant term is required. + profiles_recent_table: Pre-computed recent profiles table (optional). + profiles_recent_provided: Whether profiles_recent_table is provided. + + Returns: + A dictionary containing the model architecture components. + """ + components = {} + + # If there is ETS + if ets_model: + model_is_trendy = T_type != "N" + if model_is_trendy: + # Make lags (1, 1) + lags_model = [[1, 1]] + components_names_ETS = ["level", "trend"] + else: + # Make lags (1, ...) + lags_model = [[1]] + components_names_ETS = ["level"] + + model_is_seasonal = S_type != "N" + if model_is_seasonal: + # If the lags are for the non-seasonal model + lags_model.extend([[lag] for lag in lags_model_seasonal]) + components_number_ETS_seasonal = len(lags_model_seasonal) + if components_number_ETS_seasonal > 1: + components_names_ETS.extend([f"seasonal{i+1}" for i in range(components_number_ETS_seasonal)]) + else: + components_names_ETS.append("seasonal") + else: + components_number_ETS_seasonal = 0 + + lags_model_all = lags_model + components_number_ETS = len(lags_model) + else: + model_is_trendy = model_is_seasonal = False + components_number_ETS = components_number_ETS_seasonal = 0 + components_names_ETS = None + lags_model_all = lags_model = None + + # If there is ARIMA + if arima_model: + lags_model_all = lags_model + [[lag] for lag in lags_model_ARIMA] + + # If constant is needed, add it + if constant_required: + lags_model_all.append([1]) + + # If there are xreg + if xreg_model: + lags_model_all.extend([[1]] * xreg_number) + + lags_model_max = max(max(lag) for lag in lags_model_all) + + # Define the number of cols that should be in the matvt + obs_states = obs_in_sample + lags_model_max + + # Create ADAM profiles for correct treatment of seasonality + adam_profiles = adam_profile_creator(lags_model_all, lags_model_max, obs_in_sample + lags_model_max, + lags=lags, y_index=None, y_classes=None) + if profiles_recent_provided: + profiles_recent_table = profiles_recent_table[:, :lags_model_max] + else: + profiles_recent_table = adam_profiles['recent'] + index_lookup_table = adam_profiles['lookup'] + + components.update({ + 'model_is_trendy': model_is_trendy, + 'model_is_seasonal': model_is_seasonal, + 'components_number_ETS': components_number_ETS, + 'components_number_ETS_seasonal': components_number_ETS_seasonal, + 'components_names_ETS': components_names_ETS, + 'lags_model': lags_model, + 'lags_model_all': lags_model_all, + 'lags_model_max': lags_model_max, + 'obs_states': obs_states, + 'profiles_recent_table': profiles_recent_table, + 'index_lookup_table': index_lookup_table + }) + + return components \ No newline at end of file diff --git a/python/smooth/adam_general/core/estimator.py b/python/smooth/adam_general/core/estimator.py new file mode 100644 index 00000000..b48d24d4 --- /dev/null +++ b/python/smooth/adam_general/core/estimator.py @@ -0,0 +1,1050 @@ +import numpy as np +from adam_profile import architector +from python.smooth.adam_general.core.creator import creator +import nlopt +from python.smooth.adam_general.core.utils.ic import ic_function +import pandas as pd + + + + + +def estimator(ets_model, e_type, t_type, s_type, lags, lags_model_seasonal, lags_model_arima, + obs_states, obs_in_sample, + y_in_sample, persistence, persistence_estimate, + persistence_level, persistence_level_estimate, + persistence_trend, persistence_trend_estimate, + persistence_seasonal, persistence_seasonal_estimate, + persistence_xreg, persistence_xreg_estimate, persistence_xreg_provided, + phi, phi_estimate, + initial_type, initial_level, initial_trend, initial_seasonal, + initial_arima, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, initial_xreg_provided, + arima_model, ar_required, i_required, ma_required, arma_parameters, + components_number_arima, components_names_arima, + formula, xreg_model, xreg_model_initials, xreg_data, xreg_number, xreg_names, regressors, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_required, constant_estimate, constant_value, constant_name, + ot, ot_logical, occurrence_model, p_fitted, + bounds, loss, loss_function, distribution, + horizon, multisteps, other, other_parameter_estimate, lambda_param): + + + # Create the basic variables + adam_architect = architector( + ets_model, e_type, t_type, s_type, lags, lags_model_seasonal, + xreg_number, obs_in_sample, initial_type, + arima_model, lags_model_arima, xreg_model, constant_required, + profiles_recent_table, profiles_recent_provided + ) + + # Create the matrices for the specific ETS model + adam_created = creator( + ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, + lags, lags_model, lags_model_arima, lags_model_all, lags_model_max, + profiles_recent_table, profiles_recent_provided, + obs_states, obs_in_sample, obs_all, components_number_ets, components_number_ets_seasonal, + components_names_ets, ot_logical, y_in_sample, + persistence, persistence_estimate, + persistence_level, persistence_level_estimate, persistence_trend, persistence_trend_estimate, + persistence_seasonal, persistence_seasonal_estimate, + persistence_xreg, persistence_xreg_estimate, persistence_xreg_provided, + phi, + initial_type, initial_estimate, + initial_level, initial_level_estimate, initial_trend, initial_trend_estimate, + initial_seasonal, initial_seasonal_estimate, + initial_arima, initial_arima_estimate, initial_arima_number, + initial_xreg_estimate, initial_xreg_provided, + arima_model, ar_required, i_required, ma_required, arma_parameters, + ar_orders, i_orders, ma_orders, + components_number_arima, components_names_arima, + xreg_model, xreg_model_initials, xreg_data, xreg_number, xreg_names, + xreg_parameters_persistence, + constant_required, constant_estimate, constant_value, constant_name + ) + + # Initialize B + b_values = initialiser( + ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, + components_number_ets_non_seasonal, components_number_ets_seasonal, components_number_ets, + lags, lags_model, lags_model_seasonal, lags_model_arima, lags_model_max, + adam_created['mat_vt'], + persistence_estimate, persistence_level_estimate, persistence_trend_estimate, + persistence_seasonal_estimate, persistence_xreg_estimate, + phi_estimate, initial_type, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, + arima_model, ar_required, ma_required, ar_estimate, ma_estimate, ar_orders, ma_orders, + components_number_arima, components_names_arima, initial_arima_number, + xreg_model, xreg_number, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_estimate, constant_name, other_parameter_estimate + ) + + if B is not None: + if isinstance(B, dict): + B = {k: v for k, v in B.items() if k in b_values['B']} + b_values['B'].update(B) + else: + b_values['B'][:] = B + B = dict(zip(b_values['B'].keys(), B)) + + # Continue with the rest of the function... + # Preheat the initial state of ARIMA. Do this only for optimal initials and if B is not provided + if arima_model and initial_type == "optimal" and initial_arima_estimate and B is None: + adam_created_arima = filler( + b_values['B'], + ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, + components_number_ets, components_number_ets_non_seasonal, + components_number_ets_seasonal, components_number_arima, + lags, lags_model, lags_model_max, + adam_created['mat_vt'], adam_created['mat_wt'], adam_created['mat_f'], adam_created['vec_g'], + persistence_estimate, persistence_level_estimate, persistence_trend_estimate, + persistence_seasonal_estimate, persistence_xreg_estimate, + phi_estimate, + initial_type, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, + arima_model, ar_estimate, ma_estimate, ar_orders, i_orders, ma_orders, + ar_required, ma_required, arma_parameters, + non_zero_ari, non_zero_ma, adam_created['arima_polynomials'], + xreg_model, xreg_number, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, constant_estimate + ) + + # Write down the initials in the recent profile + profiles_recent_table[:] = adam_created_arima['mat_vt'][:, :lags_model_max] + + # Do initial fit to get the state values from the backcasting + adam_fitted = adam_fitter_wrap( + adam_created_arima['mat_vt'], adam_created_arima['mat_wt'], adam_created_arima['mat_f'], adam_created_arima['vec_g'], + lags_model_all, index_lookup_table, profiles_recent_table, + e_type, t_type, s_type, components_number_ets, components_number_ets_seasonal, + components_number_arima, xreg_number, constant_required, + y_in_sample, ot, True + ) + + adam_created['mat_vt'][:, :lags_model_max] = adam_fitted['mat_vt'][:, :lags_model_max] + # Produce new initials + b_values_new = initialiser( + ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, + components_number_ets_non_seasonal, components_number_ets_seasonal, components_number_ets, + lags, lags_model, lags_model_seasonal, lags_model_arima, lags_model_max, + adam_created['mat_vt'], + persistence_estimate, persistence_level_estimate, persistence_trend_estimate, + persistence_seasonal_estimate, persistence_xreg_estimate, + phi_estimate, initial_type, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, + arima_model, ar_required, ma_required, ar_estimate, ma_estimate, ar_orders, ma_orders, + components_number_arima, components_names_arima, initial_arima_number, + xreg_model, xreg_number, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_estimate, constant_name, other_parameter_estimate + ) + B = b_values_new['B'] + # Failsafe, just in case if the initial values contain NA / NaN + B[np.isnan(B)] = b_values['B'][np.isnan(B)] + + + + # Fix for mixed ETS models producing negative values + if (e_type == "M" and any(t in ["A", "Ad"] for t in [t_type, s_type]) or + t_type == "M" and any(t in ["A", "Ad"] for t in [e_type, s_type]) or + s_type == "M" and any(t in ["A", "Ad"] for t in [e_type, t_type])): + if e_type == "M" and ("level" in B) and (B["level"] <= 0): + B["level"] = y_in_sample[0] + if t_type == "M" and ("trend" in B) and (B["trend"] <= 0): + B["trend"] = 1 + seasonal_params = [p for p in B.keys() if p.startswith("seasonal")] + if s_type == "M" and any(B[p] <= 0 for p in seasonal_params): + for p in seasonal_params: + if B[p] <= 0: + B[p] = 1 + + # Create the vector of initials for the optimisation + if B is None: + B = b_values['B'] + if lb is None: + lb = b_values['Bl'] + if ub is None: + ub = b_values['Bu'] + + # Companion matrices for the polynomials calculation -> stationarity / stability checks + if arima_model: + # AR polynomials + ar_polynomial_matrix = np.zeros((np.sum(ar_orders) * lags, np.sum(ar_orders) * lags)) + if ar_polynomial_matrix.shape[0] > 1: + ar_polynomial_matrix[1:, :-1] = np.eye(ar_polynomial_matrix.shape[0] - 1) + # MA polynomials + ma_polynomial_matrix = np.zeros((np.sum(ma_orders) * lags, np.sum(ma_orders) * lags)) + if ma_polynomial_matrix.shape[0] > 1: + ma_polynomial_matrix[1:, :-1] = np.eye(ma_polynomial_matrix.shape[0] - 1) + else: + ma_polynomial_matrix = ar_polynomial_matrix = None + + # If the distribution is default, change it according to the error term + if distribution == "default": + if loss == "likelihood": + distribution_new = "dnorm" if e_type == "A" else "dgamma" + elif loss in ["MAEh", "MACE", "MAE"]: + distribution_new = "dlaplace" + elif loss in ["HAMh", "CHAM", "HAM"]: + distribution_new = "ds" + else: + distribution_new = "dnorm" + else: + distribution_new = distribution + + + # Parameters are chosen to speed up the optimisation process and have decent accuracy + #opts = { + # 'algorithm': algorithm, + # 'xtol_rel': xtol_rel, + # 'xtol_abs': xtol_abs, + # 'ftol_rel': ftol_rel, + # 'ftol_abs': ftol_abs, + # 'maxeval': maxeval_used, + # 'maxtime': maxtime, + # 'print_level': print_level + #} + + # Create nlopt optimizer object + opt = nlopt.opt(nlopt.LD_SLSQP, len(B)) # Use SLSQP algorithm to match R code + + # Set bounds + opt.set_lower_bounds(lb) + opt.set_upper_bounds(ub) + + # Set stopping criteria + opt.set_ftol_rel(ftol_rel) + opt.set_xtol_rel(xtol_rel) + opt.set_xtol_abs(xtol_abs) + opt.set_ftol_abs(ftol_abs) + opt.set_maxeval(maxeval_used) + if maxtime is not None: + opt.set_maxtime(maxtime) + + # Define objective function wrapper since nlopt expects different signature + def objective_wrapper(x, grad): + return CF(x, + ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, y_in_sample, + ot, ot_logical, occurrence_model, obs_in_sample, + components_number_ets, components_number_ets_seasonal, components_number_ets_non_seasonal, + components_number_arima, + lags, lags_model, lags_model_all, lags_model_max, + index_lookup_table, profiles_recent_table, + adam_created['mat_vt'], adam_created['mat_wt'], adam_created['mat_f'], adam_created['vec_g'], + persistence_estimate, persistence_level_estimate, persistence_trend_estimate, + persistence_seasonal_estimate, persistence_xreg_estimate, + phi_estimate, initial_type, initial_estimate, initial_level_estimate, + initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, + arima_model, non_zero_ari, non_zero_ma, adam_created['arima_polynomials'], + ar_estimate, ma_estimate, + ar_orders, i_orders, ma_orders, + ar_required, ma_required, arma_parameters, + xreg_model, xreg_number, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_required, constant_estimate, + bounds, loss, loss_function, distribution_new, + horizon, multisteps, + denominator, y_denominator, + other, other_parameter_estimate, lambda_, + ar_polynomial_matrix, ma_polynomial_matrix) + + # Set objective function + opt.set_min_objective(objective_wrapper) + + try: + # Run optimization + x = opt.optimize(B) + res_fun = opt.last_optimum_value() + res = type('OptimizeResult', (), { + 'x': x, + 'fun': res_fun, + 'success': True + }) + except Exception as e: + print(f"Optimization failed: {str(e)}") + res = type('OptimizeResult', (), { + 'x': B, + 'fun': 1e+300, + 'success': False + }) + + # If optimization failed, try again with modified initial values + if np.isinf(res.fun) or res.fun == 1e+300: + # Reset initial values + if ets_model: + B[:components_number_ets] = 0 + if arima_model: + start_idx = components_number_ets + persistence_xreg_estimate * xreg_number + end_idx = start_idx + sum(np.array(ar_orders) * ar_estimate + np.array(ma_orders) * ma_estimate) + B[start_idx:end_idx] = 0.01 + + try: + # Try optimization again + x = opt.optimize(B) + res_fun = opt.last_optimum_value() + res = type('OptimizeResult', (), { + 'x': x, + 'fun': res_fun, + 'success': True + }) + except Exception as e: + print(f"Second optimization attempt failed: {str(e)}") + res = type('OptimizeResult', (), { + 'x': B, + 'fun': 1e+300, + 'success': False + }) + + if print_level_hidden > 0: + print(res) + + # Check the obtained parameters and the loss value and remove redundant parameters + # Cases to consider: + # 1. Some smoothing parameters are zero or one; + # 2. The cost function value is -Inf (due to no variability in the sample); + + # Prepare the values to return + B[:] = res.x + CF_value = res.fun + # A fix for the special case of LASSO/RIDGE with lambda==1 + if any(loss == loss_type for loss_type in ["LASSO", "RIDGE"]) and lambda_ == 1: + CF_value = 0 + n_param_estimated = len(B) + + + # Return a proper logLik class equivalent + logLikADAMValue = logLikReturn( + B, + ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, y_in_sample, + ot, ot_logical, occurrence_model, p_fitted, obs_in_sample, + components_number_ets, components_number_ets_seasonal, components_number_ets_non_seasonal, + components_number_arima, + lags, lags_model, lags_model_all, lags_model_max, + index_lookup_table, profiles_recent_table, + adam_created['mat_vt'], adam_created['mat_wt'], adam_created['mat_f'], adam_created['vec_g'], + persistence_estimate, persistence_level_estimate, persistence_trend_estimate, + persistence_seasonal_estimate, persistence_xreg_estimate, + phi_estimate, initial_type, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, + arima_model, non_zero_ari, non_zero_ma, ar_estimate, ma_estimate, + adam_created['arima_polynomials'], + ar_orders, i_orders, ma_orders, ar_required, ma_required, arma_parameters, + xreg_model, xreg_number, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_required, constant_estimate, + bounds, loss, loss_function, distribution_new, horizon, multisteps, + denominator, y_denominator, other, other_parameter_estimate, lambda_, + ar_polynomial_matrix, ma_polynomial_matrix + ) + + # In case of likelihood, we typically have one more parameter to estimate - scale. + logLikADAMValue = { + 'value': logLikADAMValue, + 'nobs': obs_in_sample, + 'df': n_param_estimated + (1 if loss == "likelihood" else 0) + } + + # Here I will add regressors when I have olm + # line 3032 - 3322 + + return { + 'B': B, + 'CF_value': CF_value, + 'n_param_estimated': n_param_estimated, + 'logLikADAMValue': logLikADAMValue, + 'xreg_model': xreg_model, + 'xreg_data': xreg_data, + 'xreg_number': xreg_number, + 'xreg_names': xreg_names, + 'xreg_model_initials': xreg_model_initials, + 'formula': formula, + 'initial_xreg_estimate': initial_xreg_estimate, + 'persistence_xreg_estimate': persistence_xreg_estimate, + 'xreg_parameters_missing': xreg_parameters_missing, + 'xreg_parameters_included': xreg_parameters_included, + 'xreg_parameters_estimated': xreg_parameters_estimated, + 'xreg_parameters_persistence': xreg_parameters_persistence, + 'arima_polynomials': adam_created['arima_polynomials'] + } + + +def selector(model, models_pool, allow_multiplicative, + ets_model, e_type, t_type, s_type, damped, lags, + lags_model_seasonal, lags_model_arima, + obs_states, obs_in_sample, + y_in_sample, persistence, persistence_estimate, + persistence_level, persistence_level_estimate, + persistence_trend, persistence_trend_estimate, + persistence_seasonal, persistence_seasonal_estimate, + persistence_xreg, persistence_xreg_estimate, persistence_xreg_provided, + phi, phi_estimate, + initial_type, initial_level, initial_trend, initial_seasonal, + initial_arima, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, initial_xreg_provided, + arima_model, ar_required, i_required, ma_required, arma_parameters, + components_number_arima, components_names_arima, + xreg_model, xreg_model_initials, xreg_data, xreg_number, xreg_names, regressors, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_required, constant_estimate, constant_value, constant_name, + ot, ot_logical, occurrence_model, p_fitted, ic_function, + bounds, loss, loss_function, distribution, + horizon, multisteps, other, other_parameter_estimate, lambda_): + """Creates a pool of models and selects the best of them""" + + + # Check if the pool was provided. In case of "no", form the big and the small ones + if models_pool is None: + # The variable saying that the pool was not provided. + if not silent: + print("Forming the pool of models based on... ", end="") + + # Define the whole pool of errors + if not allow_multiplicative: + pool_errors = ["A"] + pool_trends = ["N", "A", "Ad"] + pool_seasonals = ["N", "A"] + else: + pool_errors = ["A", "M"] + pool_trends = ["N", "A", "Ad", "M", "Md"] + pool_seasonals = ["N", "A", "M"] + + # Some preparation variables + # If e_type is not Z, then check on additive errors + if e_type != "Z": + pool_errors = pool_errors_small = e_type + else: + pool_errors_small = "A" + + # If t_type is not Z, then create a pool with specified type + if t_type != "Z": + if t_type == "X": + pool_trends_small = ["N", "A"] + pool_trends = ["N", "A", "Ad"] + check_trend = True + elif t_type == "Y": + pool_trends_small = ["N", "M"] + pool_trends = ["N", "M", "Md"] + check_trend = True + else: + if damped: + pool_trends = pool_trends_small = [t_type + "d"] + else: + pool_trends = pool_trends_small = [t_type] + check_trend = False + else: + pool_trends_small = ["N", "A"] + check_trend = True + + # If s_type is not Z, then create specific pools + if s_type != "Z": + if s_type == "X": + pool_seasonals = pool_seasonals_small = ["N", "A"] + check_seasonal = True + elif s_type == "Y": + pool_seasonals_small = ["N", "M"] + pool_seasonals = ["N", "M"] + check_seasonal = True + else: + pool_seasonals_small = [s_type] + pool_seasonals = [s_type] + check_seasonal = False + else: + pool_seasonals_small = ["N", "A", "M"] + check_seasonal = True + + # If ZZZ, then the vector is: "ANN" "ANA" "ANM" "AAN" "AAA" "AAM" + # Otherwise depends on the provided restrictions + pool_small = [] + for error in pool_errors_small: + for trend in pool_trends_small: + for seasonal in pool_seasonals_small: + pool_small.append(error + trend + seasonal) + + # Align error and seasonality, if the error was not forced to be additive + # The new pool: "ANN" "ANA" "MNM" "AAN" "AAA" "MAM" + if any(model[2] == "M" for model in pool_small) and e_type not in ["A", "X"]: + for i, model in enumerate(pool_small): + if model[2] == "M": + pool_small[i] = "M" + model[1:] + + models_tested = None + model_current = None + + # Counter + checks for the components + j = 1 + i = 0 + check = True + best_i = best_j = 1 + results = [None] * len(pool_small) + + + # Branch and bound is here + while check: + i += 1 + model_current = pool_small[j-1] + + e_type = model_current[0] + t_type = model_current[1] + + if len(model_current) == 4: + phi = 0.95 + phi_estimate = True + s_type = model_current[3] + else: + phi = 1 + phi_estimate = False + s_type = model_current[2] + + results[i-1] = estimator( + ets_model, e_type, t_type, s_type, lags, lags_model_seasonal, lags_model_arima, + obs_states, obs_in_sample, + y_in_sample, persistence, persistence_estimate, + persistence_level, persistence_level_estimate, + persistence_trend, persistence_trend_estimate, + persistence_seasonal, persistence_seasonal_estimate, + persistence_xreg, persistence_xreg_estimate, persistence_xreg_provided, + phi, phi_estimate, + initial_type, initial_level, initial_trend, initial_seasonal, + initial_arima, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, initial_xreg_provided, + arima_model, ar_required, i_required, ma_required, arma_parameters, + components_number_arima, components_names_arima, + formula, xreg_model, xreg_model_initials, xreg_data, xreg_number, xreg_names, regressors, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_required, constant_estimate, constant_value, constant_name, + ot, ot_logical, occurrence_model, p_fitted, + bounds, loss, loss_function, distribution, + horizon, multisteps, other, other_parameter_estimate, lambda_param + ) + + results[i-1]["IC"] = ic_function(results[i-1]["logLikADAMValue"]) + results[i-1]["Etype"] = e_type + results[i-1]["Ttype"] = t_type + results[i-1]["Stype"] = s_type + results[i-1]["phiEstimate"] = phi_estimate + + if phi_estimate: + results[i-1]["phi"] = results[i-1]["B"].get("phi") + else: + results[i-1]["phi"] = 1 + + results[i-1]["model"] = model_current + + if models_tested is None: + models_tested = [model_current] + else: + models_tested.append(model_current) + + if j > 1: + # If the first is better than the second, then choose first + if results[best_i-1]["IC"] <= results[i-1]["IC"]: + # If Ttype is the same, then we check seasonality + if model_current[1] == pool_small[best_j-1][1]: + pool_seasonals = results[best_i-1]["Stype"] + check_seasonal = False + j = [k+1 for k in range(len(pool_small)) + if pool_small[k] != pool_small[best_j-1] and + pool_small[k][-1] == pool_seasonals] + # Otherwise we checked trend + else: + pool_trends = results[best_j-1]["Ttype"] + check_trend = False + else: + # If the trend is the same + if model_current[1] == pool_small[best_i-1][1]: + pool_seasonals = [s for s in pool_seasonals if s != results[best_i-1]["Stype"]] + if len(pool_seasonals) > 1: + # Select another seasonal model, not from previous iteration and not current + best_j = j + best_i = i + j = 3 + else: + best_j = j + best_i = i + # Move to checking the trend + j = [k+1 for k in range(len(pool_small)) + if pool_small[k][-1] == pool_seasonals[0] and + pool_small[k][1] != model_current[1]] + check_seasonal = False + else: + pool_trends = [t for t in pool_trends if t != results[best_j-1]["Ttype"]] + best_i = i + best_j = j + check_trend = False + + if not any([check_trend, check_seasonal]): + check = False + else: + j = 2 + + # If this is NULL, then this was a short pool and we checked everything + if not j: + j = len(pool_small) + if j > len(pool_small): + check = False + + # Prepare a bigger pool based on the small one + models_pool = list(set( + models_tested + + [e + t + s for e in pool_errors + for t in pool_trends + for s in pool_seasonals] + )) + j = len(models_tested) + + else: + j = 0 + results = [None] * len(models_pool) + + models_number = len(models_pool) + + # Run the full pool of models + if not silent: + print("Estimation progress: ", end="") + + # Start loop of models + while j < models_number: + j += 1 + if not silent: + if j == 1: + print("\b", end="") + print("\b" * (len(str(round((j-1)/models_number * 100))) + 1), end="") + print(f"{round(j/models_number * 100)}%", end="") + + model_current = models_pool[j-1] + # print(model_current) + e_type = model_current[0] + t_type = model_current[1] + if len(model_current) == 4: + phi = 0.95 + s_type = model_current[3] + phi_estimate = True + else: + phi = 1 + s_type = model_current[2] + phi_estimate = False + + + results[j-1] = estimator( + ets_model, e_type, t_type, s_type, lags, lags_model_seasonal, lags_model_arima, + obs_states, obs_in_sample, + y_in_sample, persistence, persistence_estimate, + persistence_level, persistence_level_estimate, + persistence_trend, persistence_trend_estimate, + persistence_seasonal, persistence_seasonal_estimate, + persistence_xreg, persistence_xreg_estimate, persistence_xreg_provided, + phi, phi_estimate, + initial_type, initial_level, initial_trend, initial_seasonal, + initial_arima, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, initial_xreg_provided, + arima_model, ar_required, i_required, ma_required, arma_parameters, + components_number_arima, components_names_arima, + formula, xreg_model, xreg_model_initials, xreg_data, xreg_number, xreg_names, regressors, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, + constant_required, constant_estimate, constant_value, constant_name, + ot, ot_logical, occurrence_model, p_fitted, + bounds, loss, loss_function, distribution, + horizon, multisteps, other, other_parameter_estimate, lambda_) + + results[j-1]["IC"] = ic_function(results[j-1]["logLikADAMValue"]) + results[j-1]["Etype"] = e_type + results[j-1]["Ttype"] = t_type + results[j-1]["Stype"] = s_type + results[j-1]["phiEstimate"] = phi_estimate + if phi_estimate: + results[j-1]["phi"] = results[j-1]["B"][next(i for i,v in enumerate(results[j-1]["B"].keys()) if v=="phi")] + else: + results[j-1]["phi"] = 1 + results[j-1]["model"] = model_current + + + if not silent: + print("... Done!") + + # Extract ICs and find the best + ic_selection = [None] * models_number + for i in range(models_number): + ic_selection[i] = results[i]["IC"] + + # Set names for ic_selection + ic_selection_dict = dict(zip(models_pool, ic_selection)) + + # Replace NaN values with large number + ic_selection = [1e100 if math.isnan(x) else x for x in ic_selection] + + return {"results": results, "icSelection": ic_selection_dict} + + +def preparator(B, ets_model, e_type, t_type, s_type, + lags_model, lags_model_max, lags_model_all, + components_number_ets, components_number_ets_seasonal, + xreg_number, distribution, loss, + persistence_estimate, persistence_level_estimate, persistence_trend_estimate, + persistence_seasonal_estimate, persistence_xreg_estimate, + phi_estimate, other_parameter_estimate, + initial_type, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, + mat_vt, mat_wt, mat_f, vec_g, + occurrence_model, ot, oes_model, + parameters_number, cf_value, + arima_model, ar_required, ma_required, + ar_estimate, ma_estimate, ar_orders, i_orders, ma_orders, + non_zero_ari, non_zero_ma, + arima_polynomials, arma_parameters, + constant_required, constant_estimate): + """Function prepares all the matrices and vectors for return""" + + + if model_do != "use": + # Fill in the matrices + adam_elements = filler( + B, + ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, + components_number_ets, components_number_ets_non_seasonal, + components_number_ets_seasonal, components_number_arima, + lags, lags_model, lags_model_max, + mat_vt, mat_wt, mat_f, vec_g, + persistence_estimate, persistence_level_estimate, persistence_trend_estimate, + persistence_seasonal_estimate, persistence_xreg_estimate, + phi_estimate, + initial_type, initial_estimate, + initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, + initial_arima_estimate, initial_xreg_estimate, + arima_model, ar_estimate, ma_estimate, ar_orders, i_orders, ma_orders, + ar_required, ma_required, arma_parameters, + non_zero_ari, non_zero_ma, arima_polynomials, + xreg_model, xreg_number, + xreg_parameters_missing, xreg_parameters_included, + xreg_parameters_estimated, xreg_parameters_persistence, constant_estimate + ) + + + # Write down phi + if phi_estimate: + phi[:] = B[next(i for i,v in enumerate(B.keys()) if v=="phi")] + + # Write down the initials in the recent profile + profiles_recent_table[:] = mat_vt[:, :lags_model_max] + profiles_recent_initial = mat_vt[:, :lags_model_max].copy() + + # Fit the model to the data + adam_fitted = adam_fitter_wrap( + mat_vt, mat_wt, mat_f, vec_g, + lags_model_all, index_lookup_table, profiles_recent_table, + e_type, t_type, s_type, components_number_ets, components_number_ets_seasonal, + components_number_arima, xreg_number, constant_required, + y_in_sample, ot, any(x in initial_type for x in ["complete", "backcasting"]) + ) + + mat_vt[:] = adam_fitted["mat_vt"] + + # Write down the recent profile for future use + profiles_recent_table = adam_fitted["profile"] + + + # Make sure that there are no negative values in multiplicative components + # This might appear in case of bounds="a" + if t_type == "M" and (np.any(np.isnan(mat_vt[1,:])) or np.any(mat_vt[1,:] <= 0)): + i = np.where(mat_vt[1,:] <= 0)[0] + mat_vt[1,i] = 1e-6 + profiles_recent_table[1,i] = 1e-6 + + if s_type == "M" and np.all(~np.isnan(mat_vt[components_number_ets_non_seasonal:components_number_ets_non_seasonal+components_number_ets_seasonal,:])) and \ + np.any(mat_vt[components_number_ets_non_seasonal:components_number_ets_non_seasonal+components_number_ets_seasonal,:] <= 0): + i = np.where(mat_vt[components_number_ets_non_seasonal:components_number_ets_non_seasonal+components_number_ets_seasonal,:] <= 0)[0] + mat_vt[components_number_ets_non_seasonal:components_number_ets_non_seasonal+components_number_ets_seasonal,i] = 1e-6 + i = np.where(profiles_recent_table[components_number_ets_non_seasonal:components_number_ets_non_seasonal+components_number_ets_seasonal,:] <= 0)[0] + profiles_recent_table[components_number_ets_non_seasonal:components_number_ets_non_seasonal+components_number_ets_seasonal,i] = 1e-6 + + # Prepare fitted and error with ts / zoo + if any(y_classes == "ts"): + y_fitted = pd.Series(np.full(obs_in_sample, np.nan), index=pd.date_range(start=y_start, periods=obs_in_sample, freq=y_frequency)) + errors = pd.Series(np.full(obs_in_sample, np.nan), index=pd.date_range(start=y_start, periods=obs_in_sample, freq=y_frequency)) + else: + y_fitted = pd.Series(np.full(obs_in_sample, np.nan), index=y_in_sample_index) + errors = pd.Series(np.full(obs_in_sample, np.nan), index=y_in_sample_index) + + errors[:] = adam_fitted["errors"] + y_fitted[:] = adam_fitted["y_fitted"] + # Check what was returned in the end + if np.any(np.isnan(y_fitted)) or np.any(pd.isna(y_fitted)): + warnings.warn("Something went wrong in the estimation of the model and NaNs were produced. " + "If this is a mixed model, consider using the pure ones instead.") + + if occurrence_model: + y_fitted[:] = y_fitted * p_fitted + + # Fix the cases, when we have zeroes in the provided occurrence + if occurrence == "provided": + y_fitted[~ot_logical] = y_fitted[~ot_logical] * p_fitted[~ot_logical] + + # Produce forecasts if the horizon is non-zero + if horizon > 0: + if any(y_classes == "ts"): + y_forecast = pd.Series(np.full(horizon, np.nan), + index=pd.date_range(start=y_forecast_start, periods=horizon, freq=y_frequency)) + else: + y_forecast = pd.Series(np.full(horizon, np.nan), index=y_forecast_index) + + y_forecast[:] = adam_forecaster_wrap( + mat_wt[-horizon:], mat_f, + lags_model_all, + index_lookup_table[:, lags_model_max + obs_in_sample + np.arange(horizon)], + profiles_recent_table, + e_type, t_type, s_type, + components_number_ets, components_number_ets_seasonal, + components_number_arima, xreg_number, constant_required, + horizon + ) + + # Make safety checks + # If there are NaN values + if np.any(np.isnan(y_forecast)): + y_forecast[np.isnan(y_forecast)] = 0 + + # Amend forecasts, multiplying by probability + if occurrence_model and not occurrence_model_provided: + y_forecast[:] = y_forecast * np.array(forecast(oes_model, h=h).mean) + elif (occurrence_model and occurrence_model_provided) or occurrence == "provided": + y_forecast[:] = y_forecast * p_forecast + + else: + if any(y_classes == "ts"): + y_forecast = pd.Series([np.nan], index=pd.date_range(start=y_forecast_start, periods=1, freq=y_frequency)) + else: + y_forecast = pd.Series(np.full(horizon, np.nan), index=y_forecast_index) + + # If the distribution is default, change it according to the error term + if distribution == "default": + if loss == "likelihood": + if e_type == "A": + distribution = "dnorm" + elif e_type == "M": + distribution = "dgamma" + elif loss in ["MAEh", "MACE", "MAE"]: + distribution = "dlaplace" + elif loss in ["HAMh", "CHAM", "HAM"]: + distribution = "ds" + elif loss in ["MSEh", "MSCE", "MSE", "GPL"]: + distribution = "dnorm" + else: + distribution = "dnorm" + + # Initial values to return + initial_value = [None] * (ets_model * (1 + model_is_trendy + model_is_seasonal) + arima_model + xreg_model) + initial_value_ets = [None] * (ets_model * len(lags_model)) + initial_value_names = [""] * (ets_model * (1 + model_is_trendy + model_is_seasonal) + arima_model + xreg_model) + # The vector that defines what was estimated in the model + initial_estimated = [False] * (ets_model * (1 + model_is_trendy + model_is_seasonal * components_number_ets_seasonal) + + arima_model + xreg_model) + + # Write down the initials of ETS + j = 0 + if ets_model: + # Write down level, trend and seasonal + for i in range(len(lags_model)): + # In case of level / trend, we want to get the very first value + if lags_model[i] == 1: + initial_value_ets[i] = mat_vt[i, :lags_model_max][0] + # In cases of seasonal components, they should be at the end of the pre-heat period + else: + initial_value_ets[i] = mat_vt[i, :lags_model_max][-lags_model[i]:] + + j = 0 + # Write down level in the final list + initial_estimated[j] = initial_level_estimate + initial_value[j] = initial_value_ets[j] + initial_value_names[j] = "level" + + if model_is_trendy: + j = 1 + initial_estimated[j] = initial_trend_estimate + # Write down trend in the final list + initial_value[j] = initial_value_ets[j] + # Remove the trend from ETS list + initial_value_ets[j] = None + initial_value_names[j] = "trend" + + # Write down the initial seasonals + if model_is_seasonal: + initial_estimated[j + 1:j + 1 + components_number_ets_seasonal] = initial_seasonal_estimate + # Remove the level from ETS list + initial_value_ets[0] = None + j += 1 + if len(initial_seasonal_estimate) > 1: + initial_value[j] = [x for x in initial_value_ets if x is not None] + initial_value_names[j] = "seasonal" + for k in range(components_number_ets_seasonal): + initial_estimated[j + k] = f"seasonal{k+1}" + else: + initial_value[j] = next(x for x in initial_value_ets if x is not None) + initial_value_names[j] = "seasonal" + initial_estimated[j] = "seasonal" + + # Write down the ARIMA initials + if arima_model: + j += 1 + initial_estimated[j] = initial_arima_estimate + if initial_arima_estimate: + initial_value[j] = mat_vt[components_number_ets + components_number_arima - 1, :initial_arima_number] + else: + initial_value[j] = initial_arima + initial_value_names[j] = "arima" + initial_estimated[j] = "arima" + + + # Set names for initial values + initial_value = {name: value for name, value in zip(initial_value_names, initial_value)} + + # Get persistence values + persistence = np.array(vec_g).flatten() + persistence = {name: value for name, value in zip(vec_g.index, persistence)} + + # Remove xreg persistence if needed + if xreg_model and regressors != "adapt": + regressors = "use" + elif not xreg_model: + regressors = None + + # Handle ARMA parameters + if arima_model: + arma_parameters_list = {} + j = 0 + if ar_required and phi_estimate: + # Avoid damping parameter phi by checking name length > 3 + arma_parameters_list["ar"] = [b for name, b in B.items() if len(name) > 3 and name.startswith("phi")] + j += 1 + elif ar_required and not phi_estimate: + # Avoid damping parameter phi + arma_parameters_list["ar"] = [p for name, p in arma_parameters.items() if name.startswith("phi")] + j += 1 + + if ma_required and ma_estimate: + arma_parameters_list["ma"] = [b for name, b in B.items() if name.startswith("theta")] + elif ma_required and not ma_estimate: + arma_parameters_list["ma"] = [p for name, p in arma_parameters.items() if name.startswith("theta")] + else: + arma_parameters_list = None + + + # Handle distribution parameters + if distribution in ["dalaplace", "dgnorm", "dlgnorm", "dt"] and other_parameter_estimate: + other = abs(B[-1]) + + # Calculate scale parameter using scaler function + # which() equivalent is just boolean indexing in numpy + scale = scaler(distribution, Etype, errors[ot_logical], y_fitted[ot_logical], obs_in_sample, other) + + # Record constant if estimated + if constant_estimate: + constant_value = B[constant_name] + + # Prepare distribution parameters to return + other_returned = {} + + # Write down parameters for distribution (always positive) + if other_parameter_estimate: + param_value = abs(B[-1]) + else: + param_value = other + + # Set parameter name based on distribution + if distribution == "dalaplace": + other_returned["alpha"] = param_value + elif distribution in ["dgnorm", "dlgnorm"]: + other_returned["shape"] = param_value + elif distribution == "dt": + other_returned["nu"] = param_value + + # Add LASSO/RIDGE lambda if applicable + if loss in ["LASSO", "RIDGE"]: + other_returned["lambda"] = lambda_ + + # Return ARIMA polynomials and indices for persistence and transition + if arima_model: + other_returned["polynomial"] = arima_polynomials + other_returned["ARIMA_indices"] = {"nonZeroARI": non_zero_ari, "nonZeroMA": non_zero_ma} + other_returned["ar_polynomial_matrix"] = np.zeros((ar_orders @ lags, ar_orders @ lags)) + + if other_returned["ar_polynomial_matrix"].shape[0] > 1: + # Set diagonal elements to 1 except first row/col + other_returned["ar_polynomial_matrix"][1:-1, 2:] = np.eye(other_returned["ar_polynomial_matrix"].shape[0]-2) + + if ar_required: + other_returned["ar_polynomial_matrix"][:, 0] = -arima_polynomials["ar_polynomial"][1:] + + other_returned["arma_parameters"] = arma_parameters + + # Amend the class of state matrix + if "ts" in y_classes: + mat_vt = pd.Series( + mat_vt.T, + index=pd.date_range( + start=y.index[0] - pd.Timedelta(lags_model_max/y.index.freq), + periods=len(mat_vt.T), + freq=y.index.freq + ) + ) + else: + y_states_index = y_in_sample_index[0] - lags_model_max * np.diff(y_in_sample_index[-2:]) + \ + np.arange(lags_model_max) * np.diff(y_in_sample_index[-2:]) + y_states_index = np.concatenate([y_states_index, y_in_sample_index]) + mat_vt = pd.Series(mat_vt.T, index=y_states_index) + + parameters_number[1, 4] = np.sum(parameters_number[1, :4]) + + + return { + "model": None, + "time_elapsed": None, + "data": np.column_stack((None, xreg_data)), + "holdout": None, + "fitted": y_fitted, + "residuals": errors, + "forecast": y_forecast, + "states": mat_vt, + "profile": profiles_recent_table, + "profile_initial": profiles_recent_initial, + "persistence": persistence, + "phi": phi, + "transition": mat_f, + "measurement": mat_wt, + "initial": initial_value, + "initial_type": initial_type, + "initial_estimated": initial_estimated, + "orders": orders, + "arma": arma_parameters_list, + "constant": constant_value, + "n_param": parameters_number, + "occurrence": oes_model, + "formula": formula, + "regressors": regressors, + "loss": loss, + "loss_value": cf_value, + "log_lik": log_lik_adam_value, + "distribution": distribution, + "scale": scale, + "other": other_returned, + "B": B, + "lags": lags, + "lags_all": lags_model_all, + "FI": fi + } \ No newline at end of file diff --git a/python/smooth/adam_general/core/sma.py b/python/smooth/adam_general/core/sma.py new file mode 100644 index 00000000..7c9fd979 --- /dev/null +++ b/python/smooth/adam_general/core/sma.py @@ -0,0 +1,126 @@ +import numpy as np + +from smooth.adam_general._adam_general import adam_fitter, adam_forecaster +from smooth.adam_general.adam_profile import adam_profile_creator + + +def sma(y, order=1, h=10, holdout=False): + """SMA""" + y = y.astype(np.float64) + + # ic = lambda e: np.sum(e**2) + obs_all = len(y) + h * (1 - holdout) + obs_in_sample = len(y) - h * holdout + y_in_sample = y + + E_type = "A" + T_type = "N" + S_type = "N" + + components_num_ETS = 0 + components_num_ETS_seasonal = 0 + xreg_number = 0 + constant_required = False + ot = np.ones_like(y_in_sample) + + def creator_sma(order): + # lags_model_all = np.ones(shape=(order, 1)) + # This needs to be a vector of values + lags_model_all = np.arange(1, order + 1, dtype="int32").reshape(order, 1) + lags_model_max = int(max(lags_model_all)) + obs_states = obs_in_sample + lags_model_max + + profiles_recent_table, index_lookup_table = adam_profile_creator( + lags_model_all=lags_model_all, + lags_model_max=lags_model_max, + obs_all=obs_all, + ).values() + + # # This needs to be generated by a profileCreator() function + # profiles_recent_table = np.mean(y_in_sample[0 : (order - 1)]) * np.ones( + # shape=(order, lags_model_max), dtype=np.float64 + # ) + + # # This as well... + # index_lookup_table = np.tile( + # np.arange(order), (obs_all + lags_model_max, 1) + # ).T + + mat_F = np.ones((order, order)) / order + mat_Wt = np.ones((obs_in_sample, order)) + + vec_G = np.ones(order) / order + # matVt = np.zeros((order, obs_states)) + mat_Vt = np.empty((order, obs_states)) + # matVt.fill(np.nan) + + adam_fitted = adam_fitter( + matrixVt=mat_Vt, + matrixWt=mat_Wt, + matrixF=mat_F, + vectorG=vec_G, + lags=lags_model_all, + indexLookupTable=index_lookup_table, + profilesRecent=profiles_recent_table, + E=E_type, + T=T_type, + S=S_type, + nNonSeasonal=components_num_ETS, + nSeasonal=components_num_ETS_seasonal, + nArima=order, + nXreg=xreg_number, + constant=constant_required, + vectorYt=y_in_sample, + vectorOt=ot, + backcast=True, + ) + + fitted_args = dict( + matrixVt=mat_Vt, + matrixWt=mat_Wt, + matrixF=mat_F, + vectorG=vec_G, + lags=lags_model_all, + indexLookupTable=index_lookup_table, + profilesRecent=profiles_recent_table, + E=E_type, + T=T_type, + S=S_type, + nNonSeasonal=components_num_ETS, + nSeasonal=components_num_ETS_seasonal, + nArima=order, + nXreg=xreg_number, + constant=constant_required, + vectorYt=y_in_sample, + vectorOt=ot, + backcast=True, + ) + + return adam_fitted, fitted_args + + sma_fitted, fitted_args = creator_sma(order=order) + + # need to convert some inputs to the expected dtypes. This is a temporary fix. + fitted_args["lags"] = np.array(fitted_args["lags"], dtype="uint64") + fitted_args["indexLookupTable"] = np.array( + fitted_args["indexLookupTable"], dtype="uint64" + ) + + sma_forecast = adam_forecaster( + matrixWt=fitted_args["matrixWt"], + matrixF=fitted_args["matrixF"], + lags=fitted_args["lags"], + indexLookupTable=fitted_args["indexLookupTable"], + profilesRecent=sma_fitted["profile"], + E=fitted_args["E"], + T=fitted_args["T"], + S=fitted_args["S"], + nNonSeasonal=fitted_args["nNonSeasonal"], + nSeasonal=fitted_args["nSeasonal"], + nArima=fitted_args["nArima"], + nXreg=fitted_args["nXreg"], + constant=fitted_args["constant"], + horizon=h, + ) + + return sma_forecast diff --git a/python/smooth/adam_general/core/utils/cost_functions.py b/python/smooth/adam_general/core/utils/cost_functions.py new file mode 100644 index 00000000..150538a8 --- /dev/null +++ b/python/smooth/adam_general/core/utils/cost_functions.py @@ -0,0 +1,359 @@ +import numpy as np +from numpy.linalg import eigvals +from python.smooth.adam_general.core.creator import filler +from python.smooth.adam_general.core.utils.utils import measurement_inverter, scaler, calculate_likelihood, calculate_entropy, calculate_multistep_loss +import numpy as np + + + + +def CF(B, etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal, yInSample, + ot, otLogical, occurrenceModel, obsInSample, + componentsNumberETS, componentsNumberETSSeasonal, componentsNumberETSNonSeasonal, + componentsNumberARIMA, + lags, lagsModel, lagsModelAll, lagsModelMax, + indexLookupTable, profilesRecentTable, + matVt, matWt, matF, vecG, + persistenceEstimate, persistenceLevelEstimate, persistenceTrendEstimate, + persistenceSeasonalEstimate, persistenceXregEstimate, phiEstimate, + initialType, initialEstimate, + initialLevelEstimate, initialTrendEstimate, initialSeasonalEstimate, + initialArimaEstimate, initialXregEstimate, + arimaModel, nonZeroARI, nonZeroMA, arEstimate, maEstimate, arimaPolynomials, + arOrders, iOrders, maOrders, arRequired, maRequired, armaParameters, + xregModel, xregNumber, + xregParametersMissing, xregParametersIncluded, + xregParametersEstimated, xregParametersPersistence, + constantRequired, constantEstimate, + bounds, loss, lossFunction, distribution, horizon, multisteps, + denominator=None, yDenominator=None, + other=None, otherParameterEstimate=False, lambda_param=None, + arPolynomialMatrix=None, maPolynomialMatrix=None, + regressors=None): # Add regressors parameter here + + # Fill in the matrices + adamElements = filler(B, etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal, + componentsNumberETS, componentsNumberETSNonSeasonal, + componentsNumberETSSeasonal, componentsNumberARIMA, + lags, lagsModel, lagsModelMax, + matVt, matWt, matF, vecG, + persistenceEstimate, persistenceLevelEstimate, persistenceTrendEstimate, + persistenceSeasonalEstimate, persistenceXregEstimate, + phiEstimate, + initialType, initialEstimate, + initialLevelEstimate, initialTrendEstimate, initialSeasonalEstimate, + initialArimaEstimate, initialXregEstimate, + arimaModel, arEstimate, maEstimate, arOrders, iOrders, maOrders, + arRequired, maRequired, armaParameters, + nonZeroARI, nonZeroMA, arimaPolynomials, + xregModel, xregNumber, + xregParametersMissing, xregParametersIncluded, + xregParametersEstimated, xregParametersPersistence, constantEstimate) + + # If we estimate parameters of distribution, take it from the B vector + if otherParameterEstimate: + other = abs(B[-1]) + if distribution in ["dgnorm", "dlgnorm"] and other < 0.25: + return 1e10 / other + + # Check the bounds, classical restrictions + if bounds == "usual": + if arimaModel and any([arEstimate, maEstimate]): + if arEstimate and sum(-adamElements['arimaPolynomials']['arPolynomial'][1:]) >= 1: + arPolynomialMatrix[:, 0] = -adamElements['arimaPolynomials']['arPolynomial'][1:] + arPolyroots = np.abs(eigvals(arPolynomialMatrix)) + if any(arPolyroots > 1): + return 1e100 * np.max(arPolyroots) + + if maEstimate and sum(adamElements['arimaPolynomials']['maPolynomial'][1:]) >= 1: + maPolynomialMatrix[:, 0] = adamElements['arimaPolynomials']['maPolynomial'][1:] + maPolyroots = np.abs(eigvals(maPolynomialMatrix)) + if any(maPolyroots > 1): + return 1e100 * np.max(np.abs(maPolyroots)) + + if etsModel: + if any(adamElements['vecG'][:componentsNumberETS] > 1) or any(adamElements['vecG'][:componentsNumberETS] < 0): + return 1e300 + if modelIsTrendy: + if adamElements['vecG'][1] > adamElements['vecG'][0]: + return 1e300 + if modelIsSeasonal and any(adamElements['vecG'][componentsNumberETSNonSeasonal:componentsNumberETSNonSeasonal+componentsNumberETSSeasonal] > (1 - adamElements['vecG'][0])): + return 1e300 + elif modelIsSeasonal and any(adamElements['vecG'][componentsNumberETSNonSeasonal:componentsNumberETSNonSeasonal+componentsNumberETSSeasonal] > (1 - adamElements['vecG'][0])): + return 1e300 + + if phiEstimate and (adamElements['matF'][1, 1] > 1 or adamElements['matF'][1, 1] < 0): + return 1e300 + + if xregModel and regressors == "adapt": + if any(adamElements['vecG'][componentsNumberETS+componentsNumberARIMA:componentsNumberETS+componentsNumberARIMA+xregNumber] > 1) or \ + any(adamElements['vecG'][componentsNumberETS+componentsNumberARIMA:componentsNumberETS+componentsNumberARIMA+xregNumber] < 0): + return 1e100 * np.max(np.abs(adamElements['vecG'][componentsNumberETS+componentsNumberARIMA:componentsNumberETS+componentsNumberARIMA+xregNumber] - 0.5)) + + elif bounds == "admissible": + if arimaModel: + if arEstimate and (sum(-adamElements['arimaPolynomials']['arPolynomial'][1:]) >= 1 or sum(-adamElements['arimaPolynomials']['arPolynomial'][1:]) < 0): + arPolynomialMatrix[:, 0] = -adamElements['arimaPolynomials']['arPolynomial'][1:] + eigenValues = np.abs(eigvals(arPolynomialMatrix)) + if any(eigenValues > 1): + return 1e100 * np.max(eigenValues) + + if etsModel or arimaModel: + if xregModel: + if regressors == "adapt": + eigenValues = np.abs(eigvals( + adamElements['matF'] - + np.diag(adamElements['vecG'].flatten()) @ + measurement_inverter(adamElements['matWt'][:obsInSample]).T @ + adamElements['matWt'][:obsInSample] / obsInSample + )) + else: + indices = np.arange(componentsNumberETS + componentsNumberARIMA) + eigenValues = np.abs(eigvals( + adamElements['matF'][np.ix_(indices, indices)] - + adamElements['vecG'][indices] @ + adamElements['matWt'][obsInSample-1, indices] + )) + else: + if etsModel or (arimaModel and maEstimate and (sum(adamElements['arimaPolynomials']['maPolynomial'][1:]) >= 1 or sum(adamElements['arimaPolynomials']['maPolynomial'][1:]) < 0)): + eigenValues = np.abs(eigvals( + adamElements['matF'] - + adamElements['vecG'] @ adamElements['matWt'][obsInSample-1] + )) + else: + eigenValues = np.array([0]) + + if any(eigenValues > 1 + 1e-50): + return 1e100 * np.max(eigenValues) + + # Write down the initials in the recent profile + profilesRecentTable[:] = adamElements['matVt'][:, :lagsModelMax] + + # Fitter and the losses calculation + adamFitted = adamFitterWrap(adamElements['matVt'], adamElements['matWt'], adamElements['matF'], adamElements['vecG'], + lagsModelAll, indexLookupTable, profilesRecentTable, + Etype, Ttype, Stype, componentsNumberETS, componentsNumberETSSeasonal, + componentsNumberARIMA, xregNumber, constantRequired, + yInSample, ot, any([t == "complete" or t == "backcasting" for t in initialType])) + + if not multisteps: + if loss == "likelihood": + scale = scaler(distribution, Etype, adamFitted['errors'][otLogical], + adamFitted['yFitted'][otLogical], obsInSample, other) + + # Calculate the likelihood + CFValue = -np.sum(calculate_likelihood(distribution, Etype, yInSample[otLogical], + adamFitted['yFitted'][otLogical], scale, other)) + + # Differential entropy for the logLik of occurrence model + if occurrenceModel or any(~otLogical): + CFValueEntropy = calculate_entropy(distribution, scale, other, obsZero, + adamFitted['yFitted'][~otLogical]) + if np.isnan(CFValueEntropy) or CFValueEntropy < 0: + CFValueEntropy = np.inf + CFValue += CFValueEntropy + + elif loss == "MSE": + CFValue = np.sum(adamFitted['errors']**2) / obsInSample + elif loss == "MAE": + CFValue = np.sum(np.abs(adamFitted['errors'])) / obsInSample + elif loss == "HAM": + CFValue = np.sum(np.sqrt(np.abs(adamFitted['errors']))) / obsInSample + elif loss in ["LASSO", "RIDGE"]: + persistenceToSkip = componentsNumberETS + persistenceXregEstimate * xregNumber + \ + phiEstimate + sum(arOrders) + sum(maOrders) + + if phiEstimate: + B[componentsNumberETS + persistenceXregEstimate * xregNumber] = \ + 1 - B[componentsNumberETS + persistenceXregEstimate * xregNumber] + + j = componentsNumberETS + persistenceXregEstimate * xregNumber + phiEstimate + + if arimaModel and (sum(maOrders) > 0 or sum(arOrders) > 0): + for i in range(len(lags)): + B[j:j+arOrders[i]] = 1 - B[j:j+arOrders[i]] + j += arOrders[i] + maOrders[i] + + if any([t == "optimal" or t == "backcasting" for t in initialType]): + if xregNumber > 0: + B = np.concatenate([B[:persistenceToSkip], + B[-xregNumber:] / denominator if Etype == "A" else B[-xregNumber:]]) + else: + B = B[:persistenceToSkip] + + if Etype == "A": + CFValue = (1 - lambda_param) * np.sqrt(np.sum((adamFitted['errors'] / yDenominator)**2) / obsInSample) + else: # "M" + CFValue = (1 - lambda_param) * np.sqrt(np.sum(np.log(1 + adamFitted['errors'])**2) / obsInSample) + + if loss == "LASSO": + CFValue += lambda_param * np.sum(np.abs(B)) + else: # "RIDGE" + CFValue += lambda_param * np.sqrt(np.sum(B**2)) + + elif loss == "custom": + CFValue = lossFunction(actual=yInSample, fitted=adamFitted['yFitted'], B=B) + else: + adamErrors = adamErrorerWrap( + adamFitted['matVt'], adamElements['matWt'], adamElements['matF'], + lagsModelAll, indexLookupTable, profilesRecentTable, + Etype, Ttype, Stype, + componentsNumberETS, componentsNumberETSSeasonal, + componentsNumberARIMA, xregNumber, constantRequired, horizon, + yInSample, ot + ) + + CFValue = calculate_multistep_loss(loss, adamErrors, obsInSample, horizon) + + if np.isnan(CFValue): + CFValue = 1e300 + + return CFValue + +def logLikADAM(B, etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal, yInSample, + ot, otLogical, occurrenceModel, pFitted, obsInSample, + componentsNumberETS, componentsNumberETSSeasonal, componentsNumberETSNonSeasonal, + componentsNumberARIMA, lags, lagsModel, lagsModelAll, lagsModelMax, + indexLookupTable, profilesRecentTable, matVt, matWt, matF, vecG, + persistenceEstimate, persistenceLevelEstimate, persistenceTrendEstimate, + persistenceSeasonalEstimate, persistenceXregEstimate, phiEstimate, + initialType, initialEstimate, initialLevelEstimate, initialTrendEstimate, + initialSeasonalEstimate, initialArimaEstimate, initialXregEstimate, + arimaModel, nonZeroARI, nonZeroMA, arEstimate, maEstimate, arimaPolynomials, + arOrders, iOrders, maOrders, arRequired, maRequired, armaParameters, + xregModel, xregNumber, xregParametersMissing, xregParametersIncluded, + xregParametersEstimated, xregParametersPersistence, constantRequired, + constantEstimate, bounds, loss, lossFunction, distribution, horizon, + multisteps, denominator=None, yDenominator=None, other=None, + otherParameterEstimate=False, lambda_param=None, arPolynomialMatrix=None, + maPolynomialMatrix=None, hessianCalculation=False): + + + if not multisteps: + if loss in ["LASSO", "RIDGE"]: + return 0 + else: + distributionNew = { + "MSE": "dnorm", + "MAE": "dlaplace", + "HAM": "ds" + }.get(loss, distribution) + + lossNew = "likelihood" if loss in ["MSE", "MAE", "HAM"] else loss + + # Call CF function with bounds="none" + logLikReturn = -CF(B, etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal, + yInSample, ot, otLogical, occurrenceModel, obsInSample, + componentsNumberETS, componentsNumberETSSeasonal, + componentsNumberETSNonSeasonal, componentsNumberARIMA, + lags, lagsModel, lagsModelAll, lagsModelMax, + indexLookupTable, profilesRecentTable, matVt, matWt, matF, vecG, + persistenceEstimate, persistenceLevelEstimate, + persistenceTrendEstimate, persistenceSeasonalEstimate, + persistenceXregEstimate, phiEstimate, initialType, + initialEstimate, initialLevelEstimate, initialTrendEstimate, + initialSeasonalEstimate, initialArimaEstimate, + initialXregEstimate, arimaModel, nonZeroARI, nonZeroMA, + arEstimate, maEstimate, arimaPolynomials, arOrders, iOrders, + maOrders, arRequired, maRequired, armaParameters, xregModel, + xregNumber, xregParametersMissing, xregParametersIncluded, + xregParametersEstimated, xregParametersPersistence, + constantRequired, constantEstimate, bounds="none", loss=lossNew, + lossFunction=lossFunction, distribution=distributionNew, + horizon=horizon, multisteps=multisteps, denominator=denominator, + yDenominator=yDenominator, other=other, + otherParameterEstimate=otherParameterEstimate, + lambda_param=lambda_param, arPolynomialMatrix=arPolynomialMatrix, + maPolynomialMatrix=maPolynomialMatrix) + + # Handle occurrence model + if occurrenceModel: + if np.isinf(logLikReturn): + logLikReturn = 0 + if any(1 - pFitted[~otLogical] == 0) or any(pFitted[otLogical] == 0): + ptNew = pFitted[(pFitted != 0) & (pFitted != 1)] + otNew = ot[(pFitted != 0) & (pFitted != 1)] + if len(ptNew) == 0: + return logLikReturn + else: + return logLikReturn + np.sum(np.log(ptNew[otNew == 1])) + np.sum(np.log(1 - ptNew[otNew == 0])) + else: + return logLikReturn + np.sum(np.log(pFitted[otLogical])) + np.sum(np.log(1 - pFitted[~otLogical])) + else: + return logLikReturn + + else: + # Call CF function with bounds="none" + logLikReturn = CF(B, etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal, + yInSample, ot, otLogical, occurrenceModel, obsInSample, + componentsNumberETS, componentsNumberETSSeasonal, + componentsNumberETSNonSeasonal, componentsNumberARIMA, + lags, lagsModel, lagsModelAll, lagsModelMax, + indexLookupTable, profilesRecentTable, matVt, matWt, matF, vecG, + persistenceEstimate, persistenceLevelEstimate, + persistenceTrendEstimate, persistenceSeasonalEstimate, + persistenceXregEstimate, phiEstimate, initialType, + initialEstimate, initialLevelEstimate, initialTrendEstimate, + initialSeasonalEstimate, initialArimaEstimate, + initialXregEstimate, arimaModel, nonZeroARI, nonZeroMA, + arEstimate, maEstimate, arimaPolynomials, arOrders, iOrders, + maOrders, arRequired, maRequired, armaParameters, xregModel, + xregNumber, xregParametersMissing, xregParametersIncluded, + xregParametersEstimated, xregParametersPersistence, + constantRequired, constantEstimate, bounds="none", loss=loss, + lossFunction=lossFunction, distribution=distribution, + horizon=horizon, multisteps=multisteps, denominator=denominator, + yDenominator=yDenominator, other=other, + otherParameterEstimate=otherParameterEstimate, + lambda_param=lambda_param, arPolynomialMatrix=arPolynomialMatrix, + maPolynomialMatrix=maPolynomialMatrix) + + # Concentrated log-likelihoods for the multistep losses + if loss in ["MSEh", "aMSEh", "TMSE", "aTMSE", "MSCE", "aMSCE"]: + logLikReturn = -(obsInSample - horizon) / 2 * (np.log(2 * np.pi) + 1 + np.log(logLikReturn)) + elif loss in ["GTMSE", "aGTMSE"]: + logLikReturn = -(obsInSample - horizon) / 2 * (np.log(2 * np.pi) + 1 + logLikReturn) + elif loss in ["MAEh", "TMAE", "GTMAE", "MACE"]: + logLikReturn = -(obsInSample - horizon) * (np.log(2) + 1 + np.log(logLikReturn)) + elif loss in ["HAMh", "THAM", "GTHAM", "CHAM"]: + logLikReturn = -(obsInSample - horizon) * (np.log(4) + 2 + 2 * np.log(logLikReturn)) + elif loss in ["GPL", "aGPL"]: + logLikReturn = -(obsInSample - horizon) / 2 * (horizon * np.log(2 * np.pi) + horizon + logLikReturn) / horizon + + # Make likelihood comparable + logLikReturn = logLikReturn / (obsInSample - horizon) * obsInSample + + # Handle multiplicative model + if Etype == "M": + # Fill in the matrices + adamElements = filler(B, etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal, + componentsNumberETS, componentsNumberETSNonSeasonal, + componentsNumberETSSeasonal, componentsNumberARIMA, + lags, lagsModel, lagsModelMax, matVt, matWt, matF, vecG, + persistenceEstimate, persistenceLevelEstimate, + persistenceTrendEstimate, persistenceSeasonalEstimate, + persistenceXregEstimate, phiEstimate, initialType, + initialEstimate, initialLevelEstimate, initialTrendEstimate, + initialSeasonalEstimate, initialArimaEstimate, + initialXregEstimate, arimaModel, arEstimate, maEstimate, + arOrders, iOrders, maOrders, arRequired, maRequired, + armaParameters, nonZeroARI, nonZeroMA, arimaPolynomials, + xregModel, xregNumber, xregParametersMissing, + xregParametersIncluded, xregParametersEstimated, + xregParametersPersistence, constantEstimate) + + # Write down the initials in the recent profile + profilesRecentTable[:] = adamElements['matVt'][:, :lagsModelMax] + + # Fit the model again to extract the fitted values + adamFitted = adamFitterWrap(adamElements['matVt'], adamElements['matWt'], + adamElements['matF'], adamElements['vecG'], + lagsModelAll, indexLookupTable, profilesRecentTable, + Etype, Ttype, Stype, componentsNumberETS, + componentsNumberETSSeasonal, componentsNumberARIMA, + xregNumber, constantRequired, yInSample, ot, + any(t in ["complete", "backcasting"] for t in initialType)) + + logLikReturn -= np.sum(np.log(np.abs(adamFitted['yFitted']))) + + return logLikReturn \ No newline at end of file diff --git a/python/smooth/adam_general/core/utils/cost_functions.py:Zone.Identifier b/python/smooth/adam_general/core/utils/cost_functions.py:Zone.Identifier new file mode 100644 index 00000000..f46bcc49 --- /dev/null +++ b/python/smooth/adam_general/core/utils/cost_functions.py:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/python/smooth/adam_general/core/utils/ic.py b/python/smooth/adam_general/core/utils/ic.py new file mode 100644 index 00000000..fef6c4e2 --- /dev/null +++ b/python/smooth/adam_general/core/utils/ic.py @@ -0,0 +1,141 @@ +import numpy as np + +def AIC(loglik, nobs=None, df=None): + """ + Calculate Akaike Information Criterion + + Parameters + ---------- + loglik : float or object with loglik attribute + Log-likelihood value + nobs : int, optional + Number of observations + df : int, optional + Degrees of freedom (number of parameters) + + Returns + ------- + float + AIC value + """ + # Extract loglik value if object is passed + if hasattr(loglik, 'loglik'): + loglik = loglik.loglik + if hasattr(loglik, 'nobs'): + nobs = loglik.nobs + if hasattr(loglik, 'df'): + df = loglik.df + + return -2 * loglik + 2 * df + +def AICc(loglik, nobs=None, df=None): + """ + Calculate corrected Akaike Information Criterion + + Parameters + ---------- + loglik : float or object with loglik attribute + Log-likelihood value + nobs : int, optional + Number of observations + df : int, optional + Degrees of freedom (number of parameters) + + Returns + ------- + float + AICc value + """ + # Extract loglik value if object is passed + if hasattr(loglik, 'loglik'): + loglik = loglik.loglik + if hasattr(loglik, 'nobs'): + nobs = loglik.nobs + if hasattr(loglik, 'df'): + df = loglik.df + + aic = AIC(loglik, nobs, df) + return aic + (2 * df * (df + 1)) / (nobs - df - 1) + +def BIC(loglik, nobs=None, df=None): + """ + Calculate Bayesian Information Criterion + + Parameters + ---------- + loglik : float or object with loglik attribute + Log-likelihood value + nobs : int, optional + Number of observations + df : int, optional + Degrees of freedom (number of parameters) + + Returns + ------- + float + BIC value + """ + # Extract loglik value if object is passed + if hasattr(loglik, 'loglik'): + loglik = loglik.loglik + if hasattr(loglik, 'nobs'): + nobs = loglik.nobs + if hasattr(loglik, 'df'): + df = loglik.df + + return -2 * loglik + np.log(nobs) * df + +def BICc(loglik, nobs=None, df=None): + """ + Calculate corrected Bayesian Information Criterion + + Parameters + ---------- + loglik : float or object with loglik attribute + Log-likelihood value + nobs : int, optional + Number of observations + df : int, optional + Degrees of freedom (number of parameters) + + Returns + ------- + float + BICc value + """ + # Extract loglik value if object is passed + if hasattr(loglik, 'loglik'): + loglik = loglik.loglik + if hasattr(loglik, 'nobs'): + nobs = loglik.nobs + if hasattr(loglik, 'df'): + df = loglik.df + + bic = BIC(loglik, nobs, df) + return bic + (np.log(nobs) * df * (df + 1)) / (nobs - df - 1) + +def ic_function(ic_name): + """ + Select information criterion function based on name + + Parameters + ---------- + ic_name : str + Name of information criterion ('AIC', 'AICc', 'BIC', or 'BICc') + + Returns + ------- + function + Selected information criterion function + """ + ic_functions = { + 'AIC': AIC, + 'AICc': AICc, + 'BIC': BIC, + 'BICc': BICc + } + + if ic_name not in ic_functions: + raise ValueError(f"Invalid information criterion: {ic_name}. Must be one of {list(ic_functions.keys())}") + + return ic_functions[ic_name] \ No newline at end of file diff --git a/python/smooth/adam_general/core/utils/ic.py:Zone.Identifier b/python/smooth/adam_general/core/utils/ic.py:Zone.Identifier new file mode 100644 index 00000000..f46bcc49 --- /dev/null +++ b/python/smooth/adam_general/core/utils/ic.py:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/python/smooth/adam_general/core/utils/utils.py b/python/smooth/adam_general/core/utils/utils.py new file mode 100644 index 00000000..f7d8e95a --- /dev/null +++ b/python/smooth/adam_general/core/utils/utils.py @@ -0,0 +1,403 @@ +import numpy as np +from scipy import stats +from scipy.linalg import eigvals +from scipy.special import gamma, digamma, beta + + + +def ma(y, order): + if order % 2 == 0: + weights = np.concatenate([[0.5], np.ones(order - 1), [0.5]]) / order + else: + weights = np.ones(order) / order + + result = np.convolve(y, weights, mode='valid') + + # Pad the result with NaNs at the edges to match the original length + pad_width = (len(y) - len(result)) // 2 + return np.pad(result, (pad_width, pad_width), mode='constant', constant_values=np.nan) + + +def msdecompose(y, lags=[12], type="additive"): + """ + Multiple Seasonal Classical Decomposition + + This function decomposes multiple seasonal time series into components using + the principles of classical decomposition. + + The function applies centered moving averages to smooth the original series + and obtain level, trend, and seasonal components of the series. It supports + both additive and multiplicative decomposition methods. + + Parameters + ---------- + y : array-like + Vector or array containing the time series data to be decomposed. + lags : list of int, optional (default=[12]) + List of lags corresponding to the frequencies in the data. + For example, [7, 365] for weekly and yearly seasonality in daily data. + type : {'additive', 'multiplicative'}, optional (default='additive') + The type of decomposition. If 'multiplicative' is selected, + then the logarithm of data is taken prior to the decomposition. + + Returns + ------- + dict + A dictionary containing the following components: + - y : array-like + The original time series. + - initial : array-like + The estimates of the initial level and trend. + - trend : array-like + The long-term trend in the data. + - seasonal : list of array-like + List of seasonal patterns for each specified lag. + - loss : str + The loss function used (always 'MSE' for this implementation). + - lags : list of int + The provided lags used for decomposition. + - type : str + The selected type of decomposition ('additive' or 'multiplicative'). + - yName : str + The name of the provided data (always 'y' in this implementation). + + Notes + ----- + - The function handles missing values by imputing them using a polynomial + and trigonometric regression. + - For multiplicative decomposition, non-positive values are treated as missing. + - The seasonal components are centered around zero for additive decomposition + and around one for multiplicative decomposition. + + Examples + -------- + >>> import numpy as np + >>> from msedecompose import msedecompose + >>> + >>> # Generate sample data with multiple seasonalities + >>> t = np.arange(1000) + >>> y = 10 + 0.01*t + 5*np.sin(2*np.pi*t/7) + 3*np.sin(2*np.pi*t/365) + np.random.normal(0, 1, 1000) + >>> + >>> # Perform decomposition + >>> result = msedecompose(y, lags=[7, 365], type="additive") + >>> + >>> # Access components + >>> trend = result['trend'] + >>> weekly_seasonal = result['seasonal'][0] + >>> yearly_seasonal = result['seasonal'][1] + + + """ + # ensure type is valid and lags a list + if type not in ["additive", "multiplicative"]: + raise ValueError("type must be 'additive' or 'multiplicative'") + + # ensure lags is a list + if not isinstance(lags, list): + raise ValueError("lags must be a list") + + y = np.asarray(y) + obs_in_sample = len(y) + y_na_values = np.isnan(y) + + # transform the data if needed and split the sample + if type == "multiplicative": + shifted_data = False + if any(y[~y_na_values] <= 0): + y_na_values[:] = y_na_values | (y <= 0) + + y_insample = np.log(y) + + else: + y_insample = y + + # treat the missing values + if any(y_na_values): + # create the design matrix + X = np.c_[np.ones(obs_in_sample), np.poly(np.arange(1, obs_in_sample + 1), degree=min(max(int(obs_in_sample/10),1),5)).T, np.sin(np.pi * np.outer(np.arange(1, obs_in_sample + 1), np.arange(1, max(lags) + 1)) / max(lags))] + # We use the least squares method to fit the model + lm_fit = np.linalg.lstsq(X[~y_na_values], y_insample[~y_na_values], rcond=None) + # replace the missing values with the fitted values + y_insample[y_na_values] = np.dot(X, lm_fit[0])[y_na_values] + del X + + obs = len(y) + lags = sorted(set(lags)) + lags_length = len(lags) + + # List of smoothed values + y_smooth = [None] * (lags_length + 1) + y_smooth[0] = y_insample # Put actuals in the first element of the list + + # List of cleared values + y_clear = [None] * lags_length + + # Smooth time series with different lags + for i in range(lags_length): + y_smooth[i + 1] = ma(y_insample, lags[i]) + + trend = y_smooth[lags_length] + + # Produce the cleared series + for i in range(lags_length): + y_clear[i] = y_smooth[i] - y_smooth[i + 1] + + # The seasonal patterns + patterns = [None] * lags_length + for i in range(lags_length): + patterns[i] = np.array([np.nanmean(y_clear[i][j::lags[i]]) for j in range(lags[i])]) + patterns[i] -= np.nanmean(patterns[i]) + + # Initial level and trend + valid_trend = trend[~np.isnan(trend)] + initial = np.array([ + valid_trend[0], + np.nanmean(np.diff(valid_trend)) + ]) + + # Fix the initial, to get to the beginning of the sample + initial[0] -= initial[1] * np.floor(max(lags) / 2) + + # Return to the original scale + if type == "multiplicative": + initial = np.exp(initial) + trend = np.exp(trend) + patterns = [np.exp(pattern) for pattern in patterns] + if shifted_data: + initial[0] -= 1 + trend -= 1 + + # Prepare the return structure + result = { + "y": y, + "initial": initial, + "trend": trend, + "seasonal": patterns, + "loss": "MSE", + "lags": lags, + "type": type, + "yName": "y" # You might want to pass the actual name as an argument + } + + return result + + +def calculate_acf(data, nlags=40): + """ + Calculate Autocorrelation Function for numpy array or pandas Series. + + Parameters: + data (np.array or pd.Series): Input time series data + nlags (int): Number of lags to calculate ACF for + + Returns: + np.array: ACF values + """ + if isinstance(data, pd.Series): + data = data.values + + return acf(data, nlags=nlags, fft=False) + + +def calculate_pacf(data, nlags=40): + """ + Calculate Partial Autocorrelation Function for numpy array or pandas Series. + + Parameters: + data (np.array or pd.Series): Input time series data + nlags (int): Number of lags to calculate PACF for + + Returns: + np.array: PACF values + """ + if isinstance(data, pd.Series): + data = data.values + + return pacf(data, nlags=nlags, method='ols') + + +def calculate_likelihood(distribution, Etype, y, y_fitted, scale, other): + if distribution == "dnorm": + if Etype == "A": + return stats.norm.logpdf(y, loc=y_fitted, scale=scale) + else: # "M" + return stats.norm.logpdf(y, loc=y_fitted, scale=scale*y_fitted) + elif distribution == "dlaplace": + if Etype == "A": + return stats.laplace.logpdf(y, loc=y_fitted, scale=scale) + else: # "M" + return stats.laplace.logpdf(y, loc=y_fitted, scale=scale*y_fitted) + elif distribution == "ds": + if Etype == "A": + return stats.t.logpdf(y, df=2, loc=y_fitted, scale=scale) + else: # "M" + return stats.t.logpdf(y, df=2, loc=y_fitted, scale=scale*np.sqrt(y_fitted)) + elif distribution == "dgnorm": + # Implement generalized normal distribution + pass + elif distribution == "dalaplace": + # Implement asymmetric Laplace distribution + pass + elif distribution == "dlnorm": + return stats.lognorm.logpdf(y, s=scale, scale=np.exp(np.log(y_fitted) - scale**2/2)) + elif distribution == "dllaplace": + return stats.laplace.logpdf(np.log(y), loc=np.log(y_fitted), scale=scale) - np.log(y) + elif distribution == "dls": + return stats.t.logpdf(np.log(y), df=2, loc=np.log(y_fitted), scale=scale) - np.log(y) + elif distribution == "dlgnorm": + # Implement log-generalized normal distribution + pass + elif distribution == "dinvgauss": + return stats.invgauss.logpdf(y, mu=np.abs(y_fitted), scale=np.abs(scale/y_fitted)) + elif distribution == "dgamma": + return stats.gamma.logpdf(y, a=1/scale, scale=scale*np.abs(y_fitted)) + +def calculate_entropy(distribution, scale, other, obsZero, y_fitted): + if distribution == "dnorm": + return obsZero * (np.log(np.sqrt(2 * np.pi) * scale) + 0.5) + elif distribution == "dlnorm": + return obsZero * (np.log(np.sqrt(2 * np.pi) * scale) + 0.5) - scale**2 / 2 + elif distribution == "dlogis": + return obsZero * 2 + elif distribution in ["dlaplace", "dllaplace", "dalaplace"]: + return obsZero * (1 + np.log(2 * scale)) + elif distribution in ["ds", "dls"]: + return obsZero * (2 + 2 * np.log(2 * scale)) + elif distribution in ["dgnorm", "dlgnorm"]: + return obsZero * (1 / other - np.log(other / (2 * scale * gamma(1 / other)))) + elif distribution == "dt": + return obsZero * ((scale + 1) / 2 * (digamma((scale + 1) / 2) - digamma(scale / 2)) + + np.log(np.sqrt(scale) * beta(scale / 2, 0.5))) + elif distribution == "dinvgauss": + return 0.5 * (obsZero * (np.log(np.pi / 2) + 1 + np.log(scale)) - np.sum(np.log(y_fitted))) + elif distribution == "dgamma": + return obsZero * (1 / scale + np.log(gamma(1 / scale)) + (1 - 1 / scale) * digamma(1 / scale)) + \ + np.sum(np.log(scale * y_fitted)) + +def calculate_multistep_loss(loss, adamErrors, obsInSample, horizon): + if loss == "MSEh": + return np.sum(adamErrors[:, horizon-1]**2) / (obsInSample - horizon) + elif loss == "TMSE": + return np.sum(np.sum(adamErrors**2, axis=0) / (obsInSample - horizon)) + elif loss == "GTMSE": + return np.sum(np.log(np.sum(adamErrors**2, axis=0) / (obsInSample - horizon))) + elif loss == "MSCE": + return np.sum(np.sum(adamErrors, axis=1)**2) / (obsInSample - horizon) + elif loss == "MAEh": + return np.sum(np.abs(adamErrors[:, horizon-1])) / (obsInSample - horizon) + elif loss == "TMAE": + return np.sum(np.sum(np.abs(adamErrors), axis=0) / (obsInSample - horizon)) + elif loss == "GTMAE": + return np.sum(np.log(np.sum(np.abs(adamErrors), axis=0) / (obsInSample - horizon))) + elif loss == "MACE": + return np.sum(np.abs(np.sum(adamErrors, axis=1))) / (obsInSample - horizon) + elif loss == "HAMh": + return np.sum(np.sqrt(np.abs(adamErrors[:, horizon-1]))) / (obsInSample - horizon) + elif loss == "THAM": + return np.sum(np.sum(np.sqrt(np.abs(adamErrors)), axis=0) / (obsInSample - horizon)) + elif loss == "GTHAM": + return np.sum(np.log(np.sum(np.sqrt(np.abs(adamErrors)), axis=0) / (obsInSample - horizon))) + elif loss == "CHAM": + return np.sum(np.sqrt(np.abs(np.sum(adamErrors, axis=1)))) / (obsInSample - horizon) + elif loss == "GPL": + return np.log(np.linalg.det(adamErrors.T @ adamErrors / (obsInSample - horizon))) + else: + return 0 + + +def scaler(distribution, Etype, errors, y_fitted, obs_in_sample, other): + """ + Calculate scale parameter for the provided parameters. + + Parameters: + - distribution (str): The distribution type + - Etype (str): Error type ('A' for additive, 'M' for multiplicative) + - errors (np.array): Array of errors + - y_fitted (np.array): Array of fitted values + - obs_in_sample (int): Number of observations in sample + - other (float): Additional parameter for some distributions + + Returns: + float: The calculated scale parameter + """ + + # Helper function to safely compute complex logarithm + def safe_log(x): + return np.log(np.abs(x) + 1j * (x.imag - x.real)) + + if distribution == "dnorm": + return np.sqrt(np.sum(errors**2) / obs_in_sample) + + elif distribution == "dlaplace": + return np.sum(np.abs(errors)) / obs_in_sample + + elif distribution == "ds": + return np.sum(np.sqrt(np.abs(errors))) / (obs_in_sample * 2) + + elif distribution == "dgnorm": + return (other * np.sum(np.abs(errors)**other) / obs_in_sample)**(1 / other) + + elif distribution == "dalaplace": + return np.sum(errors * (other - (errors <= 0) * 1)) / obs_in_sample + + elif distribution == "dlnorm": + if Etype == "A": + temp = 1 - np.sqrt(np.abs(1 - np.sum(np.log(np.abs(1 + errors / y_fitted))**2) / obs_in_sample)) + else: # "M" + temp = 1 - np.sqrt(np.abs(1 - np.sum(np.log(1 + errors)**2) / obs_in_sample)) + return np.sqrt(2 * np.abs(temp)) + + elif distribution == "dllaplace": + if Etype == "A": + return np.real(np.sum(np.abs(safe_log(1 + errors / y_fitted))) / obs_in_sample) + else: # "M" + return np.sum(np.abs(np.log(1 + errors))) / obs_in_sample + + elif distribution == "dls": + if Etype == "A": + return np.real(np.sum(np.sqrt(np.abs(safe_log(1 + errors / y_fitted)))) / obs_in_sample) + else: # "M" + return np.sum(np.sqrt(np.abs(np.log(1 + errors)))) / obs_in_sample + + elif distribution == "dlgnorm": + if Etype == "A": + return np.real((other * np.sum(np.abs(safe_log(1 + errors / y_fitted))**other) / obs_in_sample)**(1 / other)) + else: # "M" + return (other * np.sum(np.abs(safe_log(1 + errors))**other) / obs_in_sample)**(1 / other) + + elif distribution == "dinvgauss": + if Etype == "A": + return np.sum((errors / y_fitted)**2 / (1 + errors / y_fitted)) / obs_in_sample + else: # "M" + return np.sum(errors**2 / (1 + errors)) / obs_in_sample + + elif distribution == "dgamma": + if Etype == "A": + return np.sum((errors / y_fitted)**2) / obs_in_sample + else: # "M" + return np.sum(errors**2) / obs_in_sample + + else: + raise ValueError(f"Unknown distribution: {distribution}") + +def measurement_inverter(measurement): + """ + Invert the measurement matrix, setting infinite values to zero. + This is needed for the stability check for xreg models with regressors="adapt". + + Parameters: + - measurement (np.array): The measurement matrix to invert + + Returns: + np.array: The inverted measurement matrix + """ + # Create a copy to avoid modifying the original array + inverted = np.array(measurement, copy=True) + + # Invert all elements + np.divide(1, inverted, out=inverted, where=inverted!=0) + + # Set infinite values to zero + inverted[np.isinf(inverted)] = 0 + + return inverted diff --git a/python/smooth/adam_general/core/utils/utils.py:Zone.Identifier b/python/smooth/adam_general/core/utils/utils.py:Zone.Identifier new file mode 100644 index 00000000..f46bcc49 --- /dev/null +++ b/python/smooth/adam_general/core/utils/utils.py:Zone.Identifier @@ -0,0 +1,2 @@ +[ZoneTransfer] +ZoneId=3 diff --git a/python/smooth/adam_general/test_script.py b/python/smooth/adam_general/test_script.py index 48bcaa58..289b9cfc 100644 --- a/python/smooth/adam_general/test_script.py +++ b/python/smooth/adam_general/test_script.py @@ -1,6 +1,6 @@ import numpy as np -from smooth.adam_general.sma import sma +from python.smooth.adam_general.core.sma import sma if __name__ == "__main__": y = np.arange(0, 100) diff --git a/python/smooth/adam_general/tests.ipynb b/python/smooth/adam_general/tests.ipynb new file mode 100644 index 00000000..8417c1c1 --- /dev/null +++ b/python/smooth/adam_general/tests.ipynb @@ -0,0 +1,1612 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "from adam_profile import parameters_checker, architector\n", + "import numpy as np\n", + "from creator import creator, initialiser" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "# Create test data\n", + "y = np.arange(100)\n", + "data = y.reshape(-1, 1)\n", + "\n", + "# Set up test parameters\n", + "test_params = {\n", + " 'data': data,\n", + " 'model': \"ANN\",\n", + " 'h': 10,\n", + " 'holdout': False\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checked parameters:\n", + "y: numpy array of shape (100,)\n", + "xreg: None\n", + "model: ANN\n", + "lags: [1]\n", + "orders: None\n", + "formula: None\n", + "constant: True\n", + "distribution: dnorm\n", + "loss: likelihood\n", + "h: 10\n", + "holdout: False\n", + "persistence: None\n", + "phi: None\n", + "initial: None\n" + ] + } + ], + "source": [ + "# Run parameters_checker\n", + "checked_params = parameters_checker(**test_params)\n", + "print(\"Checked parameters:\")\n", + "for key, value in checked_params.items():\n", + " if isinstance(value, np.ndarray):\n", + " print(f\"{key}: numpy array of shape {value.shape}\")\n", + " else:\n", + " print(f\"{key}: {value}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Model components:\n", + "model_is_trendy: True\n", + "model_is_seasonal: True\n", + "components_number_ETS: 1\n", + "components_number_ETS_seasonal: 0\n", + "components_names_ETS: ['level', 'trend', 'seasonal']\n", + "lags_model: [[1, 1]]\n", + "lags_model_all: [[1, 1]]\n", + "lags_model_max: 1\n", + "obs_states: 101\n", + "profiles_recent_table: numpy array of shape (1, 1)\n", + "index_lookup_table: numpy array of shape (1, 102)\n" + ] + } + ], + "source": [ + "# Run architector\n", + "components = architector(\n", + " ets_model=True,\n", + " E_type=\"A\",\n", + " T_type=\"A\",\n", + " S_type=\"A\",\n", + " lags=[1],\n", + " lags_model_seasonal=[],\n", + " xreg_number=0,\n", + " obs_in_sample=100,\n", + " initial_type=\"optimal\",\n", + " arima_model=False,\n", + " lags_model_ARIMA=[],\n", + " xreg_model=False,\n", + " constant_required=False\n", + ")\n", + "print(\"\\nModel components:\")\n", + "for key, value in components.items():\n", + " if isinstance(value, np.ndarray):\n", + " print(f\"{key}: numpy array of shape {value.shape}\")\n", + " else:\n", + " print(f\"{key}: {value}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mat_vt shape: (1, 101)\n", + "mat_wt shape: (100, 1)\n", + "mat_f shape: (1, 1)\n", + "vec_g shape: (1, 1)\n", + "\n", + "mat_vt (first 5 columns):\n", + "[[101.51189329 nan nan nan nan]]\n", + "\n", + "mat_wt (first 5 rows):\n", + "[[1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]]\n", + "\n", + "mat_f:\n", + "[[1.]]\n", + "\n", + "vec_g:\n", + "[[0.]]\n" + ] + } + ], + "source": [ + "# Generate some sample data\n", + "np.random.seed(42)\n", + "y_in_sample = 100 + np.cumsum(np.random.normal(0, 1, 100))\n", + "\n", + "# Set up parameters for the creator function\n", + "ets_model = True\n", + "e_type = \"A\"\n", + "t_type = \"N\"\n", + "s_type = \"N\"\n", + "model_is_trendy = False\n", + "model_is_seasonal = False\n", + "lags = [1]\n", + "lags_model = [1]\n", + "lags_model_arima = []\n", + "lags_model_all = [1]\n", + "lags_model_max = 1\n", + "profiles_recent_table = None\n", + "profiles_recent_provided = False\n", + "obs_states = 101 # Number of observations + 1 for forecasting\n", + "obs_in_sample = 100\n", + "obs_all = 100\n", + "components_number_ets = 1\n", + "components_number_ets_seasonal = 0\n", + "components_names_ets = [\"level\"]\n", + "ot_logical = np.ones(100, dtype=bool)\n", + "\n", + "# Call the creator function\n", + "result = creator(\n", + " ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal,\n", + " lags, lags_model, lags_model_arima, lags_model_all, lags_model_max,\n", + " profiles_recent_table, profiles_recent_provided,\n", + " obs_states, obs_in_sample, obs_all, components_number_ets, components_number_ets_seasonal,\n", + " components_names_ets, ot_logical, y_in_sample\n", + ")\n", + "\n", + "# Print the results\n", + "print(\"mat_vt shape:\", result['mat_vt'].shape)\n", + "print(\"mat_wt shape:\", result['mat_wt'].shape)\n", + "print(\"mat_f shape:\", result['mat_f'].shape)\n", + "print(\"vec_g shape:\", result['vec_g'].shape)\n", + "\n", + "# Print the first few values of each matrix/vector\n", + "print(\"\\nmat_vt (first 5 columns):\")\n", + "print(result['mat_vt'][:, :5])\n", + "\n", + "print(\"\\nmat_wt (first 5 rows):\")\n", + "print(result['mat_wt'][:5, :])\n", + "\n", + "print(\"\\nmat_f:\")\n", + "print(result['mat_f'])\n", + "\n", + "print(\"\\nvec_g:\")\n", + "print(result['vec_g'])" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Architector output:\n", + "model_is_trendy: True\n", + "model_is_seasonal: True\n", + "components_number_ETS: 1\n", + "components_number_ETS_seasonal: 0\n", + "components_names_ETS: ['level', 'trend', 'seasonal']\n", + "lags_model: [[1, 1]]\n", + "lags_model_all: [[1, 1]]\n", + "lags_model_max: 1\n", + "obs_states: 101\n", + "profiles_recent_table: numpy array of shape (1, 1)\n", + "index_lookup_table: numpy array of shape (1, 102)\n", + "\n", + "Creator output:\n", + "mat_vt: numpy array of shape (1, 101)\n", + "mat_wt: numpy array of shape (100, 1)\n", + "mat_f: numpy array of shape (1, 1)\n", + "vec_g: numpy array of shape (1, 1)\n", + "arima_polynomials: None\n" + ] + } + ], + "source": [ + "# Print results\n", + "print(\"\\nArchitector output:\")\n", + "for key, value in components.items():\n", + " if isinstance(value, np.ndarray):\n", + " print(f\"{key}: numpy array of shape {value.shape}\")\n", + " else:\n", + " print(f\"{key}: {value}\")\n", + "\n", + "print(\"\\nCreator output:\")\n", + "for key, value in result.items():\n", + " if isinstance(value, np.ndarray):\n", + " print(f\"{key}: numpy array of shape {value.shape}\")\n", + " else:\n", + " print(f\"{key}: {value}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Measurement matrix W:\n", + "[[1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]\n", + " [1.]]\n" + ] + } + ], + "source": [ + "print(\"\\nMeasurement matrix W:\")\n", + "print(result['mat_wt'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "State matrix V:\n", + "[[101.51189329 nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan nan nan nan nan\n", + " nan]]\n" + ] + } + ], + "source": [ + "print(\"\\nState matrix V:\")\n", + "print(result['mat_vt'])" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Persistence vector G:\n", + "[[0.]]\n" + ] + } + ], + "source": [ + "print(\"\\nPersistence vector G:\")\n", + "print(result['vec_g'])" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "# Test the initialiser\n", + "initialiser_result = initialiser(\n", + " ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal,\n", + " components_number_ets - components_number_ets_seasonal, components_number_ets_seasonal, components_number_ets,\n", + " lags, lags_model, lags_model, lags_model_arima, lags_model_max,\n", + " result['mat_vt'],\n", + " y_in_sample=y_in_sample, ot_logical=ot_logical\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'B': array([1.00000000e-01, 9.50000000e-01, 1.01511893e+02, 0.00000000e+00]),\n", + " 'Bl': array([ 0. , 0. , -inf, -0.10815358]),\n", + " 'Bu': array([1. , 1. , inf, 0.10815358]),\n", + " 'names': ['alpha', 'phi', 'level', 'constant']}" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "initialiser_result" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The rpy2.ipython extension is already loaded. To reload it, use:\n", + " %reload_ext rpy2.ipython\n" + ] + } + ], + "source": [ + "%load_ext rpy2.ipython" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "%%R - y_in_sample\n", + "\n", + "y_in_sample <-c(100.49671, 100.35845, 101.00614, 102.52917, 102.29501, 102.06088, 103.64009,\n", + " 104.40753, 103.93805, 104.48061, 104.01719, 103.55146, 103.79343, 101.88015,\n", + " 100.15523, 99.59294, 98.58011, 98.89436, 97.98633, 96.57403, 98.03968,\n", + " 97.81390, 97.88143, 96.45668, 95.91230, 96.02322, 94.87223, 95.24793,\n", + " 94.64729, 94.35559, 93.75389, 95.60616, 95.59267, 94.53496, 95.35750,\n", + " 94.13666, 94.34552, 92.38585, 91.05767, 91.25453, 91.99299, 92.16436,\n", + " 92.04871, 91.74761, 90.26909, 89.54924, 89.08860, 90.14573, 90.48934,\n", + " 88.72630, 89.05039, 88.66531, 87.98838, 88.60006, 89.63106, 90.56234,\n", + " 89.72312, 89.41391, 89.74517, 90.72072, 90.24154, 90.05589, 88.94955,\n", + " 87.75334, 88.56587, 89.92211, 89.85010, 90.85363, 91.21527, 90.57015,\n", + " 90.93154, 92.46958, 92.43376, 93.99840, 91.37865, 92.20056, 92.28760,\n", + " 91.98860, 92.08036, 90.09279, 89.87312, 90.23023, 91.70812, 91.18985,\n", + " 90.38136, 89.87960, 90.79500, 91.12375, 90.59399, 91.10726, 91.20434,\n", + " 92.17298, 91.47093, 91.14327, 90.75116, 89.28765, 89.58377, 89.84482,\n", + " 89.84994, 89.61535)" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [], + "source": [ + "%%R -i y_in_sample\n", + "\n", + "creator <- function(etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal,\n", + " lags, lagsModel, lagsModelARIMA, lagsModelAll, lagsModelMax,\n", + " profilesRecentTable = NULL, profilesRecentProvided = FALSE,\n", + " obsStates, obsInSample, obsAll, componentsNumberETS, componentsNumberETSSeasonal,\n", + " componentsNamesETS, otLogical, yInSample,\n", + " # Persistence and phi\n", + " persistence, persistenceEstimate,\n", + " persistenceLevel, persistenceLevelEstimate, persistenceTrend, persistenceTrendEstimate,\n", + " persistenceSeasonal, persistenceSeasonalEstimate,\n", + " persistenceXreg, persistenceXregEstimate, persistenceXregProvided,\n", + " phi,\n", + " # Initials\n", + " initialType, initialEstimate,\n", + " initialLevel, initialLevelEstimate, initialTrend, initialTrendEstimate,\n", + " initialSeasonal, initialSeasonalEstimate,\n", + " initialArima, initialArimaEstimate, initialArimaNumber,\n", + " initialXregEstimate, initialXregProvided,\n", + " # ARIMA elements\n", + " arimaModel, arRequired, iRequired, maRequired, armaParameters,\n", + " arOrders, iOrders, maOrders,\n", + " componentsNumberARIMA, componentsNamesARIMA,\n", + " # Explanatory variables\n", + " xregModel, xregModelInitials, xregData, xregNumber, xregNames,\n", + " xregParametersPersistence,\n", + " # Constant\n", + " constantRequired, constantEstimate, constantValue, constantName) {\n", + " # Matrix of states. Time in columns, components in rows\n", + " matVt <- matrix(NA, componentsNumberETS + componentsNumberARIMA + xregNumber + constantRequired, obsStates,\n", + " dimnames = list(c(componentsNamesETS, componentsNamesARIMA, xregNames, constantName), NULL)\n", + " )\n", + "\n", + " # Measurement rowvector\n", + " matWt <- matrix(1, obsAll, componentsNumberETS + componentsNumberARIMA + xregNumber + constantRequired,\n", + " dimnames = list(NULL, c(componentsNamesETS, componentsNamesARIMA, xregNames, constantName))\n", + " )\n", + "\n", + " # If xreg are provided, then fill in the respective values in Wt vector\n", + " if (xregModel) {\n", + " matWt[, componentsNumberETS + componentsNumberARIMA + 1:xregNumber] <- xregData\n", + " }\n", + "\n", + " # Transition matrix\n", + " matF <- diag(componentsNumberETS + componentsNumberARIMA + xregNumber + constantRequired)\n", + "\n", + " # Persistence vector\n", + " vecG <- matrix(0, componentsNumberETS + componentsNumberARIMA + xregNumber + constantRequired, 1,\n", + " dimnames = list(c(componentsNamesETS, componentsNamesARIMA, xregNames, constantName), NULL)\n", + " )\n", + "\n", + " j <- 0\n", + " # ETS model, persistence\n", + " if (etsModel) {\n", + " j <- j + 1\n", + " rownames(vecG)[j] <- \"alpha\"\n", + " if (!persistenceLevelEstimate) {\n", + " vecG[j, ] <- persistenceLevel\n", + " }\n", + " if (modelIsTrendy) {\n", + " j <- j + 1\n", + " rownames(vecG)[j] <- \"beta\"\n", + " if (!persistenceTrendEstimate) {\n", + " vecG[j, ] <- persistenceTrend\n", + " }\n", + " }\n", + " if (modelIsSeasonal) {\n", + " if (!all(persistenceSeasonalEstimate)) {\n", + " vecG[j + which(!persistenceSeasonalEstimate), ] <- persistenceSeasonal\n", + " }\n", + " if (componentsNumberETSSeasonal > 1) {\n", + " rownames(vecG)[j + c(1:componentsNumberETSSeasonal)] <- paste0(\"gamma\", c(1:componentsNumberETSSeasonal))\n", + " } else {\n", + " rownames(vecG)[j + 1] <- \"gamma\"\n", + " }\n", + " j <- j + componentsNumberETSSeasonal\n", + " }\n", + " }\n", + "\n", + " # ARIMA model, names for persistence\n", + " if (arimaModel) {\n", + " # Remove diagonal from the ARIMA part of the matrix\n", + " matF[j + 1:componentsNumberARIMA, j + 1:componentsNumberARIMA] <- 0\n", + " if (componentsNumberARIMA > 1) {\n", + " rownames(vecG)[j + 1:componentsNumberARIMA] <- paste0(\"psi\", c(1:componentsNumberARIMA))\n", + " } else {\n", + " rownames(vecG)[j + 1:componentsNumberARIMA] <- \"psi\"\n", + " }\n", + " j <- j + componentsNumberARIMA\n", + " }\n", + "\n", + " # Modify transition to do drift\n", + " if (!arimaModel && constantRequired) {\n", + " matF[1, ncol(matF)] <- 1\n", + " }\n", + "\n", + " # Regression, persistence\n", + " if (xregModel) {\n", + " if (persistenceXregProvided && !persistenceXregEstimate) {\n", + " vecG[j + 1:xregNumber, ] <- persistenceXreg\n", + " }\n", + " rownames(vecG)[j + 1:xregNumber] <- paste0(\"delta\", xregParametersPersistence)\n", + " }\n", + "\n", + " # Damping parameter value\n", + " if (etsModel && modelIsTrendy) {\n", + " matF[1, 2] <- phi\n", + " matF[2, 2] <- phi\n", + "\n", + " matWt[, 2] <- phi\n", + " }\n", + "\n", + " # If the arma parameters were provided, fill in the persistence\n", + " if (arimaModel && (!arEstimate && !maEstimate)) {\n", + " # Call polynomial\n", + " # arimaPolynomials <- polynomialiser(NULL, arOrders, iOrders, maOrders,\n", + " # arRequired, maRequired, arEstimate, maEstimate, armaParameters, lags);\n", + " arimaPolynomials <- lapply(adamPolynomialiser(\n", + " 0, arOrders, iOrders, maOrders,\n", + " arEstimate, maEstimate, armaParameters, lags\n", + " ), as.vector)\n", + " # Fill in the transition matrix\n", + " if (nrow(nonZeroARI) > 0) {\n", + " matF[componentsNumberETS + nonZeroARI[, 2], componentsNumberETS + nonZeroARI[, 2]] <-\n", + " -arimaPolynomials$ariPolynomial[nonZeroARI[, 1]]\n", + " }\n", + " # Fill in the persistence vector\n", + " if (nrow(nonZeroARI) > 0) {\n", + " vecG[componentsNumberETS + nonZeroARI[, 2]] <- -arimaPolynomials$ariPolynomial[nonZeroARI[, 1]]\n", + " }\n", + " if (nrow(nonZeroMA) > 0) {\n", + " vecG[componentsNumberETS + nonZeroMA[, 2]] <- vecG[componentsNumberETS + nonZeroMA[, 2]] +\n", + " arimaPolynomials$maPolynomial[nonZeroMA[, 1]]\n", + " }\n", + " } else {\n", + " arimaPolynomials <- NULL\n", + " }\n", + "\n", + "\n", + " if (!profilesRecentProvided) {\n", + " # ETS model, initial state\n", + " # If something needs to be estimated...\n", + " if (etsModel) {\n", + " if (initialEstimate) {\n", + " # For the seasonal models\n", + " if (modelIsSeasonal) {\n", + " if (obsNonzero >= lagsModelMax * 2) {\n", + " # If either Etype or Stype are multiplicative, do multiplicative decomposition\n", + " decompositionType <- c(\"additive\", \"multiplicative\")[any(c(Etype, Stype) == \"M\") + 1]\n", + " yDecomposition <- msdecompose(yInSample, lags[lags != 1], type = decompositionType)\n", + " j <- 1\n", + " # level\n", + " if (initialLevelEstimate) {\n", + " matVt[j, 1:lagsModelMax] <- yDecomposition$initial[1]\n", + " # matVt[j,1:lagsModelMax] <- mean(yInSample[1:lagsModelMax]);\n", + " if (xregModel) {\n", + " if (Etype == \"A\") {\n", + " matVt[j, 1:lagsModelMax] <- matVt[j, 1:lagsModelMax] -\n", + " as.vector(xregModelInitials[[1]]$initialXreg %*% xregData[1, ])\n", + " } else {\n", + " matVt[j, 1:lagsModelMax] <- matVt[j, 1:lagsModelMax] /\n", + " as.vector(exp(xregModelInitials[[2]]$initialXreg %*% xregData[1, ]))\n", + " }\n", + " }\n", + " } else {\n", + " matVt[j, 1:lagsModelMax] <- initialLevel\n", + " }\n", + " j <- j + 1\n", + " # If trend is needed\n", + " if (modelIsTrendy) {\n", + " if (initialTrendEstimate) {\n", + " if (Ttype == \"A\" && Stype == \"M\") {\n", + " # if(initialLevelEstimate){\n", + " # # level fix\n", + " # matVt[j-1,1:lagsModelMax] <- exp(mean(log(yInSample[otLogical][1:lagsModelMax])));\n", + " # }\n", + " # trend\n", + " matVt[j, 1:lagsModelMax] <- prod(yDecomposition$initial) - yDecomposition$initial[1]\n", + " # If the initial trend is higher than the lowest value, initialise with zero.\n", + " # This is a failsafe mechanism for the mixed models\n", + " if (matVt[j, 1] < 0 && abs(matVt[j, 1]) > min(abs(yInSample[otLogical]))) {\n", + " matVt[j, 1:lagsModelMax] <- 0\n", + " }\n", + " } else if (Ttype == \"M\" && Stype == \"A\") {\n", + " # if(initialLevelEstimate){\n", + " # # level fix\n", + " # matVt[j-1,1:lagsModelMax] <- exp(mean(log(yInSample[otLogical][1:lagsModelMax])));\n", + " # }\n", + " # trend\n", + " matVt[j, 1:lagsModelMax] <- sum(abs(yDecomposition$initial)) / abs(yDecomposition$initial[1])\n", + " } else if (Ttype == \"M\") {\n", + " # trend is too dangerous, make it start from 1.\n", + " matVt[j, 1:lagsModelMax] <- 1\n", + " } else {\n", + " # trend\n", + " matVt[j, 1:lagsModelMax] <- yDecomposition$initial[2]\n", + " }\n", + " # This is a failsafe for multiplicative trend models, so that the thing does not explode\n", + " if (Ttype == \"M\" && any(matVt[j, 1:lagsModelMax] > 1.1)) {\n", + " matVt[j, 1:lagsModelMax] <- 1\n", + " }\n", + " # This is a failsafe for multiplicative trend models, so that the thing does not explode\n", + " if (Ttype == \"M\" && any(matVt[1, 1:lagsModelMax] < 0)) {\n", + " matVt[1, 1:lagsModelMax] <- yInSample[otLogical][1]\n", + " }\n", + " } else {\n", + " matVt[j, 1:lagsModelMax] <- initialTrend\n", + " }\n", + " j <- j + 1\n", + " }\n", + " #### Seasonal components\n", + " # For pure models use stuff as is\n", + " if (all(c(Etype, Stype) == \"A\") || all(c(Etype, Stype) == \"M\") ||\n", + " (Etype == \"A\" & Stype == \"M\")) {\n", + " for (i in 1:componentsNumberETSSeasonal) {\n", + " if (initialSeasonalEstimate[i]) {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- yDecomposition$seasonal[[i]]\n", + " # Renormalise the initial seasons\n", + " if (Stype == \"A\") {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <-\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] -\n", + " mean(matVt[i + j - 1, 1:lagsModel[i + j - 1]])\n", + " } else {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <-\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] /\n", + " exp(mean(log(matVt[i + j - 1, 1:lagsModel[i + j - 1]])))\n", + " }\n", + " } else {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- initialSeasonal[[i]]\n", + " }\n", + " }\n", + " }\n", + " # For mixed models use a different set of initials\n", + " else if (Etype == \"M\" && Stype == \"A\") {\n", + " for (i in 1:componentsNumberETSSeasonal) {\n", + " if (initialSeasonalEstimate[i]) {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- log(yDecomposition$seasonal[[i]]) * min(yInSample[otLogical])\n", + " # Renormalise the initial seasons\n", + " if (Stype == \"A\") {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- matVt[i + j - 1, 1:lagsModel[i + j - 1]] -\n", + " mean(matVt[i + j - 1, 1:lagsModel[i + j - 1]])\n", + " } else {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- matVt[i + j - 1, 1:lagsModel[i + j - 1]] /\n", + " exp(mean(log(matVt[i + j - 1, 1:lagsModel[i + j - 1]])))\n", + " }\n", + " } else {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- initialSeasonal[[i]]\n", + " }\n", + " }\n", + " }\n", + " } else {\n", + " # If either Etype or Stype are multiplicative, do multiplicative decomposition\n", + " j <- 1\n", + " # level\n", + " if (initialLevelEstimate) {\n", + " matVt[j, 1:lagsModelMax] <- mean(yInSample[1:lagsModelMax])\n", + " if (xregModel) {\n", + " if (Etype == \"A\") {\n", + " matVt[j, 1:lagsModelMax] <- matVt[j, 1:lagsModelMax] -\n", + " as.vector(xregModelInitials[[1]]$initialXreg %*% xregData[1, ])\n", + " } else {\n", + " matVt[j, 1:lagsModelMax] <- matVt[j, 1:lagsModelMax] /\n", + " as.vector(exp(xregModelInitials[[2]]$initialXreg %*% xregData[1, ]))\n", + " }\n", + " }\n", + " } else {\n", + " matVt[j, 1:lagsModelMax] <- initialLevel\n", + " }\n", + " j <- j + 1\n", + " if (modelIsTrendy) {\n", + " if (initialTrendEstimate) {\n", + " if (Ttype == \"A\") {\n", + " # trend\n", + " matVt[j, 1:lagsModelMax] <- yInSample[2] - yInSample[1]\n", + " } else if (Ttype == \"M\") {\n", + " if (initialLevelEstimate) {\n", + " # level fix\n", + " matVt[j - 1, 1:lagsModelMax] <- exp(mean(log(yInSample[otLogical][1:lagsModelMax])))\n", + " }\n", + " # trend\n", + " matVt[j, 1:lagsModelMax] <- yInSample[2] / yInSample[1]\n", + " }\n", + " # This is a failsafe for multiplicative trend models, so that the thing does not explode\n", + " if (Ttype == \"M\" && any(matVt[j, 1:lagsModelMax] > 1.1)) {\n", + " matVt[j, 1:lagsModelMax] <- 1\n", + " }\n", + " } else {\n", + " matVt[j, 1:lagsModelMax] <- initialTrend\n", + " }\n", + "\n", + " # Do roll back. Especially useful for backcasting and multisteps\n", + " if (Ttype == \"A\") {\n", + " matVt[j - 1, 1:lagsModelMax] <- matVt[j - 1, 1] - matVt[j, 1] * lagsModelMax\n", + " } else if (Ttype == \"M\") {\n", + " matVt[j - 1, 1:lagsModelMax] <- matVt[j - 1, 1] / matVt[j, 1]^lagsModelMax\n", + " }\n", + " j <- j + 1\n", + " }\n", + " #### Seasonal components\n", + " # For pure models use stuff as is\n", + " if (Stype == \"A\") {\n", + " for (i in 1:componentsNumberETSSeasonal) {\n", + " if (initialSeasonalEstimate[i]) {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- yInSample[1:lagsModel[i + j - 1]] - matVt[1, 1]\n", + " # Renormalise the initial seasons\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- matVt[i + j - 1, 1:lagsModel[i + j - 1]] -\n", + " mean(matVt[i + j - 1, 1:lagsModel[i + j - 1]])\n", + " } else {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- initialSeasonal[[i]]\n", + " }\n", + " }\n", + " }\n", + " # For mixed models use a different set of initials\n", + " else {\n", + " for (i in 1:componentsNumberETSSeasonal) {\n", + " if (initialSeasonalEstimate[i]) {\n", + " # abs() is needed for mixed ETS+ARIMA\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- yInSample[1:lagsModel[i + j - 1]] / abs(matVt[1, 1])\n", + " # Renormalise the initial seasons\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- matVt[i + j - 1, 1:lagsModel[i + j - 1]] /\n", + " exp(mean(log(matVt[i + j - 1, 1:lagsModel[i + j - 1]])))\n", + " } else {\n", + " matVt[i + j - 1, 1:lagsModel[i + j - 1]] <- initialSeasonal[[i]]\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + " # Non-seasonal models\n", + " else {\n", + " # level\n", + " if (initialLevelEstimate) {\n", + " matVt[1, 1:lagsModelMax] <- mean(yInSample[1:max(lagsModelMax, ceiling(obsInSample * 0.2))])\n", + " # if(xregModel){\n", + " # if(Etype==\"A\"){\n", + " # matVt[1,1:lagsModelMax] <- matVt[1,lagsModelMax] -\n", + " # as.vector(xregModelInitials[[1]]$initialXreg %*% xregData[1,]);\n", + " # }\n", + " # else{\n", + " # matVt[1,1:lagsModelMax] <- matVt[1,lagsModelMax] /\n", + " # as.vector(exp(xregModelInitials[[2]]$initialXreg %*% xregData[1,]));\n", + " # }\n", + " # }\n", + " } else {\n", + " matVt[1, 1:lagsModelMax] <- initialLevel\n", + " }\n", + " if (modelIsTrendy) {\n", + " if (initialTrendEstimate) {\n", + " matVt[2, 1:lagsModelMax] <- switch(Ttype,\n", + " \"A\" = mean(\n", + " diff(yInSample[1:max(\n", + " lagsModelMax + 1,\n", + " ceiling(obsInSample * 0.2)\n", + " )]),\n", + " na.rm = TRUE\n", + " ),\n", + " \"M\" = exp(mean(diff(log(yInSample[otLogical])), na.rm = TRUE))\n", + " )\n", + " } else {\n", + " matVt[2, 1:lagsModelMax] <- initialTrend\n", + " }\n", + " }\n", + " }\n", + "\n", + " if (initialLevelEstimate && Etype == \"M\" && matVt[1, lagsModelMax] == 0) {\n", + " matVt[1, 1:lagsModelMax] <- mean(yInSample)\n", + " }\n", + " }\n", + " # Else, insert the provided ones... make sure that this is not a backcasting\n", + " else if (!initialEstimate && initialType == \"provided\") {\n", + " j <- 1\n", + " matVt[j, 1:lagsModelMax] <- initialLevel\n", + " if (modelIsTrendy) {\n", + " j <- j + 1\n", + " matVt[j, 1:lagsModelMax] <- initialTrend\n", + " }\n", + " if (modelIsSeasonal) {\n", + " for (i in 1:componentsNumberETSSeasonal) {\n", + " # This is misaligned, but that's okay, because this goes directly to profileRecent\n", + " # matVt[j+i,(lagsModelMax-lagsModel[j+i])+1:lagsModel[j+i]] <- initialSeasonal[[i]];\n", + " matVt[j + i, 1:lagsModel[j + i]] <- initialSeasonal[[i]]\n", + " }\n", + " }\n", + " j <- j + componentsNumberETSSeasonal\n", + " }\n", + " }\n", + "\n", + " # If ARIMA orders are specified, prepare initials\n", + " if (arimaModel) {\n", + " if (initialArimaEstimate) {\n", + " matVt[componentsNumberETS + 1:componentsNumberARIMA, 1:initialArimaNumber] <-\n", + " switch(Etype,\n", + " \"A\" = 0,\n", + " \"M\" = 1\n", + " )\n", + " if (any(lags > 1)) {\n", + " yDecomposition <- tail(msdecompose(yInSample,\n", + " lags[lags != 1],\n", + " type = switch(Etype,\n", + " \"A\" = \"additive\",\n", + " \"M\" = \"multiplicative\"\n", + " )\n", + " )$seasonal, 1)[[1]]\n", + " } else {\n", + " yDecomposition <- switch(Etype,\n", + " \"A\" = mean(diff(yInSample[otLogical])),\n", + " \"M\" = exp(mean(diff(log(yInSample[otLogical]))))\n", + " )\n", + " }\n", + " matVt[componentsNumberETS + componentsNumberARIMA, 1:initialArimaNumber] <-\n", + " rep(yDecomposition, ceiling(initialArimaNumber / max(lags)))[1:initialArimaNumber]\n", + " # rep(yInSample[1:initialArimaNumber],each=componentsNumberARIMA);\n", + "\n", + " # Failsafe mechanism in case the sample is too small\n", + " # matVt[is.na(matVt)] <- switch(Etype, \"A\"=0, \"M\"=1);\n", + "\n", + " # If this is just ARIMA with optimisation, refine the initials\n", + " # if(!etsModel && initialType!=\"complete\"){\n", + " # arimaPolynomials <- polynomialiser(rep(0.1,sum(c(arOrders,maOrders))), arOrders, iOrders, maOrders,\n", + " # arRequired, maRequired, arEstimate, maEstimate, armaParameters, lags);\n", + " # if(nrow(nonZeroARI)>0 && nrow(nonZeroARI)>=nrow(nonZeroMA)){\n", + " # matVt[componentsNumberETS+nonZeroARI[,2],\n", + " # 1:initialArimaNumber] <-\n", + " # switch(Etype,\n", + " # \"A\"=arimaPolynomials$ariPolynomial[nonZeroARI[,1]] %*%\n", + " # t(matVt[componentsNumberETS+componentsNumberARIMA, 1:initialArimaNumber]) /\n", + " # tail(arimaPolynomials$ariPolynomial,1),\n", + " # \"M\"=exp(arimaPolynomials$ariPolynomial[nonZeroARI[,1]] %*%\n", + " # t(log(matVt[componentsNumberETS+componentsNumberARIMA, 1:initialArimaNumber])) /\n", + " # tail(arimaPolynomials$ariPolynomial,1)));\n", + " # }\n", + " # else{\n", + " # matVt[componentsNumberETS+nonZeroMA[,2],\n", + " # 1:initialArimaNumber] <-\n", + " # switch(Etype,\n", + " # \"A\"=arimaPolynomials$maPolynomial[nonZeroMA[,1]] %*%\n", + " # t(matVt[componentsNumberETS+componentsNumberARIMA, 1:initialArimaNumber]) /\n", + " # tail(arimaPolynomials$maPolynomial,1),\n", + " # \"M\"=exp(arimaPolynomials$maPolynomial[nonZeroMA[,1]] %*%\n", + " # t(log(matVt[componentsNumberETS+componentsNumberARIMA, 1:initialArimaNumber])) /\n", + " # tail(arimaPolynomials$maPolynomial,1)));\n", + " # }\n", + " # }\n", + " } else {\n", + " # Fill in the matrix with 0 / 1, just in case if the state will not be updated anymore\n", + " matVt[componentsNumberETS + 1:componentsNumberARIMA, 1:initialArimaNumber] <-\n", + " switch(Etype,\n", + " \"A\" = 0,\n", + " \"M\" = 1\n", + " )\n", + " # Insert the provided initials\n", + " matVt[componentsNumberETS + componentsNumberARIMA, 1:initialArimaNumber] <-\n", + " initialArima[1:initialArimaNumber]\n", + "\n", + " # matVt[componentsNumberETS+nonZeroARI[,2], 1:initialArimaNumber] <-\n", + " # switch(Etype,\n", + " # \"A\"=arimaPolynomials$ariPolynomial[nonZeroARI[,1]] %*% t(initialArima[1:initialArimaNumber]) /\n", + " # tail(arimaPolynomials$ariPolynomial,1),\n", + " # \"M\"=exp(arimaPolynomials$ariPolynomial[nonZeroARI[,1]] %*% t(log(initialArima[1:initialArimaNumber])) /\n", + " # tail(arimaPolynomials$ariPolynomial,1)));\n", + "\n", + " # If only AR is needed, but provided or if both are needed, but provided\n", + " # if(((arRequired && !arEstimate) && !maRequired) ||\n", + " # ((arRequired && !arEstimate) && (maRequired && !maEstimate)) ||\n", + " # (iRequired && !arEstimate && !maEstimate)){\n", + " # matVt[componentsNumberETS+nonZeroARI[,2],1:initialArimaNumber] <-\n", + " # switch(Etype,\n", + " # \"A\"=arimaPolynomials$ariPolynomial[nonZeroARI[,1]] %*%\n", + " # t(initialArima[1:initialArimaNumber]) /\n", + " # tail(arimaPolynomials$ariPolynomial,1),\n", + " # \"M\"=exp(arimaPolynomials$ariPolynomial[nonZeroARI[,1]] %*%\n", + " # t(log(initialArima[1:initialArimaNumber])) /\n", + " # tail(arimaPolynomials$ariPolynomial,1)));\n", + " # }\n", + " # If only MA is needed, but provided\n", + " # else if(((maRequired && !maEstimate) && !arRequired)){\n", + " # matVt[componentsNumberETS+nonZeroMA[,2],1:initialArimaNumber] <-\n", + " # switch(Etype,\n", + " # \"A\"=arimaPolynomials$maPolynomial[nonZeroMA[,1]] %*%\n", + " # t(initialArima[1:initialArimaNumber]) /\n", + " # tail(arimaPolynomials$maPolynomial,1),\n", + " # \"M\"=exp(arimaPolynomials$maPolynomial[nonZeroMA[,1]] %*%\n", + " # t(log(initialArima[1:initialArimaNumber])) /\n", + " # tail(arimaPolynomials$maPolynomial,1)));\n", + " # }\n", + " }\n", + " }\n", + "\n", + " # Fill in the initials for xreg\n", + " if (xregModel) {\n", + " if (Etype == \"A\" || initialXregProvided || is.null(xregModelInitials[[2]])) {\n", + " matVt[\n", + " componentsNumberETS + componentsNumberARIMA + 1:xregNumber,\n", + " 1:lagsModelMax\n", + " ] <- xregModelInitials[[1]]$initialXreg\n", + " } else {\n", + " matVt[\n", + " componentsNumberETS + componentsNumberARIMA + 1:xregNumber,\n", + " 1:lagsModelMax\n", + " ] <- xregModelInitials[[2]]$initialXreg\n", + " }\n", + " }\n", + "\n", + " # Add constant if needed\n", + " if (constantRequired) {\n", + " if (constantEstimate) {\n", + " # Add the mean of data\n", + " if (sum(iOrders) == 0 && !etsModel) {\n", + " matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, ] <- mean(yInSample[otLogical])\n", + " }\n", + " # Add first differences\n", + " else {\n", + " matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, ] <-\n", + " switch(Etype,\n", + " \"A\" = mean(diff(yInSample[otLogical])),\n", + " \"M\" = exp(mean(diff(log(yInSample[otLogical]))))\n", + " )\n", + " }\n", + " } else {\n", + " matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, ] <- constantValue\n", + " }\n", + " # If ETS model is used, change the initial level\n", + " if (etsModel && initialLevelEstimate) {\n", + " if (Etype == \"A\") {\n", + " matVt[1, 1:lagsModelMax] <- matVt[1, 1:lagsModelMax] -\n", + " matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, 1]\n", + " } else {\n", + " matVt[1, 1:lagsModelMax] <- matVt[1, 1:lagsModelMax] /\n", + " matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, 1]\n", + " }\n", + " }\n", + " # If ARIMA is done, debias states\n", + " if (arimaModel && initialArimaEstimate) {\n", + " if (Etype == \"A\") {\n", + " matVt[componentsNumberETS + nonZeroARI[, 2], 1:initialArimaNumber] <-\n", + " matVt[componentsNumberETS + nonZeroARI[, 2], 1:initialArimaNumber] -\n", + " matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, 1]\n", + " } else {\n", + " matVt[componentsNumberETS + nonZeroARI[, 2], 1:initialArimaNumber] <-\n", + " matVt[componentsNumberETS + nonZeroARI[, 2], 1:initialArimaNumber] /\n", + " matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, 1]\n", + " }\n", + " }\n", + " }\n", + " } else {\n", + " matVt[, 1:lagsModelMax] <- profilesRecentTable\n", + " }\n", + "\n", + " return(list(matVt = matVt, matWt = matWt, matF = matF, vecG = vecG, arimaPolynomials = arimaPolynomials))\n", + " }\n", + "\n", + "\n", + "\n", + "# Make the call to creator\n", + "created <- creator(\n", + " etsModel = TRUE,\n", + " Etype = \"A\",\n", + " Ttype = \"N\",\n", + " Stype = \"N\",\n", + " modelIsTrendy = FALSE,\n", + " modelIsSeasonal = FALSE,\n", + " lags = 1,\n", + " lagsModel = 1,\n", + " lagsModelARIMA = numeric(0),\n", + " lagsModelAll = 1,\n", + " lagsModelMax = 1,\n", + " obsStates = 101,\n", + " obsInSample = 100,\n", + " obsAll = 100,\n", + " componentsNumberETS = 1,\n", + " componentsNumberETSSeasonal = 0,\n", + " componentsNamesETS = \"level\",\n", + " otLogical = rep(TRUE, 100),\n", + " yInSample = y_in_sample, \n", + " persistence = NULL, persistenceEstimate = TRUE,\n", + " persistenceLevel = NULL, persistenceLevelEstimate = TRUE,\n", + " persistenceTrend = NULL, persistenceTrendEstimate = TRUE,\n", + " persistenceSeasonal = NULL, persistenceSeasonalEstimate = TRUE,\n", + " persistenceXreg = NULL, persistenceXregEstimate = TRUE, persistenceXregProvided = FALSE,\n", + " phi = 1,\n", + " # Initials\n", + " initialType = \"optimal\", initialEstimate = TRUE,\n", + " initialLevel = NULL, initialLevelEstimate = TRUE,\n", + " initialTrend = NULL, initialTrendEstimate = TRUE,\n", + " initialSeasonal = NULL, initialSeasonalEstimate = TRUE,\n", + " initialArima = NULL, initialArimaEstimate = TRUE, initialArimaNumber = NULL,\n", + " initialXregEstimate = TRUE, initialXregProvided = FALSE,\n", + " # ARIMA elements\n", + " arimaModel = FALSE, arRequired = FALSE, iRequired = FALSE, maRequired = FALSE, armaParameters = NULL,\n", + " arOrders = NULL, iOrders = NULL, maOrders = NULL,\n", + " componentsNumberARIMA = 0, componentsNamesARIMA = NULL,\n", + " # Explanatory variables\n", + " xregModel = FALSE, xregModelInitials = NULL, xregData = NULL, xregNumber = 0, xregNames = NULL,\n", + " xregParametersPersistence = NULL,\n", + " # Constant\n", + " constantRequired = FALSE, constantEstimate = TRUE, constantValue = NULL, constantName = NULL)\n", + "\n", + "\n", + "\n", + "res <- created[1]\n", + "matVt <- res$matVt\n", + "matWt <- res$matWt\n", + "matF <- res$matF\n", + "vecG <- res$vecG" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1] 0\n", + "Error in B[j + 1:xregNumberToEstimate] <- matVt[componentsNumberETS + : \n", + " replacement has length zero\n" + ] + }, + { + "ename": "RInterpreterError", + "evalue": "Failed to parse and evaluate line '\\ninitialiser <- function(yInSample,\\n etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal,\\n componentsNumberETSNonSeasonal, componentsNumberETSSeasonal, componentsNumberETS,\\n lags, lagsModel, lagsModelSeasonal, lagsModelARIMA, lagsModelMax,\\n matVt,\\n # persistence values\\n persistenceEstimate, persistenceLevelEstimate, persistenceTrendEstimate,\\n persistenceSeasonalEstimate, persistenceXregEstimate,\\n # initials\\n phiEstimate, initialType, initialEstimate,\\n initialLevelEstimate, initialTrendEstimate, initialSeasonalEstimate,\\n initialArimaEstimate, initialXregEstimate,\\n # ARIMA elements\\n arimaModel, arRequired, maRequired, arEstimate, maEstimate, arOrders, maOrders,\\n componentsNumberARIMA, componentsNamesARIMA, initialArimaNumber,\\n # Explanatory variables\\n xregModel, xregNumber,\\n xregParametersEstimated, xregParametersPersistence,\\n # Constant and other stuff\\n constantEstimate, constantName, otherParameterEstimate,\\n # Additional parameters\\n bounds, iOrders, other){\\n # The vector of logicals for persistence elements\\n persistenceEstimateVector <- c(\\n persistenceLevelEstimate, modelIsTrendy & persistenceTrendEstimate,\\n modelIsSeasonal & persistenceSeasonalEstimate\\n )\\n\\n # The order:\\n # Persistence of states and for xreg, phi, AR and MA parameters, initials, initialsARIMA, initials for xreg\\n B <- Bl <- Bu <- vector(\\n \"numeric\",\\n # Values of the persistence vector + phi\\n etsModel * (persistenceLevelEstimate + modelIsTrendy * persistenceTrendEstimate +\\n modelIsSeasonal * sum(persistenceSeasonalEstimate) + phiEstimate) +\\n xregModel * persistenceXregEstimate * max(xregParametersPersistence) +\\n # AR and MA values\\n arimaModel * (arEstimate * sum(arOrders) + maEstimate * sum(maOrders)) +\\n # initials of ETS\\n etsModel * all(initialType != c(\"complete\", \"backcasting\")) *\\n (initialLevelEstimate +\\n (modelIsTrendy * initialTrendEstimate) +\\n (modelIsSeasonal * sum(initialSeasonalEstimate * (lagsModelSeasonal - 1)))) +\\n # initials of ARIMA\\n all(initialType != c(\"complete\", \"backcasting\")) * arimaModel * initialArimaNumber * initialArimaEstimate +\\n # initials of xreg\\n (initialType != \"complete\") * xregModel * initialXregEstimate * sum(xregParametersEstimated) +\\n constantEstimate + otherParameterEstimate\\n )\\n\\n j <- 0\\n if (etsModel) {\\n # Fill in persistence\\n if (persistenceEstimate && any(persistenceEstimateVector)) {\\n if (any(c(Etype, Ttype, Stype) == \"M\")) {\\n # A special type of model which is not safe: AAM, MAA, MAM\\n if ((Etype == \"A\" && Ttype == \"A\" && Stype == \"M\") || (Etype == \"A\" && Ttype == \"M\" && Stype == \"A\") ||\\n (any(initialType == c(\"complete\", \"backcasting\")) &&\\n ((Etype == \"M\" && Ttype == \"A\" && Stype == \"A\") || (Etype == \"M\" && Ttype == \"A\" && Stype == \"M\")))) {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.01, 0, rep(0, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n }\\n # MMA is the worst. Set everything to zero and see if anything can be done...\\n else if ((Etype == \"M\" && Ttype == \"M\" && Stype == \"A\")) {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0, 0, rep(0, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n } else if (Etype == \"M\" && Ttype == \"A\") {\\n if (any(initialType == c(\"complete\", \"backcasting\"))) {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.1, 0, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n } else {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.2, 0.01, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n }\\n } else if (Etype == \"M\" && Ttype == \"M\") {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.1, 0.05, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n } else {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.1, 0.05, rep(0.05, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n }\\n } else {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.1, 0.05, rep(0.11, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n }\\n if (bounds == \"usual\") {\\n Bl[1:sum(persistenceEstimateVector)] <- rep(0, sum(persistenceEstimateVector))\\n Bu[1:sum(persistenceEstimateVector)] <- rep(1, sum(persistenceEstimateVector))\\n } else {\\n Bl[1:sum(persistenceEstimateVector)] <- rep(-5, sum(persistenceEstimateVector))\\n Bu[1:sum(persistenceEstimateVector)] <- rep(5, sum(persistenceEstimateVector))\\n }\\n # Names for B\\n if (persistenceLevelEstimate) {\\n j[] <- j + 1\\n names(B)[j] <- \"alpha\"\\n }\\n if (modelIsTrendy && persistenceTrendEstimate) {\\n j[] <- j + 1\\n names(B)[j] <- \"beta\"\\n }\\n if (modelIsSeasonal && any(persistenceSeasonalEstimate)) {\\n if (componentsNumberETSSeasonal > 1) {\\n names(B)[j + c(1:sum(persistenceSeasonalEstimate))] <-\\n paste0(\"gamma\", c(1:componentsNumberETSSeasonal))\\n } else {\\n names(B)[j + 1] <- \"gamma\"\\n }\\n j[] <- j + sum(persistenceSeasonalEstimate)\\n }\\n }\\n }\\n\\n # Persistence if xreg is provided\\n if (xregModel && persistenceXregEstimate) {\\n xregPersistenceNumber <- max(xregParametersPersistence)\\n B[j + 1:xregPersistenceNumber] <- rep(switch(Etype,\\n \"A\" = 0.01,\\n \"M\" = 0\\n ), xregPersistenceNumber)\\n Bl[j + 1:xregPersistenceNumber] <- rep(-5, xregPersistenceNumber)\\n Bu[j + 1:xregPersistenceNumber] <- rep(5, xregPersistenceNumber)\\n names(B)[j + 1:xregPersistenceNumber] <- paste0(\"delta\", c(1:xregPersistenceNumber))\\n j[] <- j + xregPersistenceNumber\\n }\\n\\n # Damping parameter\\n if (etsModel && phiEstimate) {\\n j[] <- j + 1\\n B[j] <- 0.95\\n names(B)[j] <- \"phi\"\\n Bl[j] <- 0\\n Bu[j] <- 1\\n }\\n\\n # ARIMA parameters (AR / MA)\\n if (arimaModel) {\\n # These are filled in lags-wise\\n if (any(c(arEstimate, maEstimate))) {\\n acfValues <- rep(-0.1, maOrders %*% lags)\\n pacfValues <- rep(0.1, arOrders %*% lags)\\n # If this is ETS + ARIMA model or no differences model, then don\\'t bother with initials\\n # The latter does not make sense because of non-stationarity in ACF / PACF\\n # Otherwise use ACF / PACF values as starting parameters for ARIMA\\n if (!(etsModel || all(iOrders == 0))) {\\n yDifferenced <- yInSample\\n # If the model has differences, take them\\n if (any(iOrders > 0)) {\\n for (i in 1:length(iOrders)) {\\n if (iOrders[i] > 0) {\\n yDifferenced <- diff(yDifferenced, lag = lags[i], differences = iOrders[i])\\n }\\n }\\n }\\n # Do ACF/PACF initialisation only for non-seasonal models\\n if (all(lags <= 1)) {\\n if (maRequired && maEstimate) {\\n # If the sample is smaller than lags, it will be substituted by default values\\n acfValues[1:min(maOrders %*% lags, length(yDifferenced) - 1)] <-\\n acf(yDifferenced, lag.max = max(1, maOrders %*% lags), plot = FALSE)$acf[-1]\\n }\\n if (arRequired && arEstimate) {\\n # If the sample is smaller than lags, it will be substituted by default values\\n pacfValues[1:min(arOrders %*% lags, length(yDifferenced) - 1)] <-\\n pacf(yDifferenced, lag.max = max(1, arOrders %*% lags), plot = FALSE)$acf\\n }\\n }\\n }\\n for (i in 1:length(lags)) {\\n if (arRequired && arEstimate && arOrders[i] > 0) {\\n if (all(!is.nan(pacfValues[c(1:arOrders[i]) * lags[i]]))) {\\n B[j + c(1:arOrders[i])] <- pacfValues[c(1:arOrders[i]) * lags[i]]\\n } else {\\n B[j + c(1:arOrders[i])] <- 0.1\\n }\\n if (sum(B[j + c(1:arOrders[i])]) > 1) {\\n B[j + c(1:arOrders[i])] <- B[j + c(1:arOrders[i])] / sum(B[j + c(1:arOrders[i])]) - 0.01\\n }\\n # B[j+c(1:arOrders[i])] <- rep(0.1,arOrders[i]);\\n Bl[j + c(1:arOrders[i])] <- -5\\n Bu[j + c(1:arOrders[i])] <- 5\\n names(B)[j + 1:arOrders[i]] <- paste0(\"phi\", 1:arOrders[i], \"[\", lags[i], \"]\")\\n j[] <- j + arOrders[i]\\n }\\n if (maRequired && maEstimate && maOrders[i] > 0) {\\n if (all(!is.nan(acfValues[c(1:maOrders[i]) * lags[i]]))) {\\n B[j + c(1:maOrders[i])] <- acfValues[c(1:maOrders[i]) * lags[i]]\\n } else {\\n B[j + c(1:maOrders[i])] <- 0.1\\n }\\n if (sum(B[j + c(1:maOrders[i])]) > 1) {\\n B[j + c(1:maOrders[i])] <- B[j + c(1:maOrders[i])] / sum(B[j + c(1:maOrders[i])]) - 0.01\\n }\\n # B[j+c(1:maOrders[i])] <- rep(-0.1,maOrders[i]);\\n Bl[j + c(1:maOrders[i])] <- -5\\n Bu[j + c(1:maOrders[i])] <- 5\\n names(B)[j + 1:maOrders[i]] <- paste0(\"theta\", 1:maOrders[i], \"[\", lags[i], \"]\")\\n j[] <- j + maOrders[i]\\n }\\n }\\n }\\n }\\n\\n # Initials\\n if (etsModel && all(initialType != c(\"complete\", \"backcasting\")) && initialEstimate) {\\n if (initialLevelEstimate) {\\n j[] <- j + 1\\n B[j] <- matVt[1, 1]\\n names(B)[j] <- \"level\"\\n if (Etype == \"A\") {\\n Bl[j] <- -Inf\\n Bu[j] <- Inf\\n } else {\\n Bl[j] <- 0\\n Bu[j] <- Inf\\n }\\n }\\n if (modelIsTrendy && initialTrendEstimate) {\\n j[] <- j + 1\\n B[j] <- matVt[2, 1]\\n names(B)[j] <- \"trend\"\\n if (Ttype == \"A\") {\\n Bl[j] <- -Inf\\n Bu[j] <- Inf\\n } else {\\n Bl[j] <- 0\\n # 2 is already too much for the multiplicative model\\n Bu[j] <- 2\\n }\\n }\\n if (modelIsSeasonal && any(initialSeasonalEstimate)) {\\n if (componentsNumberETSSeasonal > 1) {\\n for (k in 1:componentsNumberETSSeasonal) {\\n if (initialSeasonalEstimate[k]) {\\n # -1 is needed in order to remove the redundant seasonal element (normalisation)\\n B[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <-\\n matVt[componentsNumberETSNonSeasonal + k, 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1]\\n names(B)[j + 2:(lagsModel[componentsNumberETSNonSeasonal + k]) - 1] <-\\n paste0(\"seasonal\", k, \"_\", 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1)\\n if (Stype == \"A\") {\\n Bl[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- -Inf\\n Bu[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- Inf\\n } else {\\n Bl[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- 0\\n Bu[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- Inf\\n }\\n j[] <- j + (lagsModelSeasonal[k] - 1)\\n }\\n }\\n } else {\\n # -1 is needed in order to remove the redundant seasonal element (normalisation)\\n B[j + 2:(lagsModel[componentsNumberETS]) - 1] <- matVt[componentsNumberETS, 2:lagsModel[componentsNumberETS] - 1]\\n names(B)[j + 2:(lagsModel[componentsNumberETS]) - 1] <- paste0(\"seasonal_\", 2:lagsModel[componentsNumberETS] - 1)\\n if (Stype == \"A\") {\\n Bl[j + 2:(lagsModel[componentsNumberETS]) - 1] <- -Inf\\n Bu[j + 2:(lagsModel[componentsNumberETS]) - 1] <- Inf\\n } else {\\n Bl[j + 2:(lagsModel[componentsNumberETS]) - 1] <- 0\\n Bu[j + 2:(lagsModel[componentsNumberETS]) - 1] <- Inf\\n }\\n j[] <- j + (lagsModel[componentsNumberETS] - 1)\\n }\\n }\\n }\\n print(xregParametersEstimated)\\n # ARIMA initials\\n if (all(initialType != c(\"complete\", \"backcasting\")) && arimaModel && initialArimaEstimate) {\\n B[j + 1:initialArimaNumber] <- head(matVt[componentsNumberETS + componentsNumberARIMA, 1:lagsModelMax], initialArimaNumber)\\n names(B)[j + 1:initialArimaNumber] <- paste0(\"ARIMAState\", 1:initialArimaNumber)\\n if (Etype == \"A\") {\\n Bl[j + 1:initialArimaNumber] <- -Inf\\n Bu[j + 1:initialArimaNumber] <- Inf\\n } else {\\n # Make sure that ARIMA states are positive to avoid errors\\n B[j + 1:initialArimaNumber] <- abs(B[j + 1:initialArimaNumber])\\n Bl[j + 1:initialArimaNumber] <- 0\\n Bu[j + 1:initialArimaNumber] <- Inf\\n }\\n j[] <- j + initialArimaNumber\\n }\\n\\n # Initials of the xreg\\n if (initialType != \"complete\" && initialXregEstimate) {\\n xregNumberToEstimate <- sum(xregParametersEstimated)\\n B[j + 1:xregNumberToEstimate] <- matVt[componentsNumberETS + componentsNumberARIMA +\\n which(xregParametersEstimated == 1), 1]\\n names(B)[j + 1:xregNumberToEstimate] <- rownames(matVt)[componentsNumberETS + componentsNumberARIMA +\\n which(xregParametersEstimated == 1)]\\n if (Etype == \"A\") {\\n Bl[j + 1:xregNumberToEstimate] <- -Inf\\n Bu[j + 1:xregNumberToEstimate] <- Inf\\n } else {\\n Bl[j + 1:xregNumberToEstimate] <- -Inf\\n Bu[j + 1:xregNumberToEstimate] <- Inf\\n }\\n j[] <- j + xregNumberToEstimate\\n }\\n\\n if (constantEstimate) {\\n j[] <- j + 1\\n B[j] <- matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, 1]\\n names(B)[j] <- constantName\\n if (etsModel || sum(iOrders) != 0) {\\n if (Etype == \"A\") {\\n Bu[j] <- quantile(diff(yInSample[otLogical]), 0.6)\\n Bl[j] <- -Bu[j]\\n } else {\\n Bu[j] <- exp(quantile(diff(log(yInSample[otLogical])), 0.6))\\n Bl[j] <- exp(quantile(diff(log(yInSample[otLogical])), 0.4))\\n }\\n\\n # Failsafe for weird cases, when upper bound is the same or lower than the lower one\\n if (Bu[j] <= Bl[j]) {\\n Bu[j] <- Inf\\n Bl[j] <- switch(Etype,\\n \"A\" = -Inf,\\n \"M\" = 0\\n )\\n }\\n\\n # Failsafe for cases, when the B is outside of bounds\\n if (B[j] <= Bl[j]) {\\n Bl[j] <- switch(Etype,\\n \"A\" = -Inf,\\n \"M\" = 0\\n )\\n }\\n if (B[j] >= Bu[j]) {\\n Bu[j] <- Inf\\n }\\n } else {\\n # if(Etype==\"A\"){\\n # B[j]*1.01 is needed to make sure that the bounds cover the initial value\\n Bu[j] <- max(abs(yInSample[otLogical]), abs(B[j]) * 1.01)\\n Bl[j] <- -Bu[j]\\n # }\\n # else{\\n # Bu[j] <- 1.5;\\n # Bl[j] <- 0.1;\\n # }\\n # If this is just a constant\\n }\\n }\\n\\n # Add lambda if it is needed\\n if (otherParameterEstimate) {\\n j[] <- j + 1\\n B[j] <- other\\n names(B)[j] <- \"other\"\\n Bl[j] <- 1e-10\\n Bu[j] <- Inf\\n }\\n\\n return(list(B = B, Bl = Bl, Bu = Bu))\\n\\n}\\n\\n\\n# Updated initialiser function call\\ninitialiser_result <- initialiser(\\n yInSample = y_in_sample,\\n etsModel = TRUE,\\n Etype = \"A\",\\n Ttype = \"N\",\\n Stype = \"N\",\\n modelIsTrendy = FALSE,\\n modelIsSeasonal = FALSE,\\n componentsNumberETSNonSeasonal = 1,\\n componentsNumberETSSeasonal = 0,\\n componentsNumberETS = 1,\\n lags = 1,\\n lagsModel = 1,\\n lagsModelSeasonal = 1,\\n lagsModelARIMA = 0,\\n lagsModelMax = 1,\\n matVt = matVt, # Replace with actual matrix if available\\n persistenceEstimate = TRUE,\\n persistenceLevelEstimate = TRUE,\\n persistenceTrendEstimate = TRUE,\\n persistenceSeasonalEstimate = TRUE,\\n persistenceXregEstimate = TRUE,\\n phiEstimate = TRUE,\\n initialType = \"optimal\",\\n initialEstimate = TRUE,\\n initialLevelEstimate = TRUE,\\n initialTrendEstimate = TRUE,\\n initialSeasonalEstimate = FALSE,\\n initialArimaEstimate = FALSE,\\n initialXregEstimate = TRUE,\\n arimaModel = FALSE,\\n arRequired = FALSE,\\n maRequired = FALSE,\\n arEstimate = TRUE,\\n maEstimate = TRUE,\\n arOrders = 0,\\n maOrders = 0,\\n componentsNumberARIMA = 0,\\n componentsNamesARIMA = 0,\\n initialArimaNumber = 0,\\n xregModel = FALSE,\\n xregNumber = 0,\\n xregParametersEstimated = 0,\\n xregParametersPersistence = 0,\\n constantEstimate = TRUE,\\n constantName = \"constant\",\\n otherParameterEstimate = FALSE,\\n bounds = \"usual\",\\n iOrders = 0,\\n other = NULL\\n)\\n'.\nR error message: 'Error in B[j + 1:xregNumberToEstimate] <- matVt[componentsNumberETS + : \\n replacement has length zero'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRRuntimeError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/smooth/python/.venv/lib/python3.8/site-packages/rpy2/ipython/rmagic.py:407\u001b[0m, in \u001b[0;36mRMagics.eval\u001b[0;34m(self, code)\u001b[0m\n\u001b[1;32m 406\u001b[0m r_expr \u001b[38;5;241m=\u001b[39m ri\u001b[38;5;241m.\u001b[39mparse(code)\n\u001b[0;32m--> 407\u001b[0m value, visible \u001b[38;5;241m=\u001b[39m \u001b[43mri\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mevalr_expr_with_visible\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 408\u001b[0m \u001b[43m \u001b[49m\u001b[43mr_expr\u001b[49m\n\u001b[1;32m 409\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 410\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (ri\u001b[38;5;241m.\u001b[39membedded\u001b[38;5;241m.\u001b[39mRRuntimeError, \u001b[38;5;167;01mValueError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m exception:\n\u001b[1;32m 411\u001b[0m \u001b[38;5;66;03m# Otherwise next return seems to have copy of error.\u001b[39;00m\n", + "File \u001b[0;32m~/smooth/python/.venv/lib/python3.8/site-packages/rpy2/rinterface.py:192\u001b[0m, in \u001b[0;36mevalr_expr_with_visible\u001b[0;34m(expr, envir)\u001b[0m\n\u001b[1;32m 191\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m error_occured[\u001b[38;5;241m0\u001b[39m]:\n\u001b[0;32m--> 192\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m embedded\u001b[38;5;241m.\u001b[39mRRuntimeError(_rinterface\u001b[38;5;241m.\u001b[39m_geterrmessage())\n\u001b[1;32m 193\u001b[0m res \u001b[38;5;241m=\u001b[39m conversion\u001b[38;5;241m.\u001b[39m_cdata_to_rinterface(r_res)\n", + "\u001b[0;31mRRuntimeError\u001b[0m: Error in B[j + 1:xregNumberToEstimate] <- matVt[componentsNumberETS + : \n replacement has length zero\n", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mRInterpreterError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[89], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mget_ipython\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_cell_magic\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mR\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m-i y_in_sample\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43minitialiser <- function(yInSample,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m componentsNumberETSNonSeasonal, componentsNumberETSSeasonal, componentsNumberETS,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m lags, lagsModel, lagsModelSeasonal, lagsModelARIMA, lagsModelMax,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m matVt,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # persistence values\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceEstimate, persistenceLevelEstimate, persistenceTrendEstimate,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceSeasonalEstimate, persistenceXregEstimate,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # initials\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m phiEstimate, initialType, initialEstimate,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialLevelEstimate, initialTrendEstimate, initialSeasonalEstimate,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialArimaEstimate, initialXregEstimate,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # ARIMA elements\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m arimaModel, arRequired, maRequired, arEstimate, maEstimate, arOrders, maOrders,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m componentsNumberARIMA, componentsNamesARIMA, initialArimaNumber,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Explanatory variables\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregModel, xregNumber,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregParametersEstimated, xregParametersPersistence,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Constant and other stuff\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m constantEstimate, constantName, otherParameterEstimate,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Additional parameters\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m bounds, iOrders, other)\u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # The vector of logicals for persistence elements\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceEstimateVector <- c(\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceLevelEstimate, modelIsTrendy & persistenceTrendEstimate,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m modelIsSeasonal & persistenceSeasonalEstimate\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m )\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # The order:\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Persistence of states and for xreg, phi, AR and MA parameters, initials, initialsARIMA, initials for xreg\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B <- Bl <- Bu <- vector(\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mnumeric\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Values of the persistence vector + phi\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m etsModel * (persistenceLevelEstimate + modelIsTrendy * persistenceTrendEstimate +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m modelIsSeasonal * sum(persistenceSeasonalEstimate) + phiEstimate) +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregModel * persistenceXregEstimate * max(xregParametersPersistence) +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # AR and MA values\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m arimaModel * (arEstimate * sum(arOrders) + maEstimate * sum(maOrders)) +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # initials of ETS\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m etsModel * all(initialType != c(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcomplete\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbackcasting\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)) *\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m (initialLevelEstimate +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m (modelIsTrendy * initialTrendEstimate) +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m (modelIsSeasonal * sum(initialSeasonalEstimate * (lagsModelSeasonal - 1)))) +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # initials of ARIMA\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m all(initialType != c(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcomplete\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbackcasting\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)) * arimaModel * initialArimaNumber * initialArimaEstimate +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # initials of xreg\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m (initialType != \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcomplete\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) * xregModel * initialXregEstimate * sum(xregParametersEstimated) +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m constantEstimate + otherParameterEstimate\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m )\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j <- 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (etsModel) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Fill in persistence\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (persistenceEstimate && any(persistenceEstimateVector)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (any(c(Etype, Ttype, Stype) == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # A special type of model which is not safe: AAM, MAA, MAM\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if ((Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Ttype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Stype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) || (Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Ttype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Stype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) ||\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m (any(initialType == c(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcomplete\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbackcasting\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)) &&\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m ((Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Ttype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Stype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) || (Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Ttype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Stype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)))) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[1:sum(persistenceEstimateVector)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m c(0.01, 0, rep(0, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # MMA is the worst. Set everything to zero and see if anything can be done...\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m else if ((Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Ttype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Stype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[1:sum(persistenceEstimateVector)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m c(0, 0, rep(0, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else if (Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Ttype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (any(initialType == c(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcomplete\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbackcasting\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m))) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[1:sum(persistenceEstimateVector)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m c(0.1, 0, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[1:sum(persistenceEstimateVector)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m c(0.2, 0.01, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else if (Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && Ttype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[1:sum(persistenceEstimateVector)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m c(0.1, 0.05, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[1:sum(persistenceEstimateVector)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m c(0.1, 0.05, rep(0.05, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[1:sum(persistenceEstimateVector)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m c(0.1, 0.05, rep(0.11, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (bounds == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43musual\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[1:sum(persistenceEstimateVector)] <- rep(0, sum(persistenceEstimateVector))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[1:sum(persistenceEstimateVector)] <- rep(1, sum(persistenceEstimateVector))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[1:sum(persistenceEstimateVector)] <- rep(-5, sum(persistenceEstimateVector))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[1:sum(persistenceEstimateVector)] <- rep(5, sum(persistenceEstimateVector))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Names for B\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (persistenceLevelEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + 1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j] <- \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43malpha\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (modelIsTrendy && persistenceTrendEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + 1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j] <- \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbeta\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (modelIsSeasonal && any(persistenceSeasonalEstimate)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (componentsNumberETSSeasonal > 1) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + c(1:sum(persistenceSeasonalEstimate))] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m paste0(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mgamma\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, c(1:componentsNumberETSSeasonal))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + 1] <- \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mgamma\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + sum(persistenceSeasonalEstimate)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Persistence if xreg is provided\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (xregModel && persistenceXregEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregPersistenceNumber <- max(xregParametersPersistence)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + 1:xregPersistenceNumber] <- rep(switch(Etype,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m = 0.01,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m = 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m ), xregPersistenceNumber)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 1:xregPersistenceNumber] <- rep(-5, xregPersistenceNumber)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 1:xregPersistenceNumber] <- rep(5, xregPersistenceNumber)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + 1:xregPersistenceNumber] <- paste0(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mdelta\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, c(1:xregPersistenceNumber))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + xregPersistenceNumber\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Damping parameter\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (etsModel && phiEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + 1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j] <- 0.95\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j] <- \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mphi\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- 1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # ARIMA parameters (AR / MA)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (arimaModel) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # These are filled in lags-wise\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (any(c(arEstimate, maEstimate))) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m acfValues <- rep(-0.1, maOrders \u001b[39;49m\u001b[38;5;132;43;01m%*%\u001b[39;49;00m\u001b[38;5;124;43m lags)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m pacfValues <- rep(0.1, arOrders \u001b[39;49m\u001b[38;5;132;43;01m%*%\u001b[39;49;00m\u001b[38;5;124;43m lags)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # If this is ETS + ARIMA model or no differences model, then don\u001b[39;49m\u001b[38;5;130;43;01m\\'\u001b[39;49;00m\u001b[38;5;124;43mt bother with initials\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # The latter does not make sense because of non-stationarity in ACF / PACF\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Otherwise use ACF / PACF values as starting parameters for ARIMA\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (!(etsModel || all(iOrders == 0))) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m yDifferenced <- yInSample\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # If the model has differences, take them\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (any(iOrders > 0)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m for (i in 1:length(iOrders)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (iOrders[i] > 0) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m yDifferenced <- diff(yDifferenced, lag = lags[i], differences = iOrders[i])\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Do ACF/PACF initialisation only for non-seasonal models\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (all(lags <= 1)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (maRequired && maEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # If the sample is smaller than lags, it will be substituted by default values\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m acfValues[1:min(maOrders \u001b[39;49m\u001b[38;5;132;43;01m%*%\u001b[39;49;00m\u001b[38;5;124;43m lags, length(yDifferenced) - 1)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m acf(yDifferenced, lag.max = max(1, maOrders \u001b[39;49m\u001b[38;5;132;43;01m%*%\u001b[39;49;00m\u001b[38;5;124;43m lags), plot = FALSE)$acf[-1]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (arRequired && arEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # If the sample is smaller than lags, it will be substituted by default values\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m pacfValues[1:min(arOrders \u001b[39;49m\u001b[38;5;132;43;01m%*%\u001b[39;49;00m\u001b[38;5;124;43m lags, length(yDifferenced) - 1)] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m pacf(yDifferenced, lag.max = max(1, arOrders \u001b[39;49m\u001b[38;5;132;43;01m%*%\u001b[39;49;00m\u001b[38;5;124;43m lags), plot = FALSE)$acf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m for (i in 1:length(lags)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (arRequired && arEstimate && arOrders[i] > 0) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (all(!is.nan(pacfValues[c(1:arOrders[i]) * lags[i]]))) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + c(1:arOrders[i])] <- pacfValues[c(1:arOrders[i]) * lags[i]]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + c(1:arOrders[i])] <- 0.1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (sum(B[j + c(1:arOrders[i])]) > 1) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + c(1:arOrders[i])] <- B[j + c(1:arOrders[i])] / sum(B[j + c(1:arOrders[i])]) - 0.01\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # B[j+c(1:arOrders[i])] <- rep(0.1,arOrders[i]);\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + c(1:arOrders[i])] <- -5\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + c(1:arOrders[i])] <- 5\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + 1:arOrders[i]] <- paste0(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mphi\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, 1:arOrders[i], \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m[\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, lags[i], \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m]\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + arOrders[i]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (maRequired && maEstimate && maOrders[i] > 0) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (all(!is.nan(acfValues[c(1:maOrders[i]) * lags[i]]))) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + c(1:maOrders[i])] <- acfValues[c(1:maOrders[i]) * lags[i]]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + c(1:maOrders[i])] <- 0.1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (sum(B[j + c(1:maOrders[i])]) > 1) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + c(1:maOrders[i])] <- B[j + c(1:maOrders[i])] / sum(B[j + c(1:maOrders[i])]) - 0.01\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # B[j+c(1:maOrders[i])] <- rep(-0.1,maOrders[i]);\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + c(1:maOrders[i])] <- -5\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + c(1:maOrders[i])] <- 5\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + 1:maOrders[i]] <- paste0(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtheta\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, 1:maOrders[i], \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m[\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, lags[i], \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m]\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + maOrders[i]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Initials\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (etsModel && all(initialType != c(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcomplete\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbackcasting\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)) && initialEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (initialLevelEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + 1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j] <- matVt[1, 1]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j] <- \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mlevel\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- -Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (modelIsTrendy && initialTrendEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + 1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j] <- matVt[2, 1]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j] <- \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtrend\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (Ttype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- -Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # 2 is already too much for the multiplicative model\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- 2\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (modelIsSeasonal && any(initialSeasonalEstimate)) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (componentsNumberETSSeasonal > 1) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m for (k in 1:componentsNumberETSSeasonal) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (initialSeasonalEstimate[k]) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # -1 is needed in order to remove the redundant seasonal element (normalisation)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m matVt[componentsNumberETSNonSeasonal + k, 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + 2:(lagsModel[componentsNumberETSNonSeasonal + k]) - 1] <-\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m paste0(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mseasonal\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, k, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m_\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (Stype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- -Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + (lagsModelSeasonal[k] - 1)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # -1 is needed in order to remove the redundant seasonal element (normalisation)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + 2:(lagsModel[componentsNumberETS]) - 1] <- matVt[componentsNumberETS, 2:lagsModel[componentsNumberETS] - 1]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + 2:(lagsModel[componentsNumberETS]) - 1] <- paste0(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mseasonal_\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, 2:lagsModel[componentsNumberETS] - 1)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (Stype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 2:(lagsModel[componentsNumberETS]) - 1] <- -Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 2:(lagsModel[componentsNumberETS]) - 1] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 2:(lagsModel[componentsNumberETS]) - 1] <- 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 2:(lagsModel[componentsNumberETS]) - 1] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + (lagsModel[componentsNumberETS] - 1)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m print(xregParametersEstimated)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # ARIMA initials\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (all(initialType != c(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcomplete\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbackcasting\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)) && arimaModel && initialArimaEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + 1:initialArimaNumber] <- head(matVt[componentsNumberETS + componentsNumberARIMA, 1:lagsModelMax], initialArimaNumber)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + 1:initialArimaNumber] <- paste0(\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mARIMAState\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m, 1:initialArimaNumber)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 1:initialArimaNumber] <- -Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 1:initialArimaNumber] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Make sure that ARIMA states are positive to avoid errors\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + 1:initialArimaNumber] <- abs(B[j + 1:initialArimaNumber])\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 1:initialArimaNumber] <- 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 1:initialArimaNumber] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + initialArimaNumber\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Initials of the xreg\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (initialType != \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcomplete\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m && initialXregEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregNumberToEstimate <- sum(xregParametersEstimated)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j + 1:xregNumberToEstimate] <- matVt[componentsNumberETS + componentsNumberARIMA +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m which(xregParametersEstimated == 1), 1]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j + 1:xregNumberToEstimate] <- rownames(matVt)[componentsNumberETS + componentsNumberARIMA +\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m which(xregParametersEstimated == 1)]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 1:xregNumberToEstimate] <- -Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 1:xregNumberToEstimate] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j + 1:xregNumberToEstimate] <- -Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j + 1:xregNumberToEstimate] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + xregNumberToEstimate\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (constantEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + 1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j] <- matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, 1]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j] <- constantName\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (etsModel || sum(iOrders) != 0) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (Etype == \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- quantile(diff(yInSample[otLogical]), 0.6)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- -Bu[j]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- exp(quantile(diff(log(yInSample[otLogical])), 0.6))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- exp(quantile(diff(log(yInSample[otLogical])), 0.4))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Failsafe for weird cases, when upper bound is the same or lower than the lower one\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (Bu[j] <= Bl[j]) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- switch(Etype,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m = -Inf,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m = 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m )\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Failsafe for cases, when the B is outside of bounds\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (B[j] <= Bl[j]) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- switch(Etype,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m = -Inf,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m = 0\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m )\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (B[j] >= Bu[j]) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m } else \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # if(Etype==\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)\u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # B[j]*1.01 is needed to make sure that the bounds cover the initial value\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- max(abs(yInSample[otLogical]), abs(B[j]) * 1.01)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- -Bu[j]\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # else\u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Bu[j] <- 1.5;\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Bl[j] <- 0.1;\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # If this is just a constant\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m # Add lambda if it is needed\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m if (otherParameterEstimate) \u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m j[] <- j + 1\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m B[j] <- other\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m names(B)[j] <- \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mother\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bl[j] <- 1e-10\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Bu[j] <- Inf\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m }\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m return(list(B = B, Bl = Bl, Bu = Bu))\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m}\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m# Updated initialiser function call\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43minitialiser_result <- initialiser(\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m yInSample = y_in_sample,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m etsModel = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Etype = \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Ttype = \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mN\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m Stype = \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mN\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m modelIsTrendy = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m modelIsSeasonal = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m componentsNumberETSNonSeasonal = 1,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m componentsNumberETSSeasonal = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m componentsNumberETS = 1,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m lags = 1,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m lagsModel = 1,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m lagsModelSeasonal = 1,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m lagsModelARIMA = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m lagsModelMax = 1,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m matVt = matVt, # Replace with actual matrix if available\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceLevelEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceTrendEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceSeasonalEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m persistenceXregEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m phiEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialType = \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43moptimal\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialLevelEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialTrendEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialSeasonalEstimate = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialArimaEstimate = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialXregEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m arimaModel = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m arRequired = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m maRequired = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m arEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m maEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m arOrders = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m maOrders = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m componentsNumberARIMA = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m componentsNamesARIMA = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m initialArimaNumber = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregModel = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregNumber = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregParametersEstimated = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m xregParametersPersistence = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m constantEstimate = TRUE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m constantName = \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mconstant\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m otherParameterEstimate = FALSE,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m bounds = \u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43musual\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m iOrders = 0,\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m other = NULL\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/smooth/python/.venv/lib/python3.8/site-packages/IPython/core/interactiveshell.py:2478\u001b[0m, in \u001b[0;36mInteractiveShell.run_cell_magic\u001b[0;34m(self, magic_name, line, cell)\u001b[0m\n\u001b[1;32m 2476\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbuiltin_trap:\n\u001b[1;32m 2477\u001b[0m args \u001b[38;5;241m=\u001b[39m (magic_arg_s, cell)\n\u001b[0;32m-> 2478\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2480\u001b[0m \u001b[38;5;66;03m# The code below prevents the output from being displayed\u001b[39;00m\n\u001b[1;32m 2481\u001b[0m \u001b[38;5;66;03m# when using magics with decodator @output_can_be_silenced\u001b[39;00m\n\u001b[1;32m 2482\u001b[0m \u001b[38;5;66;03m# when the last Python token in the expression is a ';'.\u001b[39;00m\n\u001b[1;32m 2483\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(fn, magic\u001b[38;5;241m.\u001b[39mMAGIC_OUTPUT_CAN_BE_SILENCED, \u001b[38;5;28;01mFalse\u001b[39;00m):\n", + "File \u001b[0;32m~/smooth/python/.venv/lib/python3.8/site-packages/rpy2/ipython/rmagic.py:984\u001b[0m, in \u001b[0;36mRMagics.R\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n\u001b[1;32m 982\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m e\u001b[38;5;241m.\u001b[39mstdout\u001b[38;5;241m.\u001b[39mendswith(e\u001b[38;5;241m.\u001b[39merr):\n\u001b[1;32m 983\u001b[0m \u001b[38;5;28mprint\u001b[39m(e\u001b[38;5;241m.\u001b[39merr)\n\u001b[0;32m--> 984\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 985\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 986\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdevice \u001b[38;5;129;01min\u001b[39;00m DEVICES_STATIC:\n", + "File \u001b[0;32m~/smooth/python/.venv/lib/python3.8/site-packages/rpy2/ipython/rmagic.py:949\u001b[0m, in \u001b[0;36mRMagics.R\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n\u001b[1;32m 947\u001b[0m return_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 948\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 949\u001b[0m text_result, result, visible \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43meval\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcode\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 950\u001b[0m text_output \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m text_result\n\u001b[1;32m 951\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m visible:\n", + "File \u001b[0;32m~/smooth/python/.venv/lib/python3.8/site-packages/rpy2/ipython/rmagic.py:413\u001b[0m, in \u001b[0;36mRMagics.eval\u001b[0;34m(self, code)\u001b[0m\n\u001b[1;32m 410\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (ri\u001b[38;5;241m.\u001b[39membedded\u001b[38;5;241m.\u001b[39mRRuntimeError, \u001b[38;5;167;01mValueError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m exception:\n\u001b[1;32m 411\u001b[0m \u001b[38;5;66;03m# Otherwise next return seems to have copy of error.\u001b[39;00m\n\u001b[1;32m 412\u001b[0m warning_or_other_msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mflush()\n\u001b[0;32m--> 413\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m RInterpreterError(code, \u001b[38;5;28mstr\u001b[39m(exception),\n\u001b[1;32m 414\u001b[0m warning_or_other_msg)\n\u001b[1;32m 415\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 416\u001b[0m ro\u001b[38;5;241m.\u001b[39m_print_deferred_warnings()\n", + "\u001b[0;31mRInterpreterError\u001b[0m: Failed to parse and evaluate line '\\ninitialiser <- function(yInSample,\\n etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal,\\n componentsNumberETSNonSeasonal, componentsNumberETSSeasonal, componentsNumberETS,\\n lags, lagsModel, lagsModelSeasonal, lagsModelARIMA, lagsModelMax,\\n matVt,\\n # persistence values\\n persistenceEstimate, persistenceLevelEstimate, persistenceTrendEstimate,\\n persistenceSeasonalEstimate, persistenceXregEstimate,\\n # initials\\n phiEstimate, initialType, initialEstimate,\\n initialLevelEstimate, initialTrendEstimate, initialSeasonalEstimate,\\n initialArimaEstimate, initialXregEstimate,\\n # ARIMA elements\\n arimaModel, arRequired, maRequired, arEstimate, maEstimate, arOrders, maOrders,\\n componentsNumberARIMA, componentsNamesARIMA, initialArimaNumber,\\n # Explanatory variables\\n xregModel, xregNumber,\\n xregParametersEstimated, xregParametersPersistence,\\n # Constant and other stuff\\n constantEstimate, constantName, otherParameterEstimate,\\n # Additional parameters\\n bounds, iOrders, other){\\n # The vector of logicals for persistence elements\\n persistenceEstimateVector <- c(\\n persistenceLevelEstimate, modelIsTrendy & persistenceTrendEstimate,\\n modelIsSeasonal & persistenceSeasonalEstimate\\n )\\n\\n # The order:\\n # Persistence of states and for xreg, phi, AR and MA parameters, initials, initialsARIMA, initials for xreg\\n B <- Bl <- Bu <- vector(\\n \"numeric\",\\n # Values of the persistence vector + phi\\n etsModel * (persistenceLevelEstimate + modelIsTrendy * persistenceTrendEstimate +\\n modelIsSeasonal * sum(persistenceSeasonalEstimate) + phiEstimate) +\\n xregModel * persistenceXregEstimate * max(xregParametersPersistence) +\\n # AR and MA values\\n arimaModel * (arEstimate * sum(arOrders) + maEstimate * sum(maOrders)) +\\n # initials of ETS\\n etsModel * all(initialType != c(\"complete\", \"backcasting\")) *\\n (initialLevelEstimate +\\n (modelIsTrendy * initialTrendEstimate) +\\n (modelIsSeasonal * sum(initialSeasonalEstimate * (lagsModelSeasonal - 1)))) +\\n # initials of ARIMA\\n all(initialType != c(\"complete\", \"backcasting\")) * arimaModel * initialArimaNumber * initialArimaEstimate +\\n # initials of xreg\\n (initialType != \"complete\") * xregModel * initialXregEstimate * sum(xregParametersEstimated) +\\n constantEstimate + otherParameterEstimate\\n )\\n\\n j <- 0\\n if (etsModel) {\\n # Fill in persistence\\n if (persistenceEstimate && any(persistenceEstimateVector)) {\\n if (any(c(Etype, Ttype, Stype) == \"M\")) {\\n # A special type of model which is not safe: AAM, MAA, MAM\\n if ((Etype == \"A\" && Ttype == \"A\" && Stype == \"M\") || (Etype == \"A\" && Ttype == \"M\" && Stype == \"A\") ||\\n (any(initialType == c(\"complete\", \"backcasting\")) &&\\n ((Etype == \"M\" && Ttype == \"A\" && Stype == \"A\") || (Etype == \"M\" && Ttype == \"A\" && Stype == \"M\")))) {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.01, 0, rep(0, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n }\\n # MMA is the worst. Set everything to zero and see if anything can be done...\\n else if ((Etype == \"M\" && Ttype == \"M\" && Stype == \"A\")) {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0, 0, rep(0, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n } else if (Etype == \"M\" && Ttype == \"A\") {\\n if (any(initialType == c(\"complete\", \"backcasting\"))) {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.1, 0, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n } else {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.2, 0.01, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n }\\n } else if (Etype == \"M\" && Ttype == \"M\") {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.1, 0.05, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n } else {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.1, 0.05, rep(0.05, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n }\\n } else {\\n B[1:sum(persistenceEstimateVector)] <-\\n c(0.1, 0.05, rep(0.11, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\\n }\\n if (bounds == \"usual\") {\\n Bl[1:sum(persistenceEstimateVector)] <- rep(0, sum(persistenceEstimateVector))\\n Bu[1:sum(persistenceEstimateVector)] <- rep(1, sum(persistenceEstimateVector))\\n } else {\\n Bl[1:sum(persistenceEstimateVector)] <- rep(-5, sum(persistenceEstimateVector))\\n Bu[1:sum(persistenceEstimateVector)] <- rep(5, sum(persistenceEstimateVector))\\n }\\n # Names for B\\n if (persistenceLevelEstimate) {\\n j[] <- j + 1\\n names(B)[j] <- \"alpha\"\\n }\\n if (modelIsTrendy && persistenceTrendEstimate) {\\n j[] <- j + 1\\n names(B)[j] <- \"beta\"\\n }\\n if (modelIsSeasonal && any(persistenceSeasonalEstimate)) {\\n if (componentsNumberETSSeasonal > 1) {\\n names(B)[j + c(1:sum(persistenceSeasonalEstimate))] <-\\n paste0(\"gamma\", c(1:componentsNumberETSSeasonal))\\n } else {\\n names(B)[j + 1] <- \"gamma\"\\n }\\n j[] <- j + sum(persistenceSeasonalEstimate)\\n }\\n }\\n }\\n\\n # Persistence if xreg is provided\\n if (xregModel && persistenceXregEstimate) {\\n xregPersistenceNumber <- max(xregParametersPersistence)\\n B[j + 1:xregPersistenceNumber] <- rep(switch(Etype,\\n \"A\" = 0.01,\\n \"M\" = 0\\n ), xregPersistenceNumber)\\n Bl[j + 1:xregPersistenceNumber] <- rep(-5, xregPersistenceNumber)\\n Bu[j + 1:xregPersistenceNumber] <- rep(5, xregPersistenceNumber)\\n names(B)[j + 1:xregPersistenceNumber] <- paste0(\"delta\", c(1:xregPersistenceNumber))\\n j[] <- j + xregPersistenceNumber\\n }\\n\\n # Damping parameter\\n if (etsModel && phiEstimate) {\\n j[] <- j + 1\\n B[j] <- 0.95\\n names(B)[j] <- \"phi\"\\n Bl[j] <- 0\\n Bu[j] <- 1\\n }\\n\\n # ARIMA parameters (AR / MA)\\n if (arimaModel) {\\n # These are filled in lags-wise\\n if (any(c(arEstimate, maEstimate))) {\\n acfValues <- rep(-0.1, maOrders %*% lags)\\n pacfValues <- rep(0.1, arOrders %*% lags)\\n # If this is ETS + ARIMA model or no differences model, then don\\'t bother with initials\\n # The latter does not make sense because of non-stationarity in ACF / PACF\\n # Otherwise use ACF / PACF values as starting parameters for ARIMA\\n if (!(etsModel || all(iOrders == 0))) {\\n yDifferenced <- yInSample\\n # If the model has differences, take them\\n if (any(iOrders > 0)) {\\n for (i in 1:length(iOrders)) {\\n if (iOrders[i] > 0) {\\n yDifferenced <- diff(yDifferenced, lag = lags[i], differences = iOrders[i])\\n }\\n }\\n }\\n # Do ACF/PACF initialisation only for non-seasonal models\\n if (all(lags <= 1)) {\\n if (maRequired && maEstimate) {\\n # If the sample is smaller than lags, it will be substituted by default values\\n acfValues[1:min(maOrders %*% lags, length(yDifferenced) - 1)] <-\\n acf(yDifferenced, lag.max = max(1, maOrders %*% lags), plot = FALSE)$acf[-1]\\n }\\n if (arRequired && arEstimate) {\\n # If the sample is smaller than lags, it will be substituted by default values\\n pacfValues[1:min(arOrders %*% lags, length(yDifferenced) - 1)] <-\\n pacf(yDifferenced, lag.max = max(1, arOrders %*% lags), plot = FALSE)$acf\\n }\\n }\\n }\\n for (i in 1:length(lags)) {\\n if (arRequired && arEstimate && arOrders[i] > 0) {\\n if (all(!is.nan(pacfValues[c(1:arOrders[i]) * lags[i]]))) {\\n B[j + c(1:arOrders[i])] <- pacfValues[c(1:arOrders[i]) * lags[i]]\\n } else {\\n B[j + c(1:arOrders[i])] <- 0.1\\n }\\n if (sum(B[j + c(1:arOrders[i])]) > 1) {\\n B[j + c(1:arOrders[i])] <- B[j + c(1:arOrders[i])] / sum(B[j + c(1:arOrders[i])]) - 0.01\\n }\\n # B[j+c(1:arOrders[i])] <- rep(0.1,arOrders[i]);\\n Bl[j + c(1:arOrders[i])] <- -5\\n Bu[j + c(1:arOrders[i])] <- 5\\n names(B)[j + 1:arOrders[i]] <- paste0(\"phi\", 1:arOrders[i], \"[\", lags[i], \"]\")\\n j[] <- j + arOrders[i]\\n }\\n if (maRequired && maEstimate && maOrders[i] > 0) {\\n if (all(!is.nan(acfValues[c(1:maOrders[i]) * lags[i]]))) {\\n B[j + c(1:maOrders[i])] <- acfValues[c(1:maOrders[i]) * lags[i]]\\n } else {\\n B[j + c(1:maOrders[i])] <- 0.1\\n }\\n if (sum(B[j + c(1:maOrders[i])]) > 1) {\\n B[j + c(1:maOrders[i])] <- B[j + c(1:maOrders[i])] / sum(B[j + c(1:maOrders[i])]) - 0.01\\n }\\n # B[j+c(1:maOrders[i])] <- rep(-0.1,maOrders[i]);\\n Bl[j + c(1:maOrders[i])] <- -5\\n Bu[j + c(1:maOrders[i])] <- 5\\n names(B)[j + 1:maOrders[i]] <- paste0(\"theta\", 1:maOrders[i], \"[\", lags[i], \"]\")\\n j[] <- j + maOrders[i]\\n }\\n }\\n }\\n }\\n\\n # Initials\\n if (etsModel && all(initialType != c(\"complete\", \"backcasting\")) && initialEstimate) {\\n if (initialLevelEstimate) {\\n j[] <- j + 1\\n B[j] <- matVt[1, 1]\\n names(B)[j] <- \"level\"\\n if (Etype == \"A\") {\\n Bl[j] <- -Inf\\n Bu[j] <- Inf\\n } else {\\n Bl[j] <- 0\\n Bu[j] <- Inf\\n }\\n }\\n if (modelIsTrendy && initialTrendEstimate) {\\n j[] <- j + 1\\n B[j] <- matVt[2, 1]\\n names(B)[j] <- \"trend\"\\n if (Ttype == \"A\") {\\n Bl[j] <- -Inf\\n Bu[j] <- Inf\\n } else {\\n Bl[j] <- 0\\n # 2 is already too much for the multiplicative model\\n Bu[j] <- 2\\n }\\n }\\n if (modelIsSeasonal && any(initialSeasonalEstimate)) {\\n if (componentsNumberETSSeasonal > 1) {\\n for (k in 1:componentsNumberETSSeasonal) {\\n if (initialSeasonalEstimate[k]) {\\n # -1 is needed in order to remove the redundant seasonal element (normalisation)\\n B[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <-\\n matVt[componentsNumberETSNonSeasonal + k, 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1]\\n names(B)[j + 2:(lagsModel[componentsNumberETSNonSeasonal + k]) - 1] <-\\n paste0(\"seasonal\", k, \"_\", 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1)\\n if (Stype == \"A\") {\\n Bl[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- -Inf\\n Bu[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- Inf\\n } else {\\n Bl[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- 0\\n Bu[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- Inf\\n }\\n j[] <- j + (lagsModelSeasonal[k] - 1)\\n }\\n }\\n } else {\\n # -1 is needed in order to remove the redundant seasonal element (normalisation)\\n B[j + 2:(lagsModel[componentsNumberETS]) - 1] <- matVt[componentsNumberETS, 2:lagsModel[componentsNumberETS] - 1]\\n names(B)[j + 2:(lagsModel[componentsNumberETS]) - 1] <- paste0(\"seasonal_\", 2:lagsModel[componentsNumberETS] - 1)\\n if (Stype == \"A\") {\\n Bl[j + 2:(lagsModel[componentsNumberETS]) - 1] <- -Inf\\n Bu[j + 2:(lagsModel[componentsNumberETS]) - 1] <- Inf\\n } else {\\n Bl[j + 2:(lagsModel[componentsNumberETS]) - 1] <- 0\\n Bu[j + 2:(lagsModel[componentsNumberETS]) - 1] <- Inf\\n }\\n j[] <- j + (lagsModel[componentsNumberETS] - 1)\\n }\\n }\\n }\\n print(xregParametersEstimated)\\n # ARIMA initials\\n if (all(initialType != c(\"complete\", \"backcasting\")) && arimaModel && initialArimaEstimate) {\\n B[j + 1:initialArimaNumber] <- head(matVt[componentsNumberETS + componentsNumberARIMA, 1:lagsModelMax], initialArimaNumber)\\n names(B)[j + 1:initialArimaNumber] <- paste0(\"ARIMAState\", 1:initialArimaNumber)\\n if (Etype == \"A\") {\\n Bl[j + 1:initialArimaNumber] <- -Inf\\n Bu[j + 1:initialArimaNumber] <- Inf\\n } else {\\n # Make sure that ARIMA states are positive to avoid errors\\n B[j + 1:initialArimaNumber] <- abs(B[j + 1:initialArimaNumber])\\n Bl[j + 1:initialArimaNumber] <- 0\\n Bu[j + 1:initialArimaNumber] <- Inf\\n }\\n j[] <- j + initialArimaNumber\\n }\\n\\n # Initials of the xreg\\n if (initialType != \"complete\" && initialXregEstimate) {\\n xregNumberToEstimate <- sum(xregParametersEstimated)\\n B[j + 1:xregNumberToEstimate] <- matVt[componentsNumberETS + componentsNumberARIMA +\\n which(xregParametersEstimated == 1), 1]\\n names(B)[j + 1:xregNumberToEstimate] <- rownames(matVt)[componentsNumberETS + componentsNumberARIMA +\\n which(xregParametersEstimated == 1)]\\n if (Etype == \"A\") {\\n Bl[j + 1:xregNumberToEstimate] <- -Inf\\n Bu[j + 1:xregNumberToEstimate] <- Inf\\n } else {\\n Bl[j + 1:xregNumberToEstimate] <- -Inf\\n Bu[j + 1:xregNumberToEstimate] <- Inf\\n }\\n j[] <- j + xregNumberToEstimate\\n }\\n\\n if (constantEstimate) {\\n j[] <- j + 1\\n B[j] <- matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, 1]\\n names(B)[j] <- constantName\\n if (etsModel || sum(iOrders) != 0) {\\n if (Etype == \"A\") {\\n Bu[j] <- quantile(diff(yInSample[otLogical]), 0.6)\\n Bl[j] <- -Bu[j]\\n } else {\\n Bu[j] <- exp(quantile(diff(log(yInSample[otLogical])), 0.6))\\n Bl[j] <- exp(quantile(diff(log(yInSample[otLogical])), 0.4))\\n }\\n\\n # Failsafe for weird cases, when upper bound is the same or lower than the lower one\\n if (Bu[j] <= Bl[j]) {\\n Bu[j] <- Inf\\n Bl[j] <- switch(Etype,\\n \"A\" = -Inf,\\n \"M\" = 0\\n )\\n }\\n\\n # Failsafe for cases, when the B is outside of bounds\\n if (B[j] <= Bl[j]) {\\n Bl[j] <- switch(Etype,\\n \"A\" = -Inf,\\n \"M\" = 0\\n )\\n }\\n if (B[j] >= Bu[j]) {\\n Bu[j] <- Inf\\n }\\n } else {\\n # if(Etype==\"A\"){\\n # B[j]*1.01 is needed to make sure that the bounds cover the initial value\\n Bu[j] <- max(abs(yInSample[otLogical]), abs(B[j]) * 1.01)\\n Bl[j] <- -Bu[j]\\n # }\\n # else{\\n # Bu[j] <- 1.5;\\n # Bl[j] <- 0.1;\\n # }\\n # If this is just a constant\\n }\\n }\\n\\n # Add lambda if it is needed\\n if (otherParameterEstimate) {\\n j[] <- j + 1\\n B[j] <- other\\n names(B)[j] <- \"other\"\\n Bl[j] <- 1e-10\\n Bu[j] <- Inf\\n }\\n\\n return(list(B = B, Bl = Bl, Bu = Bu))\\n\\n}\\n\\n\\n# Updated initialiser function call\\ninitialiser_result <- initialiser(\\n yInSample = y_in_sample,\\n etsModel = TRUE,\\n Etype = \"A\",\\n Ttype = \"N\",\\n Stype = \"N\",\\n modelIsTrendy = FALSE,\\n modelIsSeasonal = FALSE,\\n componentsNumberETSNonSeasonal = 1,\\n componentsNumberETSSeasonal = 0,\\n componentsNumberETS = 1,\\n lags = 1,\\n lagsModel = 1,\\n lagsModelSeasonal = 1,\\n lagsModelARIMA = 0,\\n lagsModelMax = 1,\\n matVt = matVt, # Replace with actual matrix if available\\n persistenceEstimate = TRUE,\\n persistenceLevelEstimate = TRUE,\\n persistenceTrendEstimate = TRUE,\\n persistenceSeasonalEstimate = TRUE,\\n persistenceXregEstimate = TRUE,\\n phiEstimate = TRUE,\\n initialType = \"optimal\",\\n initialEstimate = TRUE,\\n initialLevelEstimate = TRUE,\\n initialTrendEstimate = TRUE,\\n initialSeasonalEstimate = FALSE,\\n initialArimaEstimate = FALSE,\\n initialXregEstimate = TRUE,\\n arimaModel = FALSE,\\n arRequired = FALSE,\\n maRequired = FALSE,\\n arEstimate = TRUE,\\n maEstimate = TRUE,\\n arOrders = 0,\\n maOrders = 0,\\n componentsNumberARIMA = 0,\\n componentsNamesARIMA = 0,\\n initialArimaNumber = 0,\\n xregModel = FALSE,\\n xregNumber = 0,\\n xregParametersEstimated = 0,\\n xregParametersPersistence = 0,\\n constantEstimate = TRUE,\\n constantName = \"constant\",\\n otherParameterEstimate = FALSE,\\n bounds = \"usual\",\\n iOrders = 0,\\n other = NULL\\n)\\n'.\nR error message: 'Error in B[j + 1:xregNumberToEstimate] <- matVt[componentsNumberETS + : \\n replacement has length zero'" + ] + } + ], + "source": [ + "%%R -i y_in_sample \n", + "\n", + "initialiser <- function(yInSample,\n", + " etsModel, Etype, Ttype, Stype, modelIsTrendy, modelIsSeasonal,\n", + " componentsNumberETSNonSeasonal, componentsNumberETSSeasonal, componentsNumberETS,\n", + " lags, lagsModel, lagsModelSeasonal, lagsModelARIMA, lagsModelMax,\n", + " matVt,\n", + " # persistence values\n", + " persistenceEstimate, persistenceLevelEstimate, persistenceTrendEstimate,\n", + " persistenceSeasonalEstimate, persistenceXregEstimate,\n", + " # initials\n", + " phiEstimate, initialType, initialEstimate,\n", + " initialLevelEstimate, initialTrendEstimate, initialSeasonalEstimate,\n", + " initialArimaEstimate, initialXregEstimate,\n", + " # ARIMA elements\n", + " arimaModel, arRequired, maRequired, arEstimate, maEstimate, arOrders, maOrders,\n", + " componentsNumberARIMA, componentsNamesARIMA, initialArimaNumber,\n", + " # Explanatory variables\n", + " xregModel, xregNumber,\n", + " xregParametersEstimated, xregParametersPersistence,\n", + " # Constant and other stuff\n", + " constantEstimate, constantName, otherParameterEstimate,\n", + " # Additional parameters\n", + " bounds, iOrders, other){\n", + " # The vector of logicals for persistence elements\n", + " persistenceEstimateVector <- c(\n", + " persistenceLevelEstimate, modelIsTrendy & persistenceTrendEstimate,\n", + " modelIsSeasonal & persistenceSeasonalEstimate\n", + " )\n", + "\n", + " # The order:\n", + " # Persistence of states and for xreg, phi, AR and MA parameters, initials, initialsARIMA, initials for xreg\n", + " B <- Bl <- Bu <- vector(\n", + " \"numeric\",\n", + " # Values of the persistence vector + phi\n", + " etsModel * (persistenceLevelEstimate + modelIsTrendy * persistenceTrendEstimate +\n", + " modelIsSeasonal * sum(persistenceSeasonalEstimate) + phiEstimate) +\n", + " xregModel * persistenceXregEstimate * max(xregParametersPersistence) +\n", + " # AR and MA values\n", + " arimaModel * (arEstimate * sum(arOrders) + maEstimate * sum(maOrders)) +\n", + " # initials of ETS\n", + " etsModel * all(initialType != c(\"complete\", \"backcasting\")) *\n", + " (initialLevelEstimate +\n", + " (modelIsTrendy * initialTrendEstimate) +\n", + " (modelIsSeasonal * sum(initialSeasonalEstimate * (lagsModelSeasonal - 1)))) +\n", + " # initials of ARIMA\n", + " all(initialType != c(\"complete\", \"backcasting\")) * arimaModel * initialArimaNumber * initialArimaEstimate +\n", + " # initials of xreg\n", + " (initialType != \"complete\") * xregModel * initialXregEstimate * sum(xregParametersEstimated) +\n", + " constantEstimate + otherParameterEstimate\n", + " )\n", + "\n", + " j <- 0\n", + " if (etsModel) {\n", + " # Fill in persistence\n", + " if (persistenceEstimate && any(persistenceEstimateVector)) {\n", + " if (any(c(Etype, Ttype, Stype) == \"M\")) {\n", + " # A special type of model which is not safe: AAM, MAA, MAM\n", + " if ((Etype == \"A\" && Ttype == \"A\" && Stype == \"M\") || (Etype == \"A\" && Ttype == \"M\" && Stype == \"A\") ||\n", + " (any(initialType == c(\"complete\", \"backcasting\")) &&\n", + " ((Etype == \"M\" && Ttype == \"A\" && Stype == \"A\") || (Etype == \"M\" && Ttype == \"A\" && Stype == \"M\")))) {\n", + " B[1:sum(persistenceEstimateVector)] <-\n", + " c(0.01, 0, rep(0, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\n", + " }\n", + " # MMA is the worst. Set everything to zero and see if anything can be done...\n", + " else if ((Etype == \"M\" && Ttype == \"M\" && Stype == \"A\")) {\n", + " B[1:sum(persistenceEstimateVector)] <-\n", + " c(0, 0, rep(0, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\n", + " } else if (Etype == \"M\" && Ttype == \"A\") {\n", + " if (any(initialType == c(\"complete\", \"backcasting\"))) {\n", + " B[1:sum(persistenceEstimateVector)] <-\n", + " c(0.1, 0, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\n", + " } else {\n", + " B[1:sum(persistenceEstimateVector)] <-\n", + " c(0.2, 0.01, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\n", + " }\n", + " } else if (Etype == \"M\" && Ttype == \"M\") {\n", + " B[1:sum(persistenceEstimateVector)] <-\n", + " c(0.1, 0.05, rep(0.01, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\n", + " } else {\n", + " B[1:sum(persistenceEstimateVector)] <-\n", + " c(0.1, 0.05, rep(0.05, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\n", + " }\n", + " } else {\n", + " B[1:sum(persistenceEstimateVector)] <-\n", + " c(0.1, 0.05, rep(0.11, componentsNumberETSSeasonal))[which(persistenceEstimateVector)]\n", + " }\n", + " if (bounds == \"usual\") {\n", + " Bl[1:sum(persistenceEstimateVector)] <- rep(0, sum(persistenceEstimateVector))\n", + " Bu[1:sum(persistenceEstimateVector)] <- rep(1, sum(persistenceEstimateVector))\n", + " } else {\n", + " Bl[1:sum(persistenceEstimateVector)] <- rep(-5, sum(persistenceEstimateVector))\n", + " Bu[1:sum(persistenceEstimateVector)] <- rep(5, sum(persistenceEstimateVector))\n", + " }\n", + " # Names for B\n", + " if (persistenceLevelEstimate) {\n", + " j[] <- j + 1\n", + " names(B)[j] <- \"alpha\"\n", + " }\n", + " if (modelIsTrendy && persistenceTrendEstimate) {\n", + " j[] <- j + 1\n", + " names(B)[j] <- \"beta\"\n", + " }\n", + " if (modelIsSeasonal && any(persistenceSeasonalEstimate)) {\n", + " if (componentsNumberETSSeasonal > 1) {\n", + " names(B)[j + c(1:sum(persistenceSeasonalEstimate))] <-\n", + " paste0(\"gamma\", c(1:componentsNumberETSSeasonal))\n", + " } else {\n", + " names(B)[j + 1] <- \"gamma\"\n", + " }\n", + " j[] <- j + sum(persistenceSeasonalEstimate)\n", + " }\n", + " }\n", + " }\n", + "\n", + " # Persistence if xreg is provided\n", + " if (xregModel && persistenceXregEstimate) {\n", + " xregPersistenceNumber <- max(xregParametersPersistence)\n", + " B[j + 1:xregPersistenceNumber] <- rep(switch(Etype,\n", + " \"A\" = 0.01,\n", + " \"M\" = 0\n", + " ), xregPersistenceNumber)\n", + " Bl[j + 1:xregPersistenceNumber] <- rep(-5, xregPersistenceNumber)\n", + " Bu[j + 1:xregPersistenceNumber] <- rep(5, xregPersistenceNumber)\n", + " names(B)[j + 1:xregPersistenceNumber] <- paste0(\"delta\", c(1:xregPersistenceNumber))\n", + " j[] <- j + xregPersistenceNumber\n", + " }\n", + "\n", + " # Damping parameter\n", + " if (etsModel && phiEstimate) {\n", + " j[] <- j + 1\n", + " B[j] <- 0.95\n", + " names(B)[j] <- \"phi\"\n", + " Bl[j] <- 0\n", + " Bu[j] <- 1\n", + " }\n", + "\n", + " # ARIMA parameters (AR / MA)\n", + " if (arimaModel) {\n", + " # These are filled in lags-wise\n", + " if (any(c(arEstimate, maEstimate))) {\n", + " acfValues <- rep(-0.1, maOrders %*% lags)\n", + " pacfValues <- rep(0.1, arOrders %*% lags)\n", + " # If this is ETS + ARIMA model or no differences model, then don't bother with initials\n", + " # The latter does not make sense because of non-stationarity in ACF / PACF\n", + " # Otherwise use ACF / PACF values as starting parameters for ARIMA\n", + " if (!(etsModel || all(iOrders == 0))) {\n", + " yDifferenced <- yInSample\n", + " # If the model has differences, take them\n", + " if (any(iOrders > 0)) {\n", + " for (i in 1:length(iOrders)) {\n", + " if (iOrders[i] > 0) {\n", + " yDifferenced <- diff(yDifferenced, lag = lags[i], differences = iOrders[i])\n", + " }\n", + " }\n", + " }\n", + " # Do ACF/PACF initialisation only for non-seasonal models\n", + " if (all(lags <= 1)) {\n", + " if (maRequired && maEstimate) {\n", + " # If the sample is smaller than lags, it will be substituted by default values\n", + " acfValues[1:min(maOrders %*% lags, length(yDifferenced) - 1)] <-\n", + " acf(yDifferenced, lag.max = max(1, maOrders %*% lags), plot = FALSE)$acf[-1]\n", + " }\n", + " if (arRequired && arEstimate) {\n", + " # If the sample is smaller than lags, it will be substituted by default values\n", + " pacfValues[1:min(arOrders %*% lags, length(yDifferenced) - 1)] <-\n", + " pacf(yDifferenced, lag.max = max(1, arOrders %*% lags), plot = FALSE)$acf\n", + " }\n", + " }\n", + " }\n", + " for (i in 1:length(lags)) {\n", + " if (arRequired && arEstimate && arOrders[i] > 0) {\n", + " if (all(!is.nan(pacfValues[c(1:arOrders[i]) * lags[i]]))) {\n", + " B[j + c(1:arOrders[i])] <- pacfValues[c(1:arOrders[i]) * lags[i]]\n", + " } else {\n", + " B[j + c(1:arOrders[i])] <- 0.1\n", + " }\n", + " if (sum(B[j + c(1:arOrders[i])]) > 1) {\n", + " B[j + c(1:arOrders[i])] <- B[j + c(1:arOrders[i])] / sum(B[j + c(1:arOrders[i])]) - 0.01\n", + " }\n", + " # B[j+c(1:arOrders[i])] <- rep(0.1,arOrders[i]);\n", + " Bl[j + c(1:arOrders[i])] <- -5\n", + " Bu[j + c(1:arOrders[i])] <- 5\n", + " names(B)[j + 1:arOrders[i]] <- paste0(\"phi\", 1:arOrders[i], \"[\", lags[i], \"]\")\n", + " j[] <- j + arOrders[i]\n", + " }\n", + " if (maRequired && maEstimate && maOrders[i] > 0) {\n", + " if (all(!is.nan(acfValues[c(1:maOrders[i]) * lags[i]]))) {\n", + " B[j + c(1:maOrders[i])] <- acfValues[c(1:maOrders[i]) * lags[i]]\n", + " } else {\n", + " B[j + c(1:maOrders[i])] <- 0.1\n", + " }\n", + " if (sum(B[j + c(1:maOrders[i])]) > 1) {\n", + " B[j + c(1:maOrders[i])] <- B[j + c(1:maOrders[i])] / sum(B[j + c(1:maOrders[i])]) - 0.01\n", + " }\n", + " # B[j+c(1:maOrders[i])] <- rep(-0.1,maOrders[i]);\n", + " Bl[j + c(1:maOrders[i])] <- -5\n", + " Bu[j + c(1:maOrders[i])] <- 5\n", + " names(B)[j + 1:maOrders[i]] <- paste0(\"theta\", 1:maOrders[i], \"[\", lags[i], \"]\")\n", + " j[] <- j + maOrders[i]\n", + " }\n", + " }\n", + " }\n", + " }\n", + "\n", + " # Initials\n", + " if (etsModel && all(initialType != c(\"complete\", \"backcasting\")) && initialEstimate) {\n", + " if (initialLevelEstimate) {\n", + " j[] <- j + 1\n", + " B[j] <- matVt[1, 1]\n", + " names(B)[j] <- \"level\"\n", + " if (Etype == \"A\") {\n", + " Bl[j] <- -Inf\n", + " Bu[j] <- Inf\n", + " } else {\n", + " Bl[j] <- 0\n", + " Bu[j] <- Inf\n", + " }\n", + " }\n", + " if (modelIsTrendy && initialTrendEstimate) {\n", + " j[] <- j + 1\n", + " B[j] <- matVt[2, 1]\n", + " names(B)[j] <- \"trend\"\n", + " if (Ttype == \"A\") {\n", + " Bl[j] <- -Inf\n", + " Bu[j] <- Inf\n", + " } else {\n", + " Bl[j] <- 0\n", + " # 2 is already too much for the multiplicative model\n", + " Bu[j] <- 2\n", + " }\n", + " }\n", + " if (modelIsSeasonal && any(initialSeasonalEstimate)) {\n", + " if (componentsNumberETSSeasonal > 1) {\n", + " for (k in 1:componentsNumberETSSeasonal) {\n", + " if (initialSeasonalEstimate[k]) {\n", + " # -1 is needed in order to remove the redundant seasonal element (normalisation)\n", + " B[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <-\n", + " matVt[componentsNumberETSNonSeasonal + k, 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1]\n", + " names(B)[j + 2:(lagsModel[componentsNumberETSNonSeasonal + k]) - 1] <-\n", + " paste0(\"seasonal\", k, \"_\", 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1)\n", + " if (Stype == \"A\") {\n", + " Bl[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- -Inf\n", + " Bu[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- Inf\n", + " } else {\n", + " Bl[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- 0\n", + " Bu[j + 2:lagsModel[componentsNumberETSNonSeasonal + k] - 1] <- Inf\n", + " }\n", + " j[] <- j + (lagsModelSeasonal[k] - 1)\n", + " }\n", + " }\n", + " } else {\n", + " # -1 is needed in order to remove the redundant seasonal element (normalisation)\n", + " B[j + 2:(lagsModel[componentsNumberETS]) - 1] <- matVt[componentsNumberETS, 2:lagsModel[componentsNumberETS] - 1]\n", + " names(B)[j + 2:(lagsModel[componentsNumberETS]) - 1] <- paste0(\"seasonal_\", 2:lagsModel[componentsNumberETS] - 1)\n", + " if (Stype == \"A\") {\n", + " Bl[j + 2:(lagsModel[componentsNumberETS]) - 1] <- -Inf\n", + " Bu[j + 2:(lagsModel[componentsNumberETS]) - 1] <- Inf\n", + " } else {\n", + " Bl[j + 2:(lagsModel[componentsNumberETS]) - 1] <- 0\n", + " Bu[j + 2:(lagsModel[componentsNumberETS]) - 1] <- Inf\n", + " }\n", + " j[] <- j + (lagsModel[componentsNumberETS] - 1)\n", + " }\n", + " }\n", + " }\n", + " # ARIMA initials\n", + " if (all(initialType != c(\"complete\", \"backcasting\")) && arimaModel && initialArimaEstimate) {\n", + " B[j + 1:initialArimaNumber] <- head(matVt[componentsNumberETS + componentsNumberARIMA, 1:lagsModelMax], initialArimaNumber)\n", + " names(B)[j + 1:initialArimaNumber] <- paste0(\"ARIMAState\", 1:initialArimaNumber)\n", + " if (Etype == \"A\") {\n", + " Bl[j + 1:initialArimaNumber] <- -Inf\n", + " Bu[j + 1:initialArimaNumber] <- Inf\n", + " } else {\n", + " # Make sure that ARIMA states are positive to avoid errors\n", + " B[j + 1:initialArimaNumber] <- abs(B[j + 1:initialArimaNumber])\n", + " Bl[j + 1:initialArimaNumber] <- 0\n", + " Bu[j + 1:initialArimaNumber] <- Inf\n", + " }\n", + " j[] <- j + initialArimaNumber\n", + " }\n", + "\n", + " # Initials of the xreg\n", + " if (initialType != \"complete\" && initialXregEstimate) {\n", + " xregNumberToEstimate <- sum(xregParametersEstimated)\n", + " B[j + 1:xregNumberToEstimate] <- matVt[componentsNumberETS + componentsNumberARIMA +\n", + " which(xregParametersEstimated == 1), 1]\n", + " names(B)[j + 1:xregNumberToEstimate] <- rownames(matVt)[componentsNumberETS + componentsNumberARIMA +\n", + " which(xregParametersEstimated == 1)]\n", + " if (Etype == \"A\") {\n", + " Bl[j + 1:xregNumberToEstimate] <- -Inf\n", + " Bu[j + 1:xregNumberToEstimate] <- Inf\n", + " } else {\n", + " Bl[j + 1:xregNumberToEstimate] <- -Inf\n", + " Bu[j + 1:xregNumberToEstimate] <- Inf\n", + " }\n", + " j[] <- j + xregNumberToEstimate\n", + " }\n", + "\n", + " if (constantEstimate) {\n", + " j[] <- j + 1\n", + " B[j] <- matVt[componentsNumberETS + componentsNumberARIMA + xregNumber + 1, 1]\n", + " names(B)[j] <- constantName\n", + " if (etsModel || sum(iOrders) != 0) {\n", + " if (Etype == \"A\") {\n", + " Bu[j] <- quantile(diff(yInSample[otLogical]), 0.6)\n", + " Bl[j] <- -Bu[j]\n", + " } else {\n", + " Bu[j] <- exp(quantile(diff(log(yInSample[otLogical])), 0.6))\n", + " Bl[j] <- exp(quantile(diff(log(yInSample[otLogical])), 0.4))\n", + " }\n", + "\n", + " # Failsafe for weird cases, when upper bound is the same or lower than the lower one\n", + " if (Bu[j] <= Bl[j]) {\n", + " Bu[j] <- Inf\n", + " Bl[j] <- switch(Etype,\n", + " \"A\" = -Inf,\n", + " \"M\" = 0\n", + " )\n", + " }\n", + "\n", + " # Failsafe for cases, when the B is outside of bounds\n", + " if (B[j] <= Bl[j]) {\n", + " Bl[j] <- switch(Etype,\n", + " \"A\" = -Inf,\n", + " \"M\" = 0\n", + " )\n", + " }\n", + " if (B[j] >= Bu[j]) {\n", + " Bu[j] <- Inf\n", + " }\n", + " } else {\n", + " # if(Etype==\"A\"){\n", + " # B[j]*1.01 is needed to make sure that the bounds cover the initial value\n", + " Bu[j] <- max(abs(yInSample[otLogical]), abs(B[j]) * 1.01)\n", + " Bl[j] <- -Bu[j]\n", + " # }\n", + " # else{\n", + " # Bu[j] <- 1.5;\n", + " # Bl[j] <- 0.1;\n", + " # }\n", + " # If this is just a constant\n", + " }\n", + " }\n", + "\n", + " # Add lambda if it is needed\n", + " if (otherParameterEstimate) {\n", + " j[] <- j + 1\n", + " B[j] <- other\n", + " names(B)[j] <- \"other\"\n", + " Bl[j] <- 1e-10\n", + " Bu[j] <- Inf\n", + " }\n", + "\n", + " return(list(B = B, Bl = Bl, Bu = Bu))\n", + "\n", + "}\n", + "\n", + "\n", + "# Updated initialiser function call\n", + "initialiser_result <- initialiser(\n", + " yInSample = y_in_sample,\n", + " etsModel = TRUE,\n", + " Etype = \"A\",\n", + " Ttype = \"N\",\n", + " Stype = \"N\",\n", + " modelIsTrendy = FALSE,\n", + " modelIsSeasonal = FALSE,\n", + " componentsNumberETSNonSeasonal = 1,\n", + " componentsNumberETSSeasonal = 0,\n", + " componentsNumberETS = 1,\n", + " lags = 1,\n", + " lagsModel = 1,\n", + " lagsModelSeasonal = 1,\n", + " lagsModelARIMA = 0,\n", + " lagsModelMax = 1,\n", + " matVt = matVt, # Replace with actual matrix if available\n", + " persistenceEstimate = TRUE,\n", + " persistenceLevelEstimate = TRUE,\n", + " persistenceTrendEstimate = TRUE,\n", + " persistenceSeasonalEstimate = TRUE,\n", + " persistenceXregEstimate = TRUE,\n", + " phiEstimate = TRUE,\n", + " initialType = \"optimal\",\n", + " initialEstimate = TRUE,\n", + " initialLevelEstimate = TRUE,\n", + " initialTrendEstimate = TRUE,\n", + " initialSeasonalEstimate = FALSE,\n", + " initialArimaEstimate = FALSE,\n", + " initialXregEstimate = TRUE,\n", + " arimaModel = FALSE,\n", + " arRequired = FALSE,\n", + " maRequired = FALSE,\n", + " arEstimate = TRUE,\n", + " maEstimate = TRUE,\n", + " arOrders = 0,\n", + " maOrders = 0,\n", + " componentsNumberARIMA = 0,\n", + " componentsNamesARIMA = 0,\n", + " initialArimaNumber = 0,\n", + " xregModel = FALSE,\n", + " xregNumber = 0,\n", + " xregParametersEstimated = 0,\n", + " xregParametersPersistence = 0,\n", + " constantEstimate = TRUE,\n", + " constantName = \"constant\",\n", + " otherParameterEstimate = FALSE,\n", + " bounds = \"usual\",\n", + " iOrders = 0,\n", + " other = NULL\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/python/smooth/adam_general/tests_2.ipynb b/python/smooth/adam_general/tests_2.ipynb new file mode 100644 index 00000000..c3e6ef3d --- /dev/null +++ b/python/smooth/adam_general/tests_2.ipynb @@ -0,0 +1,127 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "from statsmodels.tsa.stattools import acf, pacf" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_acf(data, nlags=40):\n", + " \"\"\"\n", + " Calculate Autocorrelation Function for numpy array or pandas Series.\n", + " \n", + " Parameters:\n", + " data (np.array or pd.Series): Input time series data\n", + " nlags (int): Number of lags to calculate ACF for\n", + " \n", + " Returns:\n", + " np.array: ACF values\n", + " \"\"\"\n", + " if isinstance(data, pd.Series):\n", + " data = data.values\n", + " \n", + " return acf(data, nlags=nlags, fft=False)\n", + "\n", + "def calculate_pacf(data, nlags=40):\n", + " \"\"\"\n", + " Calculate Partial Autocorrelation Function for numpy array or pandas Series.\n", + " \n", + " Parameters:\n", + " data (np.array or pd.Series): Input time series data\n", + " nlags (int): Number of lags to calculate PACF for\n", + " \n", + " Returns:\n", + " np.array: PACF values\n", + " \"\"\"\n", + " if isinstance(data, pd.Series):\n", + " data = data.values\n", + " \n", + " return pacf(data, nlags=nlags, method='ols')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# Example usage\n", + "np.random.seed(42)\n", + "date_rng = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')\n", + "data = np.random.randn(len(date_rng)).cumsum() + 100\n", + "\n", + "# Create both numpy array and pandas Series\n", + "np_array = data\n", + "pd_series = pd.Series(data, index=date_rng)\n", + "\n", + "# Calculate ACF and PACF for numpy array\n", + "acf_values_np = calculate_acf(np_array)\n", + "pacf_values_np = calculate_pacf(np_array)\n", + "\n", + "# Calculate ACF and PACF for pandas Series\n", + "acf_values_pd = calculate_acf(pd_series)\n", + "pacf_values_pd = calculate_pacf(pd_series)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1. , 0.98020447, 0.96291875, 0.9463405 , 0.92780577,\n", + " 0.91353458, 0.89787089, 0.87908942, 0.85978813, 0.8416599 ,\n", + " 0.82210143, 0.80328791, 0.78346136, 0.76302172, 0.74567016,\n", + " 0.73017225, 0.71631451, 0.7022657 , 0.68757643, 0.67004954,\n", + " 0.65347832, 0.6397477 , 0.6274798 , 0.61489008, 0.60059905,\n", + " 0.5850292 , 0.57013909, 0.55543017, 0.54231908, 0.52999088,\n", + " 0.51743239, 0.50457837, 0.49134351, 0.47703597, 0.46376578,\n", + " 0.44944496, 0.43629551, 0.42195921, 0.41021392, 0.40102178,\n", + " 0.39067492])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "acf_values_np" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}