Most refinance calculators answer a question nobody asked: whether the new loan is cheaper over thirty years you will not live in the house. This model bounds the answer at the move date.
The refinance decision is a purchase: you buy a lower monthly payment, and the price is the closing costs. The only question the arithmetic can settle is whether you keep the loan long enough for the purchase to pay for itself. The Worthune refinance model computes exactly that comparison, and its spec is explicit about the narrowness — what it charges, what it credits, and where it stops counting.
The seven inputs
The model accepts seven required inputs: the current loan balance, the current rate, the months remaining on the current loan, the new rate, the new term in months, the closing costs, and the months until the borrower expects to move or sell. There are no optional inputs and no defaults — every field is caller-supplied, and requests outside the published domains are rejected with a structured error, never silently adjusted.
The last input is the one most calculators omit and the one that most often changes the answer. A refinance that breaks even in month twenty-five is a good purchase for a borrower staying seven years and a bad one for a borrower moving in month twenty-four. The model bounds every savings figure at the move date, and two of its outputs exist purely to make that bound visible: the net savings at the horizon, and a boolean that says whether the break-even lands before the move.
monthly_savings = current_monthly_payment - new_monthly_payment; break_even_months = ceil(closing_costs / monthly_savings); net_savings_at_horizon = monthly_savings × months_until_move - closing_costs
Both payments come from the standard amortization formula (the published amortization primitive). When monthly savings are zero or negative, the call still succeeds: break-even is the sentinel Infinity, exported as the string "Infinity" in JSON, and the horizon outputs still answer the question. Zero closing costs with positive savings break even at month 0.
What the model deliberately charges and credits
The comparison is payment delta, not lifetime interest. A borrower who refinances twenty-two years into a thirty-year loan onto a fresh thirty-year term lowers the payment while potentially raising total interest paid over the loan's life — the model's spec names this convention as part of the contract, and a total-interest comparison is listed in the spec as a candidate for a future version, not smuggled into this one.
Closing costs are paid out of pocket, not rolled into the new balance. The new loan's principal equals the current balance. That convention keeps the break-even question clean: the costs are the purchase price, the payment reduction is the return, and the two are never entangled in the amortization itself.
- No cash-out: the new principal equals the current balance, always.
- No points modeling: a bought-down rate enters as the new rate the caller supplies.
- No PMI on either loan.
- No tax treatment of mortgage interest.
- No reinvestment of the monthly savings — the delta is counted as cash.
- Costs out of pocket — never financed into the balance.
Each exclusion is in the spec's assumptions section, which is one GET request away from any response. A caller who needs points economics can run the separate points-break-even model in the loans and credit pack, which prices the buydown decision on its own terms.
The sentinel, and why it is not an error
A borrower comparing a five percent loan against a six percent offer produces negative monthly savings. The model does not throw. It returns a successful response in which the break-even is Infinity, the net savings at the horizon are negative, and the worth-refinancing boolean is false. The sentinels array in the response annotates the field so an integrating UI can render never instead of a nonsensical number.
The distinction matters for embedders. An error says the question was malformed. This question is well-formed — the answer is that the refinance never pays for itself — and a UI that surfaces the negative horizon savings gives the user the honest dollar figure for what the mistake would cost. The verification vectors pin the tie case explicitly: identical rates and terms produce zero savings and the Infinity sentinel, on both implementations, every release.
Reading the response
A refinance call returns the current and new monthly payments, the monthly savings, the break-even months, the net savings at the caller's horizon, and the worth-refinancing boolean, together with the spec version, an assumptions array naming that version, an empty facts array (the model consumes no tax-year constants), and a record.sha256 computed over the model name, spec version, inputs, and outputs in canonical key-sorted JSON. Store the record and the answer can be recomputed and matched byte-for-byte at audit time.
A worked example
A borrower with a four hundred thousand dollar balance at six and a half percent, three hundred months remaining, is offered five and a half percent on a new three-hundred-month term with eight thousand dollars in closing costs, and expects to move in six years. The current payment is about two thousand seven hundred one dollars; the new payment is about two thousand four hundred fifty-six dollars; monthly savings are about two hundred forty-four dollars. Break-even is ceil(8000 / 245), month thirty-three. Seventy-two months minus the costs leaves roughly nine thousand six hundred dollars of net savings at the move — worth doing, and the response says so in a boolean the UI can render without arithmetic.
Change the move date to month thirty and nothing else: the same rate drop becomes a loss of roughly six hundred sixty-five dollars, and worth-refinancing flips to false. No other refinance input moved. That is why the horizon is an input.
Sources
- [1] Worthune refinance model spec. https://worthune.com/docs/models/refinance
- [2] Worthune eval datasets (the verification cases per model). https://worthune.com/evals