Frugal Calculators

Methodology

What the model actually computes, in the order it computes it. This is the full description of the mechanism — enough to reimplement it, disagree with it, or find a mistake in it.

The assumption nobody notices they made

Before any of the mechanism below matters, one ratio carries more of the answer than any other single input: price-to-rent, the purchase price divided by a year of rent. Nobody enters it — it falls out of the price and the rent you type — which is exactly why it is easy to pick a scenario whose answer was largely settled before the simulation ran.

price_to_rent = price / (rent_month × 12) gross_rent_yield = 1 / price_to_rent

US metros ordinarily run somewhere around 15–22×. Below that band, rent is expensive relative to the price and buying wins on the rent alone; above it, renting wins for the same reason in reverse. The calculator prints the ratio with every result and warns when a scenario falls outside that range. A warning is not an error — your market may genuinely be an outlier — but it does mean the verdict is telling you something about the rent you entered rather than something about owning.

The shipped scenario sits at 15.0×. An earlier default sat at 10.8×, a 9.2% gross yield, and returned a large win for buying that was mostly an artifact of that one number.

The scenario table

Three of this model's inputs are not measurements, they are guesses: the return on the invested difference, home appreciation, and rent growth. Reporting one number computed from one guess at all three reads as far more certain than it is. So every result is shown alongside five illustrative rate regimes, with your own assumption slotted in among them.

Only those three rates change between rows. Your price, your rent, the mortgage, and every cost are held exactly as you entered them, which is what makes the rows comparable to each other and to your own.

They are not labelled conservative, base and optimistic, and that is deliberate. Renting and buying are not two ends of one axis. Raising every rate together also compounds the renter's portfolio faster, so a uniformly “optimistic” row is not optimistic for buying — run that table on the shipped inputs and every row returns RENT, which tells you nothing at all.

The strongest single driver is the gap between the investment return and home appreciation. Buying tends to win while housing keeps pace with the market and to lose once the market pulls away, so the rows are named for the regime they describe and ordered by that gap, from the most buy-favourable to the most rent-favourable.

The gap is a driver, not a decider, and it is worth being precise about the difference. Within one scenario — your price, your rent, your mortgage, all held fixed — widening the gap moves the answer toward renting, which is why it orders these rows. Across different scenarios it settles nothing. A $200,000 house at $1,500 rent on a 3% mortgage and a $1,000,000 house at $3,000 rent on an 8% mortgage have exactly the same 5.5% gap, and they come out on opposite sides — buying ahead by $121,000 in the first, renting ahead by $6.2m in the second. The price-to-rent ratio and the cost of the financing matter every bit as much. Read the table as a gradient for your inputs, not as a general rule about gaps.

These are illustrative regimes, not forecasts and not probabilities. Nothing in the table says how likely any row is. They were chosen to span the decision boundary so that you can see which side of it you are on, and how far from the edge.

How much the answer depends on the table

A single figure reports 5-of-6 and 3-of-6 identically, and they mean entirely different things. So the table is summarised in words as well as counted:

  • Robust — the verdict holds in at least 80% of the rows. It does not hinge on which regime you believe.
  • Assumption-sensitive — 60% to 80% agree. The answer depends on which rate regime turns out to be right.
  • Finely balanced — below 60%, or a dead heat. The result should not be leaned on.

The bands are shares rather than counts, so adding or removing a scenario does not silently move them. This measures agreement across the rate regimes in the table and nothing else: it is not a probability, and it says nothing about the price, the rent or the financing, which are held fixed throughout and which move the answer at least as much as the rates do.

Where the line is

The scenario table picks points. The sensitivity matrix sweeps the two least knowable rates — investment return and home appreciation — against each other and colours every combination by winner. It answers a better question than "what is the answer?": how far is the answer from changing?

If the nearest flip is several points away, the exact rate you assume barely matters and you can stop arguing about whether equities return 7.4% or 7.8%. If it is in the next cell, the verdict is balanced on that assumption and you should treat it accordingly.

Your own two rates are inserted into the axes if the standard grid misses them, which it usually does — 8.5% is not a round step — so there is always a cell marking where you actually sit. Every other input is held as you entered it, so the grid describes your scenario rather than a generic one. The caption states the break-even in words, and each cell carries its own figure in a tooltip. Cells are lettered as well as coloured, so the grid still reads if colour is not available to you.

The boundary runs diagonally, which is the shape the underlying economics has: higher appreciation helps the buyer, a higher return helps the renter, and the two trade off against each other.

