Home Methodology
Methodology · v2 · last revised Aug 2026
How a deal becomes a pick.
Most listing analysis skips the only question that matters: would you end up wealthier buying this than never buying at all? We run that comparison on every 2–4-unit listing in the Bay Area regions we cover: buy it and house-hack it, against keeping your cash in an S&P 500 index fund and renting.
Below is the full process: the model, the conventions we pin, the bar a pick has to pass, and the checks that stop a bad week from shipping. The picks are the smallest part of what we publish.
Stage 01
Scan. What gets underwritten.
We cover Bay Area regions on a weekly cadence, one board per region. What enters the pipeline is decided by rules that run the same way every week:
A research base per ZIP
Seven files of documented research: neighborhoods, market profile, rental comps, a pricing framework, and more. Rent bands come from documented comps for the same unit type. In San Francisco they anchor to Rent Board registry data on what 2–4-unit buildings actually collect.
Two to four units, residential
The owner-occupied financing genre: FHA reaches it at 3.5% down. Five or more units means commercial lending, and a deterministic filter drops those listings before anyone models them.
Evidence gates that fail closed
A ZIP whose evidence can't support the analysis is dropped for the week. Nobody invents a number to keep a ZIP alive, and a dropped ZIP doesn't sneak back in later in the run.
Growth catalysts still matter here: a funded transit line is worth telling you about. It changes zero numbers in the model. A catalyst is a flag on the page, never a rate in the math.
Stage 02
Model. One comparison, in one file.
The wealth comparison lives in one deterministic module of our
pipeline, a file named engine.cjs, with every
default pinned in defaults.json. The public
calculator on this site runs the
same math. The horizon is ten years: buy the building, live in
one unit for two years while renting the rest, then move out
and run it as a full rental. Against it, the alternative:
never buy, keep renting, and put the same starting cash in an
index fund.
The house-hack arm
- 3.5% down, closing costs, an emergency reserve set aside
- Mortgage amortization; PMI ends at 78% of the original price, as the law requires
- Rents haircut for maintenance and vacancy
- Property tax at the jurisdiction's own rate and growth cap
- Leftover cash invested in the same index fund
The never-buy arm
- The full starting cash in the index on day one
- Rent, renter's insurance, utilities, each growing yearly
- Every month's surplus invested
- Same wage growth, same inflation, same return assumption
The winner is decided on hold net worth: portfolio plus property value minus mortgage debt, with reserves counted back in. A liquidation figure that subtracts selling costs prints beside it as the secondary number. Margins are signed: when the index wins, the page says so in negative dollars, and no prose argues past that verdict.
The headline number is the S&P breakeven: the annual index return at which never buying would catch the deal over the decade. We assume 10%. A deal whose breakeven sits above 10% wins at our defaults, and the higher it sits, the stronger the deal. One function turns that number into the letter grade on every record:
Read the grades like this:
Grades D and F mark deals whose cautious case loses to the index. They render as losses, they can't be picks, and their pages explain why they lose. A second solved number prints on every record too: the crash floor, the appreciation rate at which the deal and the index tie. It's derived from the model, and the answer doesn't move when our appreciation convention does. That makes it the honest headline for appreciation risk: this deal needs X%/yr, whatever anyone forecasts.
Published verdicts run with the income-tax model off. Depreciation and interest deductions are opt-in, in the calculator and in your signed-in overlay; turning them on only helps the buy side, so the published record stays the cautious version.
Deliberate simplifications, on the record:
- PMI terminates at 78% of the original purchase price (the Homeowners Protection Act rule), so optimistic appreciation can't cheat PMI away early.
- Emergency reserves earn 0% and return to final wealth: real cash, never spent, never grown.
- Wages grow with inflation in both arms. No real raises assumed.
- One maintenance-and-vacancy rate applies in both phases.
- Named tax events we don't compute, listed in the calculator's disclosure block: Schedule E income tax on rental profit, passive-loss limits, depreciation recapture at sale, capital-gains tax on the index side.
Stage 03
Scenarios: one rent number is a guess.
So every property runs three times:
Cautious
- Bottom of the rent-evidence band
- A tenanted unit is priced at the rent it collects today, never at what it would fetch empty
- Appreciation 2.5%/yr
- $15,000 repair reserve
The verdict, grade and rank all come from this run.
Expected
- Mid-band rent, features as advertised
- Appreciation 4.0%/yr
The middle of the printed range.
Best-case
- Top of the band, capped below nearby apartment-community pricing
- Appreciation 5.5%/yr
Upside context. Never the argument.
In San Francisco a stricter rule sits underneath the cautious run: rent-controlled buildings anchor to Rent Board registry figures for what comparable buildings actually collect, and the run refuses to start when a cautious rent basis doesn't conform. A deal that only wins at optimistic rents never publishes.
Each run produces its own S&P breakeven and a ten-year wealth margin in dollars. Percentages on seven-figure assets hide six-figure differences; we want the money visible as money.
Stage 04
Conventions. The numbers we pin, and why.
Three inputs used to be judgment calls. They're now conventions: one value, set in one file, enforced mechanically. A scenario that disagrees with a convention doesn't run.
Appreciation is a threshold, never a forecast
One set of appreciation rates covers every property in every
ZIP: 2.5% cautious, 4.0% base, 5.5% optimistic, defined in a
single module named appa-convention.cjs. Read the
cautious rate as a publishing standard: we publish deals that
beat the index while needing under 2.5%/yr appreciation, in a
city whose realized ten-year median has run near 4.4%.
We used to write a per-neighborhood appreciation band. We measured it and retired it. Re-derived under an unchanged rubric, the same place kept its rating about a third of the time. Nothing we built could forecast appreciation out of sample either; a flat 2.5% beat every model we tried. A number that can't survive its own re-derivation has no business pricing your decade.
Rent growth: a cap is a ceiling
Where rent control applies, modeled rent growth is the smaller
of the market baseline and the jurisdiction's formula cap,
derived in one module (rga-convention.cjs) from a
maintained table of ordinances. San Francisco's cap computes
to 1.8% and binds. A statewide cap of 8% doesn't bind against
a 2% baseline, because a ceiling on rent growth is never a
forecast of it.
The same regime prices the other arm. The renter you'd otherwise be lives under the same ordinance, so the cautious case grows their rent under the same cap. We fixed this in August 2026: a generic 3% on the renter's side against a capped 1.8% property side flattered buying, and flattering buying is the one direction the cautious case must never lean.
Financing: the FHA floor, and a dated rate
3.5% down everywhere. It's the FHA floor, and for 2–4-unit buildings no 3%-down program exists. The modeled mortgage rate is pinned to the Freddie Mac PMMS 30-year weekly average and stamped with its as-of date; a test in our suite goes red 35 days after the pin, so the model can't quietly keep running on last quarter's money.
Stage 05
The bar. What makes a pick.
Pick status is conferred by criteria, and there are three:
- It wins the cautious case at our published defaults.
- It has room for a rent shortfall: 15%.
- Its facts are verified line by line against the listing itself.
The rent cushion is the
across-the-board rent haircut at which the cautious verdict
flips. Read it as: rents can fall this far and the deal still
beats never buying. The metric and the floor are defined in
exactly one file, rent-cushion.cjs, and the gate
is enforced at three separate layers of the pipeline.
Why the floor exists
A $999,000 San Francisco duplex penciled as a winner by $3,169 over ten years, about $17 a month, with a 0.3% cushion. That margin sits inside our own error bars on unit counts, comp rents, taxes and HOA. A winner whose margin lives inside the error bars is a tie rounded in our favour. The cushion floor exists so it never publishes as a win.
Ranking is deterministic, top to bottom: highest cautious S&P breakeven first, ties broken by the signed cautious margin, then by lower price. The picks are the top of the set that passed, at most five per region. There's no override lever: rank #11 with beautiful evidence is still rank #11, and nobody can force it in.
The pick count is
an output, never a target. The board says how many beat renting and index funds this week; two means two. Thin weeks ship thin, and a zero week ships the story of why.
If the cautious case loses to the index, it isn't a pick at any rank. We'd rather ship a short list than talk anyone into a $1.5M mistake.
Stage 06
Evidence. Where every number came from.
Every input into the engine carries a recorded origin: what produced it, the exact basis text, and whether anybody actually looked. A convention is recorded as a convention. An input nobody checked can never pose as a verified one, because "we did not look" is stored as exactly that, never as "there is nothing."
Physical facts (units, beds, baths, square footage, year built) carry one of three states: corroborated, divergent, or unchecked. A divergent fact keeps both values and says which one we used. When sources disagree, independent records outrank a listing site's data fields: an assessor's roll, a rent-board filing, or the listing's own prose beats the number in a portal's summary chip, because we've caught those chips wrong on multi-unit buildings too many times.
When an analysis would rest on an unverified fact, that fact is pulled out of the lead argument and rendered in a visible needs-verification block on the page. The page may state the conditional ("if the lower flat is deliverable vacant, then X"); it never leads with it. Paid members can request verification of a specific fact, and the answer lands on the record.
Record-keeping is append-only:
- Unit-count and commercial rulings live in an
append-only verdicts ledger (
listing-verdicts.json), hash-guarded and never hand-edited. When an extraction rule changes, verdicts are re-derived under the new rule's version; nobody edits an old row. - Permanent bans are a separate store, and a ban requires the listing's own text stating the disqualifier verbatim: a timeshare interest, a deed restriction barring tenants. Suspicion routes to a verification request, never to a ban.
- Listing identity (which MLS numbers and address spellings are the same building) lives in a registry that only grows: a wrong entry is corrected by adding a new row, never by rewriting one.
- Predictions: the pipeline appends a row for each scenario it runs, inputs included, to an append-only archive. Our past claims sit on disk in the form we made them.
The public face of that discipline is the track record: every pick logged when it publishes, then graded against the numbers we claimed that week. Wrong calls stay visible.
Stage 07
Gates. Between a run and your inbox.
Modeling isn't the safety layer. The safety layer is a stack of deterministic checks that fail closed, and then people.
The machine gates
A run is refused when a scenario's appreciation or rent-growth rate disagrees with the pinned conventions, when a San Francisco cautious rent doesn't conform to the registry-anchored evidence rule, when a pick's cushion is under the floor, when a margin would print unsigned, or when an input's provenance is missing. Our own copy is gated the same way: an AI-writing check runs on every built page of this site, and rental demand may only be described by what people do (commutes, employers, trades), with protected-class wording failing the build outright.
- fails closed
- cushion checked at 3 layers
- signed margins
A failing check drops the property or the ZIP for the week. Nothing gets patched past a gate.
The human gate
An automated editorial pass reads the drafts and flags problems; it never rewrites anything, and it can't reject or promote a pick. Each release also gets a voicing review against our reader research. Then the send gate: the operator reads the board and the drafts every week before anything goes out. Sends are manual. Always.
A recent catch
On the first gated week, the #5-ranked deal arrived with a 14.9% cushion, under the 15% floor. It was demoted to the board, and #6 (cushion 21.5%) took the pick slot. The floor doesn't round.
If a verified fact contradicts the model, the deal goes back through the math, and picks re-rank wherever the corrected numbers land.
Stage 08
Publish. The board, the pages, the record.
The weekly product is the regional board plus a short notification email when it's live. The weekly send itself is retired; past issues stay readable in the archive. The board shows the entire run: picks on top, then every other property we underwrote that week, winners below the cut, losers, and rejections, each with its signed margin and a one-line reason.
Every evaluated property, whatever its verdict, gets a permanent property page carrying the full underwriting at our published defaults, with the index comparison as the reference line. Publication is a record; endorsement is a separate, smaller thing. The picks are the commitment layer, the accountable calls the track record grades. The rest is the database layer, published so you can check us. A rejection's page explains why it lost, with the number that decided it. A surface that showed only winners would be a rendering bug here, and we'd treat it as one.
The board prints its own screening funnel at the top of each region's page: how many listings were screened, how many beat the index at our defaults, how many were rejected. Those are that run's real numbers, computed by the pipeline. The rejection rate is the point.
The rejection list is the product. Rejecting a winner we can't verify buys more trust than shipping it, and a thin week published honestly beats a fat week padded quietly.
What's free and what's paid
The top four picks on each live board are members-only while they hold their rank; a page goes public once its property drops out of the top four. Pick five is free in full every week. The rest of the board, every rejection and its reason, the full history and every property page below the top four: public. Locked rows still show rank, ZIP and the signed margin, the same shape the track record uses.
Run it at your numbers
Every record takes your rent: type what you pay and the verdict re-runs at that number, badged as yours. Members set their tax bracket, horizon and down payment once, and every record they open carries a toggle between the published defaults and their numbers. The published defaults line never moves, because that line is the record. One discipline holds for everyone: cautious rents compute every verdict class, including your personalized one.
For an address we haven't covered, the lookup gives you the parcel's own facts free, and runs the same engine and the same gates on demand for $79 — one San Francisco address, delivered within one business day.
The line in the sand
What we won't do.
- We won't publish a winner whose margin sits inside our own error bars. The 15% cushion floor has no exceptions and no override.
- We won't type an appreciation rate for your neighborhood. We measured our own bands, watched them fail to reproduce, and retired them.
- We won't describe rental demand by who lives somewhere. Occupations, commutes and employers only; a protected-class description fails our build.
- We won't pad a thin week, and we won't promise analysis we haven't done. Some weeks the answer is: don't buy.
You've seen how it's built
Now put it on a building.
Everything we underwrote is public and free to read, winners and rejections alike. What you buy is one address done by hand, or the pass.
One San Francisco address, delivered within one business day. The pass covers every region and cancels any time.