Tier 1 · Pricing

Annuity Product Pricing Suite

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

Intended Use

Annuity Product Pricing Suite Price annuity products (RILA, indexed annuity, VA guarantees, spread products) for new-business profitability and reserve seeding.

Common pricing harness across annuity product family. Per §12.3 "intended use" test, these share intended use; differences in product mechanics handled as variants. See Q-03 for collapse vs split debate.


Components

Inputs, processing, outputs

data sources
DS-001 · DS-008
assumptions
A-001, A-002, A-010, A-060, A-061, A-070
engines
insmodel.L4.spread_liability
insmodel.L4.rila_model
insmodel.L4.indexed_annuity
insmodel.L4.va_guarantee
insmodel.L4.benefit_engine
insmodel.L6.projection_orchestrator
contracts
pricing_results_v1
upstream
M-120
dimensions
D6 · D7

Methodology & Mechanics

Methodology

M-070 is a pricing suite, not a single engine: a common harness across the annuity product family that composes four product models living under firmmodel/products/. Each model shares the same BaseProductModel contract (parameter schema, calculate() cash-flow projection, compute_profitability(), get_termsheet()) and the same composed calculation engines (Investment, Lapse, Expense, Benefits, Reserve, plus Stochastic/Mortality where the product needs them). The four members differ in their crediting and guarantee mechanics, which is exactly where annuity pricing risk lives.

Representative engine — IndexedAnnuityModel (P-003), RILA configuration. The snapshot below exercises this engine because it runs cleanly and deterministically and exhibits the suite's most distinctive mechanic: the embedded-derivative option budget. The engine projects monthly cohort cash flows (calculate() in firmmodel/products/indexed_annuity.py). Each month it accrues investment income on the general-account backing assets, accrues a monthly share of the embedded-option cost, deducts expenses and rider charges, applies lapse with a surrender-charge deterrent, and rolls the account value forward as AV(t+1) = av·(1 + credited_return) − fees − withdrawals (floored at zero). The credited return is the heart of pricing:

  • Upside is capped: credited = min(index_return · participation, cap).
  • Downside under RILA is buffered: a loss within the buffer credits 0%; a loss beyond the buffer passes through as −(loss − buffer).

The option budget is the spread the general account can afford to spend on hedging the crediting promise: option_budget = portfolio_yield − expense_rate − profit_margin_target − option_budget_spread (_calculate_option_budget()), floored at zero — in the canonical run, 5% − 0.30% − 0.75% − 0.25% = 3.70% annual. The cost of the promise is computed by _price_index_option() via Black-Scholes option replication: the RILA crediting feature is decomposed into a long call spread (ATM call minus a call struck at the cap, scaled by participation — the capped upside) plus, for the buffer, a short put spread (ATM put minus a put struck at 1 − buffer — the cost of absorbing the first N% of loss). The FIA variant prices the call spread only (0% floor). The embedded-derivative fair value carried on the balance sheet is av · option_cost_pct · term_remaining_fraction, so it amortises to zero across the crediting term and resets each cycle. compute_profitability() discounts monthly net profit to a PVFP, profit margin, simple IRR, and return-on-capital.

The other three suite members (summarised):

  • SpreadLiabilityModel (MYGA / fixed annuity / funding agreement / GIC, insmodel.L4.spread_liability) — pure ALM. The insurer earns portfolio_yield, credits a contractual credited_rate, and books the difference as net spread. No embedded derivative, no separate account.
  • RILAModel (P-002, insmodel.L4.rila_model) — the earlier indexed-annuity model. Same call-spread/put-spread core as P-003 but without the unified RILA/FIA handling and option-budget abstraction; P-003 is the comprehensive successor.
  • VAGuaranteeModel (variable annuity, insmodel.L4.va_guarantee) — separate-account product with embedded guarantee riders (GMDB/GMWB/GMIB/GMAB). Each guarantee is priced as a put option on the separate-account value relative to a guarantee/benefit base, funded by M&E and rider fees. Dynamic lapse is the key sensitivity: in-the-money guarantees suppress lapse, raising guarantee cost.

Key Assumptions

Key Assumptions and Their Justification