Sampling the rates instead of guessing them

The scenario table picks six regimes by hand. The Monte Carlo does the same thing hundreds of times: it samples the three uncertain rates around your numbers and reports how often buying ends ahead, at every holding period. It runs on request rather than as you type, because it is several hundred simulations rather than one.

The three rates are sampled together, not separately. Equities and house prices move with each other to a degree, and rent growth tracks general inflation and therefore house prices more closely than it tracks equities. Drawing the three independently would manufacture combinations that do not occur — a market melt-up alongside a housing crash — and would materially overstate how wide the range of outcomes is. The correlations are fixed rather than exposed as inputs, because an arbitrary matrix is easily made self-contradictory, and there is nothing to sample from when it is.

Spreads are annual; the model needs the horizon average

This is the subtle part, and getting it wrong is not a small error. The model applies one constant rate for the whole horizon. So what is being sampled is not a single year's return — it is the realised average annual rate over the time you hold. Those have very different spreads:

sd(T-year average) = annual_sd / √T

At thirty years, a 16% annual equity volatility becomes 2.9% on the average. Sampling the average with the full 16% and compounding it for thirty years produces terminal outcomes in the tens of billions on a $325,000 house — an artefact, and one that is only obvious because it is extreme.

The scaling is also what makes the spread right rather than merely smaller. Log terminal wealth is roughly T × r, so its standard deviation works out at annual_sd × √T: exactly the square-root-of-time growth in terminal dispersion that holding an asset for longer actually produces. And it self-corrects at the short end — over a single month the annualised rate is genuinely wild, and 1/√T widens the draw to match. So the spreads you enter are annual volatilities, the number anybody has an intuition for, and each holding period samples with its own scaled version.

Each holding period is its own run

A single thirty-year simulation does contain the verdict at all 360 shorter months. It is tempting to read the whole curve off one run, and wrong: every month of that run shares one rate drawn with the thirty-year spread, which is far too narrow to describe a five-year hold. It would understate the uncertainty at exactly the horizons where uncertainty matters most. So each point on the curve is its own sampling run with its own spread. The same stratified draws are reused across horizons, so the curve compares like with like and moves smoothly rather than jittering from point to point.

Stratified, and deterministic

Draws are stratified rather than purely random: each rate's range is cut into equal-probability bands and sampled once per band. On this model that cuts the variance of the resulting probability by two to six times, so 500 stratified draws carry roughly the precision of 1,700 random ones. The seed is fixed, so the same inputs give the same answer every time — a calculator whose headline changes on refresh is not one worth trusting. The reported figure carries a 95% interval, because it is an estimate from a sample and quoting it bare would be false precision.

None of this is a forecast. It is the share of a chosen distribution in which buying ends ahead, and that distribution's shape is an assumption rather than a measurement: real returns have fatter tails than a normal, and real housing markets have regimes rather than a steady drift. Read it as a sensitivity map with a number attached, not as the probability that buying is right for you.

What would have to be true?

The calculator answers “given these assumptions, what happens?”. The solver answers the question underneath it: how wrong would you have to be before this flips? A verdict of a few hundred thousand dollars tells you nothing about whether it survives a three-point miss on one input. A threshold does.

Each row takes one input, holds every other one exactly as you entered it, and finds the value where the verdict changes. Rows are sorted closest-first, so the top one is the assumption your answer is least safe from.

It is deliberately one input at a time. Several small misses together can flip an answer that no single one of them would, and nothing here accounts for that — the sensitivity matrix is the two-input version, and beyond that you are into the Monte Carlo.

Where an input has no threshold, that is reported too, and it is often the more useful result: it means that input cannot change your mind across its whole plausible range, so it is not worth arguing about.

The search is a bisection rather than anything cleverer, because the objective is not smooth — value-linked costs have kinks, loans pay off, PMI switches off — and bisection needs only a sign change, which is exactly what is being looked for. Inputs that live on a grid are snapped to it at every step: a holding period exists only on whole months, so the answer is the first month you could actually enter where the verdict really is different.

What actually determines the answer

The tipping points say how far you are from the boundary. A separate question is which inputs carry the most weight at all — the one you should go and research before deciding.

These are not the same, and they genuinely disagree. An input can move the answer by six figures and still never flip it, because your estimate is nowhere near the boundary. Another can be nearly decisive despite a modest effect, because the answer is balanced on it.

