1. Two-stage model
Every policy-year record is generated in two stages, same shape as motor:
- Frequency — whether a death claim occurs this policy year is table-rated, not a from-scratch logistic regression like motor's. An age-band mortality table (loosely Gompertz-shaped — roughly doubling every 8-9 years past 40) is the actuarial anchor; smoker status, BMI band, and occupation class each apply a multiplicative loading on top of whichever band an applicant's age falls into. This keeps the age-band table itself the thing a reviewer can check directly, and the loadings legible as loadings on it, rather than opaque coefficients in a regression.
- Severity — for policies that do have a claim, the payout is a log-normal multiple of the sum assured (not an independent amount the way motor's claim size is). A standard claim pays out at the plan's base payout ratio; an accidental death rider (when held, and the cause of death is accidental) and Whole Life/Endowment bonus accrual (scaling with years the policy has been in force) both push the multiple up from there.
Which stage count to generate is itself a runtime choice on the
generator page —
two-stage (the default) runs both steps above;
single-stage runs the frequency step only. The frequency
logic and its coefficients are identical either way, so
claim_occurred, claim_id,
cause_of_death, and claim_date
are the same regardless of mode. claim_amount_ghs — the only severity-side column — is entirely absent from the output in
single-stage mode, not null-filled. Whichever mode you pick is recorded
in the dataset's manifest and citation, same reasoning
motor's own stage_mode
toggle documents.
2. The four hypotheses
Unlike motor, all four of life's core hypotheses are on claim frequency, not severity — severity here is driven by product features (the rider, the bonus accrual), not by the same demographic factors that drive whether a claim happens at all. This also means all four apply, and are verified, in both stage modes, unlike motor's severity-only set.
| Factor | Direction on claim frequency | Rationale encoded |
|---|---|---|
| Applicant age | Positive | Older applicants sit in higher age bands on the mortality table — the anchor itself, not a separate coefficient. |
| Smoker status | Positive | Smokers carry an elevated baseline mortality loading — the standard actuarial rule of thumb. |
| BMI band | Positive | Overweight and Obese bands carry an elevated mortality loading relative to Normal/Underweight. |
| Occupation class | Positive | Hazardous occupations (mining, construction, haulage) carry a higher mortality loading than office/professional roles. |
3. Coefficients
Claim probability is modeled as
p = clip(base_rate(age_band) · smoker_loading · bmi_loading ·
occupation_loading · (1 + hazardous_extra), min_probability,
max_probability), where base_rate(age_band) is the age-band mortality
table lookup. Claim payout, when a claim occurs, is modeled as
claim_amount = sum_assured · exp(log_base +
accidental_rider_bonus·is_accidental·has_rider +
whole_life_bonus_per_year·years_in_force·is_not_term + ε), where ε is normal noise, capped at 2.5x sum assured. These
coefficients are illustrative, chosen to produce a clearly recoverable
signal at typical sample sizes — note the life line's own hypothesis
tests use n=20,000 rather than motor's n=5,000, since a death claim is
a much rarer event than a motor claim at realistic mortality rates.
Exact magnitudes aren't published on this page and aren't derived from
a real Ghanaian life table — see the current defaults, and change
them, in the
Advanced: customize the model panel on the
life generator if your thesis
calls for weaker or stronger effects, and note in your write-up which values
you changed from the defaults.
4. Determinism
Generation runs server-side using a seeded generator (numpy's
default_rng, PCG64) rather than an unseeded
source of randomness — same mechanism as motor. The same seed, record
count, and generator version (stamped in every citation and manifest —
see the Cite section on the generator page) will always reproduce
byte-identical output. Report the seed and record count alongside your
dataset — that pair, together with the generator version, is
sufficient for anyone to regenerate exactly what you analyzed.
5. What's decorative vs. load-bearing
Region, policy type/term, insured name, and premium calculations exist
to make records look like real Ghanaian life policies and are
internally consistent with each other, but they are not the object of
the four hypotheses above. Treat the premium figures as an
illustrative table-rated approximation, not as calibrated to any
actual insurer's rate card. insured_name
is excluded from generated output only if you disable it in a future name-inclusion
toggle (not yet built — see ROADMAP.md Phase 4.5.3); today it's always present,
same as every other field.
6. Known limitations
- This is synthetic data. It should never be presented as, or mistaken for, real insurer or mortality data in a publication.
- Frequency is table-rated with multiplicative loadings, not a from-scratch regression — no interaction effects between smoker status, BMI, and occupation are modeled beyond simple multiplication, unless you add them yourself downstream.
- Claim payout is capped at 2.5x sum assured regardless of how the rider bonus and Whole Life/Endowment accrual stack — a deliberate sanity cap on the tail, same role as motor's cap near the vehicle's insured value.
- If your thesis needs a different balance between the four frequency-side hypotheses, adjust the relevant loadings in the Advanced: customize the model panel on the life generator and say so in your write-up.
7. Citing this tool
Something like: "Synthetic data generated using Dataset Foundry (seed = 42, n = 5,000), a deterministic life insurance data generator built for this thesis in the absence of accessible real-world mortality data." Include the seed and record count so the exact dataset is reproducible from the tool alone — or use the auto-generated citation block on the generator page, which also includes the generator version and any advanced-config changes.