Guía rápida: Los chunks marcados con (GRÁFICO) generan figuras. El resto prepara datos/funciones/tablas.
Comparar el desempeño del índice Laspeyres de base
fija y del Laspeyres encadenado bajo distintos
escenarios de inflación y cambios en precios/cantidades.
El benchmark es un “volumen verdadero” construido solo
con cantidades.
La métrica de comparación es el RMSE de crecimientos
logarítmicos.
# Índices sobre matrices Q (cantidades) y P (precios)
idx_volumen_verdadero <- function(Q){
base <- sum(Q[,1]); 100 * colSums(Q) / base
}
idx_laspeyres_fijo <- function(Q, P){
p0 <- P[,1]; base <- sum(Q[,1] * p0); 100 * colSums(Q * p0) / base
}
idx_laspeyres_encadenado <- function(Q, P){
Tt <- ncol(Q); idx <- numeric(Tt); idx[1] <- 100
for(t in 2:Tt){
num <- sum(Q[,t] * P[,t-1]) # V_t a precios t-1
den <- sum(Q[,t-1] * P[,t-1]) # V_{t-1} a precios t-1
idx[t] <- idx[t-1] * (num/den)
}
idx
}
rmse_diff_log_growth <- function(idxA, idxB){
gA <- diff(log(idxA)); gB <- diff(log(idxB)); sqrt(mean((gA - gB)^2))
}
# Simulador de cantidades y precios (rápido y liviano)
simular_QP_mat <- function(
S=5, years=2022:2030,
qty0=c(100,200,400,120,180),
price0=c(1000,50,30,80,20),
mu_qty=c(0.03,0.02,0.025,0.015,0.02),
sd_qty=c(0.05,0.04,0.04,0.03,0.04),
mu_inflacion=0.10,
rel_price_drift=c(0.05,-0.03,0,0.02,-0.01),
sd_price=c(0.05,0.04,0.04,0.04,0.04),
shock_prob=0.10, shock_mean=-0.10, shock_sd=0.06
){
Tt <- length(years)
Q <- matrix(NA_real_, S, Tt); P <- matrix(NA_real_, S, Tt)
Q[,1] <- qty0; P[,1] <- price0
for(t in 2:Tt){
gq <- rnorm(S, mu_qty, sd_qty)
shocks <- rbinom(S, 1, shock_prob)
gq <- gq + shocks * rnorm(S, shock_mean, shock_sd)
Q[,t] <- pmax(Q[,t-1]*(1+gq), .Machine$double.eps)
gp <- rnorm(S, mu_inflacion + rel_price_drift, sd_price)
P[,t] <- pmax(P[,t-1]*(1+gp), .Machine$double.eps)
}
list(Q=Q, P=P, years=years)
}
# Evaluación Monte Carlo en grid de inflaciones
evaluar_corte_fast <- function(
inflaciones=c(seq(0,0.5,0.05),0.75,1,1.5,2,3,5),
R=200, years=2022:2030, rel_price_drift, seed=123
){
set.seed(seed)
out <- matrix(NA_real_, length(inflaciones), 3)
colnames(out) <- c("inflacion","rmse_fix","rmse_ch")
out[,1] <- inflaciones
for(i in seq_along(inflaciones)){
mu_inf <- inflaciones[i]; err_fix <- err_ch <- 0
for(r in 1:R){
sim <- simular_QP_mat(years=years, mu_inflacion=mu_inf,
rel_price_drift=rel_price_drift)
V <- idx_volumen_verdadero(sim$Q)
Lf<- idx_laspeyres_fijo(sim$Q, sim$P)
Lc<- idx_laspeyres_encadenado(sim$Q, sim$P)
err_fix <- err_fix + rmse_diff_log_growth(Lf, V)
err_ch <- err_ch + rmse_diff_log_growth(Lc, V)
}
out[i,2] <- err_fix/R; out[i,3] <- err_ch/R
}
tab <- as.data.frame(out)
tab$mejor <- ifelse(tab$rmse_ch < tab$rmse_fix, "Encadenado","Laspeyres fijo")
tab$inflacion_pct <- 100*tab$inflacion
tab
}
tabla <- evaluar_corte_fast(
inflaciones = c(seq(0,0.50,0.05), 0.75, 1.00, 1.50, 2.00, 3.00, 5.00),
R = 200, years = 2022:2030,
rel_price_drift = c(0.08,-0.05,0.00,0.03,-0.02)
)
# Solo mostramos columnas numéricas redondeadas
tabla_print <- within(tabla, {
inflacion <- round(inflacion, 3)
inflacion_pct <- round(inflacion_pct, 1)
rmse_fix <- round(rmse_fix, 4)
rmse_ch <- round(rmse_ch, 4)
})
tabla_print
# (GRÁFICO) RMSE vs Inflación
plot(tabla$inflacion_pct, tabla$rmse_ch, type="b", pch=19,
ylim=range(c(tabla$rmse_ch, tabla$rmse_fix)),
xlab="Inflación anual (%)", ylab="RMSE de crecimientos log",
main="Error vs Inflación — con drift de precios relativos")
lines(tabla$inflacion_pct, tabla$rmse_fix, type="b", pch=17)
legend("topleft", legend=c("Encadenado","Laspeyres fijo"),
pch=c(19,17), lty=1, bty="n")
# (GRÁFICO) Diferencia de error: Encadenado - Fijo (negativo = mejor Encadenado)
plot(tabla$inflacion_pct, tabla$rmse_ch - tabla$rmse_fix, type="b", pch=19,
xlab="Inflación anual (%)", ylab="ΔRMSE (Encadenado - Fijo)",
main="Diferencia de error (negativo = mejor Encadenado)")
abline(h=0, lty=2)
# Punto de corte donde conviene Fijo (si existe)
candidatas <- subset(tabla, rmse_fix <= rmse_ch)
if(nrow(candidatas)==0){
corte_txt_a <- "En todo el rango, el Encadenado tuvo menor error."
} else {
corte <- candidatas[which.min(candidatas$inflacion), ]
corte_txt_a <- sprintf("Corte ≈ %.0f%% anual: desde ahí conviene Laspeyres fijo.",
100*corte$inflacion)
}
corte_txt_a
## [1] "Corte ≈ 0% anual: desde ahí conviene Laspeyres fijo."
tabla_no_drift <- evaluar_corte_fast(
inflaciones = c(seq(0,0.50,0.05), 0.75, 1.00, 1.50, 2.00, 3.00, 5.00),
R = 200, years = 2022:2030,
rel_price_drift = c(0,0,0,0,0)
)
# Resumen de quién gana
table(tabla_no_drift$mejor)
##
## Encadenado Laspeyres fijo
## 10 7
# (GRÁFICO) ΔRMSE (Encadenado - Fijo): negativo = mejor Encadenado
plot(tabla_no_drift$inflacion_pct, tabla_no_drift$rmse_ch - tabla_no_drift$rmse_fix,
type="b", pch=19, xlab="Inflación anual (%)",
ylab="ΔRMSE (negativo = mejor Encadenado)",
main="Sin drift de precios relativos")
abline(h=0, lty=2)
set.seed(1)
years <- 2022:2031; Tt <- length(years); S <- 3
Q <- matrix(NA_real_, S, Tt); P <- matrix(NA_real_, S, Tt)
colnames(Q) <- colnames(P) <- years; rownames(Q) <- rownames(P) <- c("Comp","Mesas","Sillas")
# Precios: suben 40% anual parejo (sin drift)
P[,1] <- c(1000, 50, 30)
for(t in 2:Tt) P[,t] <- P[,t-1] * 1.40
# Cantidades: "Comp" acelera desde 2027
Q[,1] <- c(100, 200, 300)
for(t in 2:Tt){
g <- c(0.02, 0.01, 0.015)
if (years[t] >= 2027) g[1] <- 0.15
Q[,t] <- Q[,t-1] * (1 + g)
}
V <- idx_volumen_verdadero(Q)
Lf<- idx_laspeyres_fijo(Q, P)
Lc<- idx_laspeyres_encadenado(Q, P)
c(RMSE_fijo=rmse_diff_log_growth(Lf, V),
RMSE_enc=rmse_diff_log_growth(Lc, V))
## RMSE_fijo RMSE_enc
## 0.06228775 0.06228775
# (GRÁFICO) Índices
plot(years, V, type="l", lwd=2, xlab="Año", ylab="Índice (base=100)",
main="Quiebre en cantidades, precios sin drift")
lines(years, Lf, lwd=2, lty=2)
lines(years, Lc, lwd=2, lty=3)
legend("topleft", c("Volumen verdadero","Laspeyres fijo","Encadenado"),
lty=c(1,2,3), lwd=2, bty="n")
Con drift fuerte de precios relativos, el encadenado recalcula ponderaciones con precios del año previo y se vuelve sensible a la inflación → típicamente conviene Laspeyres fijo.
Sin drift (precios suben parejo), si la estructura de cantidades cambia, el encadenado actualiza ponderaciones y reduce el error frente al fijo.
Con quiebres estructurales en cantidades, el encadenado sigue mejor el volumen real que el fijo (menor RMSE).
Guía práctica:
- Hiperinflación + drift → preferir Laspeyres
fijo y rebases más frecuentes.
- Inflación baja/moderada o precios relativos
estables con cambios de cantidades →
encadenado.