Ficha Técnica - Desembolsos

Author

Análisis y Estudios Económicos - Fonplata

Metodología

Muestra de datos

Fuentes:

Para obtener los datos de desembolsos de los multilaterales revisados se uso la base de datos de transacciones de IATI (International Aid Transparency Iniciative) y para obtener la información de las aprobaciones se usaron las BDD proporcionadas por cada Banco Multilateral.

Rango de tiempo:

Proyectos de inversión que han sido aprobados desde 2003 hasta 2024.

Estadísticas Descriptivas

Banco Mundial

Para el Banco Mundial se usaron transacciones por desembolsos 59.122 obs. y para las aprobaciones 1.671 obs. de proyectos de inversión con riesgo soberano. (IBRD e IDA)

Número de proyectos de inversión por:

Banco Interamericano de Desarrollo

Para el BID se usaron transacciones por desembolsos 25.889 obs. y para las aprobaciones 1.980 obs. de proyectos de inversión (ESP - GOM - TCR - LBR) con riesgo soberano.

Número de proyectos de inversión por:

Banco Asiático de Desarrollo

Para el ASDB se usaron transacciones por desembolsos 33.807 obs. y para las aprobaciones 1.084 obs. de proyectos de inversión con riesgo soberano.

Modelo

Curva Histórica de Desembolsos

Modelo de crecimiento logístico

La ecuación es dada por:

d = \frac{b_0}{1 + e^{-(b_1 + b_2 k)}}

  • d es igual a la proporción total desembolsada después de k (meses)

  • k representa el tiempo transcurrido en meses desde la aprobación de un proyecto

Entonces la curva historica de desembolsos histórica hd(k) esta dada por:

hd(k) = \hat{b}_0 + \frac{1}{1 + \hat{b}_2 e^{-\hat{b}_1 k}}

Curva histórica de desembolsos individual

Para la estimación de coeficientes para cada país, se utilizaron como valores iniciales de los parámetros el valor de los coeficientes del el Banco Multilateral en su conjunto.

Desviaciones

Para cada proyecto se computo la desviación respecto a la curva histórica de desembolsos para cada Banco Multilateral.

Que se da como la diferencia entre la proporción desembolsada y la curva histórica:

y(k) = d(k) - hd(k)

Países Vs Sectores

Para evaluar el impacto relativo de los países y de los sectores en el desempeño de la curva de desembolsos, se llevo a cabo un análisis de regresión lineal. La variable dependiente fue la desviación del desempeño del proyecto respecto a hd(k).

y_k = \beta_0 + \sum_{i=1}^{C} \beta_i D_{\text{cat}_i} + \sum_{j=1}^{T} \gamma_j D_{\text{año}_j} + \epsilon

CodeBook

Manejo de la Base de Datos

## Se elimina los codificadores de IATI para obtner el ID a la base de datos de aprobaciones del Banco 
dataframe <- dataframe %>%
  mutate(iadb_id = str_remove(iatiidentifier, "XI-IATI-IADB-")) 

## Hacer un 'left join' de data_f1 con data_projects basado en 'id' y 'Project Number'
dataframe_combine <- left_join(dataframe, projects_bdd, by = c("id" = "Project Number"))

# Seleccionar las columnas específicas de la tabla resultante
dataframe_combine <- dataframe_combine %>%
  select(iadb_id,
         iatiidentifier,
         transactiontype_codename,
         transactiondate_isodate,
         sector_codename,
         recipientcountry_codename,
         recipientcountry_code,
         value_usd,
         defaultfinancetype_codename,
         activitystatus_codename,
         activityscope_codename,
         `Lending Type`, 
         `Project Type`, 
         `Approval Date`, 
         `Signature Date`, 
         `Status`, 
         `Modality Code`, 
         `Approval Amount`, 
         `Funding Source`)

Se procede a filtrar la BDD para obtener solo proyectos de inversión (Ejemplo BID)

# Filtrar el dataframe por los valores específicos en 'Modality Code'
inv_loans_iabd <- V2filter_iadb_combine %>%
  select(iadb_id,
         iatiidentifier,
         transactiontype_codename,
         transactiondate_isodate,
         sector_codename,
         recipientcountry_codename,
         recipientcountry_code,
         value_usd,
         defaultfinancetype_codename,
         activitystatus_codename,
         activityscope_codename,
         `Lending Type`, 
         `Project Type`, 
         `Approval Date`, 
         `Signature Date`, 
         `Status`, 
         `Modality Code`, 
         `Approval Amount`, 
         `Funding Source`) %>%
  filter(`Modality Code` %in% c("ESP", "GOM", "TCR", "LBR"))

Filtrar por el rango de tiempo 2003-2023

# Convertir 'Approval Date' a formato de fecha y filtrar el dataframe
invloans_time <- inv_loans_iabd %>%
  mutate(`Approval Date` = as.Date(`Approval Date`, format = "%Y-%m-%d")) %>%  # Asegúrate que el formato coincide con tus datos
  select(iadb_id,
         iatiidentifier,
         transactiontype_codename,
         transactiondate_isodate,
         sector_codename,
         recipientcountry_codename,
         recipientcountry_code,
         value_usd,
         defaultfinancetype_codename,
         activitystatus_codename,
         activityscope_codename,
         `Lending Type`, 
         `Project Type`, 
         `Approval Date`, 
         `Signature Date`, 
         `Status`, 
         `Modality Code`, 
         `Approval Amount`, 
         `Funding Source`) %>%
  filter(`Approval Date` >= as.Date("2003-01-01") & `Approval Date` <= as.Date("2023-12-31"))

Modificación de la BDD convirtiendola apta para el cálculo

# Convertir columnas de fecha
invloans_time$transactiondate_isodate <- as.Date(invloans_time$transactiondate_isodate, format = "%Y-%m-%d")
invloans_time$`Approval Date` <- as.Date(invloans_time$`Approval Date`, format = "%Y-%m-%d")

# Ordenar los datos por proyecto y fecha de transacción
datamodelo <- invloans_time %>%
  arrange(iadb_id, transactiondate_isodate)

Limpieza de datos



# Filtrar proyectos con d > 1.090000 o d es NA
# Primero identificamos los ID de los proyectos a eliminar
projects_to_remove <- v2datamodelo_sumary %>%
  filter(is.na(d) | d > 1.090000) %>%
  distinct(iadb_id)

# Si projects_to_remove está vacío, no se encontraron proyectos para eliminar
if(nrow(projects_to_remove) > 0) {
  # Eliminar todos los registros de esos proyectos de la base de datos original
  datamodelo_clean <- datamodelo %>%
    anti_join(projects_to_remove, by = "iadb_id")
} else {
  datamodelo_clean <- datamodelo
}

Elaboración del cálculo

Cálculo de “k” y “d”

datamodelo_clean <- mutate(datamodelo_clean, 
               Year = year(transactiondate_isodate), 
               End_Year_Date = as.Date(paste0(Year, "-12-31")))

# Filtrar transacciones que ocurren hasta el 31 de diciembre de cada año
# y calcular desembolsos acumulativos por proyecto hasta el 31 de diciembre de cada año
datamodelo_sumary_clean <- datamodelo_clean %>%
  group_by(iadb_id, Year) %>%
  filter(transactiondate_isodate <= End_Year_Date) %>%
  summarize(
    Cumulative_Disbursement_Year = sum(value_usd),
    Approval_Amount = first(`Approval Amount`),
    k
    = max(as.integer(interval(`Approval Date`, End_Year_Date) / months(1))),
    .groups = 'drop'
  )

# Calcular el desembolso acumulado total hasta cada año
v3datamodelo_sumary <- datamodelo_sumary_clean %>%
  arrange(iadb_id, Year) %>%
  group_by(iadb_id) %>%
  mutate(Cumulative_Disbursement_Total = cumsum(Cumulative_Disbursement_Year),
         d = Cumulative_Disbursement_Total / Approval_Amount)

Ejecución regresión

# Cargar librerías necesarias
library(minpack.lm)  # Para nlsLM, que maneja mejor los errores y problemas de convergencia

# Asegurarse de que 'v3datamodelo_sumary' tiene las columnas 'k' y 'd_observed'
# Ajustar el modelo logístico usando la fórmula correcta
model <- nlsLM(d ~ b0 + (1 / (1 + b2 * exp(-(b1 * k)))), 
               data = v3datamodelo_sumary, 
               start = list(b0 = 0, b1 = 0, b2 = 0),
               control = nls.lm.control(maxiter = 200))  # Aumentar iteraciones si es necesario

# Extraer los parámetros estimados
params <- coef(model)

