Introduction

In this project, we will look at data on GDP, exports, and population for the Central African Republic from 1960 to 2017. Throughout these years, the Central African Republic went through much political turmoil, such as the Central African Bush War in the mid-2000s and an important civil war starting in 2012. All this greatly affected the economy of the Central African Republic, reducing its main exports, like gold, timber, and diamonds. It also creates a lot of uncertainty in the data and makes it hard to collect accurate and consistent numbers, so different sources sometimes report very different export values for the same year. In this project, we analyze this data and try to predict the future. # Analysis

GDP

load("/Users/kirillburin/Downloads/Data_File_finalproject.Rdata")
data <- finalPro_data       
rm(finalPro_data)
library(ggplot2)
library(scales)

ggplot(data, aes(x = Year, y = GDP / 1e9)) +   # GDP in billions
  geom_line(color = "blue", size = 1) +
  labs(title = "GDP of Central African Republic (1960-2017)",
       x = "Year", 
       y = "GDP (Billions)") +
  scale_x_continuous(breaks = seq(1960, 2017, by = 10)) +  # 1960, 1970, ..., 2010
  scale_y_continuous(labels = number_format(accuracy = 0.01)) +
  theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

We can see a clear trend going up; we can see this time series variance does not look constant. Look at the drop near 1980 and compare it with the drop after 1990 and 2010. Let’s transform the series to stabilize its variance.

library(forecast)
summary(data$GDP)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 1.122e+08 3.057e+08 9.348e+08 9.394e+08 1.367e+09 2.196e+09
lambda_gdp <- BoxCox.lambda(data$GDP)
lambda_gdp   
## [1] -0.2054777
data$log_GDP <- log(data$GDP)
ggplot(data, aes(x = Year, y = log_GDP)) +
  geom_line(color = "blue", size = 1) +
  labs(title = "Log-Transformed GDP of Central African Republic (1960-2017)",
       x = "Year",
       y = "log(GDP)") +
  theme_minimal()

Because Box-Cox λ = -0.205 is close to 0 the transformation is similar to a log transformation, To keep the interpretation simple we use the log of GDP so we can think in terms of percent changes and we can see variance is more stable in the plot. We can definitely see that our time series is not stationary, we still have a strong trend, let’s remove it, by differencing.

library(dplyr)
library(ggplot2)


data_clean <- data %>%
  arrange(Year) %>%
  mutate(
    log_GDP  = log(GDP),
    dlog_GDP = log_GDP - lag(log_GDP)
  ) %>%
  filter(!is.na(dlog_GDP))


gdp_diff_ts <- ts(
  data_clean$dlog_GDP,
  start = data_clean$Year[1],  
  frequency = 1               
)


mean_dlog <- mean(data_clean$dlog_GDP, na.rm = TRUE)


ggplot(data_clean, aes(x = Year, y = dlog_GDP)) +
  geom_line() +
  geom_hline(yintercept = mean_dlog,
             linetype = "dashed",
             linewidth = 1) +
  labs(title = "Differenced Log GDP (CAR)",
       x = "Year",
       y = "Δ log(GDP)") +
  theme_minimal()

We de-trended the GDP time series by differencing the log of GDP, basically taking “this year’s GDP minus last year’s GDP in percent,” so that the differenced log GDP series shows the year to year percent change in GDP from 1960 to 2017. We already determined that the I part for Arima is 1. Let’s check for stationary:

par(mfrow = c(1, 2))


acf(gdp_diff_ts,
    main = "ACF of Differenced Log GDP")


pacf(gdp_diff_ts,
     main = "PACF of Differenced Log GDP")

par(mfrow = c(1, 1))

There are no strong spikes in the ACF and PACF of the differenced log GDP after lag 0, so there is little short-run dependence between today’s value and past values. Therefore, we use a small lag order (k = 0 or 1) in the ADF test.

adf.test(gdp_diff_ts, k = 0)
## Warning in adf.test(gdp_diff_ts, k = 0): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  gdp_diff_ts
## Dickey-Fuller = -7.1682, Lag order = 0, p-value = 0.01
## alternative hypothesis: stationary
adf.test(gdp_diff_ts, k = 1)
## Warning in adf.test(gdp_diff_ts, k = 1): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  gdp_diff_ts
## Dickey-Fuller = -4.713, Lag order = 1, p-value = 0.01
## alternative hypothesis: stationary

