data_624_hw06

Warning: package 'fpp3' was built under R version 4.4.3
── Attaching packages ──────────────────────────────────────────── fpp3 1.0.3 ──
✔ tibble      3.2.1     ✔ tsibble     1.2.0
✔ dplyr       1.1.4     ✔ tsibbledata 0.4.1
✔ tidyr       1.3.1     ✔ ggtime      1.0.0
✔ lubridate   1.9.4     ✔ feasts      0.5.0
✔ ggplot2     3.5.2     ✔ fable       0.5.0
Warning: package 'tsibble' was built under R version 4.4.3
Warning: package 'feasts' was built under R version 4.4.3
Warning: package 'fable' was built under R version 4.4.3
── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
✖ lubridate::date()    masks base::date()
✖ dplyr::filter()      masks stats::filter()
✖ tsibble::intersect() masks base::intersect()
✖ tsibble::interval()  masks lubridate::interval()
✖ dplyr::lag()         masks stats::lag()
✖ tsibble::setdiff()   masks base::setdiff()
✖ tsibble::union()     masks base::union()

9.1

a.

All three autocorrelation plots are consistent with white noise. The three figures all show autocorrelation plots for the random number sets that fluctuate around zero with no pattern. Each bar represents the correlation between the linear relationship of lagged values.

In each set less than 5% of the lags exceed the confidence interval. This is an acceptable amount of values that exceed that threshold and still have it be considered white noise. As the sample size increases, the autocorrelations fluctuate less around zero and the bounds become narrower.

b.

As the size of the sample sets gets larger, the 95% confidence threshold gets smaller because the larger sample size provides more precise estimates. The bounds are set by dividing the z-value of 1.96 by the square root of the length of the time series. The more samples in the set, the smaller the interval.

The autocorrelations are different in each figure because they are collections of random samples. Within each sample set there is no indication of autocorrelation, and since all sets are different the autocorrelations all differ. The larger sample size ensures less variation.

9.2

A plot of the Amazon closing stock price.

amzn <- gafa_stock |> 
  filter(Symbol == 'AMZN')

amzn |> autoplot(Close)

Stationary data will not have a trend or seasonality. While the Amazon closing stock price does not have seasonality, it does have a trend, indicating it is non-stationary.

The Amazon autocorrelation is plotted below.

amzn |> 
  ACF(Close) |> 
  autoplot()
Warning: Provided data has an irregular interval, results should be treated
with caution. Computing ACF by observation.

The Amazon closing stock price is non-stationary. For a stationary time series the ACF will drop to zero relatively quickly, the Amazon closing stock price decreases slowly, indicating non-stationary data.

The amazon partial-autocorrelation is plotted below.

amzn |> 
  PACF(Close) |> 
  autoplot()
Warning: Provided data has an irregular interval, results should be treated
with caution. Computing ACF by observation.

The PACF for the Amazon closing stock price shows a single spike at the first lag and then many much smaller spikes, this is consistent with a random-walk like process which is a type of non-stationary data.

9.3

a.

The Turkish GDP is plotted below.

turkish <- global_economy |> 
  filter(Country == 'Turkey')

turkish |> 
  autoplot(GDP)

It is a time series with a clear upward trend.

lambda <- turkish |> 
  features(GDP, features = guerrero) |> 
  pull(lambda_guerrero)

turkish_transformed <- turkish |> 
  mutate(gdp_boxcox = box_cox(GDP, lambda))

turkish_transformed |> 
  autoplot(gdp_boxcox) +
  labs(y = "GDP",
       x = "Year",
       title = paste0(
         "Box-Cox transformed Turkish GDP (Lambda = ",
         round(lambda, 3),
         ")"
       )
       )

The Turkish GDP is Box-Cox transformed with a Lambda of 0.157. This transformation has eliminated much of the inconsistencies of the variation in the GDP. There is still a trend but no other discernible pattern.

turkish_transformed |> 
  mutate(diff_GDP = difference(GDP)) |> 
  features(diff_GDP, unitroot_kpss)
# A tibble: 1 × 3
  Country kpss_stat kpss_pvalue
  <fct>       <dbl>       <dbl>
1 Turkey      0.386      0.0834

The unit root tests’ p-value indicates a value above 0.05 so the difference in the stationarity is not rejected.

turk_diffs <- turkish_transformed |> 
  mutate(diff_gdp_boxcox = difference(gdp_boxcox)) 

