CLIMA Score Methodology

How We Calculate Climate Risk for Mortgage Underwriting

Download This Document

Save as PDF to share with investors and stakeholders

Back to CLIMA Demo

Overall Formula

Final CLIMA Score = (Factor_A × 0.30) +
(Factor_B × 0.20) +
(Factor_C × 0.20) +
(Factor_D × 0.15) +
(Factor_E × 0.15)

Key Principle: Higher score = Safer (lower climate risk). All scores normalized to 0-10 scale.

Factor A: Climate Risk Progression 30% Weight

The most important factor - combines historical disaster frequency with future climate projections.

Historical Component (15% of Factor A)

Analyzes 20-year disaster trends using FEMA disaster declarations:

# 20-year disaster trend analysis disaster_count_last_20y = count_disasters_in_last_20_years(county_fips) disaster_count_prior_20y = count_disasters_in_prior_20_years(county_fips) # Calculate trend ratio (ratio of 1.0 = no change) trend = (disaster_count_last_20y + 1) / (disaster_count_prior_20y + 1) # Scale trend to 0-10 (higher trend = lower score = more risk) A_hist = max(0, min(10, 10 - ((trend - 0.5) / (3.0 - 0.5)) * 10))

Projected Component (85% of Factor A)

Uses real climate projections from NOAA/NASA for 2050 using SSP2-4.5 and SSP5-8.5 scenarios:

Peril Type Weight Data Source Projection
Flood Risk 40% NOAA Sea Level Rise % land area at risk of inundation
Wildfire Risk 30% USFS Wildfire Hazard Potential WHP index change 2020–2050
Heat Risk 20% NASA NEX-GDDP Days ≥95°F temperature change
Wind/Hurricane 10% NOAA Climate Models Category 3+ hurricane frequency
# Get climate projection deltas for 4 perils deltas = get_all_projection_deltas(county_fips, scenario="SSP2-4.5") # Convert each peril delta to 0-10 score # delta range: [-1, +1] where +1 = large increase in risk for peril, delta in deltas.items(): peril_score = max(0, min(10, 5 - (delta * 5))) # Weighted average across all perils A_proj = weighted_average(peril_scores, peril_weights)
Why 15% Historical / 85% Projected? Mortgages are 30-year commitments. Climate change is accelerating, making future projections more relevant than historical patterns.

Factor B: Relief Allocations per Capita 20% Weight

Measures how much federal disaster aid the area receives - proxy for underlying risk level.

# Get FEMA Public Assistance data (20 years) pa_total = get_public_assistance_funding(county_fips, years_back=20) # Calculate per capita assistance per_capita = pa_total / 100000 # Assumes ~100K county population # Scale to 0-10 (more aid = higher underlying risk = lower score) B_score = min(per_capita / 1000, 10) # $1000 per capita = maximum score

Logic: Areas receiving more federal disaster aid typically face higher underlying risk or have weaker local resilience.

Factor C: Municipal Fiscal Stress 20% Weight

Measures local government's ability to respond to disasters using multiple data sources:

Component Weight in Factor C Data Source Scoring Method
Unemployment 50% BLS Local Area Unemployment Statistics 3-year average, bracket scoring (≤3% = 10.0, ≤4% = 8.5, etc.)
Bond Market Health 25% FRED Municipal Bond Spreads State-level municipal bond yield spread vs. Treasury
Government Finances 25% Census Government Finances County debt-to-revenue ratio
# Calculate composite fiscal stress score unemp_score = bracket_score(unemployment_3yr_avg) # 1.0-10.0 based on brackets bond_score = percentile_scale(municipal_spread, invert=True) gov_score = percentile_scale(debt_ratio, invert=True) # Weighted average C_score = (unemp_score × 0.50) + (bond_score × 0.25) + (gov_score × 0.25)

Factor D: Personal Finance Resilience 15% Weight

Measures household ability to weather disasters using Census ACS 5-year data:

