Tier 1 · Pricing

Pension Risk Transfer (PRT) Pricing

M-072 · lifecycle: monitoring · RAT-072-v1.0.2 (conditional)

Intended Use

Pension Risk Transfer (PRT) Pricing Price pension-risk-transfer transactions for direct-pay annuity quotes.

Bid pricing for PRT deals. Different intended use from M-070/M-071 (transaction-pricing vs new-business retail pricing) and different regulatory profile (ERISA-related considerations).


Components

Inputs, processing, outputs

data sources
DS-001 · DS-008
assumptions
A-001, A-070, A-071
engines
insmodel.L4.prt_model
insmodel.L4.mortality_engine
insmodel.L4.expense_engine
contracts
pricing_results_v1
dimensions
D6

Methodology & Mechanics

Methodology

M-072 prices a pension-risk-transfer (PRT) group annuity buyout: the insurer receives a lump-sum premium and assumes a defined-benefit plan's obligation to pay scheduled pension benefits to retirees for life. The engine is insmodel.L4.prt_model (PRTModel, internal model_id P-005, ProductArchetypeType.PRT). It is a liability-driven, deterministic monthly cash-flow projection — no lapse, no surrender, no policyholder optionality (the contract is irrevocable). Cash flows are driven entirely by annuitant mortality, longevity improvement, and investment income on the backing general-account reserve.

The pricing mechanics, as implemented in firmmodel/products/prt_model.py:

  1. Liability cash-flow projection (calculate). For each monthly step the engine computes, on the beginning-of-period reserve: - Pension payment = annuitants_remaining × current_monthly_benefit. With a COLA rate, current_benefit steps up at each year boundary; the default cola_rate is 0. - Investment income = reserve × monthly_yield, where monthly_yield = (1 + portfolio_yield)^(1/12) − 1. - Mortality decrement = annuitants × monthly_qx, with monthly_qx = 1 − (1 − annual_qx)^(1/12). - Mortality release (profit from deaths) = deaths × (reserve / annuitants) — the per-annuitant reserve freed when an annuitant dies. - Expense = reserve × (expense_bps/10000/12) + annuitants × per_annuitant_expense/12. - Net income = investment_income − pension_payment + mortality_release − expense. - Reserve roll-forward = reserve + investment_income − pension_payment − expense, floored at 0; annuitants decremented by deaths. The projection stops early if annuitants < 1 or reserve <= 0.

  2. Mortality basis (_get_mortality_rate). Base annual qx at age 70 is set by gender (male 0.025, female 0.018), graded linearly above age 70 by mortality_age_slope (0.0008/yr), gender-blended by female_mix, then improved by a constant annual factor (1 − mortality_improvement_rate)^year, clipped to [0.0001, 1.0]. For the canonical 65% female / 35% male blend at age 70, year 0, this yields annual qx = 0.02045.

  3. Pricing / profitability (compute_profitability). The engine runs calculate on a pricing cohort seeded from initial_reserve (the premium) and initial_annuitant_count, then discounts the net-income stream at a monthly-equivalent of the annual discount_rate: - PVFP = Σ net_income_m × (1 + monthly_discount)^(−m); profit_margin = pvfp / initial_reserve. - irrtotal_net_income / initial_reserve / years (a simple annualized approximation, not a root-found IRR). - return_on_capital = pvfp / (initial_reserve × 0.04) (a flat 4% capital charge). - breakeven_year = first year cumulative net income turns positive (None if never). - longevity_sensitivity = pvfp_stressed − pvfp, where the stressed run bumps mortality_improvement_rate by +10% (more improvement → annuitants live longer → lower profit).

There is no explicit "buyout premium" solve: the premium is supplied as initial_reserve, and the model evaluates whether it is adequate by projecting whether it produces positive PVFP. Pricing adequacy is read off the sign of PVFP / profit_margin rather than computed as a closed-form annuity present value. The canonical default block supplies initial_reserve = $3.3B (the PV of the default 10,000 × $2,500/mo = $300M/yr benefit stream, ≈11x annual benefit at age 70 / 5% yield — prt_model.py line 109, set by the INV-025 fix on 2026-06-04), so the worked default funds the cohort over the full projection horizon rather than depleting; the premium remains an input, not a fair-price output.


Key Assumptions

Key Assumptions and Their Justification

