Case study · Real estate investing

Single-family rental: one system from raw transactions to a simulated portfolio

I designed, built and owned the full system a single-family investment team used to decide where to buy. It cleans ~70M transaction records, measures and forecasts home price growth, values every home, converts all of it into expected returns by zip code, and simulates the portfolio those returns would have picked.

The single-family system, built end to end Four data sources, including sales and leases from multiple providers for national coverage, feed a data foundation layer. It feeds four components: a growth index, a price forecast, a valuation model and capex and tax assumptions. Together they produce yield and IRR by zip code, which a portfolio simulation uses to pick homes. ONE SYSTEM · DESIGNED, BUILT AND OWNED END TO END Sales and leases multiple sources, national Tax assessor Macro and censusMarket fundamentals 0 Data foundation: cleaning, schema mapping, validated pipeline, monitoring 1 Growth index matching + repeat sales 2 Price forecast ~400 metros, ranked 3 Valuation (AVM) price + rent, every home 4 Capex and tax cost of owning each home Yield and IRR by zip code the system's output Portfolio simulation how the output is used Used in build-to-rent and homebuilder deal underwriting
Every box is part of one system I built and maintained. Select a box to jump to it.
Role
Owner of the full system: design, build, production, maintenance
Scope
~70M transactions · ~400 US metros · zip-level output
Methods
Coarsened exact matching, Case-Shiller index, hedonic regression, weighted ensembles, walk-forward backtesting, simulation

The problem

Build-to-rent and homebuilder deals need a defensible answer to one question: which zip codes will deliver the best yield and IRR? The data makes that hard. The same house rarely sells twice in a short window, most homes have not sold recently, and taxes, rents and upkeep costs vary county by county. No single model answers the question; it takes a chain of them that agree on the same data.

0 Data foundation

Everything downstream depends on clean, consistent inputs. Sales and lease records come from multiple sources, combined so the system covers the whole country rather than the markets any one source covers well. When our primary data provider overhauled its systems, I mapped the full schema change and moved five separate models from ad hoc notebook joins into one managed, validated pipeline with a monitoring tearsheet.

1 Measure growth: a same-store index

To measure how prices and rents really change, you need to compare the same house over time, but few homes sell twice. I built a synthetic "same house": comparable homes grouped together, whose consecutive sales act like repeat sales of one home.

Under the hood. Coarsened Exact Matching groups homes within a census tract by age, bedroom count and living area. A Case-Shiller-style repeat-measures regression on the resulting pairs produces a same-store growth index for prices and rents. It became the standard growth input across the firm's single-family work.

Left: homes in one census tract, colored by matched cell. Right: sales within one cell over time, connected as pseudo-repeat pairs.
Illustrative, synthetic data. Homes in the same cell stand in for one house; their consecutive sales become repeat-sale pairs.
Line chart of a synthetic same-store price index and rent index from 2010 to 2024, both starting at 100.
Illustrative, synthetic data. The index separates price and rent growth, which later feed yield and IRR.

Validation. Two checks confirm the index measures what it should. First, matched cells must be tight: the coefficient of variation of price per square foot within each cell should be far lower than across the whole tract. Second, the index must agree with the market: its growth is compared with published house price indices on FRED, measured by R².

Left: histogram showing matched cells have much lower coefficient of variation than whole tracts. Right: scatter of our index growth against a published index, closely following the 45-degree line.
Illustrative, synthetic data showing the two validation checks.

2 Forecast prices

This is where the investment edge comes from. The forecast has to say which metros will do better than others, not just whether the whole country goes up, and the ranking has to hold up out of sample. Three things make it reliable: it is trained on each metro's growth relative to all metros, it is judged only on rigorous walk-forward backtests, and it combines many models into a weighted ensemble so no single model's mistakes drive the ranking.