turk_diffs |>
  features(diff_gdp_boxcox, unitroot_kpss)
# A tibble: 1 × 3
  Country kpss_stat kpss_pvalue
  <fct>       <dbl>       <dbl>
1 Turkey     0.0889         0.1

The transformed data indicates the same as the un-transformed data. The p-value above 0.05 indicates that the null hypothesis should not be rejected and that the data is stationary.

turk_diffs |>
  features(gdp_boxcox, unitroot_ndiffs)
# A tibble: 1 × 2
  Country ndiffs
  <fct>    <int>
1 Turkey       1

When determining the differences, the calculation for differences to be applied to the Box-Cox transformed data is 1.

turk_diffs <- turk_diffs |> 
  mutate(
    gdp_boxcox_diff = difference(gdp_boxcox)
  )

turk_diffs |> autoplot(gdp_boxcox_diff) +
  labs(y = "Box-Cox Transformed and Differenced GDP Data",
       x = "Year",
       title = paste0(
         "Box-Cox Transformed anmd Differenced Turkish GDP",
         ")"
       )
  )
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).

The Box-Cox and differenced GDP data, when plotted, do not appear to have any pattern, trend, or seasonality any longer.

turk_diffs |> 
  ACF(gdp_boxcox_diff) |> 
  autoplot()

turk_diffs |> 
  PACF(gdp_boxcox_diff) |> 
  autoplot()

The ACF and PACF both show no correlation for the transformed and differrenced data.

The Turkish GDP data underwent a Box-Cox transformation, no seasonal differencing, and an ordinary differencing of 1.

b.

The State of Tasmania accommodation takings are plotted below.

take <- aus_accommodation |> 
  filter(State == 'Tasmania')

take |> 
  autoplot(Takings)

The takings data has a consistent upward trend and what appears to be a seasonal variation.

lambda <- take |> 
  features(Takings, features = guerrero) |> 
  pull(lambda_guerrero)

take_transformed <- take |> 
  mutate(take_boxcox = box_cox(Takings, lambda))

take_transformed |> 
  autoplot(take_boxcox) +
  labs(y = "Takings",
       x = "Quarter",
       title = paste0(
         "Box-Cox transformed Tasmanian Accommodations' Takings (Lambda = ",
         round(lambda, 3),
         ")"
       )
  )

The Tasmanian Accommodations’ Takings have had their variation made consistent by the Box-Cox transformation with a lambda of 0.002. The data still has a trend and seasonal variation.

take_transformed |> 
  mutate(diff_take = difference(Takings)) |> 
  features(diff_take, unitroot_kpss)
# A tibble: 1 × 3
  State    kpss_stat kpss_pvalue
  <chr>        <dbl>       <dbl>
1 Tasmania     0.231         0.1

The un-transformed data indicates that the data is stationary because the p-value is above 0.05.

take_diffs <- take_transformed |> 
  mutate(diff_take_boxcox = difference(take_boxcox)) 

take_diffs |>
  features(diff_take_boxcox, unitroot_kpss)
# A tibble: 1 × 3
  State    kpss_stat kpss_pvalue
  <chr>        <dbl>       <dbl>
1 Tasmania     0.258         0.1

The transformed data also indicates that the data is stationary because the p-value is above 0.05.

take_diffs |>
  features(take_boxcox, unitroot_ndiffs)
# A tibble: 1 × 2
  State    ndiffs
  <chr>     <int>
1 Tasmania      1

The calculation for the differences to be applied to the data is 1.

take_diffs <- take_diffs |> 
  mutate(
    take_boxcox_seasonal_diff = difference(take_boxcox, lag = 4),
    take_boxcox_diff = difference(take_boxcox),
    both_diff = difference(take_boxcox_seasonal_diff)
  )

take_diffs |> autoplot(take_boxcox_seasonal_diff) +
  labs(y = "Box-Cox Transformed and Seasonal Differenced Aus Accommodations Takings Data",
       x = "Year",
       title = paste0(
         "Box-Cox Transformed and Seasonal Differenced Aus Accommodations Takings GDP",
         ")"
       )
  )
Warning: Removed 4 rows containing missing values or values outside the scale range
(`geom_line()`).

take_diffs |> 
  ACF(take_boxcox_seasonal_diff) |> 
  autoplot()

The ACF plot of the transformed and seasonally differenced data indicates a sinsoidal curve.

take_diffs |>
  features(take_boxcox_seasonal_diff, unitroot_ndiffs)
