Bài 4: CEAC, CEAF, tổn thất kỳ vọng và cách báo cáo bất định

Biến kết quả PSA của ba phác đồ thành thông tin mà người ra quyết định dùng được

Vì sao bạn nên quan tâm?

Với ngưỡng 1 × GDP bình quân đầu người, mỗi năm sống khỏe mạnh thêm của một người bệnh (1 QALY) được tính tối đa 125.5 triệu VNĐ, bằng khoảng 14.9 tháng thu nhập bình quân của một người lao động năm 2025 (Cục Thống kê (Bộ Tài chính) 2026a, 2026b); theo quan điểm chi phí cơ hội, mức này có thể chỉ bằng một nửa (Woods và c.s. 2016). Lãnh đạo Sở Y tế hay cơ quan BHXH cầm báo cáo của bạn sẽ không đọc bảng 27 tham số. Họ hỏi ba câu: chọn phác đồ nào, chắc đến đâu ở những ngưỡng khác nhau, và nếu chọn sai thì mất bao nhiêu tiền cho mỗi người bệnh. Bài này dạy vẽ và đọc ba hình trả lời ba câu đó, rồi viết một câu báo cáo gọn.

Mục tiêu học tập

Sau bài này, bạn có thể:

  1. Tính và vẽ đường cong chấp nhận chi phí-hiệu quả (cost-effectiveness acceptability curve, CEAC) cho ba chiến lược từ kết quả PSA.
  2. Xác định đường biên chấp nhận chi phí-hiệu quả (cost-effectiveness acceptability frontier, CEAF) và giải thích vì sao lựa chọn tối ưu dựa trên NMB kỳ vọng, không dựa trên xác suất cao nhất.
  3. Đặt chi phí và QALY kỳ vọng lên đường biên hiệu quả (efficiency frontier) của M02.
  4. Tính đường cong tổn thất kỳ vọng (expected loss curve) và chỉ ra mối liên hệ của nó với EVPI.
  5. Lập bảng và viết câu báo cáo bất định cho người ra quyết định.

Ý chính

  • CEAC của một chiến lược là tỷ lệ số lần chạy PSA trong đó chiến lược đó có NMB cao nhất, vẽ theo ngưỡng \(\lambda\) (Fenwick, Claxton, và Sculpher 2001). Các CEAC cộng lại bằng 1 ở mọi ngưỡng.
  • Lựa chọn tối ưu ở mỗi ngưỡng là chiến lược có NMB kỳ vọng cao nhất. CEAF chỉ vẽ xác suất của chiến lược tối ưu đó (Barton, Briggs, và Fenwick 2008).
  • Chiến lược có xác suất chi phí-hiệu quả cao nhất có thể không phải là chiến lược tối ưu, khi phân phối của NMB gia tăng bị lệch.
  • Chiến lược tối ưu theo kỳ vọng luôn nằm trên đường biên hiệu quả của chi phí và QALY kỳ vọng.
  • CEAC không cho biết mất bao nhiêu khi chọn sai (Groot Koerkamp và c.s. 2007). Tổn thất kỳ vọng thì có: đường thấp nhất là chiến lược tối ưu, và giá trị thấp nhất chính là EVPI (Alarid-Escudero và c.s. 2019).
  • Báo cáo cho người ra quyết định: kết quả kỳ vọng kèm khoảng bất định 95%, xác suất chi phí-hiệu quả ở vài ngưỡng, tổn thất kỳ vọng, và nói rõ kết quả nào dựa trên giả định (Husereau và c.s. 2022).

Nội dung

CEAC

Với \(N\) lần chạy PSA và chiến lược \(s\), ở ngưỡng \(\lambda\):

\[ \text{CEAC}_s(\lambda) = \frac{1}{N}\sum_{i=1}^{N} \mathbf{1}\!\left[\text{NMB}_{s,i}(\lambda) = \max_j \text{NMB}_{j,i}(\lambda)\right], \qquad \text{NMB}_{s,i}(\lambda) = \lambda Q_{s,i} - C_{s,i}. \]

