What a cap rate is — and why software gets it wrong
A capitalization rate is the one-line summary investors use to compare income properties: the property's yearly net operating income divided by its price. A building that earns $214,229 a year after expenses and costs $3,150,000 has a cap rate of 6.80%. Buy it with cash and, before financing, that is roughly the yield you would earn.
Because the formula is one division, founders building underwriting tools, deal finders or investor dashboards often treat it as a solved problem. It isn't. The division is trivial; everything that goes into the top of it is not. Listing data is incomplete, rents are missing for some units, expenses vary by state, and the numbers pass through several systems before anyone looks at them. When one of those inputs is wrong, the tool still shows a precise-looking percentage — and an investor may act on it.
This guide walks through how to compute a cap rate the way an experienced underwriter would, and how to build that logic into software so the number can be trusted at scale. It is based on building a multifamily underwriting platform that turns raw listings into cap rates on a schedule.
Net operating income, line by line
Net operating income (NOI) is the property's income after the costs of running it, but before financing. Here is the worksheet for an example 24-unit multifamily building:
| Line | How it's calculated | Amount |
|---|---|---|
| Gross scheduled rent | 24 units × $1,350 × 12 months | $388,800 |
| − Vacancy & credit loss | 5% of gross rent | −$19,440 |
| = Effective gross income | $369,360 | |
| − Operating expenses | 42% of effective income (regional model) | −$155,131 |
| = Net operating income | $214,229 | |
| ÷ Price | Asking price | $3,150,000 |
| = Cap rate | 6.80% |
Example figures for illustration, not investment advice.
Operating expenses cover what it costs to run the building: property taxes, insurance, repairs and maintenance, property management, utilities the owner pays, and reserves. Other income — parking, laundry, pet fees — is added to effective gross income if the property has it.
What is not in NOI matters just as much: mortgage payments, large capital projects such as a new roof, depreciation and income tax. Those depend on the buyer, not the building, which is exactly why cap rates are useful for comparing properties.
Five mistakes that break the number
There is also a quieter mistake: mixing pro-forma numbers (what a seller projects) with trailing numbers (what actually happened over the last twelve months). Both are legitimate, but a tool should label which one it shows and never blend them in one calculation.
Getting it right in code
The goal is that the same inputs always give the same, explainable answer — whether it runs once or a hundred thousand times overnight. Four habits make that possible.
1. Exact decimals, rounded once. Store money in a decimal type (or whole cents) and rates as decimals such as 0.0680, never as floats. Round only when the value is displayed or saved as a final result, with the rounding rule written down.
from decimal import Decimal, ROUND_HALF_UP
def cap_rate(units, rent, vacancy, expense_ratio, price):
gross = Decimal(units) * rent * 12
egi = gross * (1 - vacancy)
noi = egi * (1 - expense_ratio)
return (noi / price).quantize(Decimal("0.0001"), ROUND_HALF_UP)
cap_rate(24, Decimal("1350"), Decimal("0.05"), Decimal("0.42"),
Decimal("3150000")) # -> Decimal("0.0680")2. Expense models as data, not code. Keep expense ratios per region and property type in a table the business can review and update. When an assumption changes, you change a row — and you can record which version of the model priced each deal.
3. Keep every input next to the output. Save the rent, unit count, vacancy, expense model version and price used for each cap rate. When an investor asks “why 6.8%?”, the answer is one click away instead of a debugging session.
4. Test against a hand-built worksheet. Take a handful of real deals an analyst has underwritten by hand and make them automated tests. If a code change moves any of those numbers, the build fails before a customer notices.
Flag bad deals before a person sees them
At scale, the most valuable feature isn't the calculation — it's knowing when not to trust it. Run quality checks on every property before its cap rate is shown:
- Rents found for every unit, or the deal is marked incomplete rather than treated as zero.
- Unit count in the data matches the listing description.
- Price and price per unit fall inside a sensible range for the market.
- The resulting cap rate is within the band you'd expect for that market; outliers go to review.
Flagged deals are held back or clearly labeled, so an analyst reviews a short list of real opportunities instead of re-checking every number by hand. In the multifamily underwriting platform, a listing missing its price, unit mix or rents gets no cap rate at all, and the dashboard says which input is missing. The same rules-first approach kept the AI real-estate deal finder accurate at roughly 75% lower running cost.
A missing number is an inconvenience. A confident wrong number is a lost deal.
If you're building in real-estate and want this math right from day one, an MVP build starts with exactly this: the data model, the math and the checks, written down before any screens are designed.