Ranking raw sensitivity would be meaningless: one unit of a mortgage rate is a hundred percentage points and one unit of a price is a dollar. So each input is nudged by a plausible amount of error instead — a percentage point on a rate, 5% on a price, a year on a horizon — and the question becomes: if each of these were off by about as much as you could reasonably be off, which moves the answer most?

The nudge sizes are a judgement, they are printed with the result, and changing them can change the order. The measurement is a centred difference, taken in both directions and halved, so a kink in the model — a loan paying off, PMI switching off — is not mistaken for sensitivity.

What to research first

The impact ranking says which input carries the most weight; the tipping points say where each one flips. Read separately they are two tables. Joined, they are an instruction:

Your decision is most sensitive to rent growth. If it turns out to be above 3.98%, the answer changes — 0.98 percentage points away. Go and find that number before you decide anything else.

That is a more useful thing for a calculator to produce than an answer, because it names the uncertainty you actually need to resolve rather than papering over it with a figure to two decimal places.

Distances for rates are quoted in percentage points, not as a relative share. A return moving from 8.5% to 6.5% is "23% lower", which is true and unusable: nobody holds a view about their return being 23% lower. They hold one about two points. Money and time keep the relative figure, where it reads naturally.

Sharing a scenario, and whose assumptions it is

Everything you change is carried in the page’s address, so a result can be bookmarked or sent to somebody and it will open exactly as you left it. Only inputs that differ from the shipped defaults are encoded, which keeps the link short and means the parts you never touched continue to track the model rather than being frozen at whatever the defaults were the day you sent it.

Each calculator here asks for far more inputs than anybody changes, so every result also says how many are still ours. A verdict computed from three edited fields and twenty-seven of our defaults is a statement about our assumptions wearing your name, and the page says so rather than letting the number imply otherwise.

The one rule

Both households spend the same amount, every month, for the entire horizon. Whoever has the cheaper month invests the difference.

difference = buyer_monthly_cost − renter_monthly_cost difference > 0 → renting is cheaper, renter invests it difference < 0 → owning is cheaper, buyer invests it

Everything else follows from this. Without it you are not comparing two strategies, you are comparing two different amounts of money, and any answer you get is an artifact of that gap rather than of renting versus owning.

Starting position

down = price × down_pct closing = price × closing_pct loan = price − down upfront = down + closing

Both households begin with exactly upfront in cash. The buyer spends it: down becomes home equity, closing is consumed outright. The renter invests the whole amount.

So the buyer starts behind by precisely the closing costs. On the shipped scenario that is $6,500 — and if the buyer sold on day one, their net worth would be negative, because selling costs apply to a home that has not yet appreciated.

Two different rate conventions

This is a detail most calculators get wrong, and it is worth stating because it changes the answer.

A US mortgage note rate is a nominal annual rate divided into twelve equal parts. An investment return quoted as 8.5% a year is an effective annual rate, which compounds. Converting them the same way is incorrect for one of them.

mortgage monthly rate = note_rate / 12 investment monthly rate = (1 + annual_return)^(1/12) − 1

Using rate/12 for the investment would overstate returns: 1.0070833¹² is more than 1.085. Using the compounding form for the mortgage would understate the payment against what a real lender charges. Both conventions are applied where they belong.

The monthly loop

Each month, in this order:

  1. Rent is computed for the current year, plus renters insurance.
  2. Ownership costs are computed against the home value at the start of the month, before this month's appreciation.
  3. The mortgage payment is split into interest and principal, and any extra principal is applied.
  4. Both portfolios grow by one month of investment return.
  5. The cost difference is invested by whoever paid less.
  6. The home appreciates by one month.
  7. Net worth is recorded for both sides.

The ordering matters. Costs are charged against the value at the start of the month, and returns are credited before the new contribution, so a dollar invested this month does not earn a return this month.

Short holds

The horizon does not have to be a whole number of years. It can be any number of whole months, because that is what the loop actually runs, and short holds are where buying looks worst: closing costs are paid and selling costs are owed on a home that has barely appreciated. On the shipped scenario a one-month hold leaves the buyer with negative net worth. A holding period that would fall between two months is refused rather than quietly rounded to a different scenario than the one you asked for.

The mortgage term is separate and stays in whole years, because that is how the contract is written.

The mortgage

payment = loan × r / (1 − (1 + r)^−n) where r = note_rate / 12, n = term_years × 12