Mỗi lần chạy chỉ có một chiến lược thắng, nên các CEAC cộng bằng 1 ở mọi ngưỡng. Khi chỉ còn hai chiến lược có thể thắng, CEAC của BPaLM chính là tỷ lệ điểm nằm dưới đường \(\Delta C = \lambda \Delta Q\) trên mặt phẳng chi phí-hiệu quả (Bài 3). Hàm decision_curves() tính cùng lúc CEAC, chiến lược tối ưu, tổn thất kỳ vọng và EVPI cho một dãy ngưỡng, với số chiến lược bất kỳ.

CEAF, đường biên và lựa chọn tối ưu

Theo lý thuyết quyết định, ở ngưỡng \(\lambda\) ta chọn chiến lược có \(E[\text{NMB}_s(\lambda)]\) cao nhất, bất kể xác suất (Claxton 1999). CEAF vẽ, ở mỗi ngưỡng, xác suất chi phí-hiệu quả của chiến lược tối ưu đó. Thường CEAF trùng với CEAC cao nhất, nhưng không phải lúc nào cũng vậy: nếu NMB gia tăng của BPaLM thường dương một chút nhưng thỉnh thoảng âm rất nhiều, BPaLM có thể thắng ở hơn một nửa số lần chạy mà vẫn có NMB kỳ vọng thấp hơn. Với ba chiến lược, chiến lược tối ưu theo kỳ vọng luôn nằm trên đường biên hiệu quả dựng từ chi phí và QALY kỳ vọng; hàm cea_frontier() của M02 dùng được ngay cho trung bình PSA (Barton, Briggs, và Fenwick 2008).

Tổn thất kỳ vọng

\[ \text{EL}_s(\lambda) = \frac{1}{N}\sum_{i=1}^{N}\left[\max_j \text{NMB}_{j,i}(\lambda) - \text{NMB}_{s,i}(\lambda)\right] . \]

\(\text{EL}_s\) gộp hai thông tin mà CEAC tách rời: xác suất chọn sai và mức thiệt hại khi sai. Chiến lược tối ưu có tổn thất kỳ vọng thấp nhất, và tổn thất đó bằng EVPI (Bài 5). Vì vậy một hình tổn thất kỳ vọng cho biết cùng lúc lựa chọn tối ưu, độ bất định của quyết định và giới hạn trên của giá trị nghiên cứu thêm (Alarid-Escudero và c.s. 2019).

Báo cáo cho người ra quyết định

Một bảng bất định gọn nên có, cho mỗi kịch bản và vài ngưỡng: \(\Delta\text{NMB}\) kỳ vọng kèm khoảng bất định 95%; xác suất chi phí-hiệu quả; lựa chọn tối ưu; tổn thất kỳ vọng của lựa chọn đó. Khóa học báo cáo ở ba mốc: 0.5 × GDP bình quân đầu người theo quan điểm chi phí cơ hội (Woods và c.s. 2016), 1 × GDP/người, mốc nhiều nghiên cứu Việt Nam dùng (Ong và c.s. 2026), và 3 × GDP/người, cận trên của khoảng ngưỡng trong kb/_shared. CHEERS 2022 yêu cầu mô tả cách phân tích bất định và báo cáo ảnh hưởng của nó lên kết quả (Husereau và c.s. 2022). Tránh ba cách nói dễ gây hiểu nhầm:

  • “Kết quả không có ý nghĩa thống kê”: quyết định dựa trên giá trị kỳ vọng; bất định chỉ cho biết có nên thu thập thêm bằng chứng không (Claxton 1999).
  • “BPaLM chỉ có một nửa khả năng tốt hơn, nên không nên dùng”: xác suất không phải quy tắc quyết định; xem NMB kỳ vọng và tổn thất kỳ vọng.
  • Một con số duy nhất không kèm ngưỡng: CEAC thay đổi theo \(\lambda\), nên luôn nêu ngưỡng đã dùng và vì sao.

Thực hành

Chạy lại PSA của Bài 3 (cùng seed, bản vectơ hóa đã được đối chiếu ở Bài 3) cho hai kịch bản. Kiểm tra: mỗi kịch bản có 1,000 hàng và ba chiến lược.

