Repository navigation
How the Numbers Work
Every formula the app uses, in plain language with the math. The code is in
web/src/model.ts (projections)
and src/financial_planner/summary.py
(averages), and is covered by tests.
- Signs and the data window
- Averages
- The monthly budget
- Compound growth
- College 529s
- Retirement income
- Spending over time
- Income over time
- Today's dollars vs. with inflation
- Internally, money out is positive and money in is negative.
- The window is
plan.monthscalendar months (12 by default) ending atplan.last_month, or at the newest counted transaction if that isn't set.ignorecategories don't move the window. -
Today is
plan.today, or the month after the window.
For each category: average = total over the window ÷ number of months. Refunds inside a spending category reduce it. Credit averages are shown as positive amounts to subtract. One-time categories use the same formula for their "per month" set-aside.
spending = Σ planned regular categories
− Σ planned credits that are ticked (not nested under a one-time cost)
+ Σ ticked non-tax one-time costs (each net of its ticked nested credits)
tax = Σ ticked tax one-time costs (each net of its ticked nested credits)
savings = Σ 529 contributions + Σ savings + Σ investment contributions
left over = take-home income − spending − savings − tax
Yearly rates are applied monthly with the equivalent monthly rate so a year of growth is exactly the yearly rate:
i = (1 + r)^(1/12) − 1
balance after n months = P·(1+i)^n + m·((1+i)^n − 1)/i (P = start, m = monthly addition)
For each child, with return r, college-cost growth g, n = months until high-school graduation,
Y = whole years until then, C = cost per year today, N = years of college:
529 at graduation = growth(P = balance today, m = monthly contribution, n, r)
cost of college = Σ_{j=0..N−1} C·(1+g)^(Y+j)
covered = 529 at graduation ÷ cost of college
surplus/shortfall = 529 at graduation − cost of college
…in today's $ = surplus/shortfall ÷ (1+g)^(n/12)
monthly needed = (cost − balance·(1+i)^n)·i ÷ ((1+i)^n − 1) (0 if already covered)
All in today's dollars. Let a be the primary partner's retirement age, yrs = a − their age today,
r the return, f inflation, w the yearly withdrawal rate. Every other partner's age at
retirement is their age today plus yrs.
balance at retirement = growth(balance today, monthly addition, round(yrs·12), rate)
monthly income = balance at retirement ÷ (1+f)^yrs × w ÷ 12
Retirement accounts use the general return r; each investment uses its own return_pct, with its
monthly addition taken from the planner.
From the estimates (age → monthly):
before the first age → 0
between two ages → straight-line interpolation
after the last age L → flat, or, with years of service S today:
estimate(L) × (S + age − age today) ÷ (S + L − age today)
grows_with_raises → × (1 + raise)^max(0, age − age today − 1.5)
The 1.5 years reflects pensions based on the highest three-year average pay. A flat monthly
pension is paid as is.
claim age = claim_age set ? min(70, max(claim_age, age at retirement))
: max(62, age at retirement)
benefit = amount at 67 × factor(round(claim age))
factor = 62: 70% · 63: 75% · 64: 80% · 65: 86.67% · 66: 93.33% · 67: 100% · 68: 108% · 69: 116% · 70: 124%
starts = the year the partner reaches the claim age
A benefit that starts after retiring isn't in "income at retirement", but is in "once all Social Security starts".
after tax = (pensions + accounts + investments + Social Security started) × (1 − tax rate)
once all Social Security starts = the same with every benefit included
gap / surplus = after-tax income − projected spending in the first retired year
The first full retired year is today's year − primary age today + 1 + a.
For calendar year y (using mid-year, y + 0.5):
children home = children whose graduation (year + month/12) is later than y + 0.5
share gone = (all children − children home) ÷ all children (0 with no children)
category = planned × max(0, 1 + share gone × kids-gone %)
× max(0, 1 + retired %) (once retired)
living = Σ categories + ticked non-tax one-time costs − ticked credits
(only those marked in_retirement once retired)
spending = living + tax set-aside (in_retirement ones once retired) + health insurance (once retired)
savings = 529s for children still home + savings (unless stopped by retirement)
+ investment contributions (until retirement)
before retirement: Σ take-home × (1 + raise)^(y − today's year) + other income
after retirement: retirement income after tax, adding each Social Security benefit from its start year
The yearly view can show amounts "with inflation": each year's figure × (1 + inflation)^(y − today's year).
Everything else on the page is in today's dollars.
Getting started
Using the app
- Tour of the App
- Monthly Planner
- Explore Spending
- College 529s
- Retirement
- Spending Over Time
- Scenarios and Sharing
Setting up your plan
- Plan Folder
- Settings Editor
- Data Sources (CSVs)
- Categories
- Categorizing and Rules
- Setup with an AI Assistant
Reference