The pricing suite is parameterised per product; the table lists the load-bearing assumptions for the representative RILA run.

ID / param Name Canonical value Derivation Justification
A-010 Base lapse curve (indexed) 2% Y1 → 20% Y7+, surrender-charge-adjusted data_calibrated Duration-graded lapse consistent with VM-20 §6 guardrails; surrender charge suppresses early lapse.
A-060 / A-061 Crediting strategy (cap / buffer / participation) cap 15% · buffer 10% · participation 100% · ANNUAL_POINT_TO_POINT product_design Contractual crediting terms set at issue; they define the embedded option the insurer must hedge.
A-070 Per-policy / spread expense 30 bps of AV (indexed) data_calibrated Industry FY2024 expense-study range; deducted monthly from AV.
(param) Option-pricing market inputs implied vol 18% · r 4% · q 1.5% published_source / market Black-Scholes inputs for call/put-spread replication; a flat-vol, single-rate simplification (see Limitations).
(param) Option budget components portfolio yield 5% · profit-margin target 0.75% · hedge-friction spread 0.25% management_target Defines affordable hedging spread; profit-margin target is a pricing lever.
(param) Policyholder behaviour (deterministic index path) expected index return 8% assumption Standalone calculate() uses a deterministic index return; full distributional pricing needs the stochastic adapter.
A-001 / A-002 Mortality (VA guarantees only) age-dependent qx via MortalityEngine published_source GMDB/GMWB costing needs mortality; spread/indexed products use de-minimis mortality only.

Operational notes. The crediting cap, buffer, floor and participation are product-design assumptions (contractual, set at issue) rather than calibrated experience assumptions — pricing risk here is the risk that the option budget is mis-set relative to the true hedge cost, not assumption-estimation error. The option budget is deliberately conservative. Lapse is the only behavioural assumption that materially feeds back into cost for indexed products; for VA guarantees, dynamic (moneyness-dependent) lapse is first-order.


Output Snapshot

Output Snapshot

Deterministic single-cohort run of the suite's representative engine, IndexedAnnuityModel (P-003) in its RILA configuration — reproducible, requires no live firm data (python scripts/model_snapshots.py M-070 in InsModel; mechanics asserted by tests/test_indexed_annuity_e2e.py, 13 tests passing). The provider is a MagicMock.

Input: account value $1,000,000 · 15% cap · 10% buffer · 100% participation · 6-year term · ANNUAL_POINT_TO_POINT crediting · implied vol 18% · r 4% · q 1.5% · index return +8%. Row shown is month 12 (the first annual crediting event).

output value meaning
credited_return 0.08 +8% index return, below the 15% cap → credited in full
index_credit 78,902.03 dollar credit to the account at the annual reset
account_value_post_credit 1,063,939.13 AV after credit, fees, and lapse decrements
option_budget_annual 0.04 3.70% affordable hedge spread (yield − expense − margin − friction)
embedded_option_cost_pct 0.09 option cost as 8.90% of notional (call spread + buffer put spread)
call_spread_value_per100 5.70 capped-upside leg of the replicating portfolio
put_spread_value_per100 3.20 buffer (downside) leg of the replicating portfolio
embedded_derivative_fv 73,135.90 balance-sheet fair value of the crediting feature, mid-term
reserve_host_plus_embedded 1,137,075.03 host contract value + embedded-derivative FV
pvfp_120mo_at8pct 239,949.94 present value of future profit over a 10-yr pricing horizon
profit_margin 0.24 PVFP as a fraction of initial account value

The embedded option cost (8.90% of notional over the 6-year term) decomposes into a 5.70 call-spread leg (the capped upside) and a 3.20 put-spread leg (the 10% buffer) — directly visible in the replicating portfolio. Note the option budget shown is a rate (3.70% p.a.), while option_cost_pct is a 6-year term cost; the engine amortises the latter monthly when comparing against budget. The PVFP and profit-margin figures are pricing diagnostics from compute_profitability(), not statutory reserves.

Captured 2026-06-04 · deterministic, no live data.


Limitations