# Vietnamese text in figures needs a UTF-8 locale (Rscript may start in the "C" locale)
if (!isTRUE(l10n_info()[["UTF-8"]])) invisible(Sys.setlocale("LC_CTYPE", "en_US.UTF-8"))
source("../_shared/R/helpers.R")
source("../_shared/R/vn_data.R")
source("code/model.R")
library(ggplot2)
inp <- load_m03_inputs()
p <- inp$p
spec <- inp$spec
u <- inp$u
ctx <- inp$ctx
ctab <- attr(ctx, "table")
fit <- fit_dist(spec)
# Same PSA as Lesson 3 (same seed, vectorised model checked there against the loop):
# A = GDF price (base case), B = negotiated price near the threshold (illustrative)
draws <- draw_psa(fit, n = u$n_psa, seed = u$seed)
price_hi <- price_scenario(p, u$price_round)
psa_a <- run_psa_vec(p, draws)
psa_b <- run_psa_vec(p, draws, fixed = list(c_drug_bpalm = price_hi))
c(rows_a = nrow(psa_a), rows_b = nrow(psa_b), strategies = length(psa_strategies(psa_a)))
    rows_a     rows_b strategies 
      1000       1000          3 

Tính CEAC, chiến lược tối ưu, tổn thất kỳ vọng và EVPI trên dãy ngưỡng từ 0 đến 3 × GDP/người. Kiểm tra (stopifnot, ở mọi ngưỡng): ba CEAC cộng bằng 1; EVPI từ decision_curves() bằng EVPI tính lại trên ma trận NMB; và khi phác đồ dài hạn không bao giờ thắng, CEAC của BPaLM bằng tỷ lệ lần chạy có NMB gia tăng (so với phác đồ ngắn) dương, EVPI bằng công thức hai chiến lược.

# Threshold grid from 0 to 3 x GDP per capita, with the three reporting thresholds on it:
# 0.5 x (wtp_low), 1 x (wtp) and 3 x GDP per capita (upper end of the shared wtp range)
report_at <- c(ctx$wtp_low, ctx$wtp, ctab$high[ctab$name == "wtp"])
wtp_grid <- sort(unique(c(seq(0, max(report_at), by = 2.5e6), report_at)))
cur_a <- decision_curves(psa_a, wtp_grid)
cur_b <- decision_curves(psa_b, wtp_grid)
cur_b[cur_b$wtp == p$wtp, c("strategy", "e_nmb", "p_ce", "exp_loss", "optimal", "evpi")]
    strategy      e_nmb  p_ce exp_loss optimal    evpi
157     long 1533723845 0.000 64376732   FALSE 3060172
158    short 1594645210 0.491  3455368   FALSE 3060172
159    bpalm 1595040406 0.509  3060172    TRUE 3060172
# Scenario A: smallest probability that BPaLM is optimal over the whole grid
min_p_a <- min(cur_a$p_ce[cur_a$strategy == "bpalm"])
max_p_long <- max(c(cur_a$p_ce[cur_a$strategy == "long"], cur_b$p_ce[cur_b$strategy == "long"]))
# Scenario B: lowest threshold on the grid at which BPaLM is optimal in at least half of the runs
cross_b <- min(cur_b$wtp[cur_b$strategy == "bpalm" & cur_b$p_ce >= 0.5])
round(c(min_p_bpalm_a = min_p_a, max_p_long_any = max_p_long, cross_b_million = cross_b / 1e6), 3)
  min_p_bpalm_a  max_p_long_any cross_b_million 
            1.0             0.0           125.5 
# Checks by a second, independent route at every threshold: (1) the CEACs of the three
# strategies add up to 1; (2) the EVPI of decision_curves() equals evpi_nmb() on the NMB matrix;
# (3) while the long regimen never wins, the CEAC of BPaLM is the share of runs with a positive
# BPaLM-vs-short INB and the EVPI equals the two-strategy formula evpi_inb() (to 1 VND).
for (k in 1:2) {
  cur <- list(cur_a, cur_b)[[k]]
  psa <- list(psa_a, psa_b)[[k]]
  for (w in wtp_grid) {
    row_w <- cur[cur$wtp == w, ]
    stopifnot(abs(sum(row_w$p_ce) - 1) < 1e-12, abs(row_w$evpi[1] - evpi_nmb(nmb_matrix(psa, w))) < 1)
    if (row_w$p_ce[row_w$strategy == "long"] == 0) {
      inb <- psa_incremental(psa, w)$d_nmb
      stopifnot(abs(row_w$p_ce[row_w$strategy == "bpalm"] - mean(inb > 0)) < 1e-12,
                abs(row_w$evpi[1] - evpi_inb(inb)) < 1)
    }
  }
}