# A tibble: 1 × 2
  State    ndiffs
  <chr>     <int>
1 Tasmania      0

After seasonal differencing, there is still an indication that ordinary differencing is needed.

take_diffs |> autoplot(both_diff) +
  labs(y = "Box-Cox Transformed and Differenced Aus Accommodations Takings Data",
       x = "Year",
       title = paste0(
         "Box-Cox Transformed anmd Differenced Aus Accommodations Takings GDP",
         ")"
       )
  )
Warning: Removed 5 rows containing missing values or values outside the scale range
(`geom_line()`).

The plot of the Takings data after Box-Cox transformation and both seasonal and ordinary differences are applied shows no more trend or seasonal variation.

The Tasmanian accommodations takings data underwent a Box-Cox transformation, a seasonally differencing of 1, and an ordinary differencing of 1.

c.

The souvenirs Sales data is plotted below.

souv <- souvenirs

souv |> autoplot(Sales)

The souvenirs Sales data shows an upward trend, a seasonal variation which peaks in December, and progressively increasing variation.

lambda <- souv |> 
  features(Sales, features = guerrero) |> 
  pull(lambda_guerrero)

souv_transformed <- souv |> 
  mutate(
    souv_boxcox = box_cox(Sales, lambda),
    souv_boxcox_seasonal_diff = difference(souv_boxcox, 12),
    souv_boxcox_both_diff = difference(souv_boxcox_seasonal_diff)
    )

souv_transformed |> 
  autoplot(souv_boxcox) +
  labs(y = "Sales",
       x = "Monthly",
       title = paste0(
         "Box-Cox transformed Souvenir Sales (Lambda = ",
         round(lambda, 3),
         ")"
       )
  )

The Box-Cox transformation has made the variation consistent using a lambda of 0.002. However the data still appears to have a trend and seasonal variation.

souv_transformed |> 
  autoplot(souv_boxcox_seasonal_diff) +
  labs(y = "Sales",
       x = "Monthly",
       title = paste0(
         "Box-Cox transformed Souvenir Sales (Lambda = ",
         round(lambda, 3),
         ")"
       )
  )
Warning: Removed 12 rows containing missing values or values outside the scale range
(`geom_line()`).

The plot of the Box-Cox transformed and seasonally differenced data no longer has a trend and has a cyclical variation but one that does not strictly appear seasonal.

souv_transformed |> 
  ACF(souv_boxcox_seasonal_diff) |> 
  autoplot()

The ACF indicates there are signs of autocorrelation in the lags and a sinosoidal curve.

souv_transformed |>
  features(souv_boxcox_seasonal_diff, unitroot_ndiffs)
# A tibble: 1 × 1
  ndiffs
   <int>
1      0

Unit root indicates that there is no need for an ordinary difference application.

The souvenir sales data underwent a Box-Cox transformation, as seasonal diferencing of 1, and no ordinary differencing.

9.5

# set the seed
set.seed(47)

# select the retail data
myseries <- aus_retail |> filter(`Series ID` == sample(aus_retail$`Series ID`, 1))

# plot the training data and the entire data
autoplot(myseries, Turnover)

The retail data has a trend, increasing variation over time, and a possible seasonal trend.

lambda <- myseries |> 
  features(Turnover, features = guerrero) |> 
  pull(lambda_guerrero)

myseries_transformed <- myseries |> 
  mutate(
    my_boxcox = box_cox(Turnover, lambda),
    my_boxcox_seasonal_diff = difference(my_boxcox, 12),
    my_boxcox_both_diff = difference(my_boxcox_seasonal_diff)
  )

myseries_transformed |> 
  autoplot(my_boxcox) +
  labs(y = "Box-Cox Transformed Turnover",
       x = "Month",
       title = paste0(
         "Box-Cox Transformed Retail Turnover (Lambda = ",
         round(lambda, 3),
         ")"
       )
  )

The Box-Cox transformation has made the variation consistent.

myseries_transformed |> 
  autoplot(my_boxcox_seasonal_diff) +
  labs(y = "Box-Cox Transformed and Seasonal Differenced Turnover",
       x = "Month",
       title = paste0(
         "Box-Cox Transformed and Seasonal Differenced Retail Turnover (Lambda = ",
         round(lambda, 3),
         ")"
       )
  )
Warning: Removed 12 rows containing missing values or values outside the scale range
(`geom_line()`).

The Box-Cox and seasonal differenced Retail Turnover data appears now to not have a notable trend or seasonal variation pattern.

