Skip to content

Add county-level HUD utility allowance schedules for Texas and Kansas#8819

Open
hua7450 wants to merge 2 commits into
PolicyEngine:mainfrom
hua7450:hud-utility-allowance-county
Open

Add county-level HUD utility allowance schedules for Texas and Kansas#8819
hua7450 wants to merge 2 commits into
PolicyEngine:mainfrom
hua7450:hud-utility-allowance-county

Conversation

@hua7450

@hua7450 hua7450 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

hud_utility_allowance previously hardcoded a Los Angeles County-only table inside the formula and returned $0 for every other county, even when tenant_pays_utilities was true. Since hud_gross_rent = pre_subsidy_rent + hud_utility_allowance feeds hud_hap, this understated the Housing Choice Voucher subsidy whenever rent (not the payment standard) was the binding constraint.

This PR moves the schedules into a parameter CSV keyed by county FIPS × bedroom count × effective year (mirroring the parameters/gov/hud/fmr/ loader pattern) and adds Texas and Kansas county-level schedules.

Addresses the utility allowance portion of #8784.

Coverage

Geography Source Effective Bedrooms
Los Angeles County, CA (06037) LACDA schedule (values previously hardcoded) 2023-07-01 SRO, 0–8
Los Angeles County, CA (06037) LACDA FY2025 schedule 2025-07-01 SRO, 0–8
28 TX counties (TDHCA HCV service area) TDHCA utility allowances 2026-01-01 0–5
Sedgwick County, KS (Wichita HA) 2025 schedule 2025-07-01 0–6
Shawnee County, KS (Topeka HA) 2025 schedule 2025 0–7
Wyandotte County, KS (KCKHA) 2026 schedule 2026 0–5
Johnson County, KS (Johnson County HA) 2026 schedule 2026-03-01 0–5

All other counties return $0 (documented limitation, unchanged from prior behavior).

Methodology (documented in README, loader, and variable)

Each PHA's HUD-52667 schedule is collapsed to one monthly value per bedroom size using a single convention, matching how LA County was originally modeled:

Multi-Family (apartment) unit type + all-electric heating/cooking/water heating + sum of every tenant-paid line item (other electric, air conditioning, water, sewer, trash, electric service charge, range, refrigerator). Gas rows, gas service charges, and heat-pump rows excluded.

Other rules:

  • Effective year: the latest schedule at or before the simulated year applies; years before a county's first schedule use its earliest schedule (same fall-forward semantics as the FMR loader).
  • SRO units: published SRO row where one exists (LA County); otherwise 75% of the zero-bedroom value per 24 CFR 982.604(b).
  • Bedrooms above a schedule's top size reuse the top value.

⚠️ Input-shape change (API consumers)

The formula now keys on county_fips instead of in_la. Payloads that set only in_la: true (without county_fips: "06037") will get a $0 utility allowance. Partner will be notified. Partner contract tests are unaffected (their rent is an input, which cuts the affected chain, and no asserted output consumes housing_assistance).

Verification

  • All 168 TX values (28 counties × 6 bedrooms) independently re-derived from the TDHCA PDF with a separately written parser — 0 mismatches; all 28 county→FIPS mappings verified against census FIPS.
  • All 4 KS schedules re-derived from the PHA PDFs — exact match.
  • LA 2023 vintage exactly equals the previously hardcoded table; LA 2025 values verified against a 600-DPI render of the (image-based) LACDA PDF.
  • Multi-agent review: 13 findings, all addressed (references restored, SRO rule implemented, test coverage added, programs.yaml updated).

Files

parameters/gov/hud/utility_allowance/   # CSV + loader + README (new)
variables/gov/hud/hud_utility_allowance.py
tests/policy/baseline/gov/hud/hud_utility_allowance.yaml
tests/policy/baseline/gov/hud/integration.yaml
programs.yaml

Test plan

  • 18 unit test cases: both LA vintages + fallback year, TX (incl. pre-2026 fallback), all 4 KS counties, SRO published row + SRO 75% rule, bedroom capping, unencoded county, tenant-does-not-pay-utilities
  • Integration case: non-LA county with tenant_pays_utilities: true flowing into hud_gross_rent (this exact combination previously had zero test coverage)
  • CI passes

🤖 Generated with Claude Code