Trong kịch bản A, xác suất BPaLM là lựa chọn tối ưu thấp nhất trên cả dãy ngưỡng là 100%; phác đồ dài hạn không thắng ở lần chạy nào, ở bất kỳ ngưỡng nào, trong cả hai kịch bản. Trong kịch bản B, CEAC của BPaLM vượt 0.5 từ ngưỡng 125.5 triệu VNĐ/QALY trên lưới.

Đặt chi phí và QALY kỳ vọng lên đường biên hiệu quả. Kiểm tra: phương án tối ưu ở ngưỡng 1 × GDP/người nằm trên đường biên.

# Expected costs and QALYs (PSA means) on the efficiency frontier of M02, per scenario
front_a <- cea_frontier(psa_means(psa_a), wtp = p$wtp)
front_b <- cea_frontier(psa_means(psa_b), wtp = p$wtp)
status_vi <- c(frontier = "trên đường biên", dominated = "bị lấn át", ext_dominated = "bị lấn át mở rộng")
show_front <- function(f, sc) {
  data.frame(scenario = sc, strategy = REGIMEN_LABELS[f$strategy], cost = f$cost / 1e6, qaly = f$qaly,
             status = status_vi[f$status], icer = ifelse(is.na(f$icer), "", fmt_num(f$icer / 1e6, 1)),
             optimal = ifelse(f$optimal, "có", ""))
}
front_tab <- rbind(show_front(front_a, "A"), show_front(front_b, "B"))
stopifnot(all(front_a$status[front_a$optimal] == "frontier"), all(front_b$status[front_b$optimal] == "frontier"))
knitr::kable(front_tab, digits = c(0, 0, 2, 3, 0, 0, 0), row.names = FALSE,
             col.names = c("Kịch bản", "Phác đồ", "Chi phí kỳ vọng (triệu VNĐ)", "QALY kỳ vọng",
                           "Trạng thái", "ICER (triệu VNĐ/QALY)", "Tối ưu ở 1 × GDP/người"))
Kịch bản Phác đồ Chi phí kỳ vọng (triệu VNĐ) QALY kỳ vọng Trạng thái ICER (triệu VNĐ/QALY) Tối ưu ở 1 × GDP/người
A BPaLM 15.07 13.363 trên đường biên có
A Phác đồ ngắn 9 tháng 21.67 12.879 bị lấn át
A Phác đồ dài hạn 29.25 12.454 bị lấn át
B Phác đồ ngắn 9 tháng 21.67 12.879 trên đường biên
B Phác đồ dài hạn 29.25 12.454 bị lấn át
B BPaLM 82.00 13.363 trên đường biên 124.7 có
icer_b <- front_b["bpalm", "icer"]

Ở kịch bản A, BPaLM là điểm duy nhất trên đường biên: nó lấn át cả hai phác đồ kia. Ở kịch bản B, phác đồ ngắn và BPaLM cùng nằm trên đường biên, với ICER của BPaLM so với phác đồ ngắn là 124.7 triệu VNĐ/QALY, sát ngưỡng 125.5 triệu; phác đồ dài hạn vẫn bị lấn át.

Vẽ CEAC và đánh dấu CEAF. Kiểm tra: ba đường của mỗi kịch bản cộng bằng 1; vòng tròn nằm trên chiến lược có NMB kỳ vọng cao nhất.