Following this, we performed an Augmented Dickey–Fuller test on the differences log GDP series with lag orders k = 0 and k = 1. In both cases the test statistics (−7.17 and −4.71) have p values smaller than 0.01, so we reject the null hypothesis of a unit root and conclude that the differences log GDP series is stationary. I concluded that no AR or MA terms are needed and chose an ARIMA(0,1,0) model.

library(forecast)


gdp_ts <- ts(data$GDP,
             start = min(data$Year),
             frequency = 1)


fit_010 <- Arima(log(gdp_ts),
                 order = c(0, 1, 0),
                 include.drift = TRUE)   # <-- no extra ')'

summary(fit_010)
## Series: log(gdp_ts) 
## ARIMA(0,1,0) with drift 
## 
## Coefficients:
##        drift
##       0.0501
## s.e.  0.0170
## 
## sigma^2 = 0.01683:  log likelihood = 36.05
## AIC=-68.11   AICc=-67.88   BIC=-64.02
## 
## Training set error measures:
##                       ME      RMSE        MAE         MPE      MAPE      MASE
## Training set 0.000318712 0.1274575 0.09047085 0.004393462 0.4412534 0.8522206
##                    ACF1
## Training set 0.04583777
par(mfrow = c(1, 2))
acf(residuals(fit_010), main = "ACF of residuals")
pacf(residuals(fit_010), main = "PACF of residuals")

par(mfrow = c(1, 1))