Each month, interest is balance × r, and principal is whatever the payment leaves over. Any extra principal is applied on top, capped so the final payment cannot overshoot into a negative balance.

The buyer is charged what actually reached the lender, not the scheduled payment. In every ordinary month these are identical. They differ only in the payoff month, where the remaining balance is smaller than a full principal instalment — there the buyer writes a smaller cheque and keeps the rest. Charging the scheduled figure would overstate their cost and depress their net worth for the whole remaining horizon.

Ownership costs

HOA dues and extra utilities grow at their own fixed rate. They are set by an association budget and by usage, so they never track the home's value.

Property tax, insurance, and maintenance each have a switch. When tracking is on, the cost scales with how far the home has moved from its purchase price:

value_ratio = current_value / purchase_price tracked = base × value_ratio floor = base × (1 + escalator)^year × value_link_floor charged = max(tracked, floor)

The year-one input sets base in each case. For property tax that means your entered annual figure implies an assessed rate of tax_year / price, which is then charged against the current value.

Why the floor exists

With a pure value link and no floor, a deep price decline drives all three costs toward zero. The buyer's carrying cost collapses, they invest the savings, and the model reports that a severe housing crash leaves the buyer better off than steady appreciation. “Buy minus rent” becomes U-shaped in appreciation.

That is an artifact. A home that has lost half its value still needs a roof. At 100%, the floor means a value-linked cost never falls below its own inflation path — appreciation can raise these costs but not cut them. On the upside the floor is inert, so the headline result is unchanged; it binds only on the downside, which is where the unfloored model went wrong.

PMI

threshold = price × pmi_stop_ltv PMI charged while balance > threshold monthly PMI = balance × pmi_rate / 12

The threshold is loan-to-value against the original purchase price, not against current value and not against equity. At 0.80, PMI stops when the balance falls to 80% of price — the same instant you reach 20% equity. Entering 0.20 would model PMI running nearly the whole loan.

A non-zero PMI rate with a zero threshold is rejected as an input error, because it charges PMI for the entire life of the loan and no conventional mortgage behaves that way.

Extra principal

Extra principal is counted as part of the buyer's monthly outlay. Under the equal-outlay rule, that means the renter invests the same amount. Without this the buyer would receive money the renter never gets, and every comparison involving extra payments would be meaningless.

Its effects all fall out of the amortization rather than being modelled separately: the loan retires early, total interest falls, PMI ends sooner because the balance drops faster, and once the loan is gone both the payment and the extra stop — so the buyer's outlay falls sharply and they begin investing the difference instead.

Net worth

renter = portfolio buyer = portfolio + home_value − selling_cost − loan_balance where selling_cost = home_value × selling_pct

The buyer is always scored on what they would actually walk away with if they sold at that moment, selling costs deducted. This is why the buyer starts with negative net worth and why the horizon matters so much.

Tax

Tax is off by default. Everything above, and every figure this page ships with, is a pre-tax comparison until you switch it on. Off means untouched: changing a tax input while the model is off changes nothing at all, and the integrity page checks that on every build.

Switched on, three things happen to the buyer that do not happen to the renter, and they do not all point the same way.

1. The mortgage interest deduction, which is usually worth nothing

This is the tax effect everybody knows about and the one most calculators get wrong. Mortgage interest is not worth interest × your tax rate. It is worth the tax saved by the amount it pushes your total itemised deductions above the standard deduction — and since that was doubled, most households never get there.

benefit = tax(income − standard_deduction) − tax(income − itemised_deductions) itemised = mortgage_interest + capped_SALT + your_other_deductions

Computed as the difference between two whole progressive tax bills, not as a rate times an amount. Those differ whenever the deduction spans a bracket boundary, which a mortgage routinely does.

Two things then conspire against it. Property tax has to share the SALT cap with your state income tax, and in a high-tax state the salary fills that cap on its own, so the property tax contributes nothing toward clearing the floor. And interest falls every year as the loan amortises. On this page’s own default scenario the household itemises in zero of thirty years, and the deduction is worth exactly nothing. The page says so in those words rather than quietly crediting a benefit nobody receives.

The benefit is charged as a reduction in what owning costs, not as a payment to the buyer. That is what keeps the one rule intact: both households still spend the same each month, the renter simply invests less, and the benefit reaches the buyer as a relative advantage — which is what a deduction is.

2. The gain on the house is mostly untaxed. The renter’s is not.

This is the effect almost nobody mentions, and on a long hold it is larger than every deduction combined.