lab <- REGIMEN_LABELS[REGIMENS]
lab_a <- "A. Giá GDF (phân tích cơ sở)"
lab_b <- "B. Giá đàm phán sát ngưỡng (minh họa)"
ceac_df <- rbind(data.frame(scenario = lab_a, cur_a), data.frame(scenario = lab_b, cur_b))
ceac_df$strategy <- factor(lab[ceac_df$strategy], levels = lab)
fig_ceac <- ggplot(ceac_df, aes(wtp / 1e6, p_ce, colour = strategy)) +
  geom_line(linewidth = 0.9) +
  geom_point(data = ceac_df[ceac_df$optimal & ceac_df$wtp %% 10e6 == 0, ], shape = 21, size = 2.2,
             fill = "white", stroke = 1) +
  geom_vline(xintercept = report_at / 1e6, linetype = "22", colour = "grey40") +
  scale_colour_manual(values = pal_course[c(4, 2, 1)], name = NULL) +
  scale_y_continuous(limits = c(0, 1)) +
  facet_wrap(~ scenario) +
  labs(x = "Ngưỡng chi phí-hiệu quả (triệu VNĐ/QALY)", y = "Xác suất đạt chi phí-hiệu quả",
       title = "CEAC và CEAF của ba phác đồ",
       subtitle = "Vòng tròn: phác đồ tối ưu (CEAF); đường đứt: 0.5, 1 và 3 × GDP/người") +
  theme_course()
save_fig(fig_ceac, "l04-ceac.png", width = 8, height = 4.3)

CEAC và CEAF của ba phác đồ, hai kịch bản

Vẽ đường cong tổn thất kỳ vọng cho kịch bản B. Kiểm tra: đường đứt đen (EVPI) luôn bám theo đường thấp nhất.

elc <- cur_b
elc$strategy <- factor(lab[elc$strategy], levels = lab)
evpi_line <- unique(cur_b[, c("wtp", "evpi")])
fig_elc <- ggplot(elc, aes(wtp / 1e6, exp_loss / 1e6, colour = strategy)) +
  geom_line(linewidth = 0.9) +
  geom_line(data = evpi_line, aes(wtp / 1e6, evpi / 1e6), inherit.aes = FALSE,
            linetype = "22", colour = "black") +
  geom_vline(xintercept = p$wtp / 1e6, linetype = "22", colour = "grey40") +
  scale_colour_manual(values = pal_course[c(4, 2, 1)], name = NULL) +
  coord_cartesian(ylim = c(0, 3 * max(evpi_line$evpi) / 1e6)) +
  labs(x = "Ngưỡng chi phí-hiệu quả (triệu VNĐ/QALY)", y = "Tổn thất kỳ vọng (triệu VNĐ/người)",
       title = "Đường cong tổn thất kỳ vọng, kịch bản B (minh họa)",
       subtitle = "Đường đứt đen: EVPI = tổn thất kỳ vọng nhỏ nhất") +
  theme_course()
save_fig(fig_elc, "l04-elc.png", width = 7, height = 4.5)
wtp_peak <- evpi_line$wtp[which.max(evpi_line$evpi)]

Đường cong tổn thất kỳ vọng, kịch bản B

Ở xa ngưỡng hòa vốn, chiến lược tối ưu gần như chắc chắn đúng nên tổn thất kỳ vọng của nó gần 0. Tổn thất đạt đỉnh 3.17 triệu VNĐ mỗi người bệnh quanh ngưỡng 125.0 triệu VNĐ/QALY, nơi BPaLM và phác đồ ngắn gần như ngang nhau. Đường của phác đồ dài hạn nằm cao hẳn: chọn nó thì gần như chắc chắn mất tiền.

Lập bảng báo cáo ở ba ngưỡng. Kiểm tra: ba ngưỡng đều nằm trên lưới đã tính (stopifnot).

