---
title: "es() - Exponential Smoothing"
author: "Ivan Svetunkov"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{es() - Exponential Smoothing}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r global_options, include=FALSE}
knitr::opts_chunk$set(fig.width=6, fig.height=4, fig.path='Figs/', fig.show='hold',
                      warning=FALSE, message=FALSE)
```

`es()` is a part of [smooth package](smooth.html). It allows constructing Exponential Smoothing (also known as ETS), selecting the most appropriate one among 30 possible ones, including exogenous variables and many more.

In this vignette we will use data from `Mcomp` package, so it is advised to install it. We also use some of the functions of the `greybox` package.

Let's load the necessary packages:
```{r load_libraries, message=FALSE, warning=FALSE}
require(Mcomp)
require(smooth)
require(greybox)
```

You may note that `Mcomp` depends on `forecast` package and if you load both `forecast` and `smooth`, then you will have a message that `forecast()` function is masked from the environment. There is nothing to be worried about - `smooth` uses this function for consistency purposes and has exactly the same original `forecast()` as in the `forecast` package. The inclusion of this function in `smooth` was done only in order not to include `forecast` in dependencies of the package.

The simplest call of this function is:

```{r es_N2457}
es(M3$N2457$x, h=18, holdout=TRUE, silent=FALSE)
```

In this case function uses branch and bound algorithm to form a pool of models to check and after that constructs a model with the lowest information criterion. As we can see, it also produces an output with brief information about the model, which contains:

1. How much time was elapsed for the model construction;
2. What type of ETS was selected;
3. Values of persistence vector (smoothing parameters);
4. What type of initialisation was used;
5. How many parameters were estimated (standard deviation is included);
6. Standard deviation of residuals. The model has multiplicative error term, so as a result the standard deviation is small.
7. Cost function type and the value of that cost function;
8. Information criteria for this model;
9. Forecast errors (because we have set `holdout=TRUE`).

The function has also produced a graph with actual values, fitted values and point forecasts.

If we need prediction interval, then we run:
```{r es_N2457_with_interval}
es(M3$N2457$x, h=18, holdout=TRUE, interval=TRUE, silent=FALSE)
```

Due to multiplicative nature of error term in the model, the interval are asymmetric. This is the expected behaviour. The other thing to note is that the output now also provides the theoretical width of prediction interval and its actual coverage.

If we save the model (and let's say we want it to work silently):
```{r es_N2457_save_model}
ourModel <- es(M3$N2457$x, h=18, holdout=TRUE, silent="all")
```

we can then reuse it for different purposes:
```{r es_N2457_reuse_model}
es(M3$N2457$x, model=ourModel, h=18, holdout=FALSE, interval="np", level=0.93)
```

We can also extract the type of model in order to reuse it later:
```{r es_N2457_modelType}
modelType(ourModel)
```

This handy function, by the way, also works with ets() from forecast package.

If we need actual values from the model, we can use `actuals()` method from `greybox` package:
```{r es_N2457_actuals}
actuals(ourModel)
```

We can then use persistence or initials only from the model to construct the other one:
```{r es_N2457_reuse_model_parts}
es(M3$N2457$x, model=modelType(ourModel), h=18, holdout=FALSE, initial=ourModel$initial, silent="graph")
es(M3$N2457$x, model=modelType(ourModel), h=18, holdout=FALSE, persistence=ourModel$persistence, silent="graph")
```
or provide some arbitrary values:
```{r es_N2457_set_initial}
es(M3$N2457$x, model=modelType(ourModel), h=18, holdout=FALSE, initial=1500, silent="graph")
```

Using some other parameters may lead to completely different model and forecasts:
```{r es_N2457_aMSTFE}
es(M3$N2457$x, h=18, holdout=TRUE, loss="aTMSE", bounds="a", ic="BIC", interval=TRUE)
```

You can play around with all the available parameters to see what's their effect on final model.

In order to combine forecasts we need to use "C" letter:
```{r es_N2457_combine}
es(M3$N2457$x, model="CCN", h=18, holdout=TRUE, silent="graph")
```

Model selection from a specified pool and forecasts combination are called using respectively:
```{r es_N2457_pool}
es(M3$N2457$x, model=c("ANN","AAN","AAdN","ANA","AAA","AAdA"), h=18, holdout=TRUE, silent="graph")
es(M3$N2457$x, model=c("CCC","ANN","AAN","AAdN","ANA","AAA","AAdA"), h=18, holdout=TRUE, silent="graph")
```

Now let's introduce some artificial exogenous variables:
```{r es_N2457_xreg_create}
x <- cbind(rnorm(length(M3$N2457$x),50,3),rnorm(length(M3$N2457$x),100,7))
```

and fit a model with all the exogenous first:
```{r es_N2457_xreg}
es(M3$N2457$x, model="ZZZ", h=18, holdout=TRUE, xreg=x)
```

or construct a model with selected exogenous (based on IC):
```{r es_N2457_xreg_select}
es(M3$N2457$x, model="ZZZ", h=18, holdout=TRUE, xreg=x, xregDo="select")
```

If we want to check if lagged x can be used for forecasting purposes, we can use `xregExpander()` function from `greybox` package:
```{r es_N2457_xreg_expanded_select}
es(M3$N2457$x, model="ZZZ", h=18, holdout=TRUE, xreg=xregExpander(x), xregDo="select")
```

If we are confused about the type of estimated model, the function `formula()` will help us:
```{r es_N2457_xreg_formula}
formula(ourModel)
```

A feature available since 2.1.0 is fitting `ets()` model and then using its parameters in `es()`:
```{r ets_es, message=FALSE, warning=FALSE}
etsModel <- forecast::ets(M3$N2457$x)
esModel <- es(M3$N2457$x, model=etsModel, h=18)
```

The point forecasts in the majority of cases should the same, but the prediction interval may be different (especially if error term is multiplicative):
```{r ets_es_forecast, message=FALSE, warning=FALSE}
forecast(etsModel,h=18,level=0.95)
forecast(esModel,h=18,level=0.95)
```

Finally, if you work with M or M3 data, and need to test a function on a specific time series, you can use the following simplified call:
```{r es_N2457_M3}
es(M3$N2457, interval=TRUE, silent=FALSE)
```

This command has taken the data, split it into in-sample and holdout and produced the forecast of appropriate length to the holdout.
