How it works
Every number on this site comes from the assumptions and formulas below. When an assumption changes, every listing is recalculated. You can change any of them for a single deal in the calculator.
The model in plain English
The default deal
Offer at asking (asking − $10K is also shown). 20% down down, the typical investor loan, with 20% and 10% down one click away. A 30-year mortgage at 7.00%. The buyer pays closing costs of 3% of the price. Self-managed by default; switch to a 9% property manager on any property page.
Two questions per building
First, does the rent cover the mortgage and every cost each month? Second, over 30 years (when the loan is paid off), does owning it beat putting the same money into a stock index fund?
A fair comparison with stocks
Both options get exactly the same money at the same times. The building is credited with what you'd keep if you sold, plus every dollar of rental profit invested in stocks as it came in. The stock side invests the cash to close and every year's shortfall instead.
Where the numbers come from
Prices and building details from listings; taxes, unit counts, sales and special assessments from county records; rents from RentCast's comparable rentals or hand research, with a rough bedroom-based estimate until those arrive. Anything estimated is labeled.
The monthly ledger
- Rent: estimated market rent per unit, not the building total. Where the listing states current rents, we show both.
- Vacancy: 6% of rent.
- Property tax: the county's most recent payable-year bill, if the property isn't homesteaded. If the seller is homesteaded, the listing's tax is lower than what an investor pays, so we estimate the non-homestead bill as market value × the median tax-to-value ratio of non-homestead 2–3 unit buildings in the city. In Minnesota, rentals of 1–3 units (class 4b) and 4+ units (class 4a) both have a 1.25% class rate (taxes payable 2026). Taxes change after a sale reassesses the property.
- Insurance: our research where we have it; otherwise $900 per unit + $0.25 per sq ft a year, ×1.1 for buildings older than 1920. Get a quote.
- Water, sewer, trash: owner-paid at $85/unit/month (St. Paul runs ~$80–95), unless tenants pay.
- Heat: $100/unit/month only when the owner pays (one boiler, or the listing says so).
- Lawn care: $60/month ($120 × 6 months, spread over 12). No snow removal.
- Repairs and capital reserve: 8% of rent each, between 7% and 10% after adjustments: +1 point capital reserve for buildings older than 1920; +1 point repairs for 8+ bedrooms; +2 points each for "as-is", "as is", "needs tlc", "handyman"; -1 point for "fully renovated".
- Mortgage: principal and interest at 7.00%, 30 years. PMI 0.75% of the loan a year when the down payment is under 20%.
NOI = rent × (1 − vacancy) − (tax + insurance + water + heat + lawn + repairs + reserve + management)
Cash flow = NOI − mortgage − PMI
Cap rate = NOI × 12 ÷ price. DSCR = NOI ÷ mortgage payment. GRM = price ÷ yearly rent. Cash-on-cash = yearly cash flow ÷ cash to close. Break-even price: the highest price at which cash flow is zero (binary search). Break-even rent: the total rent, all units scaled together, at which cash flow is zero.
The 30-year comparison
- Rents grow 3% a year, costs 3.5%, the building's value 3%, stocks 7%.
- Selling costs 6% of the value at sale. The loan is paid off in year 30.
- PMI ends once the balance falls below 78% of the (rising) value.
- Positive cash flow is invested in stocks on the property side. On the stock side, the cash to close is invested on day one and every year's shortfall is added as it would have been paid.
- All figures are future dollars.
Rent control
St. Paul: rent for a sitting tenant can rise at most 3% in 12 months. After a qualifying ("just cause") vacancy, it can rise up to 8% plus inflation (CPI). Buildings that first received a certificate of occupancy after 2004-12-31 are permanently exempt (May 2025 amendment, effective June 13, 2025). We model one turnover per unit every 3 years and assume CPI of 3%; this only matters when current rents are below market. Utility bill-backs (RUBS) on existing leases may count toward the cap. Sources: www.stpaul.gov, themacweekly.com.
Minneapolis: no rent cap; we assume under-market rents reset to market at the first renewal.
Red flags
Two layers, merged and de-duplicated. Every flag shows its evidence.
- Rule checks against public records: St. Paul vacant-building registry; county unit count vs. what's advertised; rental certificate of occupancy (units, inspection grade); homestead tax; special assessments; recent purchase and resale; long time on market and price cuts; asking price far above break-even; distance to the nearest highway.
- Keyword checks on the listing description: electrical fuses, foundation, flat roof stucco, as is, cash only, investor special, month to month, no rent roll, rubs, shared meter, foreclosure, ownership structure, assumable, motivated.
- AI review: Claude reads the description and our data and suggests flags, opportunities and questions. A suggestion is discarded unless its evidence is an exact quote from the description or a named data field. We review everything before it's published.
- Listings with a serious data problem (e.g. fewer legal units than advertised) are listed as "needs more info" instead of ranked.
How we rank
score = 0.4 × cash-flow score + 0.2 × years-to-positive score + 0.4 × vs-stocks score − flag penalty
- Cash-flow score: monthly cash flow at the default scenario, scaled so −$1,000 → 0 and +$500 → 1.
- Years-to-positive score: positive in year 1 → 1, year 30 or never → 0.
- Vs-stocks score: property ÷ stocks at year 30, scaled so 0.5× → 0 and 2× → 1.
- Flag penalty: 0.15 per high-severity red flag, 0.05 per medium-severity red flag, 0.0 per low-severity red flag.
Neighborhood lists: best cash flow now, best long-term (year-30 property ÷ stocks), value-add (under-rented, needs work at a discount, or long on market), and proceed with caution (above-median score with a serious flag).
Neighborhood profiles
- Boundaries: St. Paul's 17 official planning districts; Minneapolis's 87 official neighborhoods. Listings are placed by their map point.
- Crime: police incidents in the last 12 months vs. the 12 before. St. Paul's data includes proactive police visits and community events, which we remove; Minneapolis's is reported offenses only. The two cities define and count incidents differently, so compare neighborhoods within a city, not across cities. Areas with a lot of retail (Union Park, Midway) or few residents (Downtown) look worse per resident than they feel to live in.
- Per 1,000 residents: 2020 Census population, summed from census blocks whose center falls in the area.
- Renter share, median rent and income: Census American Community Survey 5-year estimates by tract, combined for tracts whose center falls in the area. The combined medians are household-weighted averages of tract medians, which is an approximation.
- What's changing: hand-curated, with a source for every item. We say when something is planned rather than funded.
- Typical price per unit and cash flow: medians of the listings we track there now, at the default scenario.
Deal calculator
The calculator runs the same model in your browser. Our automated tests run it and the server-side model on the same cases and require the same answers.
What's real and what's estimated
- Public record County tax, market value, homestead status, special assessments, recorded units, last sale and tax delinquency (Ramsey and Hennepin counties); St. Paul vacant-building and rental-certificate data; Minneapolis rental licenses and assessor details (roof, exterior, heating); crime incidents; Census population; highway distance.
- Estimate Rents, insurance, water, heat, repairs and reserves, and anything derived from them. Unit mixes we inferred are marked "(est.)".
- Listing price and dates come from the listing. We don't copy listing photos or descriptions; we link to the listing.