Equipo #6:
knitr::opts_chunk$set(
echo = TRUE,
message = FALSE,
warning = FALSE
)
#install.packages("rnaturalearthhires", repos = "https://packages.ropensci.org")
#install.packages("devtools")
pacman::p_load(dplyr, ggplot2, naniar, tseries, corrplot, patchwork, readxl, psych, maps, sf, rnaturalearth, rnaturalearthdata, stringi, scales, dlookr, DataExplorer, tidyr, knitr, RColorBrewer, plotly, forecast, tseries, openxlsx, vars, lmtest)
Las bases de datos de series temporales contienen datos indexados en el tiempo. Permiten almacenar y realizar análisis de grandes cantidades de datos que se ubican en intervalos de tiempo y tienen una estructura regular. Los análisis de series de tiempo buscan enfocarse en el análisis de una principal variable para estudiar su pasado y poder predecir su futuro. Las BD se series de tiempo tienen 4 componentes principales: tendencia (patrón de la evolución de los datos), estacionalidad (variación de los datos en ciertas estaciones), ciclicidad (patrones de más de un año), aleatoriedad o variación irregular (factores que no pueden predecirse).
Mediante modelos estadísticos como ARMA, ARIMA, VAR se pueden identificar patrones en el comportamiento histórico de los nuevos flujos de inversión extranjera directa y se pueden realizar proyecciones futuras. Estas proyecciones facilitan la toma de decisiones estratégicas relacionadas con el crecimiento del nearshoring. Además, estos análisis permiten aceptar o rechazar hipótesis que facilitan comprender la situación actual y futura del nearshoring en México considerando variables macroeconómicas que influyen en este suceso.
library(openxlsx)
df <- read.xlsx("act3_data.xlsx", sheet = "time series data")
kable(head(df))
Year | Quarter | New_FDI_Inflows | Exchange_Rate | INPC | Exports |
---|---|---|---|---|---|
2006 | I | 896.5577 | 10.81770 | 60.77251 | 17374.67 |
2006 | II | 2110.3751 | 10.92880 | 60.64300 | 17908.74 |
2006 | III | 1284.0054 | 10.90631 | 61.73661 | 17504.90 |
2006 | IV | 2677.7047 | 10.91399 | 62.69242 | 17485.93 |
2007 | I | 3108.2192 | 10.93540 | 63.32911 | 18499.28 |
2007 | II | 2560.7016 | 10.89572 | 63.05817 | 19238.75 |
La BD contiene 5 variables: Year, Quarter, New_FDI_Inflows, Exchange_Rate, INPC y Exports. La variable principal de interés es New_FDI_Inflows que nos servirá como indicador del Nearshoring.
Asimismo, se observa que no hay valores nulos en la base de datos. De igual manera, se presentan únicamente dos valores negativos en la variable de New_FDI_Inflows, mientras que el resto de los datos son positivos.
# Nulos Totales
sum(is.na(df))
## [1] 0
# Nulos por Columna
gg_miss_var(df)
# Mostrar registros con nulos
kable(df[rowSums(is.na(df)) > 0, c(1, 2, ncol(df))])
Year | Quarter | Exports |
---|
Las variables nominales de New_FDI_Inflows y Exports se convirtieron a valores reales junto con la conversión a pesos para tener todos los campos en la misma moneda.
# Convertir a Pesos
df$New_FDI_Inflows<- (df$New_FDI_Inflows*df$Exchange_Rate)
df$Exports<- (df$Exports*df$Exchange_Rate)
# Convertir a Reales
df$New_FDI_Inflows<- (df$New_FDI_Inflows/df$INPC)*100
df$Exports<- (df$Exports/df$INPC)*100
clases1 <- sapply(df, class)
clases1
## Year Quarter New_FDI_Inflows Exchange_Rate INPC
## "numeric" "character" "numeric" "numeric" "numeric"
## Exports
## "numeric"
Los registros de la columna Quarter se modificaron a valores numéricos; mientras que los demás se mantuvieron en el mismo formato.
# Conversión de tipo de datos
library(dplyr)
df <- df %>%
mutate(Quarter = recode(Quarter, "I" = 1, "II" = 2, "III" = 3, "IV" = 4))
df$Quarter<-as.numeric(df$Quarter)
clases2 <- sapply(df, class)
clases2
## Year Quarter New_FDI_Inflows Exchange_Rate INPC
## "numeric" "numeric" "numeric" "numeric" "numeric"
## Exports
## "numeric"
Se observa que hay más valores atípicos en la variable de interés New_FDI_Inflows; sin embargo, estos outliers no se eliminarán con el fin de representar la relalidad de esa variable en el tiempo.
par(mfrow = c(2, 2)) # 2 filas, 2 columnas (ajusta según la cantidad de variables)
boxplot(df$New_FDI_Inflows, main = "New_FDI_Inflows", col = "lightblue")
boxplot(df$Exchange_Rate, main = "Exchange_Rate", col = "lightgreen")
boxplot(df$INPC, main = "INPC", col = "lightpink")
boxplot(df$Exports, main = "Exports", col = "purple")
Los datos muestran una evolución económica con fluctuaciones en inversión extranjera directa, tipo de cambio e inflación. Es importante revisar la posible presencia de valores atípicos en New_FDI_Inflows, ya que hay valores negativos significativos.
summary(df)
## Year Quarter New_FDI_Inflows Exchange_Rate
## Min. :2006 Min. :1.000 Min. :-38180 Min. :10.82
## 1st Qu.:2010 1st Qu.:1.250 1st Qu.: 30997 1st Qu.:12.69
## Median :2015 Median :2.000 Median : 44891 Median :15.78
## Mean :2015 Mean :2.473 Mean : 50555 Mean :15.71
## 3rd Qu.:2019 3rd Qu.:3.000 3rd Qu.: 65660 3rd Qu.:19.19
## Max. :2024 Max. :4.000 Max. :243723 Max. :21.60
## INPC Exports
## Min. : 60.64 Min. :271885
## 1st Qu.: 73.87 1st Qu.:385541
## Median : 87.41 Median :541980
## Mean : 90.90 Mean :531079
## 3rd Qu.:105.44 3rd Qu.:664138
## Max. :134.59 Max. :811047
Las distribuciones sugieren que algunas variables, como New_FDI_Inflows y Exchange_Rate, pueden requerir transformaciones para mejorar la normalidad. También se observa que New_FDI_Inflows e INPC tienen una media mayor a la mediana por lo que están sesgadas a la derecha. Asimismo, Exports tiene una mediana mayor que la media, está sesgada levemente a la izquierda.
plot_histogram(df)
Se realizaron gráficos de normalidad para comparar la distribución de las variables aplciando transformaciones logarítmicas y de raíz cuadrada. Se observó que las distribuciones logarítmicas de Exchange_Rate, INPC y Exports eran mejores que las distribuciones originales de las variables, por lo que se decidió realizar la transformación logarítmica de esas variables.
plot_normality(df)
La transformación logarítmica mejora la distribución de algunas variables, haciéndolas más simétricas y reduciendo la varianza. Esto es útil para análisis econométricos y modelos que asumen normalidad.
df <- df %>%
mutate(
log_Exchange_Rate = log(Exchange_Rate + 0.0001),
log_INPC = log(INPC + 0.0001),
log_Exports = log(Exports + 0.0001)
)
# Gráfico de dispersión
plot_histogram(df)
summary(df)
## Year Quarter New_FDI_Inflows Exchange_Rate
## Min. :2006 Min. :1.000 Min. :-38180 Min. :10.82
## 1st Qu.:2010 1st Qu.:1.250 1st Qu.: 30997 1st Qu.:12.69
## Median :2015 Median :2.000 Median : 44891 Median :15.78
## Mean :2015 Mean :2.473 Mean : 50555 Mean :15.71
## 3rd Qu.:2019 3rd Qu.:3.000 3rd Qu.: 65660 3rd Qu.:19.19
## Max. :2024 Max. :4.000 Max. :243723 Max. :21.60
## INPC Exports log_Exchange_Rate log_INPC
## Min. : 60.64 Min. :271885 Min. :2.381 Min. :4.105
## 1st Qu.: 73.87 1st Qu.:385541 1st Qu.:2.541 1st Qu.:4.302
## Median : 87.41 Median :541980 Median :2.759 Median :4.471
## Mean : 90.90 Mean :531079 Mean :2.728 Mean :4.484
## 3rd Qu.:105.44 3rd Qu.:664138 3rd Qu.:2.954 3rd Qu.:4.658
## Max. :134.59 Max. :811047 Max. :3.073 Max. :4.902
## log_Exports
## Min. :12.51
## 1st Qu.:12.86
## Median :13.20
## Mean :13.13
## 3rd Qu.:13.41
## Max. :13.61
La matriz de correlación muestra que la variable dependiente New_FDI_Inflows tiene muy poca correlación con las demás variables. Todas las demás variables tanto con su estructura original como con transformación logarítmica muestras una muy alta correlación entre ellas.
plot_correlation(df)
La imagen muestra una serie de tiempo de los flujos de inversión extranjera directa (FDI) nuevos a lo largo del tiempo. El eje X representa los años (aproximadamente desde 2006 hasta mediados 2024), y el eje Y muestra el valor de los flujos de inversión. La serie presenta fluctuaciones con varios picos y caídas, destacándose un pico muy pronunciado alrededor de 2010 y otro aumento significativo después de 2020.
df$New_FDI_Inflows <- na.omit(df$New_FDI_Inflows)
New_FDI_ts2 <- ts(df$New_FDI_Inflows, start = c(2006, 1), end = c(2024, 4), frequency = 4)
plot(New_FDI_ts2, type = "l", col = "blue", lwd = 2, xlab = "Year", ylab = "New_FDI_Inflows", main = "Time Series of New_FDI_Inflows")
La serie muestra estacionalidad porque hay picos periódicos de altas y bajas que ocurren regularmente. La serie muestra una leve tendencia, con fluctuaciones entre periodos de crecimiento y periodos de disminución.
decomposition <- decompose(New_FDI_ts2)
plot(decomposition)
Se observa que las variables presentan tendencias al alza en el largo plazo, aunque el tipo de cambio muestra variaciones más abruptas en ciertos periodos, mientras que el INPC y Exports tiene un comportamiento más estable y predecible.
Tipo de Cambio (Exchange Rate)
Tendencia: Se observa una tendencia creciente desde 2005 hasta aproximadamente 2020, con algunos períodos de estabilidad. Después de 2020, hay una ligera disminución.
Estacionalidad: No parece haber patrones estacionales evidentes en los datos.
Autocorrelación: La serie parece mostrar autocorrelación, ya que los cambios en el tipo de cambio ocurren de manera escalonada con ajustes bruscos en ciertos puntos, lo que sugiere dependencia de valores pasados.
Índice Nacional de Precios al Consumidor (INPC)
Tendencia: Se aprecia una tendencia creciente y sostenida a lo largo del tiempo, indicando un aumento constante en los precios.
Estacionalidad: No se observan fluctuaciones cíclicas que sugieran un patrón estacional marcado.
Autocorrelación: La serie muestra una fuerte correlación con valores pasados, ya que el INPC sigue un patrón de crecimiento progresivo sin caídas abruptas.
Exportaciones (Exports)
Tendencia: Se observa una tendencia ascendente en las exportaciones desde el inicio de la serie hasta alrededor de 2022. En los últimos periodos, hay una caída notable en las exportaciones, lo que podría indicar una posible desaceleración o crisis en el sector.
Estacionalidad: Se pueden notar breves fluctuaciones dentro del crecimiento, lo que sugiere cierto nivel de patrones estacionales.
Autocorrelación: La serie muestra correlación con valores pasados debido a los cambios que ocurren en la variable de manera escalonada.
Exchange_Rate_ts <- ts(df$log_Exchange_Rate, start = c(2006, 1), end = c(2023, 4), frequency = 4)
INPC_ts <- ts(df$log_INPC, start = c(2006, 1), end = c(2023, 4), frequency = 4)
Exports_ts <- ts(df$log_Exports, start = c(2006, 1), end = c(2023, 4), frequency = 4)
# 1. Gráfico de series de tiempo con ggplot2
plot_time_series <- function(ts_data, var_name) {
ts_df <- data.frame(Year = time(ts_data), Value = as.numeric(ts_data))
ggplot(ts_df, aes(x = Year, y = Value)) +
geom_line(color = "blue", size = 1) +
labs(title = paste("Time Series of", var_name), x = "Year", y = var_name) +
theme_minimal()
}
# Mostrar gráficos
print(plot_time_series(Exchange_Rate_ts, "Exchange Rate"))
print(plot_time_series(INPC_ts, "INPC"))
print(plot_time_series(Exports_ts, "Exports"))
No hay evidencia de autocorrelación significativa en los residuos, lo que sugiere que el modelo captura bien la estructura temporal de los datos y no deja patrones no explicados. Esto es un buen indicador de un modelo adecuado.
# Autocorrelación y autocorrelación parcial
acf(New_FDI_ts2, main="Autocorrelation - New_FDI_Inflows")
pacf(New_FDI_ts2, main="Partial Autocorrelation - New_FDI_Inflows")
# Aucotorrelación serial
lgunj_box_result <- Box.test(New_FDI_ts2, lag = 5, type = "Ljung-Box")
lgunj_box_result
##
## Box-Ljung test
##
## data: New_FDI_ts2
## X-squared = 4.1004, df = 5, p-value = 0.5351
Se observa que para las tres variables, los p-valores son altos (> 0.05), por lo que no se rechaza la hipótesis nula de raíz unitaria; es decir, las series no son estacionarias, lo que sugiere que pueden requerir diferenciación o transformación adicional para su uso en modelos de series de tiempo.
# Aplicar la prueba ADF sobre las variables transformadas en log
adf_test_log_exchange <- adf.test(df$log_Exchange_Rate)
adf_test_log_inpc <- adf.test(df$log_INPC)
adf_test_log_exports <- adf.test(df$log_Exports)
# Mostrar resultados de la prueba ADF
print(adf_test_log_exchange)
##
## Augmented Dickey-Fuller Test
##
## data: df$log_Exchange_Rate
## Dickey-Fuller = -1.9926, Lag order = 4, p-value = 0.5784
## alternative hypothesis: stationary
print(adf_test_log_inpc)
##
## Augmented Dickey-Fuller Test
##
## data: df$log_INPC
## Dickey-Fuller = -2.1842, Lag order = 4, p-value = 0.5003
## alternative hypothesis: stationary
print(adf_test_log_exports)
##
## Augmented Dickey-Fuller Test
##
## data: df$log_Exports
## Dickey-Fuller = -0.66538, Lag order = 4, p-value = 0.9691
## alternative hypothesis: stationary
Con base a la presencia de estacionariedad, se genera modelo AUTOARIMA para determinar mejor nivel de diferenciación para cada variable.
# Aplicar auto.arima() a las variables sin diferenciarlas diferenciadas
auto_arima_FDI <- auto.arima(New_FDI_ts2) #No se aplica , se va directo a un modelo ARMA
auto_arima_model1 <- auto.arima(df$log_Exchange)
auto_arima_model2 <- auto.arima(df$log_INPC)
auto_arima_model3 <- auto.arima(df$log_Exports)
summary(auto_arima_FDI)
## Series: New_FDI_ts2
## ARIMA(0,0,0)(0,0,1)[4] with non-zero mean
##
## Coefficients:
## sma1 mean
## -0.2314 50592.372
## s.e. 0.1304 3354.131
##
## sigma^2 = 1.422e+09: log likelihood = -907.79
## AIC=1821.58 AICc=1821.92 BIC=1828.58
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set -173.8284 37206.77 25689.8 -75.25536 111.8246 0.6754892 0.05067555
summary(auto_arima_model1)
## Series: df$log_Exchange
## ARIMA(0,1,0)
##
## sigma^2 = 0.002158: log likelihood = 120.48
## AIC=-238.95 AICc=-238.89 BIC=-236.66
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 0.007195362 0.04614004 0.02255997 0.258678 0.8174822 0.9878956
## ACF1
## Training set -0.02355653
summary(auto_arima_model2)
## Series: df$log_INPC
## ARIMA(0,1,0) with drift
##
## Coefficients:
## drift
## 0.0109
## s.e. 0.0010
##
## sigma^2 = 7.939e-05: log likelihood = 241.63
## AIC=-479.26 AICc=-479.09 BIC=-474.68
##
## Training set error measures:
## ME RMSE MAE MPE MAPE
## Training set 5.535466e-05 0.008789015 0.006994749 8.856065e-05 0.1565279
## MASE ACF1
## Training set 0.5708373 -0.0004828418
summary(auto_arima_model3)
## Series: df$log_Exports
## ARIMA(0,1,1) with drift
##
## Coefficients:
## ma1 drift
## -0.3437 0.0097
## s.e. 0.1209 0.0054
##
## sigma^2 = 0.00493: log likelihood = 91.29
## AIC=-176.58 AICc=-176.23 BIC=-169.71
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 0.0002271215 0.06877616 0.05203452 0.001070896 0.3956536 0.9923729
## ACF1
## Training set 0.04732834
# Verificar residuos de AUTOARIMA en las series diferenciadas
checkresiduals(auto_arima_FDI)
##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,0,0)(0,0,1)[4] with non-zero mean
## Q* = 2.7035, df = 7, p-value = 0.911
##
## Model df: 1. Total lags used: 8
checkresiduals(auto_arima_model1)
##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,1,0)
## Q* = 3.7257, df = 10, p-value = 0.9589
##
## Model df: 0. Total lags used: 10
checkresiduals(auto_arima_model2)
##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,1,0) with drift
## Q* = 114.69, df = 10, p-value < 2.2e-16
##
## Model df: 0. Total lags used: 10
checkresiduals(auto_arima_model3)
##
## Ljung-Box test
##
## data: Residuals from ARIMA(0,1,1) with drift
## Q* = 21.705, df = 9, p-value = 0.009863
##
## Model df: 1. Total lags used: 10
Se realizaron AutoArimas para las variables explicativas con el fin de determinar el número de diferencias necesarias para reducir no estacionariedad. Se observó que tres modelos (log_Exchange, log_INPC y log_Exports) requieren una diferencia (d=1), mientras que el modelo para New_FDI_ts2 no sugiere diferenciación (d=0). Por lo tanto, se aplicará una diferencia solo a las tres variables que lo requieren.
# Si las variables en log siguen sin ser estacionarias, probamos diferenciarlas
diff_log_exchange <- diff(df$log_Exchange_Rate)
diff_log_inpc <- diff(df$log_INPC, lag= 4)
diff_log_exports <- diff(df$log_Exports)
# Aplicar ADF sobre las series diferenciadas en log
adf_test_diff_log_exchange <- adf.test(diff_log_exchange)
adf_test_diff_log_inpc <- adf.test(diff_log_inpc)
adf_test_diff_log_exports <- adf.test(diff_log_exports)
# Mostrar resultados después de la diferenciación
print(adf_test_diff_log_exchange)
##
## Augmented Dickey-Fuller Test
##
## data: diff_log_exchange
## Dickey-Fuller = -3.8203, Lag order = 4, p-value = 0.02269
## alternative hypothesis: stationary
print(adf_test_diff_log_inpc)
##
## Augmented Dickey-Fuller Test
##
## data: diff_log_inpc
## Dickey-Fuller = -2.942, Lag order = 4, p-value = 0.1922
## alternative hypothesis: stationary
print(adf_test_diff_log_exports)
##
## Augmented Dickey-Fuller Test
##
## data: diff_log_exports
## Dickey-Fuller = -3.5467, Lag order = 4, p-value = 0.0441
## alternative hypothesis: stationary
diff_log_Exchange_Rate y diff_log_Exports ahora son estacionarias después de la diferenciación
diff_log_INPC sigue sin ser estacionaria (p-value = 0.3728), se realizará nuevamente la diferenciación para convertirla a estacionaria.
Al ejecutar el presente código, log_INPC ahora ya es estacionaria después de dos diferenciaciones (diff(diff(df$log_INPC))).
# Aplicar segunda diferenciación
diff2_log_inpc <- diff(diff(df$log_INPC))
# Prueba ADF después de la segunda diferenciación
adf_test_diff2_log_inpc <- adf.test(diff2_log_inpc)
print(adf_test_diff2_log_inpc)
##
## Augmented Dickey-Fuller Test
##
## data: diff2_log_inpc
## Dickey-Fuller = -4.3146, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary
Los resultados del test de Kruskal-Wallis para todas las variables indicadas (FDI, tipo de cambio, INPC y exportaciones) muestran que los valores p son todos mayores que el umbral común de significancia de 0.05 (en todos los casos, los valores p son superiores a 0.4). Esto sugiere que no hay diferencias estadísticamente significativas entre los grupos o trimestres evaluados para ninguna de las variables analizadas. En otras palabras, no se puede rechazar la hipótesis nula, que establece que las distribuciones de las variables no difieren significativamente entre los trimestres.
# Crear un factor para los trimestres
trimestres_FDI <- cycle(New_FDI_ts2)
trimestres_ER <- cycle(Exchange_Rate_ts)
trimestres_INPC <- cycle(INPC_ts)
trimestres_EXPORTS <- cycle(Exports_ts)
# Aplicar la prueba de Kruskal-Wallis a cada variable
kruskal_FDI <- kruskal.test(as.numeric(New_FDI_ts2) ~ trimestres_FDI)
kruskal_ER <- kruskal.test(as.numeric(Exchange_Rate_ts) ~ trimestres_ER)
kruskal_INPC <- kruskal.test(as.numeric(INPC_ts) ~ trimestres_INPC)
kruskal_EXPORTS <- kruskal.test(as.numeric(Exports_ts) ~ trimestres_EXPORTS)
# Imprimir los resultados
print(kruskal_FDI)
##
## Kruskal-Wallis rank sum test
##
## data: as.numeric(New_FDI_ts2) by trimestres_FDI
## Kruskal-Wallis chi-squared = 2.7563, df = 3, p-value = 0.4307
print(kruskal_ER)
##
## Kruskal-Wallis rank sum test
##
## data: as.numeric(Exchange_Rate_ts) by trimestres_ER
## Kruskal-Wallis chi-squared = 0.015982, df = 3, p-value = 0.9995
print(kruskal_INPC)
##
## Kruskal-Wallis rank sum test
##
## data: as.numeric(INPC_ts) by trimestres_INPC
## Kruskal-Wallis chi-squared = 0.20167, df = 3, p-value = 0.9773
print(kruskal_EXPORTS)
##
## Kruskal-Wallis rank sum test
##
## data: as.numeric(Exports_ts) by trimestres_EXPORTS
## Kruskal-Wallis chi-squared = 0.29731, df = 3, p-value = 0.9605
Con base en la selección de la(s) variable(s) de interés, realizar la estimación de las siguientes especificaciones de modelos de series de tiempo:
# Ajustar modelo ARMA (1,1) a New_FDI_ts2 (ya es estacionaria)
library(TSA)
arma_model_tsa <- arma(New_FDI_ts2, order = c(1, 1))
summary(arma_model_tsa)
##
## Call:
## arma(x = New_FDI_ts2, order = c(1, 1))
##
## Model:
## ARMA(1,1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -88815 -19388 -5312 15950 197082
##
## Coefficient(s):
## Estimate Std. Error t value Pr(>|t|)
## ar1 0.3867 NA NA NA
## ma1 -0.3261 NA NA NA
## intercept 31074.6008 NA NA NA
##
## Fit:
## sigma^2 estimated as 1.457e+09, Conditional Sum-of-Squares = 107818868394, AIC = 1825.25
# Verificar residuos de ARMA
checkresiduals(arma_model_tsa)
##
## Ljung-Box test
##
## data: Residuals
## Q* = 4.522, df = 8, p-value = 0.8072
##
## Model df: 0. Total lags used: 8
En base a los valores de AIC, AICc y BIC, el modelo ARMA(2,1) es el que presenta los mejores resultados con un AIC de 1823.523, que es el más bajo entre todos los modelos probados (ARMA(1,1), ARMA(2,2), ARMA(3,3), ARMA(1,2)). Asmismo, los errores de ajuste, como el RMSE (Root Mean Squared Error), muestra un buen desempeño sin sobreajustarse a los datos.
arma_model_1_1 <- Arima(New_FDI_ts2, order = c(1, 0, 1)) # ARMA(1,1)
arma_model_2_2 <- Arima(New_FDI_ts2, order = c(2, 0, 2)) # ARMA(2,2)
arma_model_3_3 <- Arima(New_FDI_ts2, order = c(3, 0, 3)) # ARMA(3,3)
arma_model_1_2 <- Arima(New_FDI_ts2, order = c(1, 0, 2)) # ARMA(1,2)
arma_model_2_1 <- Arima(New_FDI_ts2, order = c(2, 0, 1)) # ARMA(2,1)
# Comparar los AIC de cada modelo
aic_values <- c(
AIC(arma_model_1_1),
AIC(arma_model_2_2),
AIC(arma_model_3_3),
AIC(arma_model_1_2),
AIC(arma_model_2_1)
)
names(aic_values) <- c("ARMA(1,1)", "ARMA(2,2)", "ARMA(3,3)", "ARMA(1,2)", "ARMA(2,1)")
print(aic_values)
## ARMA(1,1) ARMA(2,2) ARMA(3,3) ARMA(1,2) ARMA(2,1)
## 1826.189 1830.013 1832.666 1823.956 1823.523
# Elegimos el modelo con menor AIC
best_arma_model <- list(
"ARMA(1,1)" = arma_model_1_1,
"ARMA(2,2)" = arma_model_2_2,
"ARMA(3,3)" = arma_model_3_3,
"ARMA(1,2)" = arma_model_1_2,
"ARMA(2,1)" = arma_model_2_1
)[[which.min(aic_values)]]
summary(best_arma_model)
## Series: New_FDI_ts2
## ARIMA(2,0,1) with non-zero mean
##
## Coefficients:
## ar1 ar2 ma1 mean
## 0.9918 -0.1680 -1.0000 51659.0294
## s.e. 0.1134 0.1182 0.0353 964.5405
##
## sigma^2 = 1.384e+09: log likelihood = -906.76
## AIC=1823.52 AICc=1824.38 BIC=1835.18
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 649.4694 36207.99 24804.32 -66.93742 107.1585 0.6522063
## ACF1
## Training set -0.02370781
#AIC del arma seleccionado con mejor AIC (después de las combinaciones fue el más bajo)
AIC_BESTARMA<-AIC(arma_model_1_2)
Acorde a las pruebas realizadas, se determina que el modelo ARIMA no es el más conveniente debido a la estacionariedad de la variable dependiente. Inclusive, al realizar el AUTO ARIMA se determina que los parámetros deben ser (0,0,0) haciendo alusión a que la serie no presenta características fuertes de autorregresión o media móvil.
# Ajustar un modelo ARIMA (1,1,1) sobre New_FDI_ts2
ARIMA_model <- Arima(New_FDI_ts2, order = c(1, 1, 1))
print(ARIMA_model)
## Series: New_FDI_ts2
## ARIMA(1,1,1)
##
## Coefficients:
## ar1 ma1
## 0.0873 -1.0000
## s.e. 0.1160 0.0474
##
## sigma^2 = 1.496e+09: log likelihood = -899.72
## AIC=1805.44 AICc=1805.78 BIC=1812.39
plot(ARIMA_model$residuals, main = "ARIMA(1,1,1) - New_FDI_ts2", col="blue", lwd=2)
acf(ARIMA_model$residuals, main = "ACF - ARIMA(1,1,1)")
Box.test(ARIMA_model$residuals, lag = 1, type = "Ljung-Box") # Prueba de autocorrelación en residuos
##
## Box-Ljung test
##
## data: ARIMA_model$residuals
## X-squared = 0.0046048, df = 1, p-value = 0.9459
# Estacionariedad en los residuos
adf.test(ARIMA_model$residuals)
##
## Augmented Dickey-Fuller Test
##
## data: ARIMA_model$residuals
## Dickey-Fuller = -4.4423, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary
Observaciones del modelo:
p = 1: Incluye un término autorregresivo (AR).
d = 1: Diferenciación aplicada una vez para estacionariedad.
q = 1: Incluye un término de media móvil (MA).
La gráfica de ACF no presenta autocorrelación.
El valor p (0.9459) es > 0.05, lo que indica que el modelo ARIMA no muestra autocorrelación serial en los residuos.
El test ADF sugiere que los residuos del ARIMA son estacionarios, ya que el valor p (0.01) es < 0.05.
Se determina que en caso de realizar ARIMA el mejor modelo es ARIMA(1,1,1), ya que tiene el menor AIC (1805.44) y un RMSE de 37910.82.
arima_model_1_1_1 <- Arima(New_FDI_ts2, order = c(1, 1, 1)) # ARIMA(1,1,1)
arima_model_2_1_1 <- Arima(New_FDI_ts2, order = c(2, 1, 1)) # ARIMA(2,1,1)
arima_model_1_1_2 <- Arima(New_FDI_ts2, order = c(1, 1, 2)) # ARIMA(1,1,2)
arima_model_2_1_2 <- Arima(New_FDI_ts2, order = c(2, 1, 2)) # ARIMA(2,1,2)
arima_model_3_1_3 <- Arima(New_FDI_ts2, order = c(3, 1, 3)) # ARIMA(3,1,3)
aic_values <- c(
AIC(arima_model_1_1_1),
AIC(arima_model_2_1_1),
AIC(arima_model_1_1_2),
AIC(arima_model_2_1_2),
AIC(arima_model_3_1_3)
)
names(aic_values) <- c("ARIMA(1,1,1)", "ARIMA(2,1,1)", "ARIMA(1,1,2)", "ARIMA(2,1,2)", "ARIMA(3,1,3)")
print(aic_values)
## ARIMA(1,1,1) ARIMA(2,1,1) ARIMA(1,1,2) ARIMA(2,1,2) ARIMA(3,1,3)
## 1805.441 1807.375 1807.384 1809.286 1807.449
best_arima_model <- list(
"ARIMA(1,1,1)" = arima_model_1_1_1,
"ARIMA(2,1,1)" = arima_model_2_1_1,
"ARIMA(1,1,2)" = arima_model_1_1_2,
"ARIMA(2,1,2)" = arima_model_2_1_2,
"ARIMA(3,1,3)" = arima_model_3_1_3
)[[which.min(aic_values)]]
summary(best_arima_model)
## Series: New_FDI_ts2
## ARIMA(1,1,1)
##
## Coefficients:
## ar1 ma1
## 0.0873 -1.0000
## s.e. 0.1160 0.0474
##
## sigma^2 = 1.496e+09: log likelihood = -899.72
## AIC=1805.44 AICc=1805.78 BIC=1812.39
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 50.77835 37910.82 25943.19 -66.48989 106.7125 0.6821519 -0.0076328
#AIC del ARIMA seleccionado con mejor AIC (después de las combinaciones fue el más bajo)
AIC_BESTARIMA<-AIC(arima_model_1_1_1)
Se realizó un modelo VAR teniendo como variable Y New_FDI_Inflows, y usando dentro de la especificación del modelo las variables: diff_log_exchange, diff2_log_inpc y diff_log_exports.
# Construir el conjunto de datos con variables estacionarias
var_data <- cbind(
df$New_FDI_Inflows, # Ya es estacionaria
diff_log_exchange, # Primera diferencia
diff2_log_inpc, # Segunda diferencia
diff_log_exports # Primera diferencia
)
# Convertir a formato ts
var_data_ts <- ts(var_data, start = c(2006,1), frequency = 4)
Se determinó que el mejor número de lags para el modelo es 3 usando como evaluador el vlaor de AIC.
# Determinar el mejor número de lags usando AIC
lag_selection <- VARselect(var_data_ts, lag.max = 8, type = "const")
print(lag_selection$selection)
## AIC(n) HQ(n) SC(n) FPE(n)
## 3 3 1 3
optimal_lag <- lag_selection$selection["AIC(n)"]
colnames(var_data_ts) <- c("New_FDI_Inflows", "diff_log_exchange", "diff2_log_inpc", "diff_log_exports")
print(colnames(var_data_ts))
## [1] "New_FDI_Inflows" "diff_log_exchange" "diff2_log_inpc"
## [4] "diff_log_exports"
Acorde al modelo, se observa que:
New_FDI_Inflows no es explicada por ninguna otra variable significativa, lo que sugiere que podría ser más autónoma o influida por factores externos no capturados en este modelo.
El tipo de cambio (diff_log_exchange) está influenciado por las exportaciones (diff_log_exports.l1).
La inflación (diff2_log_inpc) es altamente autorregresiva y también influenciada por el tipo de cambio (diff_log_exchange.l3).
Las exportaciones (diff_log_exports) están determinadas por sus propios rezagos, la inflación (diff2_log_inpc.l2, l3) y el tipo de cambio (diff_log_exchange.l2).
var_model <- VAR(var_data_ts, p = optimal_lag, type = "const")
print(names(var_model$y))
## NULL
summary(var_model)
##
## VAR Estimation Results:
## =========================
## Endogenous variables: New_FDI_Inflows, diff_log_exchange, diff2_log_inpc, diff_log_exports
## Deterministic variables: const
## Sample size: 71
## Log Likelihood: -342.438
## Roots of the characteristic polynomial:
## 0.9353 0.9353 0.8554 0.6589 0.6589 0.6359 0.6359 0.6252 0.6252 0.5894 0.5894 0.2384
## Call:
## VAR(y = var_data_ts, p = optimal_lag, type = "const")
##
##
## Estimation results for equation New_FDI_Inflows:
## ================================================
## New_FDI_Inflows = New_FDI_Inflows.l1 + diff_log_exchange.l1 + diff2_log_inpc.l1 + diff_log_exports.l1 + New_FDI_Inflows.l2 + diff_log_exchange.l2 + diff2_log_inpc.l2 + diff_log_exports.l2 + New_FDI_Inflows.l3 + diff_log_exchange.l3 + diff2_log_inpc.l3 + diff_log_exports.l3 + const
##
## Estimate Std. Error t value Pr(>|t|)
## New_FDI_Inflows.l1 5.583e-02 1.280e-01 0.436 0.664247
## diff_log_exchange.l1 1.371e+05 1.293e+05 1.060 0.293482
## diff2_log_inpc.l1 1.737e+05 5.117e+05 0.339 0.735510
## diff_log_exports.l1 -1.749e+03 8.593e+04 -0.020 0.983836
## New_FDI_Inflows.l2 -4.813e-03 1.251e-01 -0.038 0.969436
## diff_log_exchange.l2 -1.272e+05 1.337e+05 -0.952 0.345214
## diff2_log_inpc.l2 1.562e+05 4.955e+05 0.315 0.753727
## diff_log_exports.l2 1.406e+05 8.785e+04 1.601 0.114833
## New_FDI_Inflows.l3 5.714e-02 1.254e-01 0.456 0.650406
## diff_log_exchange.l3 -7.357e+04 1.362e+05 -0.540 0.591173
## diff2_log_inpc.l3 9.208e+05 5.085e+05 1.811 0.075363 .
## diff_log_exports.l3 1.660e+05 9.235e+04 1.797 0.077513 .
## const 4.325e+04 1.214e+04 3.563 0.000741 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 39460 on 58 degrees of freedom
## Multiple R-Squared: 0.1501, Adjusted R-squared: -0.02573
## F-statistic: 0.8537 on 12 and 58 DF, p-value: 0.5966
##
##
## Estimation results for equation diff_log_exchange:
## ==================================================
## diff_log_exchange = New_FDI_Inflows.l1 + diff_log_exchange.l1 + diff2_log_inpc.l1 + diff_log_exports.l1 + New_FDI_Inflows.l2 + diff_log_exchange.l2 + diff2_log_inpc.l2 + diff_log_exports.l2 + New_FDI_Inflows.l3 + diff_log_exchange.l3 + diff2_log_inpc.l3 + diff_log_exports.l3 + const
##
## Estimate Std. Error t value Pr(>|t|)
## New_FDI_Inflows.l1 8.672e-08 1.425e-07 0.609 0.5451
## diff_log_exchange.l1 2.156e-01 1.440e-01 1.497 0.1398
## diff2_log_inpc.l1 -6.149e-01 5.697e-01 -1.079 0.2850
## diff_log_exports.l1 -3.169e-01 9.568e-02 -3.312 0.0016 **
## New_FDI_Inflows.l2 -1.903e-07 1.393e-07 -1.367 0.1770
## diff_log_exchange.l2 -1.857e-02 1.488e-01 -0.125 0.9012
## diff2_log_inpc.l2 4.961e-01 5.517e-01 0.899 0.3722
## diff_log_exports.l2 -4.115e-03 9.782e-02 -0.042 0.9666
## New_FDI_Inflows.l3 -1.365e-07 1.397e-07 -0.977 0.3326
## diff_log_exchange.l3 2.098e-01 1.517e-01 1.383 0.1719
## diff2_log_inpc.l3 9.426e-01 5.662e-01 1.665 0.1013
## diff_log_exports.l3 -6.547e-02 1.028e-01 -0.637 0.5268
## const 2.114e-02 1.351e-02 1.564 0.1232
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.04394 on 58 degrees of freedom
## Multiple R-Squared: 0.2708, Adjusted R-squared: 0.1199
## F-statistic: 1.795 on 12 and 58 DF, p-value: 0.07053
##
##
## Estimation results for equation diff2_log_inpc:
## ===============================================
## diff2_log_inpc = New_FDI_Inflows.l1 + diff_log_exchange.l1 + diff2_log_inpc.l1 + diff_log_exports.l1 + New_FDI_Inflows.l2 + diff_log_exchange.l2 + diff2_log_inpc.l2 + diff_log_exports.l2 + New_FDI_Inflows.l3 + diff_log_exchange.l3 + diff2_log_inpc.l3 + diff_log_exports.l3 + const
##
## Estimate Std. Error t value Pr(>|t|)
## New_FDI_Inflows.l1 5.455e-09 2.063e-08 0.264 0.7924
## diff_log_exchange.l1 -2.355e-02 2.084e-02 -1.130 0.2633
## diff2_log_inpc.l1 -8.234e-01 8.247e-02 -9.984 3.29e-14 ***
## diff_log_exports.l1 2.396e-02 1.385e-02 1.730 0.0889 .
## New_FDI_Inflows.l2 -1.719e-08 2.016e-08 -0.853 0.3974
## diff_log_exchange.l2 -2.833e-02 2.154e-02 -1.315 0.1936
## diff2_log_inpc.l2 -9.200e-01 7.986e-02 -11.521 < 2e-16 ***
## diff_log_exports.l2 7.097e-03 1.416e-02 0.501 0.6181
## New_FDI_Inflows.l3 -2.658e-08 2.022e-08 -1.315 0.1938
## diff_log_exchange.l3 5.742e-02 2.195e-02 2.616 0.0113 *
## diff2_log_inpc.l3 -7.244e-01 8.196e-02 -8.838 2.45e-12 ***
## diff_log_exports.l3 4.821e-03 1.489e-02 0.324 0.7472
## const 1.865e-03 1.956e-03 0.953 0.3443
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.00636 on 58 degrees of freedom
## Multiple R-Squared: 0.7877, Adjusted R-squared: 0.7437
## F-statistic: 17.93 on 12 and 58 DF, p-value: 2.689e-15
##
##
## Estimation results for equation diff_log_exports:
## =================================================
## diff_log_exports = New_FDI_Inflows.l1 + diff_log_exchange.l1 + diff2_log_inpc.l1 + diff_log_exports.l1 + New_FDI_Inflows.l2 + diff_log_exchange.l2 + diff2_log_inpc.l2 + diff_log_exports.l2 + New_FDI_Inflows.l3 + diff_log_exchange.l3 + diff2_log_inpc.l3 + diff_log_exports.l3 + const
##
## Estimate Std. Error t value Pr(>|t|)
## New_FDI_Inflows.l1 9.263e-08 2.099e-07 0.441 0.66057
## diff_log_exchange.l1 1.625e-01 2.121e-01 0.766 0.44661
## diff2_log_inpc.l1 5.401e-01 8.391e-01 0.644 0.52232
## diff_log_exports.l1 -3.980e-01 1.409e-01 -2.824 0.00649 **
## New_FDI_Inflows.l2 -1.713e-07 2.051e-07 -0.835 0.40696
## diff_log_exchange.l2 4.563e-01 2.192e-01 2.082 0.04180 *
## diff2_log_inpc.l2 1.862e+00 8.125e-01 2.291 0.02559 *
## diff_log_exports.l2 -2.963e-01 1.441e-01 -2.056 0.04425 *
## New_FDI_Inflows.l3 -1.579e-07 2.057e-07 -0.768 0.44585
## diff_log_exchange.l3 4.040e-01 2.233e-01 1.809 0.07569 .
## diff2_log_inpc.l3 2.386e+00 8.339e-01 2.862 0.00585 **
## diff_log_exports.l3 -2.051e-01 1.514e-01 -1.354 0.18090
## const 2.538e-02 1.990e-02 1.275 0.20738
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
##
## Residual standard error: 0.06471 on 58 degrees of freedom
## Multiple R-Squared: 0.3549, Adjusted R-squared: 0.2215
## F-statistic: 2.659 on 12 and 58 DF, p-value: 0.006545
##
##
##
## Covariance matrix of residuals:
## New_FDI_Inflows diff_log_exchange diff2_log_inpc
## New_FDI_Inflows 1.557e+09 -3.455e+01 -2.234e+00
## diff_log_exchange -3.455e+01 1.931e-03 3.668e-05
## diff2_log_inpc -2.234e+00 3.668e-05 4.045e-05
## diff_log_exports -7.550e+00 1.206e-03 -4.392e-06
## diff_log_exports
## New_FDI_Inflows -7.550e+00
## diff_log_exchange 1.206e-03
## diff2_log_inpc -4.392e-06
## diff_log_exports 4.187e-03
##
## Correlation matrix of residuals:
## New_FDI_Inflows diff_log_exchange diff2_log_inpc
## New_FDI_Inflows 1.000000 -0.01993 -0.008903
## diff_log_exchange -0.019925 1.00000 0.131262
## diff2_log_inpc -0.008903 0.13126 1.000000
## diff_log_exports -0.002957 0.42408 -0.010673
## diff_log_exports
## New_FDI_Inflows -0.002957
## diff_log_exchange 0.424081
## diff2_log_inpc -0.010673
## diff_log_exports 1.000000
La prueba de autocorrelación en residuos (Ljung-Box) mostró que solo la variable diff2_log_inpc muestra autocorrelaicón serial de los residuales, las demás variables tienen un p-value > 0.05 indicando que no tienen autocorrelación serial de residuales.
residuals_var <- residuals(var_model)
apply(residuals_var, 2, function(x) Box.test(x, lag = 10, type = "Ljung-Box"))
## $New_FDI_Inflows
##
## Box-Ljung test
##
## data: x
## X-squared = 7.2404, df = 10, p-value = 0.7026
##
##
## $diff_log_exchange
##
## Box-Ljung test
##
## data: x
## X-squared = 9.145, df = 10, p-value = 0.5184
##
##
## $diff2_log_inpc
##
## Box-Ljung test
##
## data: x
## X-squared = 29.758, df = 10, p-value = 0.0009384
##
##
## $diff_log_exports
##
## Box-Ljung test
##
## data: x
## X-squared = 5.193, df = 10, p-value = 0.8779
AIC_BESTVAR <- AIC(var_model)
Los factores macroeconómicos (tipo de cambio, INPC, exportaciones) afectan la IED, pero la IED no influye en el comportamiento futuro de estas variables. En el modelo VAR, el test de Granger muestra que New_FDI_Inflows no tiene un efecto predictivo sobre diff_log_exchange, diff2_log_inpc, y diff_log_exports (p = 0.7847). Sin embargo, diff_log_exchange (p = 0.0079), diff2_log_inpc (p = 0.0184) y diff_log_exports (p = 0.0118) sí presentan evidencia de Granger-causalidad sobre otras variables, lo que sugiere que estos factores macroeconómicos tienen un impacto predictivo sobre el comportamiento de la inversión extranjera directa y otras variables en el modelo.
El valor p de la prueba F global del modelo (0.5966) indica que New_FDI_Inflows (flujos de IED) no muestra una causalidad para las variables explicativas seleccionadas (Exchange Rate, INPC y Exports). La prueba de Ljung-Box muestra la independencia de errores en la mayoría de las variables, excepto en diff2_log_inpc. Esta variable muestra autocorrelación significativa. Las variables INPC y Exports muestran una posible relación con New_FDI_Inflows en el tercer rezago, aunque la evidencia estadística no es lo suficientemente fuerte como para ser concluyente.
granger_fdi <- causality(var_model, cause = "New_FDI_Inflows")
print(granger_fdi)
## $Granger
##
## Granger causality H0: New_FDI_Inflows do not Granger-cause
## diff_log_exchange diff2_log_inpc diff_log_exports
##
## data: VAR object var_model
## F-Test = 0.61391, df1 = 9, df2 = 232, p-value = 0.7847
##
##
## $Instant
##
## H0: No instantaneous causality between: New_FDI_Inflows and
## diff_log_exchange diff2_log_inpc diff_log_exports
##
## data: VAR object var_model
## Chi-squared = 0.033266, df = 3, p-value = 0.9984
granger_exchange <- causality(var_model, cause = "diff_log_exchange")
print(granger_exchange)
## $Granger
##
## Granger causality H0: diff_log_exchange do not Granger-cause
## New_FDI_Inflows diff2_log_inpc diff_log_exports
##
## data: VAR object var_model
## F-Test = 2.5626, df1 = 9, df2 = 232, p-value = 0.007932
##
##
## $Instant
##
## H0: No instantaneous causality between: diff_log_exchange and
## New_FDI_Inflows diff2_log_inpc diff_log_exports
##
## data: VAR object var_model
## Chi-squared = 11.764, df = 3, p-value = 0.008238
granger_inpc <- causality(var_model, cause = "diff2_log_inpc")
print(granger_inpc)
## $Granger
##
## Granger causality H0: diff2_log_inpc do not Granger-cause
## New_FDI_Inflows diff_log_exchange diff_log_exports
##
## data: VAR object var_model
## F-Test = 2.2759, df1 = 9, df2 = 232, p-value = 0.0184
##
##
## $Instant
##
## H0: No instantaneous causality between: diff2_log_inpc and
## New_FDI_Inflows diff_log_exchange diff_log_exports
##
## data: VAR object var_model
## Chi-squared = 1.5712, df = 3, p-value = 0.6659
granger_exports <- causality(var_model, cause = "diff_log_exports")
print(granger_exports)
## $Granger
##
## Granger causality H0: diff_log_exports do not Granger-cause
## New_FDI_Inflows diff_log_exchange diff2_log_inpc
##
## data: VAR object var_model
## F-Test = 2.4283, df1 = 9, df2 = 232, p-value = 0.0118
##
##
## $Instant
##
## H0: No instantaneous causality between: diff_log_exports and
## New_FDI_Inflows diff_log_exchange diff2_log_inpc
##
## data: VAR object var_model
## Chi-squared = 11.051, df = 3, p-value = 0.01145
El modelo de Panel VAR con efectos fijos muestra las siguientes relaciones clave:
New FDI Inflows: El rezago de New FDI Inflows tiene un efecto negativo y significativo en su propia variable, con un coeficiente de -0.6730 (p < 0.001). Esto sugiere que un aumento en los flujos de FDI en el trimestre anterior está asociado con una disminución en los flujos actuales de FDI.
Exports: El rezago de Exports tiene un efecto negativo y significativo en los flujos de exportación actuales (-0.4937, p < 0.05), lo que indica que un aumento en las exportaciones del trimestre anterior puede reducir las exportaciones actuales.
Los coeficientes de INPC y Exchange Rate no son significativos en este análisis, lo que sugiere que estas variables no tienen un impacto directo importante en los flujos de FDI o exportaciones cuando se controlan por los rezagos.
library(panelvar)
df_orig <- df %>% dplyr::select(Year, Quarter, New_FDI_Inflows, Exchange_Rate, INPC, Exports)
PanelVAR_FE <- pvarfeols(dependent_vars=c("New_FDI_Inflows", "Exports"),lags=1, exog_vars=c("INPC", "Exchange_Rate"), transformation="demean", data=df_orig, panel_identifier= c("Year", "Quarter"))
summary(PanelVAR_FE)
Fixed Effects OLS Panel VAR estimation
Transformation: demean
Group variable: Year
Time
variable: Quarter
Number of observations =
74
Number of groups = 19
Obs per group: min =
2
Obs per group: avg = 3.89473684210526
Obs per
group: max = 4
demeaned_New_FDI_Inflows | demeaned_Exports | |
---|---|---|
demeaned_lag1_New_FDI_Inflows | -0.6730*** | -0.1170 |
(0.1380) | (0.0956) | |
demeaned_lag1_Exports | 0.3006 | -0.4937* |
(0.3162) | (0.2192) | |
demeaned_INPC | 984.2650 | -4965.0945 |
(7786.2948) | (5396.5243) | |
demeaned_Exchange_Rate | 26543.0224 | -55703.1905 |
(56749.2533) | (39331.7657) | |
***p < 0.001; **p < 0.01; *p < 0.05 |
El modelo de Panel VAR con variables explciativas transformadas a logartimo con efectos fijos muestra lo siguiente:
New FDI Inflows: El rezago de New FDI Inflows tiene un efecto negativo y significativo en su propia variable con un coeficiente de -0.6633 (p < 0.001), lo que indica que un aumento en los flujos de FDI del trimestre anterior se asocia con una caída en los flujos actuales de FDI.
Exports: El rezago de log_Exports tiene un efecto negativo y significativo en los flujos de exportaciones actuales con un coeficiente de -0.4671 (p < 0.05). Esto sugiere que un aumento en las exportaciones del trimestre anterior reduce las exportaciones actuales.
Las variables Exchange Rate y INPC no tienen efectos significativos en los flujos de FDI ni en las exportaciones en este modelo, ya que sus coeficientes no son estadísticamente significativos.
df_log <- df %>% dplyr::select(Year, Quarter, New_FDI_Inflows, log_Exchange_Rate, log_INPC, log_Exports)
# Estimar modelo Panel VAR con efectos fijos
PanelVAR_FE_log <- pvarfeols(
dependent_vars = c("New_FDI_Inflows", "log_Exports"),
lags = 1,
exog_vars = c("log_Exchange_Rate", "log_INPC"),
transformation = "demean",
data = df_log,
panel_identifier = c("Year", "Quarter")
)
summary(PanelVAR_FE_log)
Fixed Effects OLS Panel VAR estimation
Transformation: demean
Group variable: Year
Time
variable: Quarter
Number of observations =
74
Number of groups = 19
Obs per group: min =
2
Obs per group: avg = 3.89473684210526
Obs per
group: max = 4
demeaned_New_FDI_Inflows | demeaned_log_Exports | |
---|---|---|
demeaned_lag1_New_FDI_Inflows | -0.6633*** | -0.0000 |
(0.1354) | (0.0000) | |
demeaned_lag1_log_Exports | 260845.9769 | -0.4671* |
(173954.0614) | (0.2136) | |
demeaned_log_Exchange_Rate | 656650.2032 | -1.8477 |
(853875.8593) | (1.0482) | |
demeaned_log_INPC | 203569.1207 | -1.0571 |
(621143.2731) | (0.7625) | |
***p < 0.001; **p < 0.01; *p < 0.05 |
El modelo presenta errores estándar altos y los p-values de Hansen indican que los instrumentos pueden no ser válidos; además se observa que ninguna variable parece tener un impacto estadístico confiable: * lag1_New_FDI_Inflows: -0.2577 (con error estándar 0.2045) → Indica una leve autocorrelación negativa, pero no es estadísticamente significativo.
log_Exchange_Rate, log_Exports, log_INPC: Todos con coeficiente ≈ 0 y errores estándar extremadamente grandes lo que indica problemas numéricos serios.
Hansen Test: Indica sobreidentificación extrema y problemas con los instrumentos.
PANELVAR_FE_GMM <- pvargmm(
dependent_vars = c("New_FDI_Inflows"),
lags=1,
predet_vars=c("log_Exchange_Rate", "log_Exports"),
exog_vars=c("log_INPC"),
transformation="fd",
data=df_log ,
panel_identifier=c("Year", "Quarter"),
steps=c("onestep")
)
summary(PANELVAR_FE_GMM)
Dynamic Panel VAR estimation, one-step GMM
Transformation: First-differences
Group variable:
Year
Time variable: Quarter
Number of
observations = 36
Number of groups = 18
Obs per
group: min = 2
Obs per group: avg = 2
Obs per
group: max = 2
Number of instruments = 14
New_FDI_Inflows | |
---|---|
lag1_New_FDI_Inflows | -0.2577 |
(0.2045) | |
log_Exchange_Rate | 0.0000 |
(655946.7015) | |
log_Exports | 0.0000 |
(124686.3002) | |
log_INPC | 0.0000 |
(407222.0440) | |
***p < 0.001; **p < 0.01; *p < 0.05 |
Instruments for equation
Standard
log_INPC
GMM-type
Dependent vars: L(2,2)
Predet vars: L(1,
2)
Collapse = FALSE
Hansen test of overid. restrictions: chi2(10) =
12073350630.66 Prob > chi2 = 0
(Robust, but weakened by many
instruments.)
En este caso, el p-valor (0.2966) es mayor que 0.05, por lo que NO se rechaza la hipótesis nula. Esto indica que no hay evidencia de un cambio estructural significativo en la relación entre New_FDI_Inflows y las variables explicativas (log_Exchange_Rate, log_INPC, log_Exports).
chow_test <- sctest(New_FDI_Inflows ~ log_Exchange_Rate + log_INPC + log_Exports,
type = "Chow", point = 18, data = df)
print(chow_test)
##
## Chow test
##
## data: New_FDI_Inflows ~ log_Exchange_Rate + log_INPC + log_Exports
## F = 1.255, p-value = 0.2966
# Extraer residuales
residuals_df <- as.data.frame(residuals(PanelVAR_FE))
# Calcular SSE
SSE <- sum(residuals_df^2, na.rm = TRUE)
# Número de observaciones y parámetros estimados
n <- nrow(df_orig)
k <- length(coef(PanelVAR_FE)) # Número de coeficientes estimados
# Calcular AIC manualmente
AIC_PanelVAR_FE <- n * log(SSE / n) + 2 * k
# Extraer residuales
residuals_df2 <- as.data.frame(residuals(PanelVAR_FE_log))
# Calcular SSE
SSE2 <- sum(residuals_df2^2, na.rm = TRUE)
# Número de observaciones y parámetros estimados
n2 <- nrow(df_log)
k2 <- length(coef(PanelVAR_FE_log)) # Número de coeficientes estimados
# Calcular AIC manualmente
AIC_PanelVAR_FE_log <- n2 * log(SSE2 / n2) + 2 * k2
Mediante pruebas de diagnóstico, identificar la posible presencia de las siguientes características de la serie:
Todos los modelos tienen p-values > 0.05, lo que significa que no hay evidencia de autocorrelación serial en los residuos.
test_autocorrelacion <- function(modelo) {
residuos <- residuals(modelo)
if (is.matrix(residuos)) {
p_values <- apply(residuos, 2, function(x) Box.test(x, lag = 10, type = "Ljung-Box")$p.value)
} else {
p_values <- Box.test(residuos, lag = 10, type = "Ljung-Box")$p.value
}
return(p_values)
}
# Aplicar la prueba de autocorrelación a cada modelo
autocorr_results <- data.frame(
Modelo = c("ARMA", "ARIMA", "VAR", "PanelVAR_FE_log", "PanelVAR_FE"),
Autocorr_p_value = c(
test_autocorrelacion(arma_model_1_2),
test_autocorrelacion(arima_model_1_1_1),
mean(test_autocorrelacion(var_model)), # Promedio de p-values en VAR
mean(test_autocorrelacion(PanelVAR_FE_log)), # Promedio de p-values en PanelVAR_FE_log
mean(test_autocorrelacion(PanelVAR_FE)) # Promedio de p-values en PanelVAR_FE
)
)
print(autocorr_results)
## Modelo Autocorr_p_value
## 1 ARMA 0.8153617
## 2 ARIMA 0.8987572
## 3 VAR 0.5249556
## 4 PanelVAR_FE_log 0.8486554
## 5 PanelVAR_FE 0.8530676
Se busca que los modelos tengan residuos estacionarios porque esto indica que el modelo captura de forma eficiente la dinámica de la serie de tiempo.
test_estacionariedad <- function(modelo) {
residuos <- residuals(modelo)
if (is.matrix(residuos)) {
p_values <- apply(residuos, 2, function(x) adf.test(as.numeric(x))$p.value)
} else {
p_values <- adf.test(as.numeric(residuos))$p.value
}
return(p_values)
}
# Aplicar la prueba de estacionariedad a cada modelo
stationarity_results <- data.frame(
Modelo = c("ARMA", "ARIMA", "VAR", "PanelVAR_FE_log", "PanelVAR_FE"),
Stationarity_p_value = c(
test_estacionariedad(arma_model_1_2),
test_estacionariedad(arima_model_1_1_1),
mean(test_estacionariedad(var_model)), # Promedio de p-values en VAR
mean(test_estacionariedad(PanelVAR_FE_log)), # Promedio de p-values en PanelVAR_FE_log
mean(test_estacionariedad(PanelVAR_FE)) # Promedio de p-values en PanelVAR_FE
)
)
print(stationarity_results)
## Modelo Stationarity_p_value
## 1 ARMA 0.01676033
## 2 ARIMA 0.01000000
## 3 VAR 0.01587479
## 4 PanelVAR_FE_log 0.07492563
## 5 PanelVAR_FE 0.14394902
Con base en las pruebas de diagnóstico, y la estimación de los resultados, se seleccionan los resultados de la estimación del modelo de series de tiempo que muestra el mejor desempeño.
El mejor modelo es el que no tiene autocorrelación serial en los residuos, tenga residuos estacionarios y tenga el menor AIC, por lo que, el modelo que mejor cumplió con estas condiciones es el modelo VAR.
Primeramente, se observan los AIC de todos los modelos generados
df_AIC <- data.frame(
Modelo = c("ARMA", "ARIMA", "VAR", "PanelVAR_FE_log", "PanelVAR_FE"),
AIC_Valor = c(AIC_BESTARMA, AIC_BESTARIMA, AIC_BESTVAR, AIC_PanelVAR_FE_log, AIC_PanelVAR_FE)
)
print(df_AIC)
## Modelo AIC_Valor
## 1 ARMA 1823.9565
## 2 ARIMA 1805.4410
## 3 VAR 788.8765
## 4 PanelVAR_FE_log 1471.0029
## 5 PanelVAR_FE 1502.8900
Posteriormente, se observan los AIC los modelos óptimos acorde al análisis exploratorio realizado, ante lo cual sigue preodminando el modelo VAR por tener el menor AIC y RMSE.
library(Metrics)
# Lista de modelos
modelos <- list(
"ARMA(1,1)" = arma_model_1_1,
"ARMA(2,2)" = arma_model_2_2,
"ARMA(3,3)" = arma_model_3_3,
"ARMA(1,2)" = arma_model_1_2,
"ARMA(2,1)" = arma_model_2_1
)
# Función para calcular RMSE
get_rmse <- function(model, datos_reales) {
preds <- fitted(model)
return(rmse(datos_reales, preds))
}
# Calcular AIC y RMSE
resultados <- data.frame(
AIC = sapply(modelos, AIC),
RMSE = sapply(modelos, get_rmse, datos_reales = New_FDI_ts2)
)
# Modelo VAR
AIC_BESTVAR <- AIC(var_model)
fitted_vals <- as.data.frame(fitted(var_model))
in_sample_pred <- fitted_vals$New_FDI_Inflows
df_aligned <- df[-c(1:3), ]
var_rmse <- rmse(df_aligned$New_FDI_Inflows, in_sample_pred)
# Fila del Modelo VAR
var_row <- data.frame(
AIC = AIC_BESTVAR,
RMSE = var_rmse,
row.names = "VAR_Model"
)
# Resultados
resultados <- rbind(resultados, var_row)
resultados <- resultados %>%
arrange(AIC, RMSE)
head(resultados, 3)
## AIC RMSE
## VAR_Model 788.8765 35666.29
## ARMA(2,1) 1823.5234 36207.99
## ARMA(1,2) 1823.9565 36343.22
Se decidió realizar el pronóstico para 8 periodos es decir para 2 años, ya que consideramos que un análisis de 8 trimestres podría permitir a las empresas interesadas, evaluar tendencias a mediano plazo y así evitar que se tomen decisiones basadas solo en variaciones a corto plazo, asímismo con los resultados del modelo, identificamos que la predicción a corto plazo parece ser más volátil, por lo que se tomo como punto de referencia, a poder analizar otros periodos a mediano plazo.
Se calculó el promedio de New_FDI_Inflows, y comparando los intervalos resultantes de cada periodo del modelo, el modelo VAR parece capturar bien el promedio general, aunque muestra ciertas fluctuaciones en los primeros 3 periodos, sin embargo, a partir del 4to periodo , los valores se acercan mucho a la media, por lo que, el modelo podría estar adaptándose más hacia un valor más estable de la media de la serie original, a partir de analizar más periodos, es decir, que después de 3 trimestres, se lograría obtener estabilidad.
media_newfdi<- mean(df$New_FDI_Inflows)
media_newfdi
## [1] 50554.58
# Pronóstico para 8 periodos
forecast_var <- predict(var_model, n.ahead = 8, ci = 0.95)
fanchart(forecast_var, names = "New_FDI_Inflows", main = "Forecast - New_FDI_Inflows", xlab = "Time", ylab = "New_FDI_Inflows")
print(forecast_var$fcst$New_FDI_Inflows)
## fcst lower upper CI
## [1,] 39042.01 -38301.026 116385.1 77343.04
## [2,] 69004.75 -9398.352 147407.8 78403.10
## [3,] 62590.19 -16748.218 141928.6 79338.40
## [4,] 50544.04 -31769.358 132857.4 82313.40
## [5,] 58559.70 -24087.430 141206.8 82647.13
## [6,] 56574.18 -26521.152 139669.5 83095.34
## [7,] 49382.97 -34177.743 132943.7 83560.71
## [8,] 51695.75 -32008.606 135400.1 83704.36
Aunque existe incertidumbre, la tendencia general favorece el crecimiento de la IED en México, con riesgos asociados a la volatilidad económica y política.
Escenario optimista: La IED crecería significativamente, superando las 135,000 unidades, impulsada por condiciones favorables en inversión extranjera y estabilidad macroeconómica.
Escenario realista: Se espera que la IED fluctúe entre 39,042 y 69,004 unidades, con la mayoría de los valores superando la media histórica, lo que indicaría un crecimiento sostenido, aunque con cierta incertidumbre.
Escenario pesimista: La IED podría caer hasta -38,301 unidades, lo que reflejaría un retroceso preocupante debido a posibles factores adversos en la economía y el entorno político.
# Crear un data frame con los escenarios
escenarios_df <- data.frame(
Periodo = 1:8,
Escenario_Pesimista = forecast_var$fcst$New_FDI_Inflows[, "lower"], # Límite inferior
Escenario_Real = forecast_var$fcst$New_FDI_Inflows[, "fcst"], # Predicción central
Escenario_Optimo = forecast_var$fcst$New_FDI_Inflows[, "upper"] # Límite superior
)
# Imprimir los escenarios
print(escenarios_df)
## Periodo Escenario_Pesimista Escenario_Real Escenario_Optimo
## 1 1 -38301.026 39042.01 116385.1
## 2 2 -9398.352 69004.75 147407.8
## 3 3 -16748.218 62590.19 141928.6
## 4 4 -31769.358 50544.04 132857.4
## 5 5 -24087.430 58559.70 141206.8
## 6 6 -26521.152 56574.18 139669.5
## 7 7 -34177.743 49382.97 132943.7
## 8 8 -32008.606 51695.75 135400.1
# Graficar los escenarios
library(ggplot2)
ggplot(escenarios_df, aes(x = Periodo)) +
geom_line(aes(y = Escenario_Pesimista, color = "Pesimista"), size = 1, linetype = "dashed") +
geom_line(aes(y = Escenario_Real, color = "Real"), size = 1) +
geom_line(aes(y = Escenario_Optimo, color = "Óptimo"), size = 1, linetype = "dashed") +
labs(title = "Escenarios de New_FDI_Inflows",
x = "Periodo", y = "New_FDI_Inflows") +
scale_color_manual(values = c("Pesimista" = "red", "Real" = "blue", "Óptimo" = "green")) +
theme_minimal()
El M-fluctuation test (CUSUM) evalúa si los coeficientes del modelo VAR se mantienen estables a lo largo del tiempo. En este caso, el p-valor es 0.3872 (mayor a 0.05), por lo que no hay evidencia de cambio estructural. Por lo tanto, la prueba de fluctuación (CUSUM) no encuentra cambios estructurales conforme al tiempo, lo cual coincide con el valor de la Prueba Chow la cual determina que no se detecta un cambio estructural en la regresión.
library(strucchange)
roots(var_model) # Las raíces deben estar dentro del círculo unitario
## [1] 0.9353466 0.9353466 0.8554082 0.6589002 0.6589002 0.6359199 0.6359199
## [8] 0.6251523 0.6251523 0.5894189 0.5894189 0.2383855
cusum_test <- sctest(var_model, type = "OLS-CUSUM")
print(cusum_test)
##
## M-fluctuation test
##
## data: var_model
## f(efp) = 1.6376, p-value = 0.3872
Los modelos de series de tiempo aplicados en este análisis han permitido examinar el comportamiento de los flujos de IED en México y su posible relación con factores macroeconómicos. El modelo VAR mostró ser el mejor en términos de desempeño, al no presentar autocorrelación en los residuos y tener un menor AIC en comparación con otros modelos.
En términos de causalidad, los resultados sugieren que las variables macroeconómicas seleccionadas (tipo de cambio, INPC y exportaciones) no tienen una relación causal fuerte con los flujos de IED en el corto plazo. Sin embargo, se observa que INPC y Exports podrían tener un impacto en la variable dependiente en el tercer rezago, aunque la evidencia estadística no es concluyente.
Sobre si sucederá o no el nearshoring:
Con base en el análisis de series de tiempo y el pronóstico de nueva inversión extranjera directa, concluimos que en los próximos dos años el nearshoring no ocurrirá de manera significativa ni mostrará un aumento drástico en los flujos de inversión.
Solo en 2 de los 8 trimestres proyectados, la Nueva IED se mantiene por encima del umbral de 60,666 unidades (media histórica de New_FDI_Inflows + 20%).
La tendencia general indica que la IED se mantendrá en niveles estables, con ligeros picos de aumento, pero sin una consolidación clara del nearshoring en el corto plazo.
Es posible que en un futuro posterior a los próximos dos años New_FDI_Inflows experimente un mayor aumento, pero bajo este umbral, no se espera que el nearshoring ocurra significativamente en los próximos dos años.
Sobre el nearshoring en los próximos años: Se realizó el pronóstico para los próximos dos años. Los escenarios muestran incertidumbre, pero con una tendencia que favorece el crecimiento de la IED en el país.
En un escenario óptimo, la IED podría alcanzar valores superiores a 135,000 unidades.
En un escenario realista, los valores proyectados oscilan entre 39,042 y 69,004 unidades, con la mayoría de los trimestres por encima de la media histórica.
En un escenario pesimista, la IED podría caer hasta -38,301 unidades, lo que indicaría un retroceso en la inversión si las condiciones macroeconómicas y políticas son desfavorables.
Villegas Tello, R. (4 de Abril, 2021). RPubs - Series de Tiempo. Consultado el 24 de Febrero de 2025, de Rpubs.com Sitio Web: https://rpubs.com/revite19/749499
IMCO. (Enero, 2024). Nearshoring: The impact on FDI in Mexico. Consultado el 24 de Febrero de 2025, de IMCO, Sitio Web: https://imco.org.mx/en/wp-content/uploads/2024/04/IMCO_NearshoringIED.pdf