myseries_transformed |>
  features(my_boxcox_seasonal_diff, unitroot_ndiffs)
# A tibble: 1 × 3
  State      Industry                                            ndiffs
  <chr>      <chr>                                                <int>
1 Queensland Clothing, footwear and personal accessory retailing      1

The unit root calculation indicates the the data needs an ordinary first differencing.

myseries_transformed |> 
  autoplot(my_boxcox_both_diff) +
  labs(y = "Box-Cox Transformed, Seasonal and Ordinary Differenced Turnover",
       x = "Month",
       title = paste0(
         "Box-Cox Transformed, Seasonal and Ordinary Differenced Retail Turnover (Lambda = ",
         round(lambda, 3),
         ")"
       )
  )
Warning: Removed 13 rows containing missing values or values outside the scale range
(`geom_line()`).

The retail turnover data now appears to have no trend or seasonality. After a Box-Cox transformation, a seasonal differencing, and an ordinary differencing the data appears to now be stationary.

9.6

a.

y <- numeric(100)
e <- rnorm(100)
for (i in 2:100) {
  y[i] <- 0.6 * y[i - 1] + e[i]
}
sim <- tsibble(idx = seq_len(100), y = y, index = idx)

autoplot(sim, y)

for (i in 2:100) {
  y[i] <- -0.9 * y[i - 1] + e[i]
}
sim1 <- tsibble(idx = seq_len(100), y = y, index = idx)

autoplot(sim1, y)

for (i in 2:100) {
  y[i] <- 0.9 * y[i - 1] + e[i]
}
sim2 <- tsibble(idx = seq_len(100), y = y, index = idx)

autoplot(sim2, y)

As \(\phi\) decreases the variation in the time series increases in its extremeness, as \(\phi\) increases the variation decreases.

c.

y <- numeric(100)
e <- rnorm(100)
for (i in 2:100) {
  y[i] <- e[i] + 0.6  * e[i-1]
}

tim <- tsibble(idx = seq_len(100), y = y, index = idx)

d.

autoplot(tim, y)

for (i in 2:100) {
  y[i] <- e[i] + -0.9  * e[i-1]
}

tim1 <- tsibble(idx = seq_len(100), y = y, index = idx)

autoplot(tim1, y)

for (i in 2:100) {
  y[i] <- e[i] + 0.9  * e[i-1]
}

tim2 <- tsibble(idx = seq_len(100), y = y, index = idx)

autoplot(tim2, y)

As \(\theta\) decreases, the extremeness of the variation increases. As \(\theta\) increases the extremeness of the variation decreases.

e.

y <- numeric(100)
e <- rnorm(100)
for (i in 2:100) {
  y[i] <- 0.6 * y[i - 1] + 0.6  * e[i-1] + e[i]
}

jim <- tsibble(idx = seq_len(100), y = y, index = idx)

autoplot(jim, y)

f. 

y <- numeric(100)
e <- rnorm(100)
for (i in 3:100) {
  y[i] <- (-0.8 * y[i - 1]) + 0.3 * y[i - 2] + e[i]
}
gim <- tsibble(idx = seq_len(100), y = y, index = idx)

autoplot(gim, y)

g.

The plot of the ARMA model in letter e. produces stationary data. There is no pattern of trend or seasonality.

The plot of AR2 shows a non-stationary pattern of progressively and dramatically increasing variation around zero.

9.7

a.

aus_airpassengers |> 
  autoplot(Passengers)

The plot of Australian air passengers shows a steady increasing trend over time with no signs seasonality or of variation changes, therefore a Box-Cox trasnformation will not be performed.

aus_airpassengers |> 
  gg_tsdisplay(difference(Passengers), plot_type = 'partial')
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

The differenced data now appears stationary. The PACF and ACF do not have any spikes beyond the interval boundaries.

air_fit <- aus_airpassengers |> 
  model(
    stepwise = ARIMA(Passengers),
    search = ARIMA(Passengers, stepwise = FALSE)
  )

air_fit 
# A mable: 1 x 2
        stepwise         search
         <model>        <model>
1 <ARIMA(0,2,1)> <ARIMA(0,2,1)>

The model that was selected was an ARIMA(0, 2, 1) model.

air_fit |> 
  select(search) |>
  gg_tsresiduals()

The ACF plot shows no residuals are outside the threshold limits, indicating that the residuals are behaving like white noise.

