# es() - Exponential Smoothing

#### Ivan Svetunkov

#### 2025-10-24

`es()` is a part of smooth package and is a wrapper for the ADAM function with `distribution="dnorm"`. It implements Exponential Smoothing in the ETS form, selecting the most appropriate model among 30 possible ones.

We will use some of the functions of the `greybox` package in this vignette for demonstrational purposes.

Let’s load the necessary packages:

    require(smooth)
    require(greybox)

The simplest call for the `es()` function is:

    ourModel <- es(BJsales, h=12, holdout=TRUE, silent=FALSE)

    ## Forming the pool of models based on... ANN , AAN , Estimation progress:    60 %80 %100 %... Done!

    ourModel

    ## Time elapsed: 0.07 seconds
    ## Model estimated using es() function: ETS(AAdN)
    ## With backcasting initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 237.6265
    ## Persistence vector g:
    ##  alpha   beta
    ## 0.9456 0.2965
    ## Damping parameter: 0.8795
    ## Sample size: 138
    ## Number of estimated parameters: 4
    ## Number of degrees of freedom: 134
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 483.2529 483.5537 494.9619 495.7029
    ##
    ## Forecast errors:
    ## ME: 2.818; MAE: 2.968; RMSE: 3.655
    ## sCE: 14.877%; Asymmetry: 88%; sMAE: 1.306%; sMSE: 0.026%
    ## MASE: 2.492; RMSSE: 2.383; rMAE: 0.958; rRMSE: 0.954

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. Cost function type and the value of that cost function;
7. Information criteria for this model;
8. 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 can use the `forecast()` method:

    plot(forecast(ourModel, h=12, interval="prediction"))

The same model can be reused for different purposes, for example to produce forecasts based on newly available data:

    es(BJsales, model=ourModel, h=12, holdout=FALSE)

    ## Time elapsed: 0 seconds
    ## Model estimated using es() function: ETS(AAdN)
    ## With provided initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 255.3652
    ## Persistence vector g:
    ##  alpha   beta
    ## 0.9456 0.2965
    ## Damping parameter: 0.8795
    ## Sample size: 150
    ## Number of estimated parameters: 1
    ## Number of degrees of freedom: 149
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 512.7303 512.7574 515.7410 515.8087

We can also extract the type of model in order to reuse it later:

    modelType(ourModel)

    ## [1] "AAdN"

This handy function also works with `ets()` from forecast package.

If we need actual values from the model, we can use `actuals()` method from `greybox` package:

    actuals(ourModel)

    ## Time Series:
    ## Start = 1
    ## End = 138
    ## Frequency = 1
    ##   [1] 200.1 199.5 199.4 198.9 199.0 200.2 198.6 200.0 200.3 201.2 201.6 201.5
    ##  [13] 201.5 203.5 204.9 207.1 210.5 210.5 209.8 208.8 209.5 213.2 213.7 215.1
    ##  [25] 218.7 219.8 220.5 223.8 222.8 223.8 221.7 222.3 220.8 219.4 220.1 220.6
    ##  [37] 218.9 217.8 217.7 215.0 215.3 215.9 216.7 216.7 217.7 218.7 222.9 224.9
    ##  [49] 222.2 220.7 220.0 218.7 217.0 215.9 215.8 214.1 212.3 213.9 214.6 213.6
    ##  [61] 212.1 211.4 213.1 212.9 213.3 211.5 212.3 213.0 211.0 210.7 210.1 211.4
    ##  [73] 210.0 209.7 208.8 208.8 208.8 210.6 211.9 212.8 212.5 214.8 215.3 217.5
    ##  [85] 218.8 220.7 222.2 226.7 228.4 233.2 235.7 237.1 240.6 243.8 245.3 246.0
    ##  [97] 246.3 247.7 247.6 247.8 249.4 249.0 249.9 250.5 251.5 249.0 247.6 248.8
    ## [109] 250.4 250.7 253.0 253.7 255.0 256.2 256.0 257.4 260.4 260.0 261.3 260.4
    ## [121] 261.6 260.8 259.8 259.0 258.9 257.4 257.7 257.9 257.4 257.3 257.6 258.9
    ## [133] 257.8 257.7 257.2 257.5 256.8 257.5

