A Data-Driven Approach
Every hospital administrator and clinician eventually runs into the same dilemma: a more expensive treatment isn’t always proportionally more effective, and a limited budget forces hard choices about who gets what. This is exactly the kind of problem where quantitative modeling earns its keep. In this post, we’ll build a complete cost-effectiveness analysis pipeline in Python — from the classic health-economics metrics (ICER, QALY, NMB) to portfolio-level budget optimization and uncertainty analysis — and visualize the results, including a 3D optimization surface.
The Core Trade-off: Cost vs. Effect
In health economics, treatment effectiveness is commonly measured in QALYs (Quality-Adjusted Life Years) — a single number combining survival gain and quality-of-life gain. When comparing two treatments, the key metric is the Incremental Cost-Effectiveness Ratio (ICER):
$$
ICER = \frac{C_2 - C_1}{E_2 - E_1}
$$
where $C$ is cost and $E$ is effectiveness (QALYs gained). This tells you how much extra money you must spend per additional QALY gained by switching to the more expensive option.
A treatment is dominated if another option is both cheaper and more effective. It is extendedly dominated if a combination of two other treatments on the efficiency frontier beats it. Only the surviving treatments form the efficient frontier.
To decide whether a treatment is “worth it,” economists compare its ICER against a willingness-to-pay (WTP) threshold $\lambda$ (e.g., a health system might accept spending up to a certain amount per QALY). Equivalently, we can define the Net Monetary Benefit:
$$
NMB = E \cdot \lambda - C
$$
The treatment with the highest NMB at a given $\lambda$ is the economically preferred option. When we must allocate a budget across many patients rather than choose once, this becomes a linear program:
$$
\max \sum_i x_i \left( q_i \lambda - c_i \right) \quad \text{s.t.} \quad \sum_i x_i = N, \quad \sum_i c_i x_i \le B, \quad x_i \ge 0
$$
where $x_i$ is the number of patients assigned to treatment $i$, $N$ is the total patient population, and $B$ is the available budget.
Full Python Implementation
The code below runs top to bottom in Google Colaboratory with no additional setup.
1 | # ============================================================ |
Output
Efficient frontier: ['No Treatment', 'Treatment A (Generic Drug)', 'Treatment B (Standard Therapy)', 'Treatment C (Advanced Biologic)'] Dominated treatments: ['Treatment D (Surgery)'] ICERs along frontier (JPY per QALY): ['1,666,667', '2,800,000', '25,714,286']
Code Walkthrough
Section 1 — Treatment definitions. Five options are defined: doing nothing, a cheap generic drug, a standard therapy, a surgical option, and an advanced biologic. Cost is in Japanese yen; effect is in QALYs gained relative to no treatment.
Section 2 — Efficient frontier. This implements the standard health-economics dominance algorithm. It sorts treatments by cost, discards anything that is strictly dominated (more expensive, less effective), and then discards anything that is extendedly dominated — meaning its ICER is worse than the ICER of the next treatment up the cost ladder. In our numbers, Treatment D (Surgery) turns out to be extendedly dominated: its incremental cost per QALY compared to B is worse than jumping straight from B to C, so a rational payer would skip D entirely.
Section 3 — Budget-constrained portfolio optimization. Instead of picking a single treatment, a hospital with 500 patients must decide how many patients receive each option. This is formulated as a linear program and solved with scipy.optimize.linprog using the "highs" solver (a fast, modern LP solver bundled with SciPy). We sweep the budget from zero to the cost of treating everyone with the most expensive option, solving one LP per budget level.
Section 4 — Probabilistic Sensitivity Analysis (PSA). Real-world costs and effects are uncertain, so each treatment’s cost and QALY are modeled as random draws from a normal distribution (10% standard deviation). A naive implementation would loop over each of the 200,000 simulated patients individually and compare treatments one at a time — this would be painfully slow in pure Python. Instead, all 200,000 samples for all 5 treatments are generated and compared simultaneously as NumPy arrays; the only remaining loop is over the 121 WTP threshold values, which is a trivial and fast iteration. This is what produces the Cost-Effectiveness Acceptability Curve (CEAC): at each WTP threshold, what fraction of simulations favor each treatment.
Section 5 — 3D optimization surface. This repeats the budget-constrained LP from Section 3, but now across a 25×25 grid of both budget and WTP threshold, optimizing Net Monetary Benefit instead of raw QALYs. Because each LP has only 5 variables, solving 625 of them is still very fast.
Sections 6–9 — Visualization. Four plots are generated: the cost-effectiveness plane, the budget-vs-QALY curve, the CEAC, and the 3D NMB surface.
Results
1. Cost-Effectiveness Plane

This scatter plot places every treatment by its QALY gain (x-axis) and cost (y-axis). Blue points and the dashed line form the efficient frontier — the treatments worth considering. The red point is Treatment D (Surgery): even though it costs more and delivers more QALYs than Treatment B, it does so inefficiently compared to jumping straight to Treatment C, so no rational budget-holder should choose it. This is the extended-dominance case discussed above, made visually obvious by its position off the frontier line.
2. Budget vs. Achieved QALYs

This curve shows the maximum total QALYs achievable across 500 patients as the hospital’s budget increases. Early budget increases produce steep QALY gains, because the optimizer first funds the cheap, highly efficient Treatment A for everyone. As the budget grows further, the curve flattens — the optimizer starts allocating expensive Treatment C to a growing share of patients, and each additional yen buys progressively less QALY. This diminishing-returns shape is exactly what a hospital finance committee needs to see before setting next year’s budget.
3. Cost-Effectiveness Acceptability Curve (CEAC)

Each line shows, across a range of willingness-to-pay thresholds, the probability (under the uncertainty in cost and effect) that a given treatment is the most cost-effective choice. At very low WTP thresholds, “No Treatment” and Treatment A dominate. As the threshold rises, the curves cross — Treatment B takes over the leading position, then eventually Treatment C becomes preferred at high WTP values. These crossover points are exactly where policy decisions become sensitive to the threshold a health system chooses, and the CEAC makes that sensitivity explicit rather than hiding it behind a single point estimate.
4. 3D Surface: Optimal Net Monetary Benefit

This surface shows, for every combination of budget and willingness-to-pay threshold, the best achievable Net Monetary Benefit per patient. Two things stand out. First, NMB rises steeply along the WTP axis whenever the budget is large enough to fund effective treatments — the health system is willing to “pay” more for QALYs, and it has the resources to buy them. Second, along the budget axis at low WTP, the surface stays nearly flat: when QALYs aren’t valued highly, extra budget isn’t worth spending, so the optimizer keeps assigning patients to inexpensive options. The ridge running diagonally across the surface marks the region where budget and willingness-to-pay are balanced enough that the more expensive biologic treatment becomes worthwhile at scale.
Conclusion
Treatment decisions under a budget constraint are rarely as simple as “pick the treatment with the best outcome.” The efficient frontier tells you which options are even worth considering, the linear program tells you how to allocate a fixed budget across a patient population, and the Monte Carlo / CEAC analysis tells you how confident you should be in that decision given real-world uncertainty. Combining all three into a single, fast, vectorized Python pipeline turns a fairly abstract health-economics problem into something you can re-run instantly whenever costs, effect sizes, or budgets change.

