augment(air_fit) |> 
  filter(.model == 'search') |> 
  features(.innov, ljung_box, lag = 12, dof = 1)
# A tibble: 1 × 3
  .model lb_stat lb_pvalue
  <chr>    <dbl>     <dbl>
1 search    7.79     0.732

The high p-value also indicates that the residuals are behaving like white noise.

air_fit |>
  select(search) |> 
  forecast(h = 10) |> 
  autoplot(aus_airpassengers)

The forecast for the next ten periods shows an increasing trend over time.

b.

The equation written using the backshift operator is:

(1 - B)2*yt = (1 + \(\theta\) 1 B) \(\epsilon\) t

c.

Below, the models are fit for the remainder of the problem.

model_fit <- aus_airpassengers |> 
  model(
    ARIMA010 = ARIMA(Passengers ~ 1 + pdq(0, 1, 0)),
    ARIMA212 = ARIMA(Passengers ~ 1 + pdq(2, 1, 2)),
    ARIMA021 = ARIMA(Passengers ~ 1 + pdq(0, 2, 1))
  )
Warning: Model specification induces a quadratic or higher order polynomial trend.  This
is generally discouraged, consider removing the constant or reducing the number
of differences.
model_fit 
# A mable: 1 x 3
                 ARIMA010                ARIMA212               ARIMA021
                  <model>                 <model>                <model>
1 <ARIMA(0,1,0) w/ drift> <ARIMA(2,1,2) w/ drift> <ARIMA(0,2,1) w/ poly>
model_fit |> 
  forecast(h = 10) |> 
  filter(.model == "ARIMA010") |>
  autoplot(aus_airpassengers)

The trend upwards of the ARIMA010 model is similar to that of ARIMA021 in part A. However the trend increases at slightly lower rate. The forecast is essentially a straight line, like in part A, with little variation.

d.

model_fit |> 
  forecast(h = 10) |> 
  filter(.model == "ARIMA212") |>
  autoplot(aus_airpassengers)

The ARIMA212 model forecast shows a similar trend and rate of level increase as the ARIMA010 model. The ARIMA 212 model include variation in the forecast that the previous ARIMA models did not.

nodrift_fit <- aus_airpassengers |> 
  model(
    ARIMA212 = ARIMA(Passengers ~ 0 + pdq(2, 1, 2),
                     method = "ML")
  )

nodrift_fit |> 
  forecast(h = 10) |> 
  autoplot(aus_airpassengers)

With the constant removed the variation is less for the forecast but the rate of increase of the trend is higher.

e.

model_fit |> 
  forecast(h = 10) |> 
  filter(.model == "ARIMA021") |>
  autoplot(aus_airpassengers)

The ARIMA021 with constant forecast is very similar to the ARIMA212 without the constant, its rate of increase and lack of significant variation appear very similar or the same. The constant combined with the second differencing allows for quadratic forecast growth.

9.8

a.

usa <- global_economy |> 
  filter(Country == "United States") |> 
  select(Country, Code, Year, GDP)

autoplot(usa)
Plot variable not specified, automatically selected `.vars = GDP`

The plot of the United States GDP information does not show a significant change in variation during the course of the plot, therefore a Box-Cox may not be necessary. However, one is applied below:

lambda <- usa |> 
  features(GDP, features = guerrero) |> 
  pull(lambda_guerrero)

usa_transformed <- usa |> 
  mutate(
    usa_boxcox = box_cox(GDP, lambda)
  )

usa_transformed |> 
  autoplot(usa_boxcox) +
  labs(y = "Box-Cox Transformed USA GDP",
       x = "Year",
       title = paste0(
         "Box-Cox Transformed USA GDP (Lambda = ",
         round(lambda, 3),
         ")"
       )
  )

The transformation has made the plot of the data appear closer to linear.

b.

usa_fit <- usa_transformed |> 
  model(
    search = ARIMA(usa_boxcox, stepwise = FALSE)
  )

usa_fit
# A mable: 1 x 2
# Key:     Country [1]
  Country                        search
  <fct>                         <model>
1 United States <ARIMA(1,1,0) w/ drift>

The ARIMA search function returned an ARIMA(1, 1, 0) model with drift.

usa_fit |> 
  gg_tsresiduals()

The search model looks relatively good. However, the residuals do appear to have increasing variation over time, all ACF values are within the bounds of the interval, the histogram of the residuals approaches normal but is not normal and has a strong left skew.

c.