Under the hood. Gradient-boosted (LightGBM) models forecast growth for ~400 metros at several horizons, with the target normalized cross-sectionally at each point in time. Features are selected by out-of-sample performance, and feature groups are split across ensemble members so their errors are less correlated. Members are weighted by walk-forward backtest performance: each fold trains only on the past and scores the next period. A residualized short-horizon variant removes trend continuation so the model does not lean on momentum exactly when momentum breaks.

Two panels: raw metro price growth mostly moves together with the national cycle; after normalization, the spread shows which metros consistently beat the average.
Illustrative, synthetic data. Normalizing the target strips out the shared cycle and leaves the ranking signal.
Left: walk-forward backtest folds, each training on the past and testing on the next period. Right: rank correlation by test period, steadier for the weighted ensemble than for individual models.
Illustrative, synthetic data. Walk-forward testing and ensemble weighting are what make the rankings dependable period after period.

3 Value every home

Returns depend on today's price and rent for each home, including the many that have not sold in years. The valuation model estimates both for the full national universe every quarter.

Under the hood. A hedonic regression framework, fit with two gradient-boosted models (price and rent). Each target is measured relative to the home's own census tract over a trailing window and adjusted by the metro index, which separates what is specific to the property from the market trend. The model then explains that property premium from the home's features. Validation uses a five-year entry-to-exit backtest rather than in-sample fit.

Left: raw sale prices for homes in two tracts rise with the market and differ by neighborhood. Right: after removing tract level and market trend, the remaining property premium rises with living area, fit by a hedonic line.
Illustrative, synthetic data. Stripping out neighborhood and market leaves the part of value the home's own features explain.

4 Capex and tax assumptions

Rent is not return: owning a home costs money every year. Capital expenditure and property tax assumptions turn gross rent into what an owner would actually earn, so they are estimated from data for every home rather than set as flat rates.

Under the hood. Property tax uses the observed value from assessor records whenever a home has one. Where it does not, the rate is filled in from the most granular level with enough coverage: zip code, then metro (CBSA), then state. Capex is calculated from the available data and applied to homes of the same property type in the same region.

Property tax fill-in order Use the observed property tax for the home; if missing, use the zip code rate; if missing, the metro rate; if missing, the state rate. PropertyZip codeMetro (CBSA)State observed in assessor datarate from nearby homesif zip coverage is thinlast resort Each home gets the most local rate the data can support
Property tax fill-in order, from most to least granular.

Output: yield and IRR by zip code

Growth, forecast, valuation, capex and tax chain into the numbers investors act on: expected yield and IRR for every zip code, refreshed each quarter.

Under the hood. Rent and price estimates set the gross yield; vacancy, management, property tax, capex and insurance bring it to a net yield; the forecast adds expected appreciation.

Waterfall chart: gross rent yield of 8 percent, minus vacancy and management, property tax, capex and insurance, gives a 4 percent net yield; adding forecast appreciation gives a simplified IRR of about 8.3 percent.
Illustrative numbers for one zip code, not actual assumptions. IRR shown as net yield plus appreciation for simplicity.

How it's used: portfolio simulation

To test whether the whole system picks good homes, I simulated how a buyer following it would have done. Candidate homes are ranked by forecast IRR and bought from the top until a fixed quarterly budget runs out. Real-world limits apply: the portfolio cannot take more than a set share of the available listings in any one market, so once a market hits its cap, the next-best homes elsewhere are bought instead.

The simulated portfolio is benchmarked against the realized returns of large institutional single-family owners over the same periods. Across the backtest periods, its median IRR tracked above theirs.

Left: candidate homes ranked by forecast IRR; top homes are bought, some are skipped because their market reached its cap, and buying stops when the budget is exhausted. Right: simulated portfolio median IRR versus institutional owners over eight backtest periods.
Illustrative, synthetic data showing the method, not actual results.

What it enabled

A single, systematic framework that ranks every zip code in the country by expected return, used directly in build-to-rent and homebuilder deal underwriting. Because I owned every stage, a change anywhere (a new data release, a model update) could be traced through to its effect on the final portfolio.

Skills