Tegh S. Bindra

Writing — August 2026

Where my underwriting risk weights come from

The fastest way to make a risk demo is to invent the numbers. I didn't want to, because a rule engine with made-up weights is just my taste wearing a lab coat.

My underwriting copilot scores life-insurance applications with a weighted rule engine: current smoker adds 24 points, diabetes adds 16, and so on. In most student projects those numbers come from nowhere. In mine, every single point value is:

points = round(28 × ln(real all-cause-mortality multiple))

The log matters. Mortality risks multiply — a smoker with diabetes is roughly 2.37 × 1.80 times baseline risk — but points add. Logarithms turn multiplication into addition, so the ratio between any two point values on the card is the ratio between two real mortality figures. 28 is just a scaling constant that puts the weights in a readable range.

Getting real mortality multiples

The multiples come from public-domain CDC data: NHANES 2007–2014 examination and lab files joined to the NCHS Linked Mortality File — 20,435 US adults with 2,293 linked deaths over roughly a decade of follow-up. I fit an age- and sex-adjusted logistic regression on measured risk factors. Measured is the key word: smoking status comes from serum cotinine ≥ 10 ng/mL, not from a questionnaire, because people lie on questionnaires and blood doesn't.

Where a published mega-study had a better estimate than my fit, I used it and cited it: diabetes at 1.80× is the Emerging Risk Factors Collaboration (NEJM 2011, 820k people); BMI ≥ 35 at 1.55× is the Prospective Studies Collaboration (Lancet 2009, 900k). My own NHANES fit for cotinine-confirmed smoking landed at 2.37×, which matches the published 2.2–2.3× range — a good sign the pipeline wasn't broken.

Checking it against a real insurer

Derivation is half the job; the other half is finding out whether an actual insurer would recognize these weights. I scored the 59,381 real applicants in the Kaggle Prudential Life Insurance Assessment dataset using only the factors Prudential exposes. My weights agree with the insurer's own 1–8 underwriting rating at AUC 0.68, and the same method scores AUC 0.72–0.73 on real applicants — squarely inside the range published actuarial models report.

What I refuse to claim

The portfolio the engine scores is synthetic, so headline metrics are tuned on half of it and reported on the held-out half only. The straight-through processing rate is 79.9% held-out, and it costs 52% auto-decline precision — about half of auto-declines are applicants who weren't actually high risk. That trade is printed on the model card instead of hidden, because an optimizer with no guardrails "wins" by declining everyone.

The point of all this: when someone challenges a weight, the argument is about a mortality study, not about me. You can disagree with the data. You can't disagree with my taste, and that's exactly why taste wasn't allowed to set the numbers.

Derivation and validation scripts are committed in the repo (src/derive_weights.py, src/prudential_validate.py); the raw NHANES/NCHS files are excluded because redistribution is restricted. Questions or corrections: bindrategh@gmail.com.