# Reporting table at the three thresholds (0.5, 1 and 3 x GDP per capita)
rep_rows <- NULL
for (w in report_at) {
  for (sc in c("A", "B")) {
    cur <- if (sc == "A") cur_a else cur_b
    psa <- if (sc == "A") psa_a else psa_b
    row_b <- cur[cur$wtp == w & cur$strategy == "bpalm", ]
    inb <- psa_incremental(psa, w)$d_nmb
    opt <- cur$strategy[cur$wtp == w & cur$optimal]
    rep_rows <- rbind(rep_rows, data.frame(
      scenario = sc, wtp_million = w / 1e6,
      d_nmb = fmt_ui(inb, 1, 1e6),
      p_bpalm = row_b$p_ce,
      optimal = lab[[opt]],
      loss_million = cur$exp_loss[cur$wtp == w & cur$optimal] / 1e6
    ))
  }
}
stopifnot(all(report_at %in% wtp_grid))
knitr::kable(rep_rows, digits = c(0, 2, 0, 3, 0, 2), row.names = FALSE,
             col.names = c("Kịch bản", "Ngưỡng (triệu VNĐ/QALY)",
                           "ΔNMB BPaLM − phác đồ ngắn, triệu VNĐ (khoảng bất định 95%)",
                           "P(BPaLM tối ưu)", "Lựa chọn tối ưu", "Tổn thất kỳ vọng của lựa chọn tối ưu (triệu VNĐ/người)"))
Kịch bản Ngưỡng (triệu VNĐ/QALY) ΔNMB BPaLM − phác đồ ngắn, triệu VNĐ (khoảng bất định 95%) P(BPaLM tối ưu) Lựa chọn tối ưu Tổn thất kỳ vọng của lựa chọn tối ưu (triệu VNĐ/người)
A 62.75 37.0 (khoảng bất định 95%: 28.8 đến 46.5) 1.000 BPaLM 0.00
B 62.75 -30.0 (khoảng bất định 95%: -37.2 đến -20.9) 0.000 Phác đồ ngắn 9 tháng 0.00
A 125.50 67.3 (khoảng bất định 95%: 51.9 đến 85.3) 1.000 BPaLM 0.00
B 125.50 0.4 (khoảng bất định 95%: -14.1 đến 18.3) 0.509 BPaLM 3.06
A 376.50 188.8 (khoảng bất định 95%: 143.8 đến 242.6) 1.000 BPaLM 0.00
B 376.50 121.8 (khoảng bất định 95%: 77.7 đến 174.4) 1.000 BPaLM 0.00
at_base_b <- cur_b[cur_b$wtp == p$wtp, ]
p_b_base <- at_base_b$p_ce[at_base_b$strategy == "bpalm"]
opt_b_base <- lab[[at_base_b$strategy[at_base_b$optimal]]]
dnmb_b_base <- rep_rows$d_nmb[rep_rows$scenario == "B" & rep_rows$wtp_million == p$wtp / 1e6]

Một câu báo cáo cho kịch bản A, viết từ bảng trên: ở mọi ngưỡng từ 0.5 đến 3 × GDP bình quân đầu người, BPaLM là lựa chọn tối ưu ở mọi lần chạy PSA; ở 1 × GDP/người, NMB gia tăng kỳ vọng so với phác đồ ngắn là 67.3 (khoảng bất định 95%: 51.9 đến 85.3) triệu VNĐ mỗi người bệnh. Và cho kịch bản B (giá giả định): ở ngưỡng 125.5 triệu VNĐ/QALY và giá BPaLM 12.9 triệu VNĐ mỗi tháng, NMB gia tăng kỳ vọng của BPaLM là 0.4 (khoảng bất định 95%: -14.1 đến 18.3) triệu VNĐ mỗi người bệnh; xác suất BPaLM là lựa chọn tối ưu là 51%; lựa chọn tối ưu theo kỳ vọng là BPaLM, và tổn thất kỳ vọng của lựa chọn đó là 3.06 triệu VNĐ mỗi người bệnh. Hai câu này cho người ra quyết định biết nên chọn gì, chắc đến đâu, và rủi ro bằng tiền là bao nhiêu.

Mẹo thực hành
  • Tính mọi đường cong (CEAC, CEAF, tổn thất kỳ vọng, EVPI) trong cùng một vòng lặp trên một dãy ngưỡng; các con số khi đó chắc chắn nhất quán với nhau.
  • Đặt chính xác các ngưỡng cần báo cáo (0.5, 1, 3 × GDP/người) vào lưới, thay vì đọc gần đúng trên hình.
  • Giữ cả phương án bị lấn át trong PSA: CEAC cho thấy nó gần như không bao giờ thắng, và đó cũng là một kết quả.
  • Đặt hình tổn thất kỳ vọng cạnh CEAC khi trình bày: một hình trả lời “chắc đến đâu”, hình kia trả lời “sai thì mất bao nhiêu”.
