# ============================
# Ví dụ 5.2 - Phiên bản đầy đủ
# Đã sửa lỗi "promise already under evaluation"
# Có công thức bound (3.17), (3.20), (4.18), (4.25)
# ============================

rm(list = ls())
set.seed(20250811)

# ----------------------------
# 1. Tham số mô hình
# ----------------------------
alpha <- 2          # shape Gamma(Y)
lambda <- 4         # rate Gamma(Y) => E[Y] = alpha/lambda = 0.5
premium <- 0.6      # phí thu mỗi kỳ
n_periods <- 50
u_values <- seq(0.2, 2.0, by = 0.2)
n_sim <- 20000      # số lần mô phỏng cho mỗi u

# Lãi suất
i_fixed <- 0.05                     # cố định
i_min <- 0.04; i_max <- 0.06         # ngẫu nhiên (Uniform)

# Hằng số từ ví dụ (giả định hoặc từ dữ liệu)
beta2 <- 1
beta0 <- 1
kappa0 <- 2.390436
kappa3 <- 2.482485
i_bound <- 0.06184   # dùng để tính bound (3.20) và (4.25)
kappa1 <- kappa3 * (1 + i_bound)
kappa2 <- kappa0 * (1 + i_bound)

# ----------------------------
# 2. Hàm MGF Gamma
# ----------------------------
mgf_gamma <- function(t, shape = alpha, rate = lambda) {
  if (t >= rate) stop("t must be < rate for Gamma MGF")
  (rate / (rate - t))^shape
}

# ----------------------------
# 3. Hàm tìm Lundberg k
# ----------------------------
find_lundberg_k <- function(premium_val, shape = alpha, rate = lambda) {
  EY <- shape / rate
  if (premium_val <= EY) return(NA_real_)
  f <- function(k) mgf_gamma(k, shape, rate) - exp(k * premium_val)
  lower <- 1e-8; upper <- rate - 1e-8
  if (f(lower) * f(upper) > 0) stop("Cannot bracket Lundberg root")
  uniroot(f, lower = lower, upper = upper, tol = 1e-10)$root
}
k_lundberg <- find_lundberg_k(premium)

# ----------------------------
# 4. Hàm mô phỏng
# ----------------------------
make_simulator <- function(premium_val, claim_shape, claim_rate,
                           n_periods_val, n_sim_val,
                           i_fixed_val, i_min_val, i_max_val) {
  function(u0, interest_type = c("none", "fixed", "random")) {
    interest_type <- match.arg(interest_type)
    ruin_count <- 0L
    for (sim in seq_len(n_sim_val)) {
      U <- u0
      ruined <- FALSE
      for (t in seq_len(n_periods_val)) {
        U <- U + premium_val
        if (interest_type == "none") {
          i_t <- 0
        } else if (interest_type == "fixed") {
          i_t <- i_fixed_val
        } else {
          i_t <- runif(1, i_min_val, i_max_val)
        }
        U <- U * (1 + i_t)
        Yt <- rgamma(1, shape = claim_shape, rate = claim_rate)
        U <- U - Yt
        if (U < 0) { ruined <- TRUE; break }
      }
      if (ruined) ruin_count <- ruin_count + 1L
    }
    ruin_count / n_sim_val
  }
}

sim_fn <- make_simulator(premium, alpha, lambda, n_periods, n_sim,
                         i_fixed, i_min, i_max)

# ----------------------------
# 5. Chạy mô phỏng
# ----------------------------
cat("Running simulations...\n")
## Running simulations...
res_sim_none   <- vapply(u_values, function(u) sim_fn(u, "none"), numeric(1))
res_sim_fixed  <- vapply(u_values, function(u) sim_fn(u, "fixed"), numeric(1))
res_sim_random <- vapply(u_values, function(u) sim_fn(u, "random"), numeric(1))

# ----------------------------
# 6. Bound lý thuyết
# ----------------------------
# (3.17): ψ*(u) ≤ exp(-u * κ1)
bound_3_17 <- exp(-u_values * kappa1)

# (3.20): ψ*(u) ≤ exp(-u * κ0 * (1+i))
bound_3_20 <- exp(-u_values * kappa0 * (1 + i_bound))

# (4.18): ψ*(u) ≤ β2 * E[e^{κ3 Y1}] * E[e^{-κ3 (u + X1) Z1}], Z1 fixed
E_exp_k3Y <- mgf_gamma(kappa3)
Z1_fixed <- 1 + i_bound
bound_4_18 <- beta2 * E_exp_k3Y * exp(-kappa3 * (u_values + premium) * Z1_fixed)

# (4.25): ψ*(u) ≤ β0 * E[e^{-u κ0 Z1}], Z1 fixed
bound_4_25 <- beta0 * exp(-u_values * kappa0 * Z1_fixed)

# Lundberg bound
bound_lundberg <- exp(-k_lundberg * u_values)

# ----------------------------
# 7. Tổng hợp kết quả
# ----------------------------
results_df <- data.frame(
  u = u_values,
  sim_none   = res_sim_none,
  sim_fixed  = res_sim_fixed,
  sim_random = res_sim_random,
  bound_lundberg = bound_lundberg,
  bound_3_17 = bound_3_17,
  bound_3_20 = bound_3_20,
  bound_4_18 = bound_4_18,
  bound_4_25 = bound_4_25
)
print(results_df)
##      u sim_none sim_fixed sim_random bound_lundberg  bound_3_17  bound_3_20
## 1  0.2  0.48290   0.34685    0.35390     0.77805453 0.590255152 0.601907131
## 2  0.4  0.37655   0.23120    0.22810     0.60536885 0.348401145 0.362292195
## 3  0.6  0.29095   0.15545    0.15875     0.47100998 0.205645571 0.218066256
## 4  0.8  0.23095   0.10630    0.10205     0.36647145 0.121383357 0.131255634
## 5  1.0  0.18025   0.06830    0.06645     0.28513477 0.071647152 0.079003702
## 6  1.2  0.13685   0.04265    0.04590     0.22185040 0.042290101 0.047552892
## 7  1.4  0.10965   0.02540    0.03030     0.17261171 0.024961950 0.028622425
## 8  1.6  0.08145   0.01730    0.01655     0.13430132 0.014733919 0.017228042
## 9  1.8  0.06355   0.01060    0.01020     0.10449375 0.008696772 0.010369681
## 10 2.0  0.04745   0.00630    0.00675     0.08130184 0.005133314 0.006241585
##     bound_4_18  bound_4_25
## 1  0.843360281 0.601907131
## 2  0.497797751 0.362292195
## 3  0.293827687 0.218066256
## 4  0.173433306 0.131255634
## 5  0.102369902 0.079003702
## 6  0.060424362 0.047552892
## 7  0.035665791 0.028622425
## 8  0.021051917 0.017228042
## 9  0.012426002 0.010369681
## 10 0.007334512 0.006241585
write.csv(results_df, "example5_2_full_results.csv", row.names = FALSE)
cat("Saved results to example5_2_full_results.csv\n")
## Saved results to example5_2_full_results.csv
# ----------------------------
# 8. Vẽ biểu đồ
# ----------------------------
if (!requireNamespace("ggplot2", quietly = TRUE)) install.packages("ggplot2")
if (!requireNamespace("reshape2", quietly = TRUE)) install.packages("reshape2")
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.3.3
df_long <- melt(results_df, id.vars = "u",
                variable.name = "method", value.name = "value")

ggplot(df_long, aes(x = u, y = value, color = method)) +
  geom_line() + geom_point() +
  scale_y_log10() +
  labs(title = "Mô phỏng vs Bound",
       x = "Vốn ban đầu u", y = "Giá trị (log scale)") +
  theme_minimal(base_size = 14)

ggsave("example5_2_full_plot.png", width = 9, height = 6, dpi = 300)
cat("Saved plot to example5_2_full_plot.png\n")
## Saved plot to example5_2_full_plot.png