← Back to Investor Market Scorecard

How the Investor Market Scorecard works

Every score, weight, data source, and limitation — documented. If you disagree with a methodology decision, you'll find the exact reasoning below. This page updates with every revision to the scoring logic.

Current data: 2026-04-30  ·  894 metros scored  ·  8316 ZIPs scored

1. The Three Scores

Each market receives three scores on a 0–100 scale, where 100 = best in universe and 0 = worst in universe. Scores are computed as weighted percentile ranks across the universe of qualifying markets. They are not absolute measures — a score of 75 means "this market ranks in the 75th percentile for this dimension across all scored markets."

Cash Flow Score

Measures how well a market generates rental income relative to purchase price, weighted by evidence of active tenant demand. A high-yield market where homes sit unsold for 120+ days scores lower than a slightly lower-yield market where homes move in 20 days — because the latter is evidence that tenants and buyers are competing for the same space.

Components: Gross rent yield (60%) + Days to Pending inverse (40%).

Growth Score

Measures the appreciation trajectory of a market: where values have been and where Zillow's model expects them to go. A third leg — rent growth — cross-validates whether household demand supports the price trajectory.

Components: ZHVI 1-year change (40%) + ZHVF 12-month forecast (40%) + ZORI 1-year rent change (20%).

Stability Score

Measures how balanced and predictable a market is. An extremely hot market (homes selling in 5 days over ask) and an extremely cold market (homes sitting 200+ days) both score lower than a moderate market — because stability means predictable conditions, not maximum speed.

Components: Market Temperature Index (50%) + Absorption rate (25%) + Days to Pending bell curve (25%).

2. Components and Weights

Cash Flow Score — detail

ComponentSourceWeightNotes
Gross rent yield annual_rent / zhvi × 100 from mv_buy_vs_rent_ratio (metro) or fact_rentals + mv_zip_home_values (ZIP) 60% Percentile rank across universe. Null if no ZORI data.
Days to Pending (inverse) mean_days_to_pending from mv_metro_market_snapshot 40% Lower DTP → higher score. Proxy for tenant demand and resale liquidity.
Why 60/40? Yield is the headline number investors care about, but yield without demand evidence is the yield-trap pattern. Days to Pending captures whether the market actually transacts — if homes sit unsold, rentals likely sit unrented.

Growth Score — detail

ComponentSourceWeightNotes
ZHVI 1-year change zhvi_yoy_pct from mv_metro_market_snapshot 40% Direct evidence of recent appreciation.
ZHVF 12-month forecast zhvf_growth_rate from mv_metro_market_snapshot 40% Forward-looking signal from Zillow's forecast model.
ZORI 1-year change zori_yoy_pct from mv_metro_market_snapshot 20% Rent growth confirms household demand. If unavailable, the other two components are re-weighted to 50/50.
Why not 50/50 historical/forward? That would over-weight Zillow's forecast, which carries its own model risk. Adding ZORI trend as a third leg cross-validates with actual rental market behavior rather than depending entirely on Zillow's appreciation model.

Stability Score — detail

ComponentSourceWeightNotes
Market Temperature Index market_temp_index from mv_metro_market_snapshot 50% Zillow's composite heat index — already aggregates multiple stability inputs.
Absorption rate absorption_rate from mv_metro_market_snapshot 25% Higher absorption = healthier balance of supply and demand.
Days to Pending (bell curve) mean_days_to_pending 25% Peaks at ~45 days. Markets too fast (<10) or too slow (>90) score lower than moderate-speed markets. Formula: MAX(0, 100 − |dtp − 45| × 1.5).
Why is DTP bell-curved in Stability but inverted in Cash Flow? In Cash Flow, fast movement means tenants are competing — always a positive signal. In Stability, extreme speed (bidding wars, no inspection contingencies) and extreme slowness (oversupply, stagnation) are both instability indicators. Moderate transaction speed is the stable condition.

3. The Math

Percentile rank

All components except the DTP bell curve use PostgreSQL window function percentile ranks:

pct_rank(c) = PERCENT_RANK() OVER (ORDER BY raw_value(c)) × 100

For "lower is better" components (Days to Pending in Cash Flow), the rank is inverted:

pct_rank_inv(c) = (1.0 − PERCENT_RANK() OVER (ORDER BY raw_value(c))) × 100

This means the market with the lowest DTP gets a percentile rank of ~100, and the market with the highest DTP gets ~0.

Missing-data re-weighting

When a component is null (e.g., no ZORI YoY data for a metro), the score is computed from the available components, with weights rescaled proportionally:

total_weight_present = SUM(weight(c) for c in components_present)
score(d) = SUM(weight(c) × pct_rank(c) for c in components_present) / total_weight_present

Example: If ZORI YoY is null for a metro, the Growth score is computed from ZHVI YoY (40%) and ZHVF (40%), re-scaled to 50/50.

Qualification rules

A market is excluded from scoring entirely (not just penalized) if:

  • Cash Flow: No ZORI data — cannot compute yield without rent
  • Growth: All three components are null
  • Stability: All three components are null