hua7450 and others added 2 commits July 1, 2026 16:12
Move the utility allowance schedules from a hardcoded LA-only table in
the formula into a parameter CSV keyed by county FIPS, bedroom count,
and effective year, mirroring the fmr/ loader pattern. Adds the 28
Texas counties in the TDHCA HCV service area (2026 schedule) and four
Kansas PHAs (Wichita/Sedgwick, Topeka/Shawnee, KCKHA/Wyandotte, and
Johnson County), and updates LA County to the LACDA FY2025 schedule
while preserving the 2023-vintage values.

Each schedule is collapsed to one monthly value per bedroom size using
a documented convention: Multi-Family (apartment) unit type, all-
electric heating/cooking/water heating, summing every tenant-paid line
item. SRO units use the published SRO row where one exists (LA),
otherwise 75% of the zero-bedroom value per 24 CFR 982.604(b).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (c20b1ba) to head (9b7b4c3).
⚠️ Report is 19 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #8819   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            1         1           
  Lines           18        21    +3     
=========================================
+ Hits            18        21    +3     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@hua7450 hua7450 marked this pull request as ready for review July 1, 2026 20:27
@hua7450 hua7450 requested a review from PavelMakarchuk July 1, 2026 20:56

@PavelMakarchuk PavelMakarchuk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: County-level HUD utility allowance schedules (TX/KS)

Strong PR — SRO rule correct, LA backward-compat byte-for-byte, data spot-checks match, and good test coverage. Requesting changes on a few items; the first is a genuine microsim regression risk, the rest are verification/hardening.

Verified correct

  • SRO = 75% of 0BR matches 24 CFR 982.604(b) exactly; published SRO rows take precedence (LA's real 179/194 used, not the 0.75× approximation).
  • LA backward-compat is byte-for-byte — all 10 values for 06037/2023 reproduce the old hardcoded table; the old default=719 (bedrooms ≥8) is preserved via np.clip(...,0,8).
  • Data spot-checks pass: Wichita KS 2025 (0/1/2BR = 210/224/266) exact against source; schema clean (33 counties = 1 CA + 28 TX + 4 KS, SRO as bedrooms=-1, no duplicate merge keys).
  • Merge is order/length-safe; unset/unmatched county_fips → $0 (no NaN/crash); tenant_pays_utilities gate preserved; fall-forward year + bedroom capping vectorized and tested.

Requested changes

  1. LA detection is inconsistent across two HUD variables (please verify in microsim). hud_utility_allowance.py:46 keys LA off county_fips == "06037", but pha_payment_standard.py:19,37 still keys LA off in_la. If the dataset stores county for LA households without county_fips, they'd get the LA payment standard but a $0 utility allowance — a silent regression. Likely safe (in the non-dataset path in_la derives from county_fips, and FMR already relies on it), but please confirm on enhanced_cps or single-source the LA detection.
  2. TX 2026 values are unverified against a source. The fetchable TDHCA schedule is the 2024 vintage (e.g. Atascosa 201/217/257); the CSV's 2026 values (206/222/265) are genuinely newer but unconfirmed — please attach/link the 2026 TDHCA schedule. Also KS counties are split across years (Sedgwick/Shawnee 2025, Johnson/Wyandotte 2026); confirm each PHA's effective date.
  3. Partner input-shape change (in_lacounty_fips): legacy in_la:true payloads without county_fips now silently return $0. Graceful (no crash) and documented in the PR body — just confirm the API partner has been notified.
  4. Hardcoded 0.75 SRO factor (__init__.py:43) is a statutory value (24 CFR 982.604(b)) invisible to the reform/parameter system — prefer a YAML parameter applied post-lookup in the formula (FMR has the same 0.15 precedent, so not a hard blocker).
  5. Add validate="many_to_one" to the schedule merge (hud_utility_allowance.py:63) — safe today (keys are structurally unique) but fails loudly if a future CSV ever duplicates a key.
  6. Test gaps: the non-LA tenant_pays_utilities:true integration case stops at hud_gross_rent and never asserts hud_hap — that flow-through is the regression this PR is meant to guard, so please assert hud_hap too. And add an unset-county_fips (microsim household) → $0 case.

Suggestions

  • The loader's nearest-year logic (_effective_year_by_county) duplicates the FMR loader's "latest ≤ target, else earliest" concept a second way — consider a shared helper.
  • Variable uses a documentation field where reference is preferred (methodology already in README).
  • One agent saw reverse version-file diffs (CHANGELOG.md/pyproject.toml); the GitHub file list looks clean, so likely a merge-commit artifact — worth a glance to be sure.

🤖 Reviewed with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants