← Catálogo · Capítulo 6

T06_CP03_mECO_IV_Demanda.R

Ver crudo
# =============================================================================
# TEMA 06 — CP3: IV — Estimación de la Curva de Demanda
# =============================================================================
# Manual de Microeconometría — Carlos de Anta Puig
# Profesor de Econometría y Microeconometría — UNIR
# https://github.com/carlanta/MicroEconometrics  Versión 1.0 — 2026
#
# OBJETIVO: Estimar la elasticidad-precio de la demanda en presencia de
#           simultaneidad (precio endógeno). Instrumentos: coste transporte
#           y clima (desplazadores de oferta). Sobreidentificado → Sargan.
# INSTRUCCIONES: Session > Set Working Directory > To Source File Location
# =============================================================================

pausa <- function(msg="\n>>> Pulsa ENTER para continuar...") {
  if (interactive()) readline(msg) else Sys.sleep(0.5)
}
pkgs <- c("AER","lmtest","sandwich")
for (p in pkgs) if (!requireNamespace(p, quietly=TRUE)) install.packages(p, quiet=TRUE)
suppressPackageStartupMessages({ library(AER); library(lmtest); library(sandwich) })
.get_script_dir <- function() {
  args <- commandArgs(trailingOnly = FALSE)
  for (a in args) {
    if (startsWith(a, "--file=")) return(dirname(normalizePath(substring(a, 8))))
  }
  for (i in seq_len(sys.nframe())) {
    ofile <- tryCatch(sys.frame(i)$ofile, error = function(e) NULL)
    if (!is.null(ofile)) return(dirname(normalizePath(ofile)))
  }
  return(normalizePath("."))
}
.sdir <- .get_script_dir()
DATA_DIR <- normalizePath(file.path(.sdir, "..", "data"), mustWork=FALSE)
OUTPUT_DIR <- normalizePath(file.path(.sdir, "..", "output"), mustWork=FALSE)
if (!dir.exists(OUTPUT_DIR)) dir.create(OUTPUT_DIR, recursive=TRUE)

cat("\n================================================================\n")
cat("  CP03 — Curva de Demanda: Simultaneidad Oferta-Demanda\n")
cat("================================================================\n\n")
cat("  En el equilibrio de mercado, precio y cantidad se determinan\n")
cat("  conjuntamente. Un shock de demanda sube precio Y cantidad,\n")
cat("  haciendo que MCO SUBESTIME la pendiente negativa de la demanda.\n")
cat("  Instrumentamos el precio con desplazadores de oferta.\n\n")

load(file.path(DATA_DIR, "T06_CP03_oferta_demanda.RData"))
cat("Dataset:", nrow(mercado_iv), "observaciones de mercado\n\n")

# --- DESCRIPTIVOS ---
cat("--- ESTADÍSTICOS DESCRIPTIVOS ---\n\n")
vars <- c("cantidad","precio","ingreso","coste_transporte","clima")
labs <- c("Cantidad","Precio","Ingreso","Coste transporte","Clima")
cat(sprintf("  %-16s %8s %8s %8s %8s\n", "Variable","Media","D.E.","Mín.","Máx."))
cat(sprintf("  %s\n", paste(rep("-",54), collapse="")))
for (i in seq_along(vars)) {
  x <- mercado_iv[[vars[i]]]
  cat(sprintf("  %-16s %8.2f %8.2f %8.2f %8.2f\n", labs[i],
              mean(x), sd(x), min(x), max(x)))
}
pausa()

# --- EDA ---
cat("\n--- ANÁLISIS EXPLORATORIO GRÁFICO ---\n\n")
png(file.path(OUTPUT_DIR, "T06_CP03_eda.png"), width=2000, height=700, res=150)
par(mfrow=c(1,3), mar=c(4.5,4.5,2.5,0.5), cex.main=0.82)

plot(mercado_iv$precio, mercado_iv$cantidad, pch=1, col=gray(0.5), cex=0.5,
     xlab="Precio", ylab="Cantidad", main="Cantidad vs Precio")
abline(lm(cantidad ~ precio, data=mercado_iv), lwd=2, lty=1)
text(5, 45, "MCO (sesgo simult.)", cex=0.7, font=3)

plot(mercado_iv$coste_transporte, mercado_iv$precio,
     pch=1, col=gray(0.5), cex=0.5,
     xlab="Coste transporte", ylab="Precio",
     main="1a etapa: coste transp.")
abline(lm(precio ~ coste_transporte, data=mercado_iv), lwd=2, lty=1)

plot(mercado_iv$clima, mercado_iv$precio,
     pch=1, col=gray(0.5), cex=0.5,
     xlab="Clima", ylab="Precio",
     main="1a etapa: clima")