We can also use persistence or initials only from the model to construct the other one:

    # Provided initials
    es(BJsales, model=modelType(ourModel),
       h=12, holdout=FALSE,
       initial=ourModel$initial)

    ## Time elapsed: 0.01 seconds
    ## Model estimated using es() function: ETS(AAdN)
    ## With provided initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 255.3336
    ## Persistence vector g:
    ##  alpha   beta
    ## 0.9661 0.2933
    ## Damping parameter: 0.8757
    ## Sample size: 150
    ## Number of estimated parameters: 4
    ## Number of degrees of freedom: 146
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 518.6672 518.9431 530.7098 531.4009

    # Provided persistence
    es(BJsales, model=modelType(ourModel),
       h=12, holdout=FALSE,
       persistence=ourModel$persistence)

    ## Time elapsed: 0.01 seconds
    ## Model estimated using es() function: ETS(AAdN)
    ## With backcasting initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 255.3608
    ## Persistence vector g:
    ##  alpha   beta
    ## 0.9456 0.2965
    ## Damping parameter: 0.8743
    ## Sample size: 150
    ## Number of estimated parameters: 2
    ## Number of degrees of freedom: 148
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 514.7216 514.8032 520.7428 520.9474

or provide some arbitrary values:

    es(BJsales, model=modelType(ourModel),
       h=12, holdout=FALSE,
       initial=200)

    ## Time elapsed: 0.02 seconds
    ## Model estimated using es() function: ETS(AAdN)
    ## With provided initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 255.3602
    ## Persistence vector g:
    ## alpha  beta
    ## 0.964 0.295
    ## Damping parameter: 0.8745
    ## Sample size: 150
    ## Number of estimated parameters: 5
    ## Number of degrees of freedom: 145
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 520.7205 521.1371 535.7737 536.8175

Using some other parameters may lead to completely different model and forecasts (see discussion of the additional parameters in the online textbook about ADAM):

    es(BJsales, h=12, holdout=TRUE, loss="MSEh", bounds="a", ic="BIC")

    ## Time elapsed: 0.16 seconds
    ## Model estimated using es() function: ETS(AAN)
    ## With backcasting initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: MSEh; Loss function value: 93.4976
    ## Persistence vector g:
    ##  alpha   beta
    ## 1.5294 0.0057
    ##
    ## Sample size: 138
    ## Number of estimated parameters: 2
    ## Number of degrees of freedom: 136
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 1021.862 1021.951 1027.717 1027.936
    ##
    ## Forecast errors:
    ## ME: -0.85; MAE: 1.304; RMSE: 1.471
    ## sCE: -4.488%; Asymmetry: -65.2%; sMAE: 0.574%; sMSE: 0.004%
    ## MASE: 1.094; RMSSE: 0.959; rMAE: 0.421; rRMSE: 0.384

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

In order to combine forecasts we need to use “C” letter:

    es(BJsales, model="CCN", h=12, holdout=TRUE)

    ## Time elapsed: 0.16 seconds
    ## Model estimated: ETS(CCN)
    ## Loss function type: likelihood
    ##
    ## Number of models combined: 10
    ## Sample size: 138
    ## Average number of estimated parameters: 4.1651
    ## Average number of degrees of freedom: 133.8349
    ##
    ## Forecast errors:
    ## ME: 2.834; MAE: 2.982; RMSE: 3.673
    ## sCE: 14.961%; sMAE: 1.312%; sMSE: 0.026%
    ## MASE: 2.503; RMSSE: 2.394; rMAE: 0.962; rRMSE: 0.959

Model selection from a specified pool and forecasts combination are called using respectively:

    # Select the best model in the pool
    es(BJsales, model=c("ANN","AAN","AAdN","MNN","MAN","MAdN"),
       h=12, holdout=TRUE)

    ## Time elapsed: 0.06 seconds
    ## Model estimated using es() function: ETS(AAdN)
    ## With backcasting initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 237.6265
    ## Persistence vector g:
    ##  alpha   beta
    ## 0.9456 0.2965
    ## Damping parameter: 0.8795
    ## Sample size: 138
    ## Number of estimated parameters: 4
    ## Number of degrees of freedom: 134
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 483.2529 483.5537 494.9619 495.7029
    ##
    ## Forecast errors:
    ## ME: 2.818; MAE: 2.968; RMSE: 3.655
    ## sCE: 14.877%; Asymmetry: 88%; sMAE: 1.306%; sMSE: 0.026%
    ## MASE: 2.492; RMSSE: 2.383; rMAE: 0.958; rRMSE: 0.954

    # Combine the pool of models
    es(BJsales, model=c("CCC","ANN","AAN","AAdN","MNN","MAN","MAdN"),
       h=12, holdout=TRUE)

    ## Time elapsed: 0.07 seconds
    ## Model estimated: ETS(CCN)
    ## Loss function type: likelihood
    ##
    ## Number of models combined: 6
    ## Sample size: 138
    ## Average number of estimated parameters: 4.3115
    ## Average number of degrees of freedom: 133.6885
    ##
    ## Forecast errors:
    ## ME: 2.838; MAE: 2.985; RMSE: 3.677
    ## sCE: 14.983%; sMAE: 1.313%; sMSE: 0.026%
    ## MASE: 2.505; RMSSE: 2.397; rMAE: 0.963; rRMSE: 0.96

Now we introduce explanatory variable in ETS:

    x <- BJsales.lead

and fit an ETSX model with the exogenous variable first:

    es(BJsales, model="ZZZ", h=12, holdout=TRUE,
       xreg=x)

    ## Time elapsed: 0.42 seconds
    ## Model estimated using es() function: ETSX(AMdN)
    ## With backcasting initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 237.5191
    ## Persistence vector g (excluding xreg):
    ##  alpha   beta
    ## 0.9525 0.2876
    ## Damping parameter: 0.8784
    ## Sample size: 138
    ## Number of estimated parameters: 5
    ## Number of degrees of freedom: 133
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 485.0381 485.4927 499.6744 500.7942
    ##
    ## Forecast errors:
    ## ME: 2.88; MAE: 3.002; RMSE: 3.705
    ## sCE: 15.201%; Asymmetry: 90.1%; sMAE: 1.321%; sMSE: 0.027%
    ## MASE: 2.52; RMSSE: 2.415; rMAE: 0.968; rRMSE: 0.967

If we want to check if lagged x can be used for forecasting purposes, we can use `xregExpander()` function from `greybox` package:

    es(BJsales, model="ZZZ", h=12, holdout=TRUE,
       xreg=xregExpander(x), regressors="use")

    ## Time elapsed: 1.47 seconds
    ## Model estimated using es() function: ETSX(AMdN)
    ## With backcasting initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 236.465
    ## Persistence vector g (excluding xreg):
    ## alpha  beta
    ## 1.000 0.313
    ## Damping parameter: 0.8382
    ## Sample size: 138
    ## Number of estimated parameters: 7
    ## Number of degrees of freedom: 131
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 486.9301 487.7916 507.4208 509.5433
    ##
    ## Forecast errors:
    ## ME: 2.35; MAE: 2.848; RMSE: 3.347
    ## sCE: 12.406%; Asymmetry: 72.5%; sMAE: 1.253%; sMSE: 0.022%
    ## MASE: 2.391; RMSSE: 2.182; rMAE: 0.919; rRMSE: 0.874

We can also construct a model with selected exogenous (based on IC):

    es(BJsales, model="ZZZ", h=12, holdout=TRUE,
       xreg=xregExpander(x), regressors="select")

    ## Time elapsed: 1.04 seconds
    ## Model estimated using es() function: ETS(AMdN)
    ## With backcasting initialisation
    ## Distribution assumed in the model: Normal
    ## Loss function type: likelihood; Loss function value: 237.5686
    ## Persistence vector g:
    ##  alpha   beta
    ## 0.9453 0.2947
    ## Damping parameter: 0.8739
    ## Sample size: 138
    ## Number of estimated parameters: 4
    ## Number of degrees of freedom: 134
    ## Information criteria:
    ##      AIC     AICc      BIC     BICc
    ## 483.1371 483.4379 494.8461 495.5871
    ##
    ## Forecast errors:
    ## ME: 2.819; MAE: 2.97; RMSE: 3.657
    ## sCE: 14.882%; Asymmetry: 88%; sMAE: 1.306%; sMSE: 0.026%
    ## MASE: 2.493; RMSSE: 2.384; rMAE: 0.958; rRMSE: 0.954

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:

    es(Mcomp::M3$N2457, 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.