mortgagetape

‹ All scoring models

Scoring Models · ZIP Product Mix predictor (NEW)

Category: ZIP / Market Estimation

What it does

Multi-stage classifier estimating the expected mortgage-product distribution — Conventional / FHA / VA / USDA / Jumbo / Non-QM — for a given ZIP code and optional borrower profile. Trained on HMDA 2022-2025 first-lien originations (17.5M loans; 4-class agency multinomial HGB + per-class isotonic), Non-QM binary side-model on Optimal Blue locks (4.04M rows over 24 months), Jumbo pre-model rule using the FHFA 1-unit conforming limit for the activity year. Blend at inference: Jumbo rule fires first (100% Jumbo if loan_amount exceeds the county-year limit); else the agency model returns {Conv, FHA, VA, USDA} probabilities and a slice of P(Conv) is reallocated to Non-QM via the side-model. Test performance: agency top-1 accuracy 77.9% vs 70% base-rate (+8pp lift); Non-QM AUC 0.975 with all OB features / 0.865 on HMDA-only feature ablation. ZIP coverage: ~20,400 ZCTAs (~50% of the ~42K USPS ZIP universe).

Why it matters. Two questions this answers well: (1) Where is my originator footprint pulling from? Given a set of target ZIPs, model the expected agency mix to size up investor pipelines, wholesale capacity, and MI vendor arrangements ahead of season. (2) What's the typical borrower here? A ZIP with 60% FHA vs 60% Jumbo vs 60% Non-QM implies very different LO scripts, appraisal expectations, and secondary-market execution.

What it is NOT. PROHIBITED for individual borrower product-routing ("this borrower should get FHA vs Conv"). Traditional argmax and mean-probability AIR FAIL on the FHA / VA / USDA classes because the underlying US market has real 3-4× race-based product-usage differentials that the model faithfully reflects. But the model also does NOT amplify those differentials — the amplification test shows regression to the mean (Black-race actual FHA 33.8% → predicted mean P(FHA) 27.15%, a −6.65pp attenuation). And the Conv-feasible steering test PASSES: for borrowers with a moderate-DTI + moderate-income primary-residence profile, Conv AIR is 0.95+ across race, ethnicity, and sex — the model does not steer eligible borrowers away from Conv. This is why the model is approved for market-share estimation / capacity planning / product-mix reporting and prohibited for routing / recommendation / anything that would push a specific borrower into a higher-cost product. See the fair-lending audit JSON in the model artifact for the full three-audit read-out (direct AIR, redlining shape on tract minority percent deciles, adverse-selection on Conv-feasible profiles).

Universe note. Only scores ZCTAs that appear in HMDA 2022-2025 with at least one origination. Uncovered ZIPs (rural / unincorporated / recently-created) return a 400 — try a nearby ZIP. The ZIP-to-tract crosswalk is Census 2020 ZCTA-to-Tract relationship file (public, area-share weighted), not HUD USPS (which needs authenticated download). Non-QM label uses OB loan_type='NonConforming' AND total_loan_amount ≤ conforming_limit — strips jumbo out of the positive class so the side-model isolates true Non-QM / portfolio behavior rather than mixing Jumbo signal.

› Try it on the home page (Loan-level model scoring → ZIP Product Mix)

API connector

Programmatic access. Calibrated probability + risk band + operating recommendation in the response.

POST /api/score_zip_product
Content-Type: application/json

{
  "zip_code":         "94103",        // REQUIRED (5-digit US ZIP)
  "loan_amount":      500000,         // optional; triggers Jumbo rule vs conforming limit
  "loan_purpose":     "1",            // optional: 1=purchase, 31=refi, 32=cash-out, 4=other
  "occupancy_type":   "1",            // optional: 1=primary, 2=second home, 3=investment
  "dti_band":         "36%-<43%",     // optional: 20-30 / 30-36 / 36-43 / 43-50 / 50-60
  "income_thousands": 120,            // optional
  "loan_term_months": 360,            // optional
  "applicant_age":    "35-44",        // optional: 25-34 / 35-44 / 45-54 / 55-64 / 65+
  "total_units":      "1",            // optional: 1 / 2 / 3 / 4
  "activity_year":    2025            // optional: defaults to current year
}

Response shape: zip_code, state, msa_code, activity_year_used, conforming_limit_1u_used, jumbo_rule_triggered (bool), p_nonqm_sidemodel (float or null), product_distribution (dict of 6 classes each with label + probability), top_product, top_product_probability, and usage_verdict (fair-lending posture with approved + prohibited use case lists). Chat responses include the mix as a sorted table and surface the fair-lending posture inline — do not strip it.

Schema reference (request / response shape): GET /api/score_zip_product/schema

Model metadata (training cohort, AUC, calibration): GET /api/score_zip_product/info

See also: How to read these AUC numbers.