Revisión de parametros

summary(model)

Caso BID

Formula: d ~ b0 + (1/(1 + b2 * exp(-(b1 * k))))

Parameters:
    Estimate Std. Error t value             Pr(>|t|)    
b0 -0.051657   0.015858  -3.258              0.00113 ** 
b1  0.040475   0.001047  38.641 < 0.0000000000000002 ***
b2  5.544292   0.406804  13.629 < 0.0000000000000002 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2668 on 4913 degrees of freedom

Number of iterations to convergence: 10 
Achieved convergence tolerance: 0.0000000149

Computo Curva Histórica de Desembolsos

#parámetros estimados
b0_hat <- -0.051657
b1_hat <- 0.040475
b2_hat <- 5.544292 
# Suponiendo que datamodelo_sumary tiene 'k'
v3datamodelo_sumary$hd_k <- b0_hat + 1 / (1 + b2_hat * exp(-b1_hat * v3datamodelo_sumary$k))
# Cargar la librería ggplot2
# Grafica de Curva de Desembolsos
library(ggplot2)

# Crear un gráfico de la curva de desembolsos histórica
ggplot(v3datamodelo_sumary, aes(x = k, y = hd_k)) +
  geom_line(color = "red", size = 1) +  # Dibuja una línea para representar hd(k)
  labs(title = "Historic Disbursement Curve hd(k) - BID",
       x = "Months Since Approval (k)",
       y = "Expected Disbursement Proportion (hd(k))") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))  # Centra el título del gráfico

Clasificación de proyectos

# Suponiendo que 'std_deviation' es la desviación estándar calculada de las desviaciones de desembolso
std_deviation <- sd(v3datamodelo_sumary$d - v3datamodelo_sumary$hd_k)

# Añadir límites al dataframe
v3datamodelo_sumary$upper_limit <- v3datamodelo_sumary$hd_k + 0.5 * std_deviation
v3datamodelo_sumary$lower_limit <- v3datamodelo_sumary$hd_k - 0.5 * std_deviation

# Clasificar cada proyecto
v3datamodelo_sumary$classification <- with(v3datamodelo_sumary, ifelse(d > upper_limit, "Above Average",
                                                ifelse(d < lower_limit, "Below Average", "Average")))

Filtración Proyectos Activos

# Realizar el merge basado en los identificadores de proyecto
data_actives_GRAFICO <- merge(v3datamodelo_sumary, modified_iadb_projects, 
                    by.x = "iadb_id", by.y = "Project Number", 
                    all.x = TRUE)

# Filtrar por el valor "ACTIVE" en la columna Status
data_actives_GRAFICO <- subset(data_actives_GRAFICO, Status == "ACTIVE")

Gráfica de curva histórica con clasificaciones


 #Graficar los resultados
p_activos <- ggplot(data_actives_GRAFICO, aes(x = k)) +
  geom_point(aes(y = d, color = classification), size = 1.5, alpha = 0.6) +
  geom_line(aes(y = hd_k, color = 'Historic Disbursement Curve'), size = 1) +
  geom_line(aes(y = upper_limit, color = 'Upper limit'), linetype = "dashed", size = 1) +
  geom_line(aes(y = lower_limit, color = 'Lower limit'), linetype = "dashed", size = 1) +
  scale_color_manual(values = c('Above Average' = '#2CA02C',  # Verde más claro
                                'Average' = '#1F77B4',        # Azul claro
                                'Below Average' = '#D62728',  # Rojo claro
                                'Historic Disbursement Curve' = 'black',
                                'Upper limit' = '#98DF8A',     # Verde pastel
                                'Lower limit' = '#FF9896')) +  # Rojo pastel
  scale_y_continuous(limits = c(0, 1)) +  # Ajustar el límite superior del eje y a 1
  labs(title = "Curva Historica de Desembolsos",
       subtitle = "Investment loans active 2024",
       x = "Months since approval",
       y = "Cumulative Disbursement (Prop. of Approved Amount)") +
  theme_minimal() +
  theme(legend.position = "bottom",
        legend.title = element_blank(),
        plot.title = element_text(size = 16, face = "bold"),
        plot.subtitle = element_text(size = 12),
        axis.text = element_text(size = 8),
        axis.title = element_text(size = 8, face = "bold"),
        legend.text = element_text(size = 7))

# Mostrar el gráfico
print(p_activos)