Limitations and Known Gaps

  1. The suite is a harness, not a single validated engine. M-070 documents four distinct product models under one card per the §12.3 "intended use" collapse (Q-03 remains an open collapse-vs-split debate). The snapshot exercises only IndexedAnnuityModel (RILA); the spread and VA-guarantee engines are summarised but not independently snapshotted here.
  2. Deterministic index path in the standalone pricing run. calculate() projects on a single expected index return (8%); the capped/buffered payoff is path-dependent and asymmetric, so a single point estimate understates the true distributional cost. Full stochastic pricing requires StochasticScenarioAdapter.
  3. Black-Scholes option pricing uses flat vol and a single rate. _price_index_option() assumes constant implied volatility and a single risk-free rate with no skew/term-structure. Real RILA/FIA hedging trades against a vol surface; the replication is first-order.
  4. Embedded-derivative FV is a simplified amortisation, not a re-priced mark. The carried FV is a linear amortisation of the issue-date option cost across the term, not a fresh Black-Scholes re-mark each period to current moneyness.
  5. Profitability metrics are simplified. IRR is a total_profit / AV / years approximation rather than a true cash-flow IRR solve; return-on-capital uses a flat 8% capital charge for all indexed products.
  6. RILAModel (P-002) is partly superseded. It overlaps IndexedAnnuityModel (P-003); its IndexedProductEngine dependency is noted as stubbed in source. Carrying both is a known redundancy.
  7. No live firm-data path (BV-032). All figures are from documented canonical inputs and MagicMock providers; reserve/MRB figures shown are pricing-harness outputs, not statutory or LDTI-reported values.

Tracked for ratification (not applied in this documentation pass). The following are output-changing / modeling-code items left for ratification, noted here for transparency: produce the Tier-1 validation-evidence pack (backtesting per MRM §10.2 + a sensitivity suite across the material assumptions); independently snapshot/validate the two non-snapshotted members (SpreadLiabilityModel, VAGuaranteeModel), not just the representative RILA run; complete 2L independent effective challenge and close RAT-070-v1.0.0 per MRM §10.6 (peer_review.status pending → signed); and resolve the embedded-derivative FV methodology (linear amortisation of issue-date option cost / flat-vol single-rate Black-Scholes vs a fresh re-mark to current moneyness). No model outputs, back-test numbers, or validation results were fabricated or changed in this pass.


Validation Evidence

Validation Packet

evidence status reference
End-to-end test suite present tests/test_indexed_annuity_e2e.py — 13 tests (crediting cap/buffer, option budget, embedded-derivative FV, profitability, termsheet, stochastic adapter).
VA guarantee tests present tests/test_va_guarantee_model.py.
Deterministic snapshot present scripts/model_snapshots.py M-070 (representative RILA engine).
Per-archetype snapshots partial Only the indexed-annuity engine is snapshotted; spread and VA-guarantee archetypes are not.
Validation evidence pack (MRM §10.5 item 5) present insightalm/modelling/validation_evidence/M-070/v1.0.0/README.md (2026-06-06) — maps each §10.5 sub-item to the 98 passing InsModel tests + the deterministic snapshot + the PRU disclosed-block bounds cross-check. Closes COND-001 on RAT-070-v1.0.0; honest gaps carried below.
Change log (MRM §10.5 item 7) present insightalm/modelling/model_cards/M-070-changes.md (2026-06-06). Closes COND-002 on RAT-070-v1.0.0.
Independent challenge (2L) pending 2L re-review of COND-001/COND-002 + supersession to RAT-070-v1.0.1 is 2L's job; current peer_review.status = pending (registry); next Tier-1 revalidation due 2026-08-23. Q-03 collapse-vs-split still open.
Backtest (model-vs-reality) + quantitative sensitivity-elasticity suite pending The e2e suite asserts engine mechanics + mechanical crediting-term/lapse sensitivities; a Tier-1 model-vs-reality backtest (MRM §10.2, BV-032) and a calibrated elasticity table over the continuous market inputs (implied vol, portfolio yield, profit-margin target) are not yet produced — carried as honest gaps in the validation pack and Limitations, not closed.

References

References