Why exclusion rather than penalization? A market missing rental data shouldn't receive a low Cash Flow Score (implying "bad cash flow market") — it should receive no score (meaning "we cannot judge"). This is what distinguishes data honesty from a binary trap classifier that penalizes data gaps.

4. Signal Logic and Thresholds

Signals are derived on every query — they are not stored and are recomputed from scores each time. This means methodology revisions don't require database migrations.

SignalConditionsInterpretation
Strong All three scores ≥ 70 AND ZHVI 1-yr > 0 Top-quartile across all three dimensions with positive appreciation.
Clear All three scores ≥ 50 AND ZHVI 1-yr > 0 Above median on all three dimensions with positive appreciation. No obvious red flags.
Watch Cash Flow ≥ 75 AND exactly one of {Growth, Stability} < 40 High yield, but one dimension is below average. Investigate the weak leg before committing.
High Risk Cash Flow ≥ 75 AND (any score < 25 OR ZHVI 1-yr < −3%) Yield trap warning: high yield paired with a serious weakness or active depreciation.
Avoid Cash Flow ≥ 75 AND (≥ 2 scores < 25 OR ZHVI 1-yr < −5%) Classic yield trap pattern: headline yield looks attractive but multiple dimensions signal severe risk.
Neutral All other combinations No dominant signal in either direction. Average market.
Unscored Insufficient data Market does not meet minimum data thresholds. See Coverage section.
Threshold sensitivity: The depreciation thresholds (−3% for High Risk, −5% for Avoid) are judgment calls. A market depreciating at −4% appears in the High Risk band — a more conservative analyst would treat it as Avoid. These thresholds will be reviewed after the first full year of data.

5. Coverage and Limitations

Metro coverage

The scorecard queries all MSAs in mv_metro_market_snapshot. As of 2026-04-30:

  • 894 total MSAs in the snapshot
  • 894 MSAs receive full Cash Flow + Growth + Stability scoring — limited by ZORI YoY coverage
  • The remaining MSAs appear with Stability and partial Growth scoring only, marked "Unscored" on Cash Flow

ZIP coverage

ZIP-level scoring covers only ZIPs with native ZORI rental data. As of the current release:

  • 8316 ZIPs receive full scoring (approximately 29.6% of ~26,297 US ZIPs)
  • ZIPs without ZORI data are not surfaced in the ZIP table — they are not scored and not shown as "Avoid" or "Unscored"
  • Stability components (DTP, Market Temperature, Absorption) are inherited from the parent MSA at the ZIP level — they are not ZIP-native
Why only 29.6% of ZIPs? Zillow's ZORI product covers ZIP codes with sufficient rental transaction volume to produce statistically reliable rent estimates. ZIP codes with thin rental markets — rural areas, industrial zones, very small towns — are excluded by Zillow before they reach our warehouse.

What this tool does NOT measure

  • No vacancy data. Days to Pending and Absorption Rate serve as demand proxies. Actual vacancy rates are not in the warehouse.
  • No population or income trends. Census ACS data is deferred to a future version. ZHVI trend serves as the demand proxy in v1.
  • No neighborhood-level signals. All scores are market-level or ZIP-level. Block or street-level analysis is not possible with this data.
  • No cap rate calculation. Gross yield is not net yield. Operating expenses, vacancy allowance, property management, and financing costs are excluded.
  • No property tax adjustment. High-tax states (e.g., IL, NJ) may show attractive gross yields that erode significantly after taxes.
  • No crime or school data. Out of scope for v1.

6. Data Sources

DatasetSourceRefresh cadenceWarehouse table
Home values (ZHVI) Zillow Research Monthly mv_metro_market_snapshot, mv_zip_home_values
Rental index (ZORI) Zillow Research Monthly mv_metro_market_snapshot, fact_rentals
Home value forecast (ZHVF) Zillow Research Monthly mv_metro_market_snapshot, fact_forecasts
Days to Pending Zillow Research Monthly mv_metro_market_snapshot
Market Temperature Index Zillow Research (composite) Monthly mv_metro_market_snapshot
Absorption Rate Zillow Research Monthly mv_metro_market_snapshot
Buy vs. Rent Ratio Computed from ZHVI + ZORI Monthly (with source data) mv_buy_vs_rent_ratio

Refresh cadence

Scores recompute when materialized views refresh (currently monthly). The Redis cache has a 7-day TTL — worst-case staleness after an MV refresh is 7 days. Cache keys embed the latest observation_date, so a fresh MV refresh produces different cache keys and naturally invalidates prior entries.

7. Changelog

v1.0 — May 2026
Initial release. Metro-level scoring for all MSAs with ZORI coverage. ZIP-level scoring for ~7,780 ZIPs. Three composite dimensions: Cash Flow, Growth, Stability. Five signal tiers: Strong, Clear, Watch, High Risk, Avoid.

← Back to the Scorecard  ·  Report a data issue