abline(lm(precio ~ clima, data=mercado_iv), lwd=2, lty=1)
dev.off()
cat("  Gráfico: output/T06_CP03_eda.png\n")
cat("  Ambos instrumentos (coste, clima) correlacionan con el precio.\n")
pausa()

# --- MCO vs IV ---
cat("\n--- ESTIMACIÓN: MCO vs MC2E ---\n\n")
mco <- lm(cantidad ~ precio + ingreso, data=mercado_iv)
iv  <- ivreg(cantidad ~ precio + ingreso | coste_transporte + clima + ingreso,
             data=mercado_iv)
s_iv <- summary(iv, diagnostics=TRUE)

cat(sprintf("  %-12s | %9s %8s | %9s %8s\n", "","MCO","EE","IV","EE"))
cat(sprintf("  %s\n", paste(rep("-",52), collapse="")))
for (v in c("precio","ingreso")) {
  cat(sprintf("  %-12s | %9.4f %8.4f | %9.4f %8.4f\n", v,
              coef(summary(mco))[v,1], coef(summary(mco))[v,2],
              coef(s_iv)[v,1], coef(s_iv)[v,2]))
}
cat(sprintf("\n  MCO: elasticidad-precio = %.4f\n", coef(mco)["precio"]))
cat(sprintf("  IV:  elasticidad-precio = %.4f\n", coef(iv)["precio"]))
cat("\n  MCO subestima la pendiente negativa (en valor absoluto)\n")
cat("  porque la simultaneidad genera sesgo positivo.\n")
pausa()

# --- DIAGNÓSTICOS ---
cat("\n--- DIAGNÓSTICOS ---\n\n")
f1 <- summary(lm(precio ~ coste_transporte + clima + ingreso,
                  data=mercado_iv))$fstatistic
cat(sprintf("  F primera etapa: %.2f", f1[1]))
if (f1[1] > 10) cat(" ✓ Instrumentos fuertes.\n\n") else cat(" ✗ Débiles.\n\n")

diag_iv <- s_iv$diagnostics
if ("Sargan" %in% rownames(diag_iv)) {
  cat(sprintf("  Sargan (sobreidentificación): stat = %.3f | p = %.4f\n",
              diag_iv["Sargan",1], diag_iv["Sargan",4]))
  if (diag_iv["Sargan",4] > 0.05) {
    cat("  ✓ No se rechaza: AMBOS instrumentos son válidos.\n\n")
  } else {
    cat("  ✗ Se rechaza: al menos un instrumento no es exógeno.\n\n")
  }
}
if ("Wu-Hausman" %in% rownames(diag_iv)) {
  cat(sprintf("  Wu-Hausman: F = %.3f | p = %.4f\n",
              diag_iv["Wu-Hausman",1], diag_iv["Wu-Hausman",4]))
  if (diag_iv["Wu-Hausman",4] < 0.05) {
    cat("  ✓ Precio ES endógeno (simultaneidad confirmada).\n\n")
  } else {
    cat("  ✗ No se rechaza exogeneidad del precio.\n\n")
  }
}
pausa()

# --- GRÁFICO FINAL ---
png(file.path(OUTPUT_DIR, "T06_CP03_demanda.png"), width=1200, height=600, res=150)
par(mar=c(4.5, 4.5, 2.5, 1))
plot(mercado_iv$precio, mercado_iv$cantidad, pch=1, col=gray(0.6), cex=0.4,
     xlab="Precio", ylab="Cantidad demandada",
     main="Curva de demanda: MCO vs IV")
abline(mco, lwd=2.5, lty=1)
abline(iv, lwd=2.5, lty=2)
legend("topright",
       c(sprintf("MCO (pend. = %.2f)", coef(mco)["precio"]),
         sprintf("IV  (pend. = %.2f)", coef(iv)["precio"])),
       lty=c(1,2), lwd=2.5, cex=0.8, bty="n")
dev.off()
cat("  Gráfico: output/T06_CP03_demanda.png\n")
cat("  La recta IV tiene mayor pendiente negativa (en valor absoluto):\n")
cat("  refleja la verdadera respuesta de la demanda al precio.\n")
pausa()

# --- RESUMEN ---
cat("\n================================================================\n")
cat("  RESUMEN CP03 — Curva de Demanda\n")
cat("================================================================\n\n")
cat(sprintf("  MCO: elasticidad-precio = %.4f (sesgada)\n", coef(mco)["precio"]))
cat(sprintf("  IV:  elasticidad-precio = %.4f (corregida)\n", coef(iv)["precio"]))
cat(sprintf("  F primera etapa: %.0f\n", f1[1]))
cat("  La simultaneidad subestima la respuesta negativa de la demanda.\n")
cat("  Coste de transporte y clima son instrumentos válidos (Sargan).\n")
cat("================================================================\n")