usa_test <- usa |> 
  model(
    no_boxcox = ARIMA(GDP, stepwise = FALSE)
  ) 

usa_test
# A mable: 1 x 2
# Key:     Country [1]
  Country            no_boxcox
  <fct>                <model>
1 United States <ARIMA(0,2,2)>

The data without a Box-Cox transformation yields the an ARIMA(0, 2, 2) model.

Below several models are fit for exploration.

usa_fit_2 <- usa_transformed |> 
  model(
    select = ARIMA(usa_boxcox),
    ARIMA112 = ARIMA(usa_boxcox ~ 1 + pdq(1, 1, 2)),
    ARIMA012 = ARIMA(usa_boxcox ~ 1 + pdq(0, 1, 2)),
    ARIMA011 = ARIMA(usa_boxcox ~ 1 + pdq(0, 1, 1)),
    ARIMA111 = ARIMA(usa_boxcox ~ 1 + pdq(1, 1, 1),
                     method = "ML")
  )
usa_fit_2 |>
  glance() |>
  select(.model, AICc) |>
  arrange(AICc)
# A tibble: 5 × 2
  .model    AICc
  <chr>    <dbl>
1 select    657.
2 ARIMA011  659.
3 ARIMA111  659.
4 ARIMA012  660.
5 ARIMA112  661.

According to the AICc scores the ARIMA(1, 1, 0) with drift model is the preferred model from the group.

usa_fit_2 |> 
  select("ARIMA112") |> 
  gg_tsresiduals()

The ARIMA(1, 1, 2) plot of residuals is similar to the ARIMA(1, 1, 0), the ACF has no values that extend past the bounds of the interval. The histogram is similar being left skewed.

usa_fit_2 |> 
  select("ARIMA011") |> 
  gg_tsresiduals()

The ARIMA(0, 1, 1) plot of residuals is similar to the ARIMA(1, 1, 0), the ACF has no values that extend past the bounds of the interval. The histogram is similar being left skewed but is closer to approaching normal.

usa_fit_2 |> 
  select("ARIMA012") |> 
  gg_tsresiduals()

The ARIMA(0, 1, 2) plot of residuals is similar to the ARIMA(1, 1, 0), the ACF has no values that extend past the bounds of the interval. The histogram is similar being left skewed but is closer to approaching normal.

usa_fit_2 |>
  select("ARIMA111") |> 
  gg_tsresiduals()

The ARIMA(1, 1, 1) plot of residuals is similar to the ARIMA(1, 1, 0), the ACF has no values that extend past the bounds of the interval. The histogram is similar being left skewed.

d.

As previously demonstrated the best model of this group based on the AICc was the ARIMA(1, 1, 0) with drift. Below is the residual plots:

usa_fit |> 
  gg_tsresiduals()

The search model looks relatively good. However, the residuals do appear to have increasing variation over time with a possible upward trend, all ACF values are within the bounds of the interval, the histogram of the residuals approaches but is not normal and has a strong left skew.

e.

The best model of this group is likely the select model of ARIMA(1,1,0) with drift.

usa_lambda <- lambda

usa_final <- usa |>
  model(
    ARIMA110 = ARIMA(
      box_cox(GDP, usa_lambda) ~ 1 + pdq(1, 1, 0)
    )
  )

usa_final |>
  forecast(h = 20) |>
  autoplot(usa)

The forecast appears reasonable. The forecast line and its intervals extend beyond the observed data at about the same slope as the observed data.

f.

usa_ets <- usa |> 
  model(
    ets = ETS(GDP)
  )

usa_ets |> report()
Series: GDP 
Model: ETS(M,A,N) 
  Smoothing parameters:
    alpha = 0.9990876 
    beta  = 0.5011949 

  Initial states:
         l[0]        b[0]
 448093333334 64917355687

  sigma^2:  7e-04

     AIC     AICc      BIC 
3190.787 3191.941 3201.089 
usa_ets |> 
  forecast(h = 20) |> 
  autoplot(usa)

When comparing the ARIMA(1, 1, 0) model and the ETS model, the ARIMA model forecast increases at a higher rate, however the prediction intervals of the ETS model indicate more uncertainty in the prediction interval.

usa_lambda <- lambda

usa_final <- usa |>
  model(
    ARIMA110 = ARIMA(
      box_cox(GDP, usa_lambda) ~ 1 + pdq(1, 1, 0)
    )
  )

usa_final |>
  forecast(h = 20) |>
  autoplot(usa)