Parameter Canonical value Derivation Justification
Annuitant mortality basis (A-001) base qx male 0.025 / female 0.018 at age 70 published_source Stands in for the SOA 2012 IAM annuitant table; annuitant (not insured-life) mortality is the correct basis for group annuities.
Mortality age slope 0.0008 per year above age 70 calibrated Linear approximation of the qx age-gradient for the retiree band.
Mortality improvement (A-002 analogue) 1.0% p.a. constant reduction published_source Stand-in for SOA Scale MP-2021. Applied as a scalar (1−r)^year — the dominant longevity-risk lever, stress-tested at +10%.
Gender mix (female_mix) 0.65 (65% female) data_calibrated Typical DB-pension retiree demographic; higher female share lengthens duration.
Portfolio yield 5.0% market_data General-account backing-asset yield; single blended yield, not a duration-matched asset curve.
Expense loading 15 bps of reserve + $40/annuitant/yr (A-070) data_calibrated Reserve-proportional admin cost plus per-life servicing cost.
COLA rate 0.0% (configurable) contractual Base PRT block assumes level (non-escalating) benefits.
Pricing discount rate 6.0% parameter Risk-adjusted rate for PVFP; distinct from the 5% asset yield, creating the priced spread.
Capital charge 4% of premium regulatory proxy Flat PRT capital basis for return-on-capital; a simplification of a full economic-capital model.

The profit/risk margin is implicit, not an explicit additive load: it emerges from the spread between the 5% asset yield earned and the 6% discount rate at which liabilities are valued, net of mortality release and expense. The model does not add a separate explicit profit loading on top of the liability present value.


Output Snapshot

Output Snapshot

Deterministic single-block run of PRTModel — reproducible, requires no live firm data (python scripts/model_snapshots.py M-072 in InsModel; mechanics asserted by tests/test_prt_model.py). The provider is a MagicMock.

Canonical block (mirrors the snapshot-script header): 10,000 annuitants · avg age 70 · 65% female · $2,500/mo benefit · $3.3B premium/reserve (≈11x annual benefit PV) · 5% yield · 1% improvement · discount 6% · 240mo (full horizon; premium-solve still open).

