Calculation catalog › Spending and withdrawals

Spending shortfall annual

Unfunded total spending in a projection year.

Field: Spending shortfall Unit: US dollars Basis: nominal dollars Computed by: Engine Status: Complete chain

Appears in: chart (shortfall); csv (shortfall); results-table (Shortfall column); scenarios-page (Annual "Total shortfall" and lifetime "Total spending shortfall"); mcp (run_projection.years[].shortfall)

Calculation records

  • Annual funding shortfall after the HECM backstop Composition record, justified by derivation

    Purpose: What the year could not fund once every withdrawal and any reverse-mortgage draw had been applied.

    Statement: projection/internal/annualHecmBackstop.ts#annualHecmBackstopPlan publishes shortfallAfterHecm = Math.max(0, portfolioShortfall - draw), the value the year publishes as projection/internal/types/result.ts#YearResult.shortfall: the funding gap that remains after every withdrawal AND any HECM backstop draw. projection/internal/types/result.ts#ProjectionResult.depletionYear is the first year this exceeds projection/moneyTolerance.ts#ANNUAL_FUNDING_TOLERANCE_PLAN_DOLLARS, the ledger's own half-cent residual budget; a residual at or below that budget is not depletion. Units: nominal USD per year. Rounding: none.

    Formula: shortfall = max(0, needAfterWithdrawals - hecmDraw); depletionYear = first year with shortfall > ANNUAL_FUNDING_TOLERANCE_PLAN_DOLLARS

    • needAfterWithdrawals: Funding gap left after every withdrawal (unit: usd/year) (domain: nonnegative)
    • hecmDraw: Tax-free HECM line-of-credit proceeds drawn as a backstop (unit: usd/year) (domain: nonnegative; 0 without a HECM)
    • ANNUAL_FUNDING_TOLERANCE_PLAN_DOLLARS: The ledger's accepted annual residual (unit: usd) (domain: half a cent)

    Timing: once per projection year, after the funding fixed point and the HECM backstop

    Rounding: none

    Limits:

    • Asserted on a real simulatePlan run that realizes the worksheet's four inputs: a $10,000 cash account, a $12,000 lifestyle need, and a last-resort HECM whose principal limit is exactly $1,500, leaving the worksheet's $500. Plan assumptions beyond the worksheet's inputs: a single 64-year-old filing single in KY with a zero state rate, zero inflation, zero account and property return, a zero pre-65 premium so healthcare charges nothing, a primary residence worth $30,000 carrying the HECM at the schema's minimum 5 percent principal limit with a zero growth rate, and no earlier projection year, so the worksheet's "earlier-year shortfalls 0" holds by construction
    • The worksheet declines to state the depletion tolerance numerically, so the test imports ANNUAL_FUNDING_TOLERANCE_PLAN_DOLLARS from production, confirms the $500 exceeds it, and only then asserts the run's depletionYear
    • The year's pre-HECM gap is asserted separately from the published figure, because publishing the pre-HECM gap is the worksheet's first wrong reading

    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: spending-shortfall-annual.md Mutation receipt: spending-shortfall-annual.mutation.md

    Evidence tests: annualHecmBackstop.evidence.test.ts

    Implemented in: annualHecmBackstop.ts; result.ts; moneyTolerance.ts

    Is the number of: spending-shortfall-annual

Records that feed this number

  • Annual HECM draw, including the last-resort backstop Formula record, justified by derivation

    Purpose: What an open reverse-mortgage line actually lends the household this year.

    Statement: projection/internal/types/result.ts#YearResult.hecmDraw is the accepted coordinated draw plus any backstop draw planned by projection/internal/annualHecmBackstop.ts#annualHecmBackstopPlan against a true portfolio shortfall. With the coordinated draw zero, the backstop is min(true shortfall, available open line), where the available line is max(0, principalLimit - loanBalance); draw policy does not gate it, because every open line is a last backstop before the household is reported depleted. Units: nominal USD per year. Rounding: none.

    Formula: backstop = min(shortfall, max(0, principalLimit - loanBalance)); hecmDraw = coordinated + backstop; shortfallAfterHecm = max(0, shortfall - backstop)

    • shortfall: True portfolio shortfall before the backstop (unit: usd) (domain: above the annual funding tolerance)
    • principalLimit: HECM line principal limit (unit: usd) (domain: nonnegative)
    • loanBalance: Amount already drawn on the line (unit: usd) (domain: nonnegative)

    Timing: once per projection year, after the accepted withdrawal plan

    Rounding: none

    Limits:

    • Asserted twice: at the exported backstop planner with the worksheet's open line, 40,000 shortfall and 25,000 available line verbatim, and as the published hecmDraw of a real simulatePlan year built from the same inputs (a last-resort line on a 500,000 primary residence at the schema's minimum 5-percent principal limit and a zero growth rate, so the available line is exactly 25,000, against a 40,000 lifestyle need with no portfolio at all). Plan assumptions beyond the worksheet's inputs for that ledger year: a 64-year-old filing single in KY at a zero state rate, so no Medicare or marketplace premium can change the need, and no coordinated draw is possible because the policy is lastResort
    • The worksheet derives only the backstop case; the extract states no sizing formula for a coordinated draw, so this record makes no claim about one

    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: hecm-draw-annual.md Mutation receipt: hecm-draw-annual.mutation.md

    Evidence tests: annualHecmBackstop.evidence.test.ts

    Implemented in: result.ts; annualHecmBackstop.ts

    Is the number of: hecm-draw-annual

    Feeds: spending-shortfall-annual, accounts-net-worth-annual

  • Annual net portfolio need Composition record, justified by derivation

    Purpose: What the portfolio has to supply this year, floored so a surplus is never reported as a need.

    Statement: projection/internal/annualYearResultAssembly.ts#annualYearResultAssembly publishes projection/internal/types/result.ts#YearResult.netPortfolioNeed as Math.max(0, expenses.total + tax + penalties - incomes.total), computed from the committed ledger totals and the settled tax and penalty scalars at the end of the annual pass. It is what the year REQUIRED, not what the portfolio managed to supply: a year that cannot fund it still publishes the need and records the gap in shortfall. A year whose incomes cover every outflow publishes exactly 0. Units: nominal USD per year. Rounding: none.

    Formula: netPortfolioNeed = max(0, expenses.total + tax + penalties - incomes.total)

    • expenses.total: The year's net outflow (unit: usd/year) (domain: nonnegative)
    • tax, penalties: Settled tax and the penalty scalar, which is not inside tax (unit: usd/year) (domain: nonnegative)
    • incomes.total: The year's cash income (unit: usd/year) (domain: nonnegative)

    Timing: once per projection year, published last in the year-result assembly

    Rounding: none

    Limits:

    • Asserted at annualYearResultAssembly, the function that computes the field, with the worksheet's four year-row components, and separately on a real simulatePlan run where the published need equals its own row's published expenses, tax, penalties and incomes
    • The floor case the worksheet names (the same outflows against $120,000 of income) is asserted at the same function, because the published need must be exactly 0 rather than the negative surplus
    • Penalties are a separate term from tax and are not inside it; omitting them is the worksheet's first wrong reading

    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: portfolio-need-annual.md Mutation receipt: portfolio-need-annual.mutation.md

    Evidence tests: annualYearResultAssembly.evidence.test.ts

    Implemented in: annualYearResultAssembly.ts; result.ts

    Is the number of: portfolio-need-annual

    Feeds: spending-shortfall-annual

Engine source: engine/src/projection/internal/types/result.ts (YearResult.shortfall)

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.