Engine source: - ecosystem/InsModel/Models/firmmodel/products/indexed_annuity.pyIndexedAnnuityModel (P-003), representative engine. - firmmodel/products/spread_model.pySpreadLiabilityModel; firmmodel/products/rila_model.pyRILAModel (P-002); firmmodel/products/va_guarantee_model.pyVAGuaranteeModel; firmmodel/products/base_product.py — shared contract; firmmodel/products/stochastic_adapter.py.

Tests: tests/test_indexed_annuity_e2e.py (13), tests/test_va_guarantee_model.py. Snapshot: scripts/model_snapshots.py M-070.

Standards: - ASOP No. 56 — Modeling. - FASB ASU 2018-12 (LDTI) — Market Risk Benefit (MRB) measurement for VA guarantee embedded derivatives. - ASOP No. 22 — cash-flow-testing context for annuity reserve seeding.

Internal: M-001 for engine-card depth exemplar; BV-032 (firm-data divergence); Q-03 (collapse-vs-split for the annuity family).


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-06-04 — Tier-1 hand-authoring of Methodology, Key Assumptions and Their Justification, Output Snapshot (deterministic RILA run via scripts/model_snapshots.py M-070), Limitations, Validation Packet, and References from indexed_annuity.py + IndexedAnnuityModel legacy_metadata; stub marker advanced to ``.
  • 2026-06-06 (RAT-070-v1.0.0 remediation, 1L) — assembled the Tier-1 validation-evidence pack at validation_evidence/M-070/v1.0.0/README.md (98 passing InsModel tests + deterministic snapshot reproducing this card's Output Snapshot + PRU disclosed-block bounds cross-check; honest gaps carried) closing COND-001; authored the per-version change log at M-070-changes.md closing COND-002; reconciled registry documentation_pack flags (validation_evidence/change_log → present); refreshed the Validation Packet rows to point at the pack/log. No model outputs, back-test numbers, or validation results were fabricated (Decision 053 §4).
  • 2026-06-06 — documentation-pack completion pass: added a dedicated Standards Coverage section (ASOP 56 / ASOP 22 / ASU 2018-12 LDTI, each tied to applicability) with a frontmatter-vs-References reconciliation note and an asc_944-tag flag raised to engine-governance (no reg tag silently added); expanded Dependencies with the MRM §10.5(8) shared-component aggregate-risk view (benefit_engine shared with M-001/M-002/M-071; projection_orchestrator shared with M-001/M-002/M-003/M-051/M-100, sourced from engine_registry.yaml model_membership); corrected the Validation Packet "Independent challenge (2L)" row from "per registry" to an honest pending state (RAT-070-v1.0.0 not closed, peer_review.status = pending, revalidation due 2026-08-23, validation_evidence not produced) and added a backtest/sensitivity-evidence "pending" row; noted gated/ratification items under Limitations. No model outputs, back-test numbers, or validation results were fabricated or changed.

2L Inventory Review

Open findings (1)

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.


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-070-v1.0.2

2L issued RAT-070-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-003 2026-08-23 Tier-1 validation-evidence ADEQUACY gap — UNCHANGED from RAT-070-v1.0.1, independently re-verified as STILL OPEN at this re-review (2026-06-08). The assembled pack and the model card honestly carry two open Tier-1 elements that MRM §10.5 item 5 calls for and charter §4.2 requires: (1) NO model-vs- reality back-test against a realized outcome (BV-032) — the PRU TestPRUCalibration cross-check is a bounds/sanity reconciliation (test_fee_level_in_range asserts rider 100-150 bps; test_equity_allocation _typical asserts 0.50-0.90; test_pru_mrb_scaling asserts embedded- derivative FV > $100M and < 10% of a $193.4B SA block), NOT a reconciliation against PRU's disclosed ~$4.3B MRB within a documented tolerance; and (2) NO quantitative sensitivity-elasticity suite tabulating dPVFP / d(option-cost) per unit shock to the three continuous market inputs (implied vol, portfolio yield, profit-margin target) — only the MECHANICAL crediting-term responses (cap clamp, buffer pass-through, ITM lapse suppression) are tested. 1L should build the Tier-1 back-test (a realized-outcome reconciliation within a documented tolerance) and the calibrated elasticity table (in the style of M-001/M-002 sensitivity atlases) before this RAT can be superseded by RAT-070-v1.0.3 with decision: approved.