Ver código
library(dplyr)
library(ggplot2)
library(lubridate)
library(corrplot)
library(broom)
library(knitr)
library(gridExtra)
library(gt)
library(scales)
library(purrr)
library(tibble)
library(tidyr)
options(scipen = 999)Análisis Empírico del Período 2022-2025 con Diferencias Logarítmicas
En contextos económicos caracterizados por alta inflación y volatilidad cambiaria, los inversionistas buscan activos que puedan preservar su poder adquisitivo. Este estudio examina si el Índice Bursátil de Caracas (IBC) ha funcionado como una cobertura efectiva contra la inflación y la devaluación monetaria en Venezuela durante el período 2022-2025.
La teoría financiera, específicamente el efecto Fisher, sugiere que los activos financieros deben ajustarse proporcionalmente a los cambios en el nivel general de precios. Esta relación se puede expresar como una elasticidad, donde el coeficiente indica qué porcentaje cambia el activo por cada 1% de cambio en los precios.
El efecto Fisher postula que en equilibrio, las tasas de interés nominales (y por extensión, los precios de los activos financieros) se ajustan para reflejar las expectativas de inflación. En su formulación moderna para mercados de capitales, esto se expresa como:
\[\Delta \ln(P_t) = \alpha + \beta \cdot \Delta \ln(I_t) + \varepsilon_t\]
donde:
- \(P_t\) es el precio del activo financiero (IBC)
- \(I_t\) es el índice de precios (INPC)
- \(\beta\) es la elasticidad de Fisher, que mide la respuesta proporcional del activo ante cambios en los precios.
Si \(\beta = 1\), el activo proporciona una cobertura perfecta contra la inflación. Si \(\beta > 1\), proporciona una cobertura superior. Si \(0 < \beta < 1\), proporciona cobertura parcial.
Mientras que el análisis estático proporciona una visión general del período completo, el análisis dinámico mediante ventanas móviles revela cómo la efectividad de cobertura evoluciona temporalmente. Este enfoque es crucial para identificar períodos de mayor o menor eficiencia del instrumento financiero.
El análisis se basa en modelos de regresión lineal que relacionan las variaciones logarítmicas del IBC con las de las variables explicativas:
Modelo Base: Δln(IBC) = α + β·Δln(Variable) + ε
Donde: - Δln representa la variación logarítmica (variación porcentual) - β es el coeficiente de elasticidad de interés - α es la constante del modelo - ε es el término de error
El estudio examina tres relaciones fundamentales:
Este análisis busca responder tres preguntas fundamentales:
library(dplyr)
library(ggplot2)
library(lubridate)
library(corrplot)
library(broom)
library(knitr)
library(gridExtra)
library(gt)
library(scales)
library(purrr)
library(tibble)
library(tidyr)
options(scipen = 999)df_IBC <- read.csv("df_IBC.csv")
INFLA <- read.csv("INFLA.csv")
TC <- read.csv("TC.csv")
df_IBC$fecha <- as.Date(df_IBC$fecha)
INFLA$fecha <- as.Date(INFLA$fecha)
TC$fecha <- as.Date(TC$fecha)datos_completos <- df_IBC %>%
left_join(INFLA, by = "fecha") %>%
left_join(TC, by = "fecha") %>%
arrange(fecha) %>%
na.omit()
datos_analisis <- datos_completos %>%
mutate(
ln_ibc = log(Indice_Bursatil),
ln_inpc = log(INPC),
ln_tc_oficial = log(Oficial),
ln_tc_paralelo = log(Paralelo),
delta_ln_ibc = ln_ibc - lag(ln_ibc),
delta_ln_inpc = ln_inpc - lag(ln_inpc),
delta_ln_tc_oficial = ln_tc_oficial - lag(ln_tc_oficial),
delta_ln_tc_paralelo = ln_tc_paralelo - lag(ln_tc_paralelo),
cambio_ibc_pct = (Indice_Bursatil / lag(Indice_Bursatil) - 1) * 100,
inflacion_mensual_pct = (INPC / lag(INPC) - 1) * 100,
ibc_real = Indice_Bursatil / (INPC / first(INPC)),
ibc_usd_oficial = Indice_Bursatil / Oficial,
ibc_usd_paralelo = Indice_Bursatil / Paralelo,
ibc_acumulado = (Indice_Bursatil / first(Indice_Bursatil)) * 100,
inflacion_acumulada = (INPC / first(INPC)) * 100,
devaluacion_oficial_acum = (Oficial / first(Oficial)) * 100,
devaluacion_paralelo_acum = (Paralelo / first(Paralelo)) * 100,
año = year(fecha),
periodo = as.character(year(fecha))
) %>%
slice(-1)Las diferencias logarítmicas tienen una interpretación directa como tasas de crecimiento continuas. Para cambios pequeños, \(\Delta \ln(X) \approx \frac{\Delta X}{X}\), pero para cambios grandes (como los observados en Venezuela), la diferencia logarítmica es más precisa y permite una interpretación de elasticidad válida.
modelo_elasticidad_inflacion <- lm(delta_ln_ibc ~ delta_ln_inpc, data = datos_analisis)
elasticidad_inflacion <- coef(modelo_elasticidad_inflacion)[2]
r_cuadrado_inflacion <- summary(modelo_elasticidad_inflacion)$r.squared
p_valor_inflacion <- summary(modelo_elasticidad_inflacion)$coefficients[2,4]
interpretacion_elasticidad <- case_when(
elasticidad_inflacion >= 1 ~ "cobertura perfecta o superior",
elasticidad_inflacion > 0 ~ "cobertura parcial",
TRUE ~ "no proporciona cobertura"
)
tidy(modelo_elasticidad_inflacion) %>%
mutate(
term = case_when(
term == "(Intercept)" ~ "Intercepto (α)",
term == "delta_ln_inpc" ~ "Elasticidad Inflación (β)",
TRUE ~ term
)
) %>%
gt() %>%
tab_header(
title = "Elasticidad del IBC Respecto a la Inflación",
subtitle = "Modelo: Δln(IBC) = α + β·Δln(INPC) + ε"
) %>%
fmt_number(columns = c(estimate, std.error, statistic), decimals = 4) %>%
fmt_scientific(columns = p.value, decimals = 3) %>%
cols_label(
term = "Parámetro",
estimate = "Coeficiente",
std.error = "Error Estándar",
statistic = "Estadístico t",
p.value = "Valor p"
) %>%
tab_footnote(
footnote = "β representa la elasticidad: % de cambio en IBC por cada 1% de cambio en INPC"
)| Elasticidad del IBC Respecto a la Inflación | ||||
|---|---|---|---|---|
| Modelo: Δln(IBC) = α + β·Δln(INPC) + ε | ||||
| Parámetro | Coeficiente | Error Estándar | Estadístico t | Valor p |
| Intercepto (α) | 0.0559 | 0.0264 | 2.1182 | 4.094 × 10−2 |
| Elasticidad Inflación (β) | 0.5521 | 0.2252 | 2.4513 | 1.908 × 10−2 |
| β representa la elasticidad: % de cambio en IBC por cada 1% de cambio en INPC | ||||
Interpretación de la Elasticidad:
El coeficiente β = 0.5521 indica que por cada 1% de aumento en los precios (INPC), el IBC cambia en promedio 0.5521%. Esto sugiere que el IBC proporciona cobertura parcial contra la inflación. El R² de 0.1397 indica que 14% de la variabilidad en el IBC se explica por cambios en los precios.
modelo_elasticidad_oficial <- lm(delta_ln_ibc ~ delta_ln_tc_oficial, data = datos_analisis)
modelo_elasticidad_paralelo <- lm(delta_ln_ibc ~ delta_ln_tc_paralelo, data = datos_analisis)
resultados_devaluacion <- bind_rows(
tidy(modelo_elasticidad_oficial) %>% mutate(modelo = "Oficial"),
tidy(modelo_elasticidad_paralelo) %>% mutate(modelo = "Paralelo")
) %>%
filter(term != "(Intercept)") %>%
select(modelo, estimate, std.error, p.value) %>%
gt() %>%
tab_header(
title = "Elasticidades del IBC Respecto a Tipos de Cambio",
subtitle = "Modelos: Δln(IBC) = α + β·Δln(TC) + ε"
) %>%
fmt_number(columns = c(estimate, std.error), decimals = 4) %>%
fmt_scientific(columns = p.value, decimals = 3) %>%
cols_label(
modelo = "Tipo de Cambio",
estimate = "Elasticidad (β)",
std.error = "Error Estándar",
p.value = "Valor p"
) %>%
tab_footnote(
footnote = "β representa la elasticidad: % de cambio en IBC por cada 1% de devaluación"
)
resultados_devaluacion| Elasticidades del IBC Respecto a Tipos de Cambio | |||
|---|---|---|---|
| Modelos: Δln(IBC) = α + β·Δln(TC) + ε | |||
| Tipo de Cambio | Elasticidad (β) | Error Estándar | Valor p |
| Oficial | 0.7443 | 0.1607 | 4.398 × 10−5 |
| Paralelo | 0.8723 | 0.1369 | 1.987 × 10−7 |
| β representa la elasticidad: % de cambio en IBC por cada 1% de devaluación | |||
# Parámetro: tamaño de la ventana en meses
ventana_meses <- 6
# Creamos un data.frame para almacenar resultados dinámicos
elasticidades_dinamicas <- tibble()
fechas_unicas <- unique(datos_analisis$fecha)
for (i in seq_along(fechas_unicas)) {
fecha_final <- fechas_unicas[i]
fecha_inicial <- fecha_final %m-% months(ventana_meses-1)
datos_ventana <- datos_analisis %>%
filter(fecha >= fecha_inicial & fecha <= fecha_final)
if (nrow(datos_ventana) >= 4) {
# Estimamos elasticidades en la ventana
modelo_inflacion <- lm(delta_ln_ibc ~ delta_ln_inpc, data = datos_ventana)
modelo_tc_oficial <- lm(delta_ln_ibc ~ delta_ln_tc_oficial, data = datos_ventana)
modelo_tc_paralelo <- lm(delta_ln_ibc ~ delta_ln_tc_paralelo, data = datos_ventana)
elasticidades_dinamicas <- bind_rows(
elasticidades_dinamicas,
tibble(
fecha = fecha_final,
elasticidad_inflacion = coef(modelo_inflacion)[2],
elasticidad_tc_oficial = coef(modelo_tc_oficial)[2],
elasticidad_tc_paralelo = coef(modelo_tc_paralelo)[2]
)
)
}
}grafico_elasticidades_temporales <- elasticidades_dinamicas %>%
select(fecha, elasticidad_inflacion, elasticidad_tc_oficial, elasticidad_tc_paralelo) %>%
pivot_longer(cols = -fecha, names_to = "variable", values_to = "elasticidad") %>%
mutate(
variable = case_when(
variable == "elasticidad_inflacion" ~ "Inflación",
variable == "elasticidad_tc_oficial" ~ "TC Oficial",
variable == "elasticidad_tc_paralelo" ~ "TC Paralelo"
)
) %>%
ggplot(aes(x = fecha, y = elasticidad, color = variable)) +
geom_hline(yintercept = 1, linetype = "dashed", color = "gray40", alpha = 0.8) +
geom_hline(yintercept = 0, linetype = "solid", color = "gray60", alpha = 0.6) +
geom_line(aes(group = variable), alpha = 0.7, size = 0.8) +
geom_smooth(aes(group = variable), method = "loess", se = TRUE, alpha = 0.2, size = 1.2) +
scale_color_manual(values = c("Inflación" = "#2E86AB", "TC Oficial" = "#A23B72", "TC Paralelo" = "#F18F01")) +
scale_x_date(date_labels = "%Y-%m", date_breaks = "4 months") +
labs(
title = "Evolución Temporal de Elasticidades del IBC",
subtitle = paste("Ventanas móviles de", ventana_meses, "meses | Línea punteada: cobertura perfecta (β=1)"),
x = "Período",
y = "Elasticidad (β)",
color = "Variable",
caption = "Interpretación: β > 1 indica sobrecobertura; β = 1 cobertura perfecta; β < 1 cobertura parcial"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom",
panel.grid.minor = element_blank()
) +
annotate("text", x = min(elasticidades_dinamicas$fecha) + lubridate::days(60), y = 1.1,
label = "β = 1: Cobertura Perfecta", size = 3, color = "gray40")
print(grafico_elasticidades_temporales)modelo_elasticidad_completo <- lm(delta_ln_ibc ~ delta_ln_inpc + delta_ln_tc_oficial + delta_ln_tc_paralelo,
data = datos_analisis)
r_cuadrado_completo <- summary(modelo_elasticidad_completo)$r.squared
tidy(modelo_elasticidad_completo) %>%
filter(term != "(Intercept)") %>%
mutate(
term = case_when(
term == "delta_ln_inpc" ~ "Elasticidad Inflación (β₁)",
term == "delta_ln_tc_oficial" ~ "Elasticidad TC Oficial (β₂)",
term == "delta_ln_tc_paralelo" ~ "Elasticidad TC Paralelo (β₃)",
TRUE ~ term
)
) %>%
gt() %>%
tab_header(
title = "Modelo Multivariable de Elasticidades del IBC",
subtitle = "Efectos simultáneos de inflación y devaluación"
) %>%
fmt_number(columns = c(estimate, std.error, statistic), decimals = 4) %>%
fmt_scientific(columns = p.value, decimals = 3) %>%
cols_label(
term = "Parámetro",
estimate = "Elasticidad",
std.error = "Error Estándar",
statistic = "Estadístico t",
p.value = "Valor p"
) %>%
tab_footnote(
footnote = "Cada elasticidad representa el % de cambio en IBC por cada 1% de cambio en la variable explicativa, manteniendo las demás constantes"
)| Modelo Multivariable de Elasticidades del IBC | ||||
|---|---|---|---|---|
| Efectos simultáneos de inflación y devaluación | ||||
| Parámetro | Elasticidad | Error Estándar | Estadístico t | Valor p |
| Elasticidad Inflación (β₁) | −0.0178 | 0.2364 | −0.0752 | 9.405 × 10−1 |
| Elasticidad TC Oficial (β₂) | 0.0334 | 0.3011 | 0.1111 | 9.122 × 10−1 |
| Elasticidad TC Paralelo (β₃) | 0.8526 | 0.2538 | 3.3590 | 1.899 × 10−3 |
| Cada elasticidad representa el % de cambio en IBC por cada 1% de cambio en la variable explicativa, manteniendo las demás constantes | ||||
modelo_sensibilidad <- lm(cambio_ibc_pct ~ inflacion_mensual_pct, data = datos_analisis)
comparacion_modelos <- bind_rows(
tidy(modelo_elasticidad_inflacion) %>%
filter(term != "(Intercept)") %>%
mutate(modelo = "Elasticidad (log-log)",
interpretacion = "% cambio IBC por 1% cambio INPC"),
tidy(modelo_sensibilidad) %>%
filter(term != "(Intercept)") %>%
mutate(modelo = "Sensibilidad (nivel-nivel)",
interpretacion = "Puntos porcentuales cambio IBC por 1pp inflación")
) %>%
select(modelo, estimate, std.error, p.value, interpretacion) %>%
gt() %>%
tab_header(
title = "Comparación de Enfoques Metodológicos",
subtitle = "Elasticidad vs. Sensibilidad del IBC ante Inflación"
) %>%
fmt_number(columns = c(estimate, std.error), decimals = 4) %>%
fmt_scientific(columns = p.value, decimals = 3) %>%
cols_label(
modelo = "Enfoque",
estimate = "Coeficiente",
std.error = "Error Estándar",
p.value = "Valor p",
interpretacion = "Interpretación"
)
comparacion_modelos| Comparación de Enfoques Metodológicos | ||||
|---|---|---|---|---|
| Elasticidad vs. Sensibilidad del IBC ante Inflación | ||||
| Enfoque | Coeficiente | Error Estándar | Valor p | Interpretación |
| Elasticidad (log-log) | 0.5521 | 0.2252 | 1.908 × 10−2 | % cambio IBC por 1% cambio INPC |
| Sensibilidad (nivel-nivel) | 0.5474 | 0.2292 | 2.217 × 10−2 | Puntos porcentuales cambio IBC por 1pp inflación |
variables_correlacion <- datos_analisis %>%
select(delta_ln_ibc, delta_ln_inpc, delta_ln_tc_oficial, delta_ln_tc_paralelo) %>%
na.omit()
colnames(variables_correlacion) <- c("Δln(IBC)", "Δln(INPC)", "Δln(TC Oficial)", "Δln(TC Paralelo)")
matriz_correlacion <- cor(variables_correlacion)
corrplot(matriz_correlacion,
method = "color",
type = "upper",
addCoef.col = "black",
tl.col = "black",
tl.srt = 45,
title = "Matriz de Correlaciones entre Diferencias Logarítmicas",
mar = c(0,0,2,0))matriz_correlacion %>%
as.data.frame() %>%
rownames_to_column("Variable") %>%
gt() %>%
tab_header(title = "Matriz de Correlaciones Detallada") %>%
fmt_number(columns = -Variable, decimals = 4)| Matriz de Correlaciones Detallada | ||||
|---|---|---|---|---|
| Variable | Δln(IBC) | Δln(INPC) | Δln(TC Oficial) | Δln(TC Paralelo) |
| Δln(IBC) | 1.0000 | 0.3738 | 0.6057 | 0.7232 |
| Δln(INPC) | 0.3738 | 1.0000 | 0.6795 | 0.5197 |
| Δln(TC Oficial) | 0.6057 | 0.6795 | 1.0000 | 0.8299 |
| Δln(TC Paralelo) | 0.7232 | 0.5197 | 0.8299 | 1.0000 |
inversion_inicial <- 1000
resultados_inversion <- datos_analisis %>%
mutate(
valor_ibc = inversion_inicial * (ibc_acumulado / 100),
valor_efectivo = inversion_inicial,
valor_efectivo_real = inversion_inicial / (inflacion_acumulada / 100),
valor_usd_oficial = inversion_inicial / first(Oficial) * Oficial,
valor_usd_paralelo = inversion_inicial / first(Paralelo) * Paralelo,
poder_adquisitivo_ibc = valor_ibc / (inflacion_acumulada / 100),
poder_adquisitivo_efectivo = valor_efectivo_real,
poder_adquisitivo_usd_oficial = valor_usd_oficial / (inflacion_acumulada / 100),
poder_adquisitivo_usd_paralelo = valor_usd_paralelo / (inflacion_acumulada / 100)
)
resultado_final <- resultados_inversion %>%
slice_tail(n = 1)
data.frame(
Estrategia = c("IBC", "Efectivo", "USD Oficial", "USD Paralelo"),
Valor_Final_Bs = c(resultado_final$valor_ibc,
resultado_final$valor_efectivo,
resultado_final$valor_usd_oficial,
resultado_final$valor_usd_paralelo),
Poder_Adquisitivo_Real = c(resultado_final$poder_adquisitivo_ibc,
resultado_final$poder_adquisitivo_efectivo,
resultado_final$poder_adquisitivo_usd_oficial,
resultado_final$poder_adquisitivo_usd_paralelo),
Rendimiento_Real = c((resultado_final$poder_adquisitivo_ibc / inversion_inicial - 1) * 100,
(resultado_final$poder_adquisitivo_efectivo / inversion_inicial - 1) * 100,
(resultado_final$poder_adquisitivo_usd_oficial / inversion_inicial - 1) * 100,
(resultado_final$poder_adquisitivo_usd_paralelo / inversion_inicial - 1) * 100)
) %>%
gt() %>%
tab_header(
title = "Comparación de Estrategias de Inversión",
subtitle = paste("Inversión inicial: 1,000 Bs (enero 2022) - Resultados al",
format(resultado_final$fecha, "%B %Y"))
) %>%
fmt_number(
columns = c(Valor_Final_Bs, Poder_Adquisitivo_Real),
decimals = 0,
pattern = "Bs {x}"
) %>%
fmt_number(columns = Rendimiento_Real, decimals = 1, pattern = "{x}%") %>%
cols_label(
Estrategia = "Estrategia",
Valor_Final_Bs = "Valor Final",
Poder_Adquisitivo_Real = "Poder Adquisitivo Real (Base 2022)",
Rendimiento_Real = "Rendimiento Real"
) %>%
data_color(
columns = Rendimiento_Real,
colors = scales::col_numeric(
palette = c("red", "white", "green"),
domain = NULL
)
)| Comparación de Estrategias de Inversión | |||
|---|---|---|---|
| Inversión inicial: 1,000 Bs (enero 2022) - Resultados al May 2025 | |||
| Estrategia | Valor Final | Poder Adquisitivo Real (Base 2022) | Rendimiento Real |
| IBC | Bs 54,847 | Bs 2,019 | 101.9% |
| Efectivo | Bs 1,000 | Bs 37 | −96.3% |
| USD Oficial | Bs 22,596 | Bs 832 | −16.8% |
| USD Paralelo | Bs 25,557 | Bs 941 | −5.9% |
grafico_elasticidad <- ggplot(datos_analisis, aes(x = delta_ln_inpc, y = delta_ln_ibc)) +
geom_point(alpha = 0.6, color = "#2E86AB", size = 2) +
geom_smooth(method = "lm", se = TRUE, color = "#C73E1D", fill = "#C73E1D", alpha = 0.2) +
labs(
title = "Elasticidad del IBC Respecto a la Inflación",
subtitle = paste("Elasticidad estimada:", round(elasticidad_inflacion, 4)),
x = "Δln(INPC) - Tasa de crecimiento de precios",
y = "Δln(IBC) - Tasa de crecimiento del índice bursátil",
caption = "La línea roja representa la elasticidad estimada con intervalo de confianza del 95%"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12),
axis.title = element_text(size = 11)
)
print(grafico_elasticidad)grafico_poder_adquisitivo <- ggplot(resultados_inversion, aes(x = fecha)) +
geom_line(aes(y = poder_adquisitivo_ibc, color = "IBC"), size = 1.2) +
geom_line(aes(y = poder_adquisitivo_efectivo, color = "Efectivo"), size = 1.2) +
geom_line(aes(y = poder_adquisitivo_usd_oficial, color = "USD Oficial"), size = 1.2) +
geom_line(aes(y = poder_adquisitivo_usd_paralelo, color = "USD Paralelo"), size = 1.2) +
geom_hline(yintercept = inversion_inicial, linetype = "dashed", alpha = 0.7, color = "gray50") +
annotate("text", x = min(resultados_inversion$fecha), y = inversion_inicial + 50,
label = "Inversión inicial", hjust = 0, color = "gray50") +
scale_color_manual(
values = c("IBC" = "#2E86AB", "Efectivo" = "#A23B72",
"USD Oficial" = "#F18F01", "USD Paralelo" = "#C73E1D")
) +
scale_y_continuous(labels = scales::comma_format()) +
labs(
title = "Evolución del Poder Adquisitivo Real por Estrategia",
subtitle = "Inversión inicial: 1,000 Bs (enero 2022)",
x = "Fecha",
y = "Poder Adquisitivo (Bs constantes enero 2022)",
color = "Estrategia",
caption = "Fuente: Elaboración propia basada en datos del IBC, INPC y tipos de cambio"
) +
theme_minimal() +
theme(
legend.position = "bottom",
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12),
axis.title = element_text(size = 11)
)
print(grafico_poder_adquisitivo)El análisis integral de elasticidades del IBC revela un instrumento financiero con capacidad de cobertura limitada e inconsistente. Mientras que proporciona algún grado de protección contra inflación y devaluación en promedio, su efectividad varía considerablemente a lo largo del tiempo.
La metodología de análisis dinámico demuestra ser superior al enfoque estático tradicional, ya que revela patrones temporales críticos que no son visibles en promedios de largo plazo. Esta variabilidad temporal constituye un factor de riesgo adicional que debe ser considerado en decisiones de inversión y estrategias de cobertura.