Calculation catalog › Accounts and growth

Pension election annuity present value

Present value of the lifetime pension annuity to the planning age at the curve-anchored discount rate, compared with the lump-sum offer.

Field: Pension annuity present value Unit: US dollars Basis: today's dollars (real) Computed by: Engine Status: Complete chain

Appears in: insights (pension-election-pending card rationale "the annuity's discounted value (~$X)" and the discount rate)

Calculation records

  • Pension annuity present value at the curve-anchored discount rate Model record, justified by derivation

    Purpose: What the pension's lifetime payments are worth today, the number a lump-sum offer has to beat.

    Statement: decisions/pensionElection.ts#analyzePensionElections publishes curveRatePct = curveNominalDiscountRatePct(max(5, planning age - current age), plan inflation): the embedded TIPS real-yield curve linearly interpolated at that horizon (flat outside the 5-to-30-year anchors) plus the plan's inflation percentage. presentValueAtCurveRate is pensionAnnuityPresentValue at that rate: for each owner age from max(start age, current age) through the horizon age, the annual benefit (monthly x 12) grown by COLA from the start age, paid in full while the owner lives and at survivorPct while a survivor lives (only if the owner reached the start age), discounted by (1 + rate/100)^(owner age - current age). Units: percent per year; valuation-year dollars. Rounding: none.

    Formula: PV = sum_t paid_t / (1 + r/100)^t, t = owner age - current age; r = realYield(max(5, planningAge - currentAge)) + inflation

    • r: Curve-anchored nominal discount rate (unit: percent/year) (domain: finite)
    • paid_t: Benefit paid at offset t: full while the owner lives, survivorPct of it while a survivor does (unit: usd/year) (domain: nonnegative)
    • horizon age: max(owner death age, current age + the survivor's remaining years) (unit: years) (domain: integer)

    Timing: once per pension carrying a lump-sum offer, valued at the projection start year

    Rounding: none; the sensitivity table rounds its rate columns to 0.1 percentage points, the published curve rate is not rounded

    Limits:

    • One number drives both horizons: analyzePensionElections passes ownerDeathAge = the owner's planning age, so planning age 70 against current age 64 gives the 3.995% rate AND the six payments the published presentValueAtCurveRate discounts, $62,915.883021698835 (on the official 2026-06-30 curve row; $63,008.166010097986 at 3.95% on the row stored before decision D-TREASURY). The first derivation valued the published field over three payments to a death age of 67 while taking its rate from planning age 70, which reports the helper's figure in the field's place; it was corrected on 2026-09-18, and that mismatch is now the worksheet's first wrong reading, asserted as not matching
    • The three-payment stream is a SECOND case, taken explicitly at the helper pensionAnnuityPresentValue with ownerDeathAge 67 at the same 3.995% rate, and is $33,304.25282719482; the helper accepts any death age, so that case says nothing about the field's payment count
    • Beyond the worksheet's inputs the evidence plan fixes: a single household (so no survivor extends the horizon), a 1962-born owner so the 2026 current age is 64, a pension with a lump-sum offer in the start year (the analysis skips pensions without one), zero return, and inflationPct 2 as the rate's inflation term
    • The curve is the embedded 2026 TIPS real-yield snapshot; the rate is a planning anchor, not a quote, and a corporate-spread view is left to the user
    • The stream is discounted at annual offsets from the valuation year with no mid-year convention, and COLA compounds from the start age rather than the valuation year

    Provenance: derived by claude, implemented by claude.

    Independent review: codex

    Gates (6 of 6 pass): fixture registers a test: pass; pins resolve: pass; families exist: pass; worksheet exists: pass; mutation receipt exists: pass; provenance independent: pass

    Worksheet: pension-election-annuity-present-value.md Mutation receipt: pension-election-annuity-present-value.mutation.md

    Evidence tests: pensionElection.evidence.test.ts

    Implemented in: pensionElection.ts

    Is the number of: pension-election-annuity-present-value

Engine source: engine/src/decisions/pensionElection.ts (analyzePensionElections (presentValueAtCurveRate, curveRatePct))

The evidence links on this page (each record's worksheet, mutation receipt, evidence tests and implementation, and the source links) are pinned to engine commit 2624dbdba9fd, committed 2026-10-11. The live calculation index and output-family census links point at the repository's main branch, so you can check this snapshot against them.