Under IRC 121 a couple filing jointly excludes $500,000 of gain on a principal residence, provided they owned and lived in it for two of the last five years. There is no equivalent for a brokerage account: the renter’s portfolio gain is taxed in full on the way out.

On the default scenario that asymmetry moves the verdict by about $310,000 — and in the opposite direction from what a reader expects after being told the mortgage deduction is worthless. The exclusion has not been indexed since 1997, so in an expensive metro a long hold now routinely produces a gain larger than it covers, and the excess is taxed. That is modelled too. A sale inside two years gets no exclusion at all.

3. Both portfolios are taxed properly

With tax off, the tax_drag input applies a flat haircut to the return. It is a fine placeholder and a poor model: it taxes growth that has not been realised, it has no notion of a cost basis, and it cannot express the settlement at the end. With tax on it is ignored — the two are alternative answers to the same question, and charging both would tax the portfolio twice.

What runs instead is two separate charges. Every year, tax on dividends as they are paid, split between the qualified and ordinary rates, plus the gains the fund realises through its own turnover. Then once at the horizon, tax on the deferred gain against the basis — tracked as contributions, because that is what a basis is. If you say the portfolio is never sold, the deferred charge never lands.

The same code prices the portfolio on all three calculators, so they cannot disagree about what a brokerage account costs. The integrity page checks that too.

Every rule and figure this model uses

Published rather than summarised. A reviewer went through this methodology and listed ten federal rules they could not confirm were implemented; nine were, one was not and has since been added. The only honest answer to that is to show the parameters instead of asserting they are right, so here they are — read from the same table the calculation uses, so what is printed here cannot drift from what was charged. Check them against the revenue procedure yourself.

Every figure in the 2026 table

SingleMarried filing jointlyMarried filing separatelyHead of household
Standard deduction$16,100$32,200$16,100$24,150
Additional, per age/blindness box

Section 63(f), per qualifying condition and per spouse.

$2,050$1,650$1,650$2,050
Top of the 0% capital-gains band$49,450$98,900$49,450$66,200
Top of the 15% capital-gains band$545,500$613,700$306,850$579,600
Net investment income tax threshold

3.8% on the lesser of net investment income and MAGI above this. Not indexed.

$200,000$250,000$125,000$200,000
SALT cap

Phased down at 30% of MAGI above the threshold below, never past the floor.

$40,400$40,400$20,200$40,400
SALT phase-down begins$505,000$505,000$252,500$505,000
SALT floor$10,000$10,000$5,000$10,000
Mortgage acquisition-debt cap

Interest above this is prorated by the share of the debt under the cap, not disallowed.

$750,000$750,000$375,000$750,000
Mortgage insurance premiums, phase-out start

Deductible again from 2026. Lost in 10% steps per $1,000 of AGI over this, gone $10,000 later.

$100,000$100,000$50,000$100,000
Principal-residence exclusion (section 121)

Owned and lived in for two of the last five years. Not indexed since 1997.

$250,000$500,000$250,000$250,000

Ordinary income rate bands

Single10% to $12,400, 12% to $50,400, 22% to $105,700, 24% to $201,775, 32% to $256,225, 35% to $640,600, 37% above
Married filing jointly10% to $24,800, 12% to $100,800, 22% to $211,400, 24% to $403,550, 32% to $512,450, 35% to $768,700, 37% above
Married filing separately10% to $12,400, 12% to $50,400, 22% to $105,700, 24% to $201,775, 32% to $256,225, 35% to $384,350, 37% above
Head of household10% to $17,700, 12% to $67,450, 22% to $105,700, 24% to $201,750, 32% to $256,200, 35% to $640,600, 37% above

Not filing-status dependent

Residential recovery period27.5 years, straight line, building only
Depreciation recapture ceiling25% on unrecaptured section 1250 gain
Passive loss allowance$25,000, phasing out between $100,000 and $150,000 of MAGI at 50% per dollar
Section 199A deduction20% of qualifying rental income, when the rental is a trade or business

Both sales land in the same tax year, and that is the worst case

The model values everything at the horizon, which means the house sells and the portfolio is liquidated in the same twelve months. A tax year has one set of capital-gains brackets and one surtax threshold, so the two gains stack on each other — the second one starts where the first left off, part way up the tiers.

