Red Door Analytics
Stata package · released · accompanies a paper

What jmqaly does

jmqaly computes quality-adjusted life years after a joint model of a longitudinal outcome and survival, fitted with merlin. It is a standalone command that accompanies one paper rather than a member of the merlin family: it is released on its own, and it requires one specific version of merlin rather than tracking the family’s line.

For a horizon you give it, jmqaly returns the restricted QALY — quality of life weighted by the probability of being alive to experience it, accumulated to that horizon and optionally discounted. The integral over time is Gauss–Legendre; the integral over the random effects is merlin’s.

What makes that the paper’s estimator rather than an approximation of it: quality of life and survival are multiplied at each quadrature node of the random-effect distribution, and the product is marginalised once. The result therefore carries the association between quality of life and survival that the joint model estimates. Marginalising the two apart and multiplying the answers throws it away.

Capabilities

A horizon you set, or one it has to find

Everything below is what the package documents and what it refuses. A command that tells you which quantities it will not compute is easier to trust with the ones it will.

RESTRICTED

To a horizon you choose

The QALY accumulated to a time you pass in timevar(), for one covariate pattern or as a difference between two, with confidence intervals.

LIFETIME

The horizon is found, not given

With lifetime the horizon doubles until the accumulated QALY stops moving, and the answer is reported with the horizon reached and the share of the total still estimated to be missing beyond it. “Integrated to 232, with an estimated 3e−05 of the total remaining” is a statement a reader can check; “integrated to infinity” is not.

DISCOUNTING

Continuous or discrete

A discount rate through drate(), applied continuously by default and discretely with dmethod(discrete).

NEITHER IS A DEFAULT

Two different estimands

A QALY restricted to a horizon and a lifetime QALY are not the same quantity, so the package refuses to choose for you. A lifetime horizon also extrapolates the fitted survival well beyond the data with no population-rate anchor — a model quantity rather than an all-cause one, and the documentation says so.

QUALITY OF LIFE

Five families, and the ones it refuses

The longitudinal submodel may be gaussian, bernoulli, gamma, poisson or beta. merlin supplies no expected value for its ordinal families, so those are refused rather than approximated.

SURVIVAL

Whatever merlin can predict

The survival function is resolved from the fitted family, so any survival family merlin predicts from is supported. The fit must be two-level with exactly one survival submodel, and cross-submodel associations are refused — share the random effects between submodels instead.

Installation

Get started

Install from the package repository within Stata.

net install jmqaly, from("https://raw.githubusercontent.com/RedDoorAnalytics/jmqaly-stata/main/")

A first model

// a joint model: flexible parametric survival sharing a random intercept
// with a linear mixed model for quality of life
merlin (stime trt M1[id], family(rp, df(1) failure(died))) ///
       (qol time time#trt M1[id]@1, family(gaussian) timevar(time))

range tvar 0 10 100

// restricted QALYs by arm, the difference, and confidence intervals
jmqaly dq, at1(trt 1) at2(trt 0) timevar(tvar) ci

// discounted at 3.5% a year
jmqaly ddq, at1(trt 1) at2(trt 0) timevar(tvar) drate(0.035)

// lifetime QALYs: the horizon is found rather than given, and reported
jmqaly lt, at1(trt 1) at2(trt 0) lifetime drate(0.035)

It requires StataNow 19.5, and merlin 2.5.0 specifically. 2.5.0 is the released merlin, so it is what installing from the merlin repository gives you. jmqaly checks the version and refuses to run beside any other — a diagnostic rather than a wrong answer — because its compiled library is built against merlin’s internal structures. Source, help and the certification suite are in the package repository.

Related

Where it sits

jmqaly is not part of the merlin family. The family — merlin and the packages built around it — is one engine and its satellites, developed and released together. jmqaly is a single command published alongside its paper, pinned to one merlin version, and maintained on that footing. It needs merlin to fit the joint model; it is not part of what merlin is.
Cite

Citing jmqaly

Cite the paper — jmqaly is the reference implementation of its estimators.

@article{crowther2026,
  author  = {Crowther, M. J. and Gasparini, A. and Ekberg, S. and Felizzi, F. and Gallagher, E. and Paracha, N.},
  title   = {{A Framework for the Estimation of Quality-Adjusted Life-Years Using Joint Models of Longitudinal and Survival Data}},
  journal = {Medical Decision Making},
  year    = {2026},
  doi     = {10.1177/0272989x261477224}
}

RIS and the full library are on the publications page.

Estimating QALYs from a joint model?

The estimators in jmqaly came out of applied work on quality of life and survival in oncology trials. Talk to us about the modelling behind a submission, or about extending this to a design the package does not yet cover.

Get in touch Start a project