Box.test(residuals(fit_010), lag = 10, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  residuals(fit_010)
## X-squared = 5.2479, df = 10, p-value = 0.874

The ARIMA(0,1,0) model with drift fits our data well. The estimate for the drift term is around 0.05, which implies that GDP grew by about 5% per year on average. Moreover, this estimate is statistically significant since t ≈ 3, so we reject the hypothesis of zero average growth. Finally, the model with drift has both AIC and BIC smaller than the model without it, and therefore is better. As can be seen from the ACF and PACF of the residuals, we do not observe any significant spikes, which suggests that residuals are like white noise. The Box–Ljung test gives a p-value of 0.874, and thus we cannot reject the no-autocorrelation-inresiduals hypothesis.

library(ggplot2)


res <- residuals(fit_010)


res_df <- data.frame(res = res)

ggplot(res_df, aes(x = res)) +
  geom_histogram(aes(y = ..density..), bins = 20, color = "black", fill = "lightgray") +
  geom_density(linewidth = 1) +
  labs(title = "Density of ARIMA Residuals",
       x = "Residuals",
       y = "Density") +
  theme_minimal()
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Don't know how to automatically pick scale for object of type <ts>. Defaulting
## to continuous.

qqnorm(res, main = "QQ Plot of Residuals")
qqline(res, col = "red", lwd = 2)

The histogram and density plot from the ARIMA model seem like a bell curve shape and are focused around zero, and the QQ graph dots are very near the direct line. This means the residuals are probably spread out in a typical manner, so along with the Box–Ljung check, we handle them as regular random noise. We will make our predictions now.

library(forecast)
library(ggplot2)


gdp_ts <- ts(data$GDP,
             start = min(data$Year),
             frequency = 1)


fit_010 <- Arima(log(gdp_ts),
                 order = c(0, 1, 0),
                 include.drift = TRUE)


h <- 5   # change this if you want more/less years
fc_log <- forecast(fit_010, h = h)


plot(fc_log, main = "Forecast of log(GDP) with ARIMA(0,1,0) + drift")

log_mean  <- fc_log$mean
log_lower <- fc_log$lower[, "95%"]
log_upper <- fc_log$upper[, "95%"]

gdp_forecast <- data.frame(
  Year  = time(log_mean),
  GDP   = exp(as.numeric(log_mean)),
  Lower = exp(as.numeric(log_lower)),
  Upper = exp(as.numeric(log_upper))
)

gdp_forecast
##   Year        GDP      Lower      Upper
## 1 2018 2049554137 1589450450 2642845621
## 2 2019 2154840996 1504071613 3087179942
## 3 2020 2265536505 1458583098 3518932630
## 4 2021 2381918511 1432524631 3960515351
## 5 2022 2504279132 1418381640 4421527884

With the ARIMA(0,1,0) thing with drift on log(GDP), the guess says that log(GDP) – and so GDP too – should just keep going up bit by bit over those five years coming up. When we flip the guesses back to the normal GDP thing, the GDP they think will happen goes up from near 2.05 billion in 2018 to near 2.50 billion in 2022 (like the normal numbers we had). Those 95% guess zones are real big and get bigger when we look ahead more: like, in 2018 that zone is like 1.59–2.64 billion, but by 2022 it is like 1.42–4.42 billion. So, the model thinks GDP will keep growing okay, but it is not sure, and GDP could be way more or less than what it thinks, mostly later on.

ggplot(data, aes(x = Year, y = Exports)) +
  geom_line(color = "blue", linewidth = 1) +
  labs(title = "Central African Republic Exports (1960–2017)",
       x = "Year",
       y = "Exports") +
  theme_minimal()

data <- data %>%
  mutate(log_Exports = log(Exports))

Let’s do the same as we did for the GDP but with Exports.

ggplot(data, aes(x = Year, y = log_Exports)) +
  geom_line(color = "darkgreen", linewidth = 1) +
  labs(title = "Log of Central African Republic Exports (1960–2017)",
       x = "Year",
       y = "log(Exports)") +
  theme_minimal()

library(forecast)  


lambda_exp <- BoxCox.lambda(data$Exports)   
lambda_exp
## [1] -0.3650884
data <- data %>%
  mutate(Exports_bc = BoxCox(Exports, lambda_exp))

ggplot(data, aes(x = Year, y = Exports_bc)) +
  geom_line(color = "purple", linewidth = 1) +
  labs(title = paste0("Box–Cox Transformed Exports (λ = ", round(lambda_exp, 3), ")"),
       x = "Year",
       y = "Box–Cox(Exports)") +
  theme_minimal()

We attempted a Box–Cox transformation for Exports, and the result was -0.37. It is an ordinary log transform, but with a non linearity. Since the log transform is already a reliable tool for interpreting percentage changes, and it matches GDP , we decided to use log(Exports) in ARIMA analysis.

library(dplyr)
library(ggplot2)
library(tseries)


exp_clean <- data %>%
  arrange(Year) %>% 
  mutate(
    log_Exports  = log(Exports),
    dlog_Exports = log_Exports - lag(log_Exports)
  ) %>%
  filter(!is.na(dlog_Exports))   # drop the first NA from differencing


ggplot(exp_clean, aes(x = Year, y = dlog_Exports)) +
  geom_line() +
  labs(title = "Differenced Log Exports (CAR, 1961–2017)",
       x = "Year",
       y = "Δ log(Exports)") +
  theme_minimal()

exp_diff_ts <- ts(
  exp_clean$dlog_Exports,
  start = exp_clean$Year[1],
  frequency = 1
)


adf.test(exp_diff_ts, k = 1)
## Warning in adf.test(exp_diff_ts, k = 1): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  exp_diff_ts
## Dickey-Fuller = -8.0573, Lag order = 1, p-value = 0.01
## alternative hypothesis: stationary
adf.test(exp_diff_ts, k = 2)
## Warning in adf.test(exp_diff_ts, k = 2): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  exp_diff_ts
## Dickey-Fuller = -4.183, Lag order = 2, p-value = 0.01
## alternative hypothesis: stationary
par(mfrow = c(1, 2))
acf(exp_diff_ts,  main = "ACF of Δ log(Exports)")
pacf(exp_diff_ts, main = "PACF of Δ log(Exports)")

par(mfrow = c(1, 1))
exp_ts <- ts(data$Exports,
             start = min(data$Year),
             frequency = 1)


m010 <- Arima(log(exp_ts), order = c(3, 1, 0), include.drift = FALSE)  # like GDP model
m210 <- Arima(log(exp_ts), order = c(2, 1, 2), include.drift = FALSE)
m112 <- Arima(log(exp_ts), order = c(2, 1, 0), include.drift = FALSE)


BIC(m010, m210, m112) 
##      df       BIC
## m010  4 -69.34071
## m210  5 -66.76662
## m112  3 -69.71076
AIC(m010, m210, m112)
##      df       AIC
## m010  4 -77.51291
## m210  5 -76.98188
## m112  3 -75.83991
fit_exp <- m112   

summary(fit_exp)
## Series: log(exp_ts) 
## ARIMA(2,1,0) 
## 
## Coefficients:
##           ar1      ar2
##       -0.3816  -0.2829
## s.e.   0.1269   0.1255
## 
## sigma^2 = 0.01437:  log likelihood = 40.92
## AIC=-75.84   AICc=-75.39   BIC=-69.71
## 
## Training set error measures:
##                       ME      RMSE        MAE        MPE     MAPE      MASE
## Training set -0.01794603 0.1167409 0.08800061 -0.7426934 2.961359 0.8703288
##                    ACF1
## Training set 0.04665926
res_exp <- residuals(fit_exp)

par(mfrow = c(1, 2))
acf(res_exp,  main = "ACF of residuals (Exports)")
pacf(res_exp, main = "PACF of residuals (Exports)")

par(mfrow = c(1, 1))

Box.test(res_exp, lag = 10, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  res_exp
## X-squared = 10.117, df = 10, p-value = 0.4303
hist(res_exp,
     breaks = 10,
     freq   = FALSE,
     main   = "Density of Exports residuals",
     xlab   = "Residuals")
lines(density(res_exp))

# 2) QQ plot of residuals
qqnorm(res_exp, main = "QQ plot of Exports residuals")
qqline(res_exp)

par(mfrow = c(1, 1))

ARIMA(2,1,0) without drift is the optimal model because it has a low BIC, which penalizes big models and makes them easier to handle. The ADF test and ACF/PACF suggest a stationary series for exports, with some short-run dependence after taking logs and differencing. We tested different ARIMA models on log(Exports) and compared them using AIC and BIC. Due to its similar AIC and smallest BIC when compared to complex models, we settled on this simpler model of ARIMA(2,1,0) without drift.

library(forecast)


exp_ts <- ts(data$Exports,
             start = min(data$Year),
             frequency = 1)


fit_exp <- Arima(log(exp_ts),
                 order = c(2, 1, 0),
                 include.drift = FALSE)

summary(fit_exp)
## Series: log(exp_ts) 
## ARIMA(2,1,0) 
## 
## Coefficients:
##           ar1      ar2
##       -0.3816  -0.2829
## s.e.   0.1269   0.1255
## 
## sigma^2 = 0.01437:  log likelihood = 40.92
## AIC=-75.84   AICc=-75.39   BIC=-69.71
## 
## Training set error measures:
##                       ME      RMSE        MAE        MPE     MAPE      MASE
## Training set -0.01794603 0.1167409 0.08800061 -0.7426934 2.961359 0.8703288
##                    ACF1
## Training set 0.04665926
h <- 5
fc_exp <- forecast(fit_exp, h = h)


plot(fc_exp, main = "Forecast of log(Exports) with ARIMA(2,1,0)")

log_mean  <- fc_exp$mean
log_lower <- fc_exp$lower[,"95%"]
log_upper <- fc_exp$upper[,"95%"]

exp_mean  <- exp(as.numeric(log_mean))
exp_lower <- exp(as.numeric(log_lower))
exp_upper <- exp(as.numeric(log_upper))

exp_forecast <- data.frame(
  Year    = time(log_mean),
  Exports = exp_mean,
  Lower   = exp_lower,
  Upper   = exp_upper
)

exp_forecast   # table in original Exports units
##   Year  Exports    Lower    Upper
## 1 2018 12.56527 9.934078 15.89337
## 2 2019 12.60671 9.563594 16.61813
## 3 2020 12.57748 9.331630 16.95236
## 4 2021 12.57691 9.002211 17.57108
## 5 2022 12.58539 8.739669 18.12334
plot(exp_ts,
     xlim = c(start(exp_ts)[1], end(exp_ts)[1] + h),
     main = "Exports Forecast from ARIMA(2,1,0)",
     xlab = "Year", ylab = "Exports")

lines(ts(exp_mean,
         start = end(exp_ts)[1] + 1,
         frequency = 1),
      col = "blue")

lines(ts(exp_lower,
         start = end(exp_ts)[1] + 1,
         frequency = 1),
      col = "blue", lty = 2)

lines(ts(exp_upper,
         start = end(exp_ts)[1] + 1,
         frequency = 1),
      col = "blue", lty = 2)

For exports, we first took logs and calculated the year-to-year percentage changes. Then, we fitted an ARIMA(2,1,0) model on the log exports without drift. This model met all our checks. The AR terms are significant, the AIC and BIC values are good, and the residuals resemble white noise (Box-Ljung p ≈ 0.43). This shows it does not miss any clear pattern. When we forecast with this model and convert back to the original export scale, the forecast indicates that exports are expected to slightly decline over time. This trend aligns with the average change of about -1% per year observed in the data. The prediction bands widen in later years, indicating more uncertainty as we look further into the future. Overall, the model suggests that exports will remain at about the same level or slowly decrease.

library(dplyr)
library(ggplot2)
library(forecast)


data_pop <- data %>% arrange(Year)



ggplot(data_pop, aes(x = Year, y = Population / 1000)) +
  geom_line(color = "blue", linewidth = 1) +
  labs(title = "Population (level)",
       x = "Year",
       y = "Population (thousands)") +
  theme_minimal()

ggplot(data_pop, aes(x = Year, y = log(Population))) +
  geom_line(color = "darkgreen", linewidth = 1) +
  labs(title = "Log of Population",
       x = "Year", y = "log(Population)") +
  theme_minimal()

Even the population series seems to have quite stable variance visually, we still took the log of Population. The use of log(Population) makes the changes more understandable as percent changes, and it allows us to compare population growth directly with log(GDP) and log(Exports) as all the variables are now on the same scale.

Once the logs were taken, the population series appears to be even smoother and more stable, so it is definitely log(Population) that makes the most sense here and we can proceed with the next steps of the analysis.

library(ggplot2)
library(tseries)


pop_ts     <- ts(data$Population,
                 start = min(data$Year),
                 frequency = 1)
log_pop_ts <- log(pop_ts)


pop_diff2_ts <- diff(log_pop_ts, differences = 2)


pop_diff2_df <- data.frame(
  Year      = as.numeric(time(pop_diff2_ts)),   # years line up with the ts automatically
  ddlog_Pop = as.numeric(pop_diff2_ts)
)


ggplot(pop_diff2_df, aes(x = Year, y = ddlog_Pop)) +
  geom_line() +
  labs(title = "Second Difference of Log Population (CAR)",
       x = "Year",
       y = "Δ² log(Population)") +
  theme_minimal()

adf.test(pop_diff2_ts, k = 2)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  pop_diff2_ts
## Dickey-Fuller = -3.3896, Lag order = 2, p-value = 0.06657
## alternative hypothesis: stationary
adf.test(pop_diff2_ts, k = 3)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  pop_diff2_ts
## Dickey-Fuller = -3.2152, Lag order = 3, p-value = 0.09399
## alternative hypothesis: stationary
par(mfrow = c(1, 2))
acf(pop_diff2_ts,  main = "ACF of Δ² log(Pop)")
pacf(pop_diff2_ts, main = "PACF of Δ² log(Pop)")

par(mfrow = c(1, 1))

ADF test p-values for a second-differenced log population are about 0.07 and 0.09. These values are not below 0.05, so at a strict 5% level we very slightly fail to reject the null hypothesis of a unit root. However, they are very close to zero and both are below 0.10, so at a 10% significance level the null is rejected and the series is considered stationary. This is sufficient for our project to consider the second difference of log(Population) as approximately stationary, and therefore, we are allowed to proceed with fitting an ARIMA model, especially taking into account that ACF and PACF plots do not show a strong remaining trend.

library(forecast)


pop_ts <- ts(data$Population,
             start = min(data$Year),
             frequency = 1)


m020 <- Arima(log(pop_ts), order = c(0, 2, 0))  
m120 <- Arima(log(pop_ts), order = c(4, 2, 3))
m021 <- Arima(log(pop_ts), order = c(3, 2, 2))
m121 <- Arima(log(pop_ts), order = c(4, 2, 3))
m022 <- Arima(log(pop_ts), order = c(2, 2, 3))


AIC(m020, m120, m021, m121, m022)
##      df       AIC
## m020  1 -560.1506
## m120  8 -751.6507
## m021  6 -755.3660
## m121  8 -751.6507
## m022  6 -749.1095
BIC(m020, m120, m021, m121, m022)
##      df       BIC
## m020  1 -558.1252
## m120  8 -735.4479
## m021  6 -743.2139
## m121  8 -735.4479
## m022  6 -736.9574
fit_pop <- Arima(log(pop_ts), order = c(3, 2, 2))  # ARIMA(3,2,2) on log(Pop)

summary(fit_pop)
## Series: log(pop_ts) 
## ARIMA(3,2,2) 
## 
## Coefficients:
##         ar1     ar2      ar3     ma1     ma2
##       0.835  0.2800  -0.5642  1.6471  0.9780
## s.e.  0.135  0.2208   0.1423  0.0856  0.0856
## 
## sigma^2 = 7.961e-06:  log likelihood = 383.68
## AIC=-755.37   AICc=-753.65   BIC=-743.21
## 
## Training set error measures:
##                         ME        RMSE          MAE          MPE        MAPE
## Training set -0.0002248845 0.002645861 0.0006146597 -0.001568756 0.004261555
##                    MASE       ACF1
## Training set 0.03097708 -0.3309808
res_pop <- residuals(fit_pop)


par(mfrow = c(1, 2))
acf(res_pop,  main = "ACF of residuals (Pop)")
pacf(res_pop, main = "PACF of residuals (Pop)")

par(mfrow = c(1, 1))


Box.test(res_pop, lag = 10, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  res_pop
## X-squared = 6.7315, df = 10, p-value = 0.7505
qqnorm(res_pop, main = "QQ plot of Population residuals")
qqline(res_pop)

par(mfrow = c(1, 1))

The residual ACF shows only one small significant spike at lag 1, and the Box–Ljung test (p ≈ 0.75) does not reject the null of no autocorrelation. Overall, the residuals look like white noise, so the ARIMA(3,2,2) model for log(Population) seems reasonable.

library(forecast)


h <- 5
fc_pop <- forecast(fit_pop, h = h)


plot(fc_pop, main = "Forecast of log(Population) with ARIMA(3,2,2)")

log_mean  <- fc_pop$mean
log_lower <- fc_pop$lower[,"95%"]
log_upper <- fc_pop$upper[,"95%"]

pop_mean  <- exp(as.numeric(log_mean))
pop_lower <- exp(as.numeric(log_lower))
pop_upper <- exp(as.numeric(log_upper))

pop_forecast <- data.frame(
  Year       = time(log_mean),
  Population = pop_mean,
  Lower      = pop_lower,
  Upper      = pop_upper
)

pop_forecast
##   Year Population   Lower   Upper
## 1 2018    4735763 4709421 4762252
## 2 2019    4818981 4697464 4943642
## 3 2020    4902258 4581405 5245581
## 4 2021    4980582 4352612 5699151
## 5 2022    5051214 4030115 6331026

Interpritations

Based on these three different data sets, real GDP in the Central African Republic has been growing at a rate of about 5% per year on average. Our ARIMA model for log(GDP) also suggests that this upward trend will continue for the next few years with a lot of uncertainty regarding the exact trajectory. On the other hand, exports, after logging and differencing, have a slightly negative average change of about −1% per year and a mostly flat forecast, which means that recent and future GDP growth is less dependent on export expansion and more on domestic activities (services, government, aid, etc.).

The population is expected to keep growing but at a gradually declining rate, so income per capital can still increase. However, the country may be heavily relying on non-export sources of growth, which could be a risky situation if those sources were to weaken in the future.