That is correct, and it is also the most expensive way to do it. It is what the “score everything at the horizon” convention implies, not what somebody with a choice would do. Two things anybody can actually do about it, both switched off by default so the headline stays the conservative figure:

  • Split the years. Complete the sale in December and start selling the portfolio in January. Two sets of brackets, two lots of surtax headroom, and nothing else about the decision changes. It only helps a household with two realisations to separate, so it does most for an owner whose gain outran the exclusion, and nothing at all for a renter.
  • Spread the liquidation. Sell the portfolio down over several years instead of all at once, so each year gets its own run through the 0/15/20 tiers. Spreading a $1.1m gain over ten years takes its tax from about $229,000 to about $148,000.

Read the second one carefully before reaching for it. Spreading helps whoever holds the larger portfolio, and on this page that is the renter, whose entire net worth is in one. On a $900,000 house held thirty years, spreading both households' sales over five years moves the verdict about $91,000 toward renting. It is a real saving and it is not an argument for buying.

What is deliberately not offered

  • Tax-loss harvesting. It needs losses, and a deterministic compounding path never has any. Approximating it as a haircut on the gain would be inventing a number.
  • Donating appreciated shares. It avoids the gain by giving the money away, so it does not belong in a comparison of what you end up owning.
  • A 1031 exchange defers a rental's gain indefinitely — but the landlord never receives the cash, and the two sides stop being comparable.
  • Realising in a low-income year, by retiring first and selling afterwards. Real, and out of reach here: the model holds one income and one marginal rate across the whole horizon. This is the largest thing the tax model cannot see.
  • Never selling at all is offered, and is the biggest lever of the lot. Switch off “portfolio is sold at the horizon” and the deferred gain is never realised, which is what happens if it passes at death with a stepped-up basis.

What the tax model is not

A marginal-rate model of one household in a steady state, with one year’s law held constant across the whole horizon — on a thirty-year run that last one is the largest simplification in it. No AMT, no credits, no payroll tax, no state brackets, and no points at closing or capital improvements raising the basis. Those last two would both help the buyer, so leaving them out is conservative. Good enough to change a decision; not good enough to file with.

The crossover

The crossover is the first month the buyer's net worth exceeds the renter's. It is deliberately not called a breakeven: it says nothing about whether buying stays ahead. The model counts how many times the lead changes hands, and reports that count alongside the crossover, so a single date is never mistaken for a durable verdict.

Checks that must pass

The simulation asserts these and refuses to report a result if any fails. A comparison that quietly hands one side extra money is worse than no comparison at all.

  • Principal is conserved. Repaid principal plus remaining balance equals the original loan, at every point — including horizons that end with the loan still open.
  • The loan is gone at scheduled payoff. A fixed-rate loan left alone must amortize to exactly zero on its final scheduled payment.
  • Equal outlay. Both households' lifetime spending must match to within a rounding error. This is the rule the whole comparison rests on, so it is verified rather than assumed.
  • Inputs are finite. NaN and infinity are rejected up front. NaN fails every comparison silently, which previously produced an all-NaN report whose verdict line read “TIE”.

Numerical precision

Monthly amortization is a recursion, and extreme rate and term combinations can accumulate more floating-point error than the result can carry. The model computes an error bound for the given inputs and warns when the reported balance would be materially wrong, rather than presenting a confidently incorrect figure.

What is not modelled

  • Income tax, unless you switch it on. Off by default, and everything on this page is then a pre-tax comparison. Switched on, it models federal and state marginal rates, the mortgage interest deduction against the standard deduction, the property tax inside the SALT cap, the IRC 121 exclusion on the gain, and a dividend-and-turnover model of the portfolio on both sides. It is a marginal-rate model of one household in a steady state: no AMT, no credits, no payroll tax, no state brackets, and one year’s law held constant for the whole horizon. Good enough to change a decision, not good enough to file with.
  • Two things the tax model deliberately leaves out, both of which would help the buyer: points paid at closing, and capital improvements raising the basis and so reducing the taxable gain.
  • Transaction friction beyond the closing and selling percentages you enter.
  • Rent control, vacancy, or stepwise rent changes. Rent grows smoothly here.
  • Lumpy maintenance. Upkeep is charged evenly; real roofs fail all at once.
  • Liquidity, mobility, and concentration risk. Owning is a large, leveraged, undiversified bet on one asset in one town — often the town your job is in. None of that carries a dollar figure here.

Every rate in the model is nominal. The optional inflation input deflates the final answer into today's dollars for reporting only; it does not enter the simulation, because doing so would double-count.