Lỗi thường gặp
  • Chọn chiến lược có CEAC cao nhất: lựa chọn tối ưu là NMB kỳ vọng cao nhất; hai điều này có thể khác nhau.
  • Đọc CEAC như một khoảng tin cậy của ICER: CEAC là xác suất theo ngưỡng; nó không cho biết độ lớn của lợi ích hay thiệt hại.
  • Vẽ CEAC bằng các cặp so sánh với một phương án gốc: với ba phương án, mỗi lần chạy chỉ có một phương án thắng; tính từ NMB của cả ba.
  • Báo cáo CEAC mà không nói phần nào dựa trên giả định: CEAC chỉ chắc chắn như các phân phối đầu vào và cấu trúc mô hình (Bài 1, Bài 5).

Bài tập

  1. (Dễ) Trong kịch bản B, ở ngưỡng nào \(E[\Delta\text{NMB}] = 0\) (ICER của các trung bình)? Ở ngưỡng nào CEAC của BPaLM bằng 0.5? Vì sao hai ngưỡng này gần nhau?
# Exercise 1: in scenario B, where is E[INB] = 0 (ICER of the means), and where does the
# CEAC of BPaLM cross 0.5 (median INB = 0)?
inc_b <- psa_incremental(psa_b, p$wtp)
wtp_mean <- mean(inc_b$d_cost) / mean(inc_b$d_qaly)            # ICER of the means
median_inb <- function(w) median(w * inc_b$d_qaly - inc_b$d_cost)
wtp_half <- uniroot(median_inb, c(0, max(report_at)))$root
round(c(icer_of_means_million = wtp_mean / 1e6, ceac_half_million = wtp_half / 1e6), 2)
icer_of_means_million     ceac_half_million 
               124.68                125.07 
# Width of the region between the two thresholds, relative to the base threshold
region_width <- abs(wtp_half - wtp_mean)
round(c(width_million = region_width / 1e6, share_of_wtp = region_width / p$wtp), 3)
width_million  share_of_wtp 
        0.390         0.003 

ICER của các trung bình là 124.68 triệu VNĐ/QALY; CEAC bằng 0.5 ở 125.07 triệu VNĐ/QALY (ngưỡng mà trung vị của \(\Delta\text{NMB}\) bằng 0). Hai ngưỡng trùng nhau khi phân phối của \(\Delta\text{NMB}\) đối xứng, vì khi đó trung vị bằng trung bình. Giữa hai ngưỡng là vùng mà chiến lược có xác suất cao nhất khác chiến lược tối ưu; ở đây vùng đó rộng 0.39 triệu VNĐ/QALY, tức 0.3% ngưỡng 1 × GDP/người, rất hẹp.

  1. (Vừa) Vẽ lại CEAC của kịch bản B chỉ với 200 lần chạy đầu. CEAC lệch tối đa bao nhiêu so với khi dùng 1,000 lần? So với sai số Monte Carlo của một xác suất?
# Exercise 2: a noisier CEAC from fewer runs (first 200 draws only)
sub <- decision_curves(psa_b[1:200, ], wtp_grid)
both <- merge(cur_b[cur_b$strategy == "bpalm", c("wtp", "p_ce")],
              sub[sub$strategy == "bpalm", c("wtp", "p_ce")], by = "wtp", suffixes = c("_full", "_200"))
max_dev_200 <- max(abs(both$p_ce_full - both$p_ce_200))
round(c(max_deviation = max_dev_200, binomial_se_at_0.5 = sqrt(0.5 * 0.5 / 200)), 3)
     max_deviation binomial_se_at_0.5 
             0.086              0.035 

