set.seed(1234)
T_proj <- 12 # quarters ahead
N_sims <- 2000 # Monte Carlo simulations
# System parameters
a1_pc <- 0.45; a2_pc <- 0.20; a_fwd_pc <- 0.25
a3_pc <- 0.25; a4_pc <- 0.12
b1_is <- 0.70; b2_is <- -0.15; b3_is <- -0.25
lambda_r <- 0.65; phi_pi <- 1.5; phi_y <- 0.5
# Initial conditions
pi0 <- 0.055; pi_1 <- 0.060; y0 <- -0.01; i0 <- 0.115; e0 <- log(5.0)
simulate_mpp <- function(seed_s) {
set.seed(seed_s)
pi_v <- c(pi_1, pi0, numeric(T_proj))
y_v <- c(0, y0, numeric(T_proj))
e_v <- c(e0, e0, numeric(T_proj))
i_v <- c(i0, i0, numeric(T_proj))
for (t in 3:(T_proj + 2)) {
r_real <- i_v[t-1] - pi_v[t-1]
y_v[t] <- b1_is * y_v[t-1] + b2_is * y_v[t-2] + b3_is * r_real + rnorm(1, 0, 0.007)
pi_fwd_t <- pi_v[t-1] + rnorm(1, 0, 0.004)
# FX change: computed from lagged values + contemporaneous shock
fx_shock <- rnorm(1, 0, 0.015)
delta_e_t <- (i_v[t-1] - 0.055 - 0.03) / 4 + fx_shock
pi_v[t] <- a1_pc * pi_v[t-1] + a2_pc * pi_v[t-2] +
a_fwd_pc * pi_fwd_t + a3_pc * y_v[t-1] +
a4_pc * delta_e_t + rnorm(1, 0, 0.006)
pi_v[t] <- max(pi_v[t], 0)
i_v[t] <- (1 - lambda_r) * i_v[t-1] +
lambda_r * (phi_pi * (pi_v[t] - pi_star) + phi_y * y_v[t] + 0.10)
e_v[t] <- e_v[t-1] + delta_e_t + rnorm(1, 0, 0.01)
}
pi_v[3:(T_proj + 2)]
}
mat_pi <- sapply(1:N_sims, simulate_mpp)
# Quantiles for the fan chart
qtis <- t(apply(mat_pi, 1, quantile,
probs = c(0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90)))
df_fan <- as.data.frame(qtis)
colnames(df_fan) <- paste0("q", c(10, 20, 30, 40, 50, 60, 70, 80, 90))
df_fan$quarter <- seq(as.Date("2024-04-01"), by = "quarter", length.out = T_proj)
ggplot(df_fan, aes(x = quarter)) +
geom_ribbon(aes(ymin = q10 * 100, ymax = q90 * 100), fill = "#0f3460", alpha = 0.12) +
geom_ribbon(aes(ymin = q20 * 100, ymax = q80 * 100), fill = "#0f3460", alpha = 0.18) +
geom_ribbon(aes(ymin = q30 * 100, ymax = q70 * 100), fill = "#0f3460", alpha = 0.22) +
geom_ribbon(aes(ymin = q40 * 100, ymax = q60 * 100), fill = "#0f3460", alpha = 0.28) +
geom_line(aes(y = q50 * 100), color = "#0f3460", linewidth = 1.3) +
geom_hline(yintercept = pi_star * 100, linetype = "dashed",
color = "#e94560", linewidth = 0.9) +
annotate("text", x = df_fan$quarter[2], y = pi_star * 100 + 0.3,
label = paste0("Target: ", pi_star * 100, "%"),
color = "#e94560", size = 3.8, fontface = "bold") +
scale_y_continuous(labels = function(x) paste0(x, "%")) +
scale_x_date(date_labels = "%Y", date_breaks = "1 year") +
labs(
title = "Fan Chart — Inflation Projection (CPI)",
subtitle = paste0("Monte Carlo distribution (N = ", N_sims,
" simulations) — 20/40/60/80% confidence bands"),
x = NULL, y = "CPI (% p.a.)",
caption = "Small-Scale Model (MPP) — simulated data for pedagogical purposes"
) +
theme_mpp