Calculation catalog › Longevity

Longevity depletion year

First projection year with any spending shortfall; null when investable assets last through the horizon.

Field: Depletion year Unit: calendar year Basis: no dollar basis Computed by: Engine Status: Complete chain

Appears in: results-headline (KpiBar "Money lasts" sub "short in YEAR"); results-headline (ResultsPage narrative "This plan runs out of money in YEAR"); results-table (Balances chart "depleted" reference line and "Portfolio depletes in YEAR" callout); report (headline-results block depletionYear); compare-page (Depletion age (NAME) row: the older person's age in that year, named in the label (PlanHeadlineComparison.depletionAge, whose person PlanHeadlineComparison.depletionAgePersonId gives)); scenarios-page (Headline "Depletion year"); ss-page (Claim-age table "Depletes" column YEAR / never); survivor-page (Degenerate-timings note "runs out of money in YEAR"); relocation-page (RelocationCandidateRow.depletionYear (carried)); monte-carlo-page (Historical stress windows "Depletes" column); insights (InsightCardView flat-delta note "The base plan runs out of money in YEAR"); mcp (run_projection.summary.depletionYear); mcp (compare_scenarios.a.depletionYear); mcp (compare_scenarios.b.depletionYear); optimize-page (Couldn't-optimize well and the solver-limit note "Your plan's projection runs short of money in YEAR" (OptimizedSchedule.projectionDepletionYear, when the first solve has no solution)); mcp (run_optimizer.schedule.projectionDepletionYear (present only when the first solve has no solution))

Calculation records

  • Depletion year: the first projection year whose shortfall clears the funding tolerance Model record, justified by derivation

    Purpose: The year the headline results call the plan depleted, or null when every year was funded.

    Statement: ProjectionResult.depletionYear is the first projection year, in year order, whose YearResult.shortfall (the funding shortfall left after every withdrawal and any HECM backstop draw) is strictly greater than projection/moneyTolerance.ts#ANNUAL_FUNDING_TOLERANCE_PLAN_DOLLARS ($0.005, the ledger's own residual budget). A residual at or below that budget is not depletion; once a year is recorded the value is never replaced by a later one; and the field is null when no year exceeds the tolerance. Units: calendar year, or null. Rounding: none; the comparison is strict.

    Formula: depletionYear = min{ y : shortfall_y > ANNUAL_FUNDING_TOLERANCE_PLAN_DOLLARS }, else null

    • shortfall_y: Year y's funding shortfall after every withdrawal and any HECM backstop draw (unit: usd) (domain: shortfall_y >= 0)
    • ANNUAL_FUNDING_TOLERANCE_PLAN_DOLLARS: The funding fixed point's accepted residual (unit: usd) (domain: 0.005)
    • depletionYear: First qualifying calendar year (unit: year) (domain: a projection year, or null)

    Timing: annual; tested in each year's funding-and-close phase, in year order

    Rounding: none; strictly greater than the half-cent tolerance

    Limits:

    • Beyond the worksheet's inputs the evidence plan fixes: one cash account (so no market shock and no taxable yield reach it), a 51-year-old single filer under 65 (no Medicare premium, no early-withdrawal exposure), zero income, zero inflation and zero return, base spending as the only expense, and an explicit horizonEndYear of 2028 so the three rows are exactly 2026-2028
    • The tolerance is a residual budget, not a balance test: a year that closes at exactly zero with every dollar of spending funded is not depletion, which is why the $30,000 opening balance against the same $10,000 gap still publishes null
    • The field records the FIRST qualifying year only; later shortfalls do not move it, and a plan that recovers after a shortfall year still reports that year
    • The comparison is strict (>), so a shortfall of exactly $0.005 is accepted as a rounding residual rather than depletion; the evidence does not pin that boundary, which would need a plan whose funding residual lands on the tolerance exactly

    Provenance: derived by codex, implemented by claude.

    Independent review: cursor

    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: longevity-depletion-year.md Mutation receipt: longevity-depletion-year.mutation.md

    Evidence tests: simulate.depletionYear.evidence.test.ts

    Implemented in: simulate.ts; annualFundingApplicationAndClosePhase.ts

    Is the number of: longevity-depletion-year

    Feeds: display-years-before-plan-end, longevity-last-funded-year

Transformations

  • Compare view differences the engine's last funded years (projection/moneyLasts.ts#lastFundedYear, re-exported by compareDeltas.ts).

Engine source: engine/src/projection/internal/types/result.ts (ProjectionResult.depletionYear)

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.