# Get Census ACS 5-year data income = get_median_household_income(county_fips) # e.g., $65,000 home_value = get_median_home_value(county_fips) # e.g., $350,000 housing_burden = get_housing_cost_burden(county_fips) # e.g., 28% # Calculate Value-to-Income ratio (mortgage affordability) vti_ratio = home_value / (income × 1.0) # Scale each component to 0-10 income_score = min(10, max(0, (income - 30000) / 50000 * 10)) vti_score = max(0, min(10, 10 - (vti_ratio - 2) / 3 * 10)) burden_score = max(0, min(10, 10 - housing_burden / 5)) # Weighted average (higher income, lower VTI, lower burden = better) D_score = (income_score × 0.4) + (vti_score × 0.3) + (burden_score × 0.3)

Components:

Factor E: Insurance Availability 15% Weight

Measures insurance market functionality using NFIP (National Flood Insurance Program) data:

# Get NFIP data for the county policies_per_unit = get_nfip_policies_per_housing_unit(county_fips) avg_premium = get_nfip_average_premium(county_fips) claim_frequency = get_nfip_claims_per_policy_year(county_fips) # Scale each component coverage_score = percentile_scale(policies_per_unit, invert=False) # Higher = better premium_score = percentile_scale(avg_premium, invert=True) # Lower = better claims_score = percentile_scale(claim_frequency, invert=True) # Lower = better # Simple average of available metrics E_score = (coverage_score + premium_score + claims_score) / 3

Metrics:

Score Normalization & Scaling

All individual scores are normalized to 0-10 scale using percentile scaling:

def percentile_scale(value, invert=False, fallback_min=None, fallback_max=None): """ Scale any value to 0-10 range Args: value: Raw value to scale invert: If True, return 10 - scaled_value (for risk metrics) fallback_min/max: Baseline ranges for scaling """ # Use fallback ranges or determine from value magnitude min_val, max_val = determine_scaling_range(value) # Linear scaling to 0-10 scaled = max(0, min(10, (value - min_val) / (max_val - min_val) * 10)) # Invert if needed (for risk factors where higher = worse) if invert: scaled = 10 - scaled return scaled
Inversion Logic: For risk factors (like disaster frequency), higher values = worse outcomes = lower scores. The system automatically inverts these scales.

Score Interpretation

Score Range Grade Risk Level Description
9.0-10.0 A+ Minimal Risk Excellent climate resilience
7.0-8.9 A Low Risk Low climate-linked mortgage risk
5.0-6.9 B Moderate Risk Standard underwriting appropriate
3.0-4.9 C Elevated Risk Consider pricing adjustments
0.0-2.9 D/F High Risk Very high risk - consider declining

Configuration & Weights

All weights and parameters are configurable in config.yaml:

scoring: weights: climate_risk: 0.30 # Factor A: Climate Risk Progression relief_allocations: 0.20 # Factor B: Relief Allocation Efficiency fiscal_stress: 0.20 # Factor C: Municipal Fiscal Stress personal_finance: 0.15 # Factor D: Personal Finance Resilience insurance_coverage: 0.15 # Factor E: Insurance Availability factorA: historical_weight: 0.15 # Historical disasters (15%) projected_weight: 0.85 # Climate projections (85%) peril_weights: flood: 0.40 # Flood risk weight wildfire: 0.30 # Wildfire risk weight heat: 0.20 # Heat risk weight wind: 0.10 # Wind/Hurricane risk weight

Key Design Principles

Ready to See CLIMA in Action?

Try the live demo with any ZIP code

Live CLIMA Demo

About CLIMA: CLIMA (Climate-Linked Infrastructure & Mortgage Analytics) is an enterprise-grade climate risk scoring system for mortgage underwriting. Validated on 145,452 observations and 30,131 disaster county-years with 0.841 default prediction AUC and 0.904 disaster prediction AUC, both exceeding industry standard (0.80).

Documentation: Complete methodology, validation reports, and source code are publicly available for regulatory compliance and independent verification.