The math behind the Mortgage Offer Analyzer
A mathematical walkthrough of the tool.
Notation used throughout:
| Symbol | Meaning |
|---|---|
| principal — the amount actually borrowed | |
| quoted annual nominal rate (as a decimal) | |
| compounding periods per year (12 = monthly) | |
| periodic rate | |
| term in years | |
| total number of payments | |
| the fixed periodic payment (principal + interest) | |
| balance still owed after payment | |
| upfront fees, paid at closing | |
| home value at purchase | |
| holding period in years; periods |
Part 1 — The loan, and where the payment number comes from
The rule of the loan
Each period two things happen, in this order: the outstanding balance grows by the interest factor, then you hand over a fixed payment .
That is the entire financial content of a mortgage. Everything else on the site is a consequence of this one line.
Solving the recurrence
It is a linear first-order recurrence, so unroll it:
The sum is geometric. Two competing terms: your debt compounding upward, and your accumulated payments compounding upward, racing each other.
Fixing the payment
A mortgage is defined by the condition that the balance reaches zero exactly at period — that is what “30-year fixed” means. Set and solve:
Two limits worth checking yourself:
- . Expand , giving . No
interest, so principal splits evenly. The site special-cases this branch in
calc(), where the payment is chosen. - with . . A perpetual loan: you pay the interest forever and never touch principal. This is the floor no term can go below — if the balance never shrinks at all.
Total interest
Total handed over across the full term is . Of that, is money you actually borrowed. The rest is interest:
Note this is not . That would be interest on the full principal for the whole term, but the balance is falling the entire time. The true amount is — a sum under the decaying balance curve — and the two expressions agree.
Effective annual rate
The quoted rate is a nominal convention: “6% compounded monthly” means 0.5% applied twelve times, which is not 6% of growth. Actual growth over one year:
For : . This is the site’s apples-to-apples number when two offers compound differently.
One numerical note
Everything above needs . Computing that as pow(1+i,k) - 1
catastrophically cancels for small : you subtract 1 from a number barely
above 1 and lose every significant digit. The site computes it as
using expm1/log1p, which are built to hold
precision near zero.
Part 2 — The balance at an arbitrary time, and the shape of that curve
A cleaner closed form
Part 1 gave . Regroup the terms that carry :
This is the form worth remembering. It says the balance is an exponential displaced by a constant, and the constant is the whole story.
What is. It is the principal of a loan whose interest exactly equals the payment — the perpetuity from Part 1, the balance that would sit still forever. Call it the equilibrium . Then
and is a repelling fixed point of the recurrence . Start below it and you are pushed away downward, faster and faster. Start above it and the balance runs away upward — that is a loan that never amortizes. A real mortgage always has , and the gap is the seed of the exponential.
(Worked case used throughout: , , 30 years. Then and . The loan starts only 17% below its own runaway point — which is why the early years feel like nothing is happening.)
Treating as continuous
Write , the continuously-compounded equivalent of (in finance, the force of interest). Then and
Both derivatives are negative for the whole term. So the balance curve is decreasing and concave: it falls slowly at first and the fall accelerates, lying above the straight line from to the entire way. Nothing about a mortgage is linear, and this is where the intuition breaks for most people.
Concavity has a blunt consequence. Setting :
For the worked case: payments years. You are 21 years into a 30-year loan before you have repaid half the principal.
How each payment splits
Payment is a fixed , but it is doing two jobs. Interest owed that period is ; whatever is left knocks down principal:
The principal portion has an exact structure. Let . Then
The principal portion grows by exactly the factor every single period — a clean geometric sequence, , with . The interest portion is its mirror image, , decaying toward zero.
In the worked case, payment 1 is $2,166.67 interest and $361.61 principal — 86% of your money evaporating. Payment 360 is $13.62 interest and $2,514.65 principal. Same $2,528.27 either way.
What the site computes at a holding horizon
If you sell or refinance after years, that is periods. The site needs three numbers:
The last one is just conservation: of the dollars handed over, exactly went to principal, so the remainder was interest.
horizon() evaluates these. Two details: it clamps , since holding
past the term is just holding to the term, and it carries the same
branch as calc(), where the balance degenerates to .
These three are not yet the cost of holding for years. Two components have not appeared: mortgage insurance, derived in Part 3, and the upfront fees , which Part 4 folds in alongside the payoff of .
Part 3 — Mortgage insurance, the one piecewise part of the model
Everything so far has been one smooth exponential. Mortgage insurance is where that stops.
What it is
If you borrow more than 80% of what the home is worth, the lender requires private mortgage insurance (PMI), a policy insuring the lender against your default. It protects the lender, not you, and you pay for it on top of , until the loan is small enough relative to the home that the lender stops demanding it.
Three new inputs: the home’s value at purchase , an annual premium rate , and a choice of removal rule .
Loan-to-value
here is the value at purchase, and it never moves. Not the current market value, not an appraisal you order later. That is not a modeling shortcut: the federal Homeowners Protection Act (HPA) defines termination against the original value — “the lesser of the sales price … or the appraised value at the time at which the subject residential mortgage transaction was consummated” (12 U.S.C. § 4901(12)) — so a rising market does not shorten this schedule.
The only moving part in the ratio is the numerator , falling along the Part 2 curve. That fall is the whole mechanism by which PMI ends.
Is it owed at all?
Only if the loan starts above 80% LTV:
pmiOwed() tests this. It compares against with
, so a loan sitting exactly at 80% —
on a home — is not dragged over the line by binary rounding.
The premium
Charged per period at rate , against one of two bases the lender picks:
Note the balance used is , the balance before payment . Under the declining basis the premium shrinks along the amortization curve; under the fixed basis it is a constant dollar amount. Both conventions are in real use, which is why it is an input rather than an assumption.
When it stops
Two rules, both from 12 U.S.C. § 4902. PMI ends at whichever fires first.
1. The LTV threshold. Premiums stop once the balance reaches . The site offers the two HPA exit points: (you may request cancellation in writing) and (the servicer must terminate automatically).
Setting in the Part 2 closed form:
2. The amortization midpoint. § 4902© forbids the requirement “beyond the first day of the month immediately following … the midpoint of the amortization period”, regardless of balance. This binds only when the loan amortizes too slowly to reach in half the term — a high initial LTV, a long term, or both.
(Worked case: at 6.25%, 30 years, , . Then , the midpoint is 180, so the threshold binds and — PMI runs 8.25 years. The site reports period 99.)
Note: Prepayment effects are not modeled
The site has no extra-payment input: it models the scheduled balance of Part 2 and nothing else, so scheduled and actual coincide and is the answer for either threshold.
If you do pay extra, the two thresholds diverge, and the statute is explicit about it. The 80% cancellation date is, at your option, the date the balance “based solely on actual payments, reaches 80 percent of the original value” (§ 4901(2)(A)(ii)) — prepayment pulls it in. The 78% termination date is fixed “based solely on the initial amortization schedule … and irrespective of the outstanding balance” (§ 4901(18)(A)) — prepayment does not move it, and neither does it move the midpoint.
So under prepayment the site’s PMI figure stays exact for and becomes an upper bound for .
Accumulated PMI
The site carries the running total
so it can be read off at any horizon. Under the fixed basis this is trivially linear, . Under the declining basis, sum the Part 2 closed form for :
and recognize the second term: from Part 2, , so the sum is . Substituting and multiplying by , since :
Declining-basis PMI is a fixed fraction of the interest paid over the same window. Which makes sense once you see it: both are the same balance integral, one scaled by and the other by . In the worked case , interest through period 99 is , and of that is — exactly the total PMI the site reports.
The site does not use this identity; calc() accumulates the sum in a loop and
stores it. The stored array makes horizon() an lookup, and the chart
calls it hundreds of times per offer to draw a line — cheaper than recomputing
logarithms at every sample. And the loop is the specification: its per-period
test is the termination rule transcribed, where the closed form is a derivation
whose rounding has to be kept in agreement with it.
Why the cost curve has no jump at
is a running total, so it is continuous everywhere. PMI ending removes a rate, not a level: the sequence drops to zero, which is a discontinuity in the increment. In the sum, only the slope inherits that discontinuity; the value stays continuous. Formally is and not at .
Part 5 quantifies how small that slope discontinuity is on screen.
Part 4 — Total cost, and the cost to walk away
Parts 1-3 produced pieces. This part adds upfront fees, assembles everything into the two totals that decide which offer is cheaper, and states what those totals leave out.
Fees
is the upfront cost of taking the loan: origination, points, and the rest of the closing charges. It is paid in cash at closing and not rolled into , so it never accrues interest and never amortizes. In the model it is a constant, added once.
It is also the only quantity so far that is large at and never grows. That asymmetry is what makes the comparison interesting: a lower rate bought with points is a fixed cost now against a slowly accumulating saving later.
Cost to term
If you hold the loan to the end:
Cost to walk away
If you sell or refinance at years, periods, you stop paying and must clear the remaining balance in one lump:
Note: PMI enters as , the premiums actually paid through , and nothing more. Paying off ends the loan, and premiums that would have been charged between and are never incurred.
The two agree where they should. At : , is the full total, and .
The five-component decomposition
The site draws both totals as a stacked bar. The components are chosen to partition the total exactly — they sum to it, with no overlap and no remainder:
| Component | At horizon | To term |
|---|---|---|
| Interest paid | ||
| PMI | ||
| Upfront fees | ||
| Remaining balance | ||
| Principal retired |
To see that they sum correctly, add interest paid and principal retired. The subtracted from the first is exactly the second, so it cancels:
which is every payment you made. Adding the remaining balance, PMI, and fees gives . The same cancellation at gives .
Inflation and equity are not modeled
Two modeling choices are worth stating plainly, because both affect how you should read the comparison.
No time value of money. Every term above is a nominal dollar, and dollars from different years are added as equals. There is no discounting, no assumed inflation, no return on the cash you did not spend on points. A dollar of fees at closing counts the same as a dollar of interest in year 28, even though the first is unambiguously more expensive.
Not your net financial position. is the total cash the loan consumes. The house is not credited back — no sale price, no appreciation, no selling costs, no tax treatment of interest. Notice this makes the “principal retired” component misleading if read alone: that money was not lost, it became equity. It appears in the total because the total is cash out, not net worth.
These choices are made because the tool is designed to compare offers on the same house. Every omitted term — the house’s value, the appreciation, the sale costs — is identical across offers and cancels in the difference. What survives is exactly what the offers differ on: , , and the PMI schedule.
The consequence is that the differences between offers are trustworthy and the absolute totals are not a forecast of your finances.
Part 5 — The cost-over-time chart
The chart plots from Part 4 as a function of how long you hold, one curve per offer, :
Everything interesting about it follows from one derivative.
The slope
Take the difference of over one period. The payment and the change in balance are both in there, and they nearly cancel:
Holding the loan one more period costs exactly the interest accrued plus the premium charged. The payment cancels completely. This is the Part 4 point in derivative form: principal is a transfer, not a cost, so the portion of that retires principal moves money from your pocket into your equity and nets to zero here. Only interest and insurance leave.
Three consequences, all visible in the chart:
- It is strictly increasing. for the whole term. Holding longer always costs more in nominal dollars.
- It is concave. The slope is proportional to , which falls on the Part 2 curve, so the curve flattens as the loan amortizes. Early years are the expensive ones.
- It starts at . At nothing is paid, no premium is charged, and . Walking away on day one means repaying the principal and eating the fees. The vertical spread between curves at is purely the difference in fees.
The PMI slope discontinuity, quantified
Under the declining basis , so while PMI runs
and afterwards it is . Comparing the two at the same balance, the slope falls by
independent of principal, balance, term, and time. For a typical against , that is .
Under the fixed basis , a constant, so the slope falls by that constant amount. The relative drop is not universal — it depends on how far the loan has amortized by :
where the second form uses , valid when the threshold rule binds rather than the midpoint. It is always the larger of the two, since the fixed premium never shrank while the balance did. With and on the same rates, against .
That is the whole answer to why is invisible on screen. The value is continuous (Part 3), so there is no step; the slope changes by under ten percent at a single point, on a curve that climbs tens of thousands of dollars across the plot. A few pixels of bend.
Break-evens
A break-even is not where two curves cross. With four offers, two also-ran curves can cross each other and nothing about the recommendation changes. What matters is where the winner changes, so the site tracks the pointwise argmin:
and records the where changes value. Between the two samples that bracket a change, the gap is interpolated linearly to place the crossing:
Two filters keep the result honest. A lead change is ignored unless the new leader is ahead by more than half a dollar, so floating-point noise is not reported as a crossing — the same tie window the verdict text uses. And a leader must hold the lead for at least 2% of the plotted range to be labeled: when two offers differ mainly in fees, the curves are nearly coincident at the start and the argmin can flicker between them many times before settling.
Economically the picture is simple. At the ranking is by fees alone. As grows the rate difference accumulates against that fixed head start, and the break-even is where it has been repaid.
Sampling
horizon() rounds its argument to a whole number of periods,
. Sampling the curve on an evenly spaced pixel grid
would therefore land many adjacent samples on the same and produce a visible
staircase. The site instead places a vertex at every scheduled payment,
, which is the natural grid for a function that is only defined there.
For long terms it strides to keep the vertex count bounded.
The break-even search uses a separate uniform grid, since it is looking for sign changes in a difference rather than drawing a shape.
Generated from MATH.md in the
project repository.
Nothing on this page is legal or financial advice.