Chênh lệch lớn nhất trên cả dãy ngưỡng là 0.086, bằng 2.4 lần sai số chuẩn nhị thức của một xác suất 0.5 với 200 lần chạy (0.035); lấy giá trị lớn nhất trên hàng trăm ngưỡng thì vượt 2 lần sai số chuẩn là chuyện thường. CEAC dao động mạnh nhất quanh ngưỡng hòa vốn, đúng nơi người ra quyết định quan tâm nhất.

  1. (Khó) Người mua muốn xác suất BPaLM là lựa chọn tối ưu ít nhất 90% ở ngưỡng 1 × GDP/người. Giá đàm phán tối đa là bao nhiêu? Gợi ý: trong mỗi lần chạy, chi phí tuyến tính theo giá, nên hai kịch bản A và B cho độ dốc của từng lần chạy.
# Exercise 3: which negotiated price gives P(BPaLM optimal) >= 0.9 at the base threshold?
# Within each run cost is linear in the price, so two runs per draw (A: sampled price,
# B: price_hi) give that run's slope (discounted months billed).
slope <- (psa_b$cost_bpalm - psa_a$cost_bpalm) / (price_hi - draws$c_drug_bpalm)
p_ce_at_price <- function(price) {
  q <- psa_b
  q$cost_bpalm <- psa_b$cost_bpalm + slope * (price - price_hi)
  nmb <- nmb_matrix(q, p$wtp)
  mean(max.col(nmb, ties.method = "first") == which(colnames(nmb) == "bpalm"))
}
prices <- seq(price_hi - 10e6, price_hi + 5e6, by = 0.5e6)
p_ce_curve <- sapply(prices, p_ce_at_price)
price_90 <- max(prices[p_ce_curve >= 0.9])
# Check the linear shortcut against a direct run at one price
check_run <- run_psa_vec(p, draws[1:5, ], fixed = list(c_drug_bpalm = price_90))
stopifnot(max(abs(check_run$cost_bpalm - (psa_b$cost_bpalm[1:5] + slope[1:5] * (price_90 - price_hi)))) < 1e-3)
round(c(price_hi_million = price_hi / 1e6, price_90_million = price_90 / 1e6, p_ce = p_ce_at_price(price_90),
        course_90_usd = price_90 * p$dur_bpalm / ctx$fx_vnd_per_usd), 3)
price_hi_million price_90_million             p_ce    course_90_usd 
          12.900           10.900            0.933         2619.143 

Giá tối đa trên lưới là 10.9 triệu VNĐ mỗi tháng (khoảng US$2,619 một đợt), thấp hơn giá của kịch bản B 2.0 triệu VNĐ nhưng vẫn gấp 9.2 lần giá GDF. Đòi hỏi xác suất cao là một lựa chọn chính sách thể hiện mức ngại rủi ro, không phải quy tắc của phân tích chi phí-hiệu quả; nếu dùng, hãy nói rõ. stopifnot so lối tắt tuyến tính với năm lần chạy mô hình trực tiếp.

Tài liệu tham khảo

# Slide Lời giảng chính Hình/Code
1 Ba câu hỏi của người ra quyết định chọn gì, chắc đến đâu, sai thì mất bao nhiêu callout đầu bài
2 CEAC tỷ lệ lần chạy mỗi phương án thắng; ba đường cộng bằng 1 công thức
3 CEAC hai kịch bản A: BPaLM ở mức 1 trên mọi ngưỡng; B: BPaLM và phác đồ ngắn đổi chỗ quanh 125.5 triệu VNĐ/QALY figs/l04-ceac.png
4 CEAF và đường biên kỳ vọng chọn theo NMB kỳ vọng; phương án tối ưu nằm trên đường biên chunk l04-frontier
5 Giới hạn của CEAC không nói mất bao nhiêu —
6 Tổn thất kỳ vọng xác suất sai × mức thiệt hại; đường thấp nhất = tối ưu công thức
7 Hình tổn thất kỳ vọng đỉnh ở ngưỡng hòa vốn; bằng EVPI figs/l04-elc.png
8 Bảng báo cáo 0.5, 1, 3 × GDP/người; kỳ vọng, khoảng 95%, xác suất, tổn thất chunk l04-report
9 Câu báo cáo mẫu một câu trả lời cả ba câu hỏi câu mẫu
10 Ba cách nói nên tránh ý nghĩa thống kê; xác suất làm quy tắc; thiếu ngưỡng —
11 Chuyển tiếp tổn thất kỳ vọng = EVPI → Bài 5 —