Re-captured 2026-06-06 from python3 scripts/model_snapshots.py M-072 against the post-INV-025 funded default (initial_reserve $3.3B, prt_model.py line 109, InsModel #52 / commit bda809a). Deterministic, no live firm data (MagicMock provider). With the block now funded the projection reaches the full 240-month horizon rather than exhausting at month 13.

output value meaning
initial_premium_reserve 3,300,000,000.00 premium received / opening reserve (PV of default benefit stream, ≈11x annual benefit)
pvfp_at6pct -1,176,158,338.41 present value of net income at 6% discount
profit_margin -0.3564 pvfp / initial_reserve
longevity_sensitivity_plus10pct -7,656,904.12 PVFP impact of +10% improvement rate (negative: more improvement → lower profit)
month1_pension_payment 25,000,000.00 10,000 × $2,500 (independent of reserve)
month1_investment_income 13,444,608.49 $3.3B × monthly-equiv of 5%
month1_mortality_release 5,677,160.06 reserve freed by month-1 deaths
month1_net_income -6,324,064.79 NII + release − payment − expense
month1_mortality_rate_annual_qx 0.0204 blended qx ≈ 0.02045
final_month_projected 240 reaches the full projection horizon
final_reserve 257,290,679.09 end-of-horizon reserve

Reading the snapshot (honest interpretation, not a defect to hide): PVFP is negative (−$1.18B, profit_margin −0.36) on this canonical block. This is the correct deterministic output of the engine as currently parameterised, not a bug: the liabilities are discounted at 6% while the backing assets earn only 5%, so the priced spread is adverse and the supplied $3.3B premium is not an adequate (fair) buyout price under those assumptions. The model is an adequacy scorer of a supplied premium, not a fair-price solver (see Limitation 2 — premium-solve still absent), so a negative PVFP is the engine correctly flagging that the default premium/spread is uneconomic. The first-month flow mechanics (pension payment 10,000 × $2,500 = $25M, blended annual qx ≈ 0.02045) are reserve-independent and individually checked by tests/test_prt_model.py. The longevity-sensitivity sign is negative as expected (more improvement → annuitants live longer → lower profit). See Limitations.

Re-captured 2026-06-06 from the snapshot script (deterministic, no live data); supersedes the stale $300M/month-13-depletion table cleared 2026-06-04 (INV-025).


Limitations

Limitations and Known Gaps

  1. Default block now funds the benefit stream (degenerate-default fixed); premium-solve still absent. The earlier degenerate default — initial_reserve $300M against a $25M/mo benefit stream, which exhausted the reserve at month 13 — was fixed in code on 2026-06-04 (INV-025 partial fix, prt_model.py line 109): the default initial_reserve is now $3.3B, the PV of the default benefit stream (≈11x annual benefit at age 70, 5% yield), so the canonical cohort funds over the full projection horizon. What remains true is that the engine still has no premium-solve: it scores the adequacy of a supplied premium (via the sign of PVFP / profit_margin) rather than computing the actuarially fair buyout price. A production run still supplies its own reserve; the default is now a self-consistent funded block but is not derived from a fair-price solve (see Limitation 2). Building the premium-solve is tracked for ratification (INV-025 still-open leg) and is not applied in this documentation pass.
  2. Premium is an input, not an output. Unlike a true annuity-pricing routine, M-072 does not return a buyout premium from liability cash flows plus a loading. Premium adequacy is inferred from the sign of PVFP/profit_margin. There is no closed-form PV(benefits) + loading → price solve.
  3. Scalar mortality improvement, not age-banded. Improvement is a single annual percentage rather than the age-banded SOA Scale MP-2021 structure; biases qx at age extremes.
  4. Single blended portfolio yield — no asset-liability duration matching. Investment income uses one flat portfolio_yield; no duration-matched asset portfolio or reinvestment/disintermediation risk, material for long-dated annuitant liabilities.
  5. Single-life mortality only — no joint-and-survivor benefit form. Real PRT books carry J&S annuitants; the engine models single-life decrement only, understating tail duration for J&S-heavy blocks.
  6. No stochastic longevity. Longevity risk is captured solely by a deterministic ±10% improvement-rate shift; no stochastic mortality distribution or trend-uncertainty band.
  7. Simplified expense and capital model. Expense is reserve-bps plus per-life; no explicit acquisition cost. Return-on-capital uses a flat 4% charge, not an economic-capital computation.
  8. No reinsurance / cession modeled. Any reinsurance is an entity-level adjustment outside this product model.
  9. Firm-data path divergent (BV-032). The snapshot is deterministic with synthetic inputs only; no 10-K-grounded PRT-book figures are asserted.

Validation Evidence

Validation Packet

evidence status reference
Unit/behavioural test suite present tests/test_prt_model.py — 24 tests (calculation, mortality decrement, reserve runoff, COLA, gender-mix, profitability, longevity sensitivity, governance). All green 2026-06-06.
Deterministic snapshot present scripts/model_snapshots.py M-072 — re-captured into §Output Snapshot 2026-06-06.
Validation evidence pack (MRM §10.5 item 5) present insightalm/modelling/validation_evidence/M-072/v1.0.0/README.md — maps each §10.5 sub-item to named tests + the snapshot (closes RAT-072 COND-001).
Per-version change log (MRM §10.5 item 7) present insightalm/modelling/model_cards/M-072-changes.md (closes RAT-072 COND-002).
Calibrated-block frozen gold case pending A frozen weight/output regression test asserting the $3.3B canonical run cell-for-cell is not yet added in InsModel (the snapshot is reproducible but not pinned by an assert). Tracked — not asserted here.
Premium-solve / fair-price validation missing No premium-solve exists in the engine (Limitation 2); engine-build, honestly conditional.
Independent challenge (2L) per registry see lifecycle.

References

References

Engine and tests (InsModel): - ecosystem/InsModel/Models/firmmodel/products/prt_model.pyPRTModel (insmodel.L4.prt_model, model_id P-005). - tests/test_prt_model.py — 24-test suite. Snapshot: scripts/model_snapshots.py M-072. - firmmodel/governance/legacy_metadata/PRTModel.yaml — extracted SR 11-7 narrative.

Actuarial / methodology: - SOA Research Report — Pension Risk Transfer: Actuarial Considerations (2019). - American Academy of Actuaries Practice Note — Assumptions for Group Annuity Contracts Used to Settle DB Pension Plan Obligations (2023). - ASOP No. 27 (rev. 2024) — economic assumptions for measuring pension obligations. - ASOP No. 35 — demographic assumptions (mortality, longevity improvement). - ASOP No. 56 — Modeling. - SOA 2012 Individual Annuity Mortality (IAM) Basic Table; SOA Mortality Improvement Scale MP-2021.

Internal: Decision 020 (Assumption Policy); Decision 023 (Policy-Based Binding); BV-032 (firm-data divergence).


Change Log

Change Log

Card change history. Code-side change history lives in git log of the component files.

  • 2026-05-08 — stub created from registry data per Decision 023 Phase 5 / B-07.
  • 2026-05-09 — added DS-018 + DS-062 references and Standards Coverage section per Stage B (DG-005 closure). (Corrected 2026-06-04: an earlier wording of this entry stated that Methodology / Key Assumptions / Validation "remain stubbed for actuarial author follow-on" — those sections are in fact authored; the stale note has been removed.)
  • 2026-06-06 — 1L remediation of RAT-072-v1.0.0 (Decision 053 §2.2). Re-captured the Output Snapshot from scripts/model_snapshots.py M-072 (deterministic; pvfp −$1.18B / profit_margin −0.36 / longevity_sens −$7.66M / final_reserve $257.3M at month 240) — supersedes the pending-re-capture placeholder; added the honest interpretation that negative PVFP is the engine correctly flagging the default premium/spread as uneconomic (not a defect). Assembled the validation-evidence pack at validation_evidence/M-072/v1.0.0/README.md mapping MRM §10.5 item 5 sub-items to the 24 real tests/test_prt_model.py cases + the snapshot (closes COND-001). Created the per-version change log model_cards/M-072-changes.md (closes COND-002). No model outputs, back-test numbers, or validation results were fabricated; the premium-solve, frozen-gold regression, and realized-outcome back-test remain honestly conditional.
  • 2026-06-04 — recorded the INV-025 default-funding code change: engine default initial_reserve raised $300M → $3.3B (PV of the default benefit stream, ≈11x annual benefit; prt_model.py line 109, InsModel #52 / commit bda809a), and the snapshot script's M-072 config + caption updated to the $3.3B / 240mo canonical block ("full horizon; premium-solve still open"). Card refreshed to match: cleared the stale $300M / month-13-depletion Output Snapshot (numeric re-capture left for the gated snapshot run), rewrote Limitation 1 (degenerate-default fixed; premium-solve still absent), reframed the Validation-Packet priced-block row to a pending calibrated-block frozen-gold case, and anchored the Methodology worked default on the funded $3.3B block. No model outputs, back-test numbers, or validation results were fabricated or changed; the premium-solve, snapshot re-capture, frozen-gold case, and Tier-1 validation pack remain tracked for ratification.

2L Inventory Review

Open findings (2)

Independent 2nd-line review (INV-2026-06) — implemented capability vs registered scope. Each carries a recommended fix and is tracked in insightalm-mrm until closed.

HIGH INV-029 · P5 · validation-gap

Validation evidence + change logs missing across most of the inventory

Only M-001/M-020/M-050 carried full documentation packs before this pass. Most models record validation_evidence: missing and change_log: missing with peer_review: pending. Gold tests freeze behaviour but many assert only structural invariants (e.g. reserve>0), not correctness against external truth. The flagship T0-vs-10-K match is circular (BV-032).

Recommendation: For each Tier-1 model: produce a validation-evidence pack (back-test vs disclosed results once BV-032 re-calibration lands, sensitivity suite, challenger comparison), a change log, and a 2L ratification. Sequence behind BV-032 (firm-data) for anything needing 10-K reconciliation.

LOW INV-025 · P4 · degenerate-default

PRT default params underfund the benefit stream; no premium-solve

Shipped initial_reserve ($300M) is far too small for the shipped benefit stream (10,000 x $2,500/mo = $25M/mo), so the canonical projection exhausts the reserve at month 13 and returns degenerate profitability (PVFP ~ -premium, no breakeven). The engine has no premium-solve: it scores adequacy of a *supplied* premium rather than computing the actuarially fair buyout price.

Recommendation: Ship internally-consistent defaults (reserve = PV of the benefit stream) AND add a premium-solve (PV(benefits)+loading -> price). Add a calibrated-block frozen case.


Validation Coverage

Per-tier expectations

Per MRM Framework §10.2 + §10.3, this model's regulatory_frameworks tag list activates the following overlays:

asop_56 internal
component tier-1 expectation status
Registry entry required present
Model card (§10.5 doc pack) required present
Validation evidence required present
Change log required present
Independent effective challenge (2L) required pending

Ratification

Conditionally approved — RAT-072-v1.0.2

2L issued RAT-072-v1.0.2 with the following conditions outstanding. Bridge audit Rule 2 treats this as a WARN; the model can remain in monitoring with the conditions on record.

id deadline condition
COND-001 2026-08-23 NARROWED, STILL OPEN (the remaining Tier-1 blocker). The validation-evidence pack provides adequate conceptual soundness, multi-config/OOS, sensitivity on the material assumptions, and internal-consistency cross-checks within tolerance — all independently re-run by the reviewer on this pass (24 tests pass; snapshot reproduces to the cent; test bodies inspected and real). What is still missing for an unconditional Tier-1 approval is the §10.5 item-5 sub- requirement COND-001 names: (a) a model-vs-realized-outcome back-test against disclosed-firm PRT results (pending real disclosed data — BV-032; the PRU Institutional-Retirement block is a conceptual anchor only, no residual computed), and (b) an independent challenger re-implementation (gold-copy / QuantLib) for a credentialed-grade effective challenge. Build these (engine/data work, not a documentation fix per Decision 053 §4) and file the residual + tolerance, then this clears.
COND-002 2026-08-23 CLEARED. Per-version change log filed at insightalm/modelling/model_cards/M-072-changes.md, satisfying MRM §10.5 item 7: keyed on M-072 v1.0.0, begins at the v1.0.0 release point, records the material INV-025 default-funding change with revalidation evidence, and carries the open items forward honestly. Verified by direct read on this pass; no fabricated figures (the log's snapshot table matches what the reviewer re-ran).