## 8.3 Methods with seasonality

Holt (1957) and Winters (1960) extended Holt’s method to capture seasonality. The Holt-Winters seasonal method comprises the forecast equation and three smoothing equations — one for the level \(\ell_t\), one for the trend \(b_t\), and one for the seasonal component \(s_t\), with corresponding smoothing parameters \(\alpha\), \(\beta^*\) and \(\gamma\). We use \(m\) to denote the frequency of the seasonality, i.e., the number of seasons in a year. For example, for quarterly data \(m=4\), and for monthly data \(m=12\).

There are two variations to this method that differ in the nature of the seasonal component. The additive method is preferred when the seasonal variations are roughly constant through the series, while the multiplicative method is preferred when the seasonal variations are changing proportional to the level of the series. With the additive method, the seasonal component is expressed in absolute terms in the scale of the observed series, and in the level equation the series is seasonally adjusted by subtracting the seasonal component. Within each year, the seasonal component will add up to approximately zero. With the multiplicative method, the seasonal component is expressed in relative terms (percentages), and the series is seasonally adjusted by dividing through by the seasonal component. Within each year, the seasonal component will sum up to approximately \(m\).

### Holt-Winters’ additive method

The component form for the additive method is: \[\begin{align*} \hat{y}_{t+h|t} &= \ell_{t} + hb_{t} + s_{t+h-m(k+1)} \\ \ell_{t} &= \alpha(y_{t} - s_{t-m}) + (1 - \alpha)(\ell_{t-1} + b_{t-1})\\ b_{t} &= \beta^*(\ell_{t} - \ell_{t-1}) + (1 - \beta^*)b_{t-1}\\ s_{t} &= \gamma (y_{t}-\ell_{t-1}-b_{t-1}) + (1-\gamma)s_{t-m}, \end{align*}\] where \(k\) is the integer part of \((h-1)/m\), which ensures that the estimates of the seasonal indices used for forecasting come from the final year of the sample. The level equation shows a weighted average between the seasonally adjusted observation \((y_{t} - s_{t-m})\) and the non-seasonal forecast \((\ell_{t-1}+b_{t-1})\) for time \(t\). The trend equation is identical to Holt’s linear method. The seasonal equation shows a weighted average between the current seasonal index, \((y_{t}-\ell_{t-1}-b_{t-1})\), and the seasonal index of the same season last year (i.e., \(m\) time periods ago).

The equation for the seasonal component is often expressed as \[ s_{t} = \gamma^* (y_{t}-\ell_{t})+ (1-\gamma^*)s_{t-m}. \] If we substitute \(\ell_t\) from the smoothing equation for the level of the component form above, we get \[ s_{t} = \gamma^*(1-\alpha) (y_{t}-\ell_{t-1}-b_{t-1})+ [1-\gamma^*(1-\alpha)]s_{t-m}, \] which is identical to the smoothing equation for the seasonal component we specify here, with \(\gamma=\gamma^*(1-\alpha)\). The usual parameter restriction is \(0\le\gamma^*\le1\), which translates to \(0\le\gamma\le 1-\alpha\).

### Holt-Winters’ multiplicative method

The component form for the multiplicative method is: \[\begin{align*} \hat{y}_{t+h|t} &= (\ell_{t} + hb_{t})s_{t+h-m(k+1)} \\ \ell_{t} &= \alpha \frac{y_{t}}{s_{t-m}} + (1 - \alpha)(\ell_{t-1} + b_{t-1})\\ b_{t} &= \beta^*(\ell_{t}-\ell_{t-1}) + (1 - \beta^*)b_{t-1} \\ s_{t} &= \gamma \frac{y_{t}}{(\ell_{t-1} + b_{t-1})} + (1 - \gamma)s_{t-m} \end{align*}\]

### Example: Domestic overnight trips in Australia

We apply Holt-Winters’ method with both additive and multiplicative seasonality to forecast quarterly visitor nights in Australia spent by domestic tourists. Figure 8.6 shows the data from 1998–2017, and the forecasts for 2018–2020. The data show an obvious seasonal pattern, with peaks observed in the March quarter of each year, corresponding to the Australian summer.

```
<- tourism %>%
aus_holidays filter(Purpose == "Holiday") %>%
summarise(Trips = sum(Trips)/1e3)
<- aus_holidays %>%
fit model(
additive = ETS(Trips ~ error("A") + trend("A") + season("A")),
multiplicative = ETS(Trips ~ error("M") + trend("A") + season("M"))
)<- fit %>% forecast(h = "3 years")
fc
%>%
fc autoplot(aus_holidays, level = NULL) + xlab("Year") +
ylab("Overnight trips (millions)") +
scale_color_brewer(type = "qual", palette = "Dark2")
```

Quarter | Time | Observation | Level | Slope | Season | Forecast |
---|---|---|---|---|---|---|

\(t\) | \(y_t\) | \(\ell_t\) | \(b_t\) | \(s_t\) | \(\hat{y}_{t+1\vert t}\) | |

1997 Q1 | 0 | 1.5 | ||||

1997 Q2 | 1 | -0.3 | ||||

1997 Q3 | 2 | -0.7 | ||||

1997 Q4 | 3 | 9.8 | 0.0 | -0.5 | ||

1998 Q1 | 4 | 11.8 | 9.9 | 0.0 | 1.5 | 11.3 |

1998 Q2 | 5 | 9.3 | 9.9 | 0.0 | -0.3 | 9.7 |

1998 Q3 | 6 | 8.6 | 9.7 | -0.0 | -0.7 | 9.2 |

1998 Q4 | 7 | 9.3 | 9.8 | 0.0 | -0.5 | 9.2 |

⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | |

2017 Q1 | 80 | 12.4 | 10.9 | 0.1 | 1.5 | 12.3 |

2017 Q2 | 81 | 10.5 | 10.9 | 0.1 | -0.3 | 10.7 |

2017 Q3 | 82 | 10.5 | 11.0 | 0.1 | -0.7 | 10.3 |

2017 Q4 | 83 | 11.2 | 11.3 | 0.1 | -0.5 | 10.6 |

\(h\) | \(\hat{y}_{T+h\vert T}\) | |||||

2018 Q1 | 1 | 12.9 | ||||

2018 Q2 | 2 | 11.2 | ||||

2018 Q3 | 3 | 11.0 | ||||

2018 Q4 | 4 | 11.2 | ||||

2019 Q1 | 5 | 13.4 | ||||

2019 Q2 | 6 | 11.7 | ||||

2019 Q3 | 7 | 11.5 | ||||

2019 Q4 | 8 | 11.7 | ||||

2020 Q1 | 9 | 13.9 | ||||

2020 Q2 | 10 | 12.2 | ||||

2020 Q3 | 11 | 11.9 | ||||

2020 Q4 | 12 | 12.2 |

Quarter | Time | Observation | Level | Slope | Season | Forecast |
---|---|---|---|---|---|---|

\(t\) | \(y_t\) | \(\ell_t\) | \(b_t\) | \(s_t\) | \(\hat{y}_{t+1\vert t}\) | |

1997 Q1 | 0 | 1.2 | ||||

1997 Q2 | 1 | 1.0 | ||||

1997 Q3 | 2 | 0.9 | ||||

1997 Q4 | 3 | 10.0 | -0.0 | 0.9 | ||

1998 Q1 | 4 | 11.8 | 10.0 | -0.0 | 1.2 | 11.6 |

1998 Q2 | 5 | 9.3 | 9.9 | -0.0 | 1.0 | 9.7 |

1998 Q3 | 6 | 8.6 | 9.8 | -0.0 | 0.9 | 9.2 |

1998 Q4 | 7 | 9.3 | 9.8 | -0.0 | 0.9 | 9.2 |

⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | |

2017 Q1 | 80 | 12.4 | 10.8 | 0.1 | 1.2 | 12.6 |

2017 Q2 | 81 | 10.5 | 10.9 | 0.1 | 1.0 | 10.6 |

2017 Q3 | 82 | 10.5 | 11.1 | 0.1 | 0.9 | 10.2 |

2017 Q4 | 83 | 11.2 | 11.3 | 0.1 | 0.9 | 10.5 |

\(h\) | \(\hat{y}_{T+h\vert T}\) | |||||

2018 Q1 | 1 | 13.3 | ||||

2018 Q2 | 2 | 11.2 | ||||

2018 Q3 | 3 | 10.8 | ||||

2018 Q4 | 4 | 11.1 | ||||

2019 Q1 | 5 | 13.8 | ||||

2019 Q2 | 6 | 11.7 | ||||

2019 Q3 | 7 | 11.3 | ||||

2019 Q4 | 8 | 11.6 | ||||

2020 Q1 | 9 | 14.4 | ||||

2020 Q2 | 10 | 12.2 | ||||

2020 Q3 | 11 | 11.7 | ||||

2020 Q4 | 12 | 12.1 |

The applications of both methods (with additive and multiplicative seasonality) are presented in Tables 8.3 and 8.4 respectively. Because both methods have exactly the same number of parameters to estimate, we can compare the training RMSE from both models. In this case, the method with multiplicative seasonality fits the data slightly better.

The estimated states for both models are plotted in Figure 8.7. The small value of \(\gamma\) for the multiplicative model means that the seasonal component hardly changes over time. The small value of \(\beta^{*}\) means the slope component hardly changes over time (compare the vertical scales of the slope and level components).

### Holt-Winters’ damped method

Damping is possible with both additive and multiplicative Holt-Winters’ methods. A method that often provides accurate and robust forecasts for seasonal data is the Holt-Winters method with a damped trend and multiplicative seasonality: \[\begin{align*} \hat{y}_{t+h|t} &= \left[\ell_{t} + (\phi+\phi^2 + \dots + \phi^{h})b_{t}\right]s_{t+h-m(k+1)}. \\ \ell_{t} &= \alpha(y_{t} / s_{t-m}) + (1 - \alpha)(\ell_{t-1} + \phi b_{t-1})\\ b_{t} &= \beta^*(\ell_{t} - \ell_{t-1}) + (1 - \beta^*)\phi b_{t-1} \\ s_{t} &= \gamma \frac{y_{t}}{(\ell_{t-1} + \phi b_{t-1})} + (1 - \gamma)s_{t-m}. \end{align*}\]

`ETS(y ~ error("M") + trend("Ad") + season("M"))`

### Example: Holt-Winters method with daily data

The Holt-Winters method can also be used for daily type of data, where the seasonal period is \(m=7\), and the appropriate unit of time for \(h\) is in days. Here we forecast pedestrian traffic at a busy Melbourne train station in July 2016.

```
<- pedestrian %>%
sth_cross_ped filter(
== "Southern Cross Station",
Sensor yearmonth(Date) == yearmonth("2016 July")
%>%
) index_by(Date) %>%
summarise(Count = sum(Count))
%>%
sth_cross_ped model(hw = ETS(Count ~ error("M") + trend("Ad") + season("M"))) %>%
forecast(h = "2 weeks") %>%
autoplot(sth_cross_ped)
```

Clearly the model has identified the weekly seasonal pattern and the increasing trend at the end of the data, and the forecasts are a close match to the test data.