lihtc-calc
Professional-grade Low-Income Housing Tax Credit (LIHTC) calculator for Python.
Model LIHTC transactions end-to-end: eligible and qualified basis, QCT/DDA 30% boost, 4% vs 9% applicable percentage, 10-year credit delivery, investor IRR, 15-year compliance tracking, and IRC §42(j) recapture math — all with type hints and structured result objects.
Why lihtc-calc?
LIHTC is the primary federal subsidy for affordable housing in the United States, allocating ~$10 billion in annual tax credits. Transactions involve layers of IRC §42 math that are easy to mis-model in spreadsheets. lihtc-calc provides auditable, tested Python functions that match IRS and state-agency conventions.
Installation
pip install lihtc-calc
No external dependencies — pure Python 3.9+.
Quickstart
from datetime import date
from lihtccalc import (
LIHTCDeal,
build_credit_result,
ComplianceTracker,
recapture_amount,
investor_irr,
build_investor_cash_flows,
gp_lp_split,
)
# Define a 9% new-construction deal in a QCT
deal = LIHTCDeal(
project_name="Riverside Commons",
total_dev_cost=12_000_000,
eligible_basis_adjustment=0.82, # 82% of TDC is eligible basis
applicable_fraction_units=0.95,
applicable_fraction_floor_area=0.93, # floor-area fraction is binding
credit_type="9pct",
placed_in_service_date=date(2024, 3, 1),
qct_or_dda=True, # 130% basis boost applied
low_income_set_aside_pct=0.40,
total_units=80,
low_income_units=76,
)
# Credit summary
result = build_credit_result(deal)
print(result.summary())
# === LIHTC Credit Summary: Riverside Commons ===
# Credit type : 9pct
# QCT/DDA boost : Yes (130%)
# Eligible basis : $9,840,000
# Boosted basis : $12,792,000
# Applicable fraction : 93.00%
# Qualified basis : $11,896,560
# Annual credit : $1,070,690
# 10-year credits : $10,706,904
# Investor IRR
annual = result.annual_credit
equity = result.total_credits_10yr * 0.95 # 95-cent credit price
flows = build_investor_cash_flows(equity, annual, residual_value=100_000)
irr = investor_irr(flows)
print(f"Investor IRR: {irr:.2%}")
# GP/LP equity split (standard 99.99% LP structure)
gp, lp = gp_lp_split(equity)
print(f"LP equity: ${lp:,.0f} | GP equity: ${gp:,.0f}")
# 15-year compliance tracking
tracker = ComplianceTracker(deal=deal)
for yr in range(1, 6):
cy = tracker.track_year(yr, low_income_units=76, total_units=80)
print(tracker.summary())
# Recapture if compliance breaks in year 5
event = recapture_amount(deal, violation_year=5)
print(event.summary())
Key Features
| Feature | Detail |
|---|---|
| Basis math | Eligible basis, QCT/DDA 130% boost, qualified basis via lower of unit/floor-area fraction |
| 4% vs 9% credit | Fixed applicable percentages (3.64% / 9.00%) matching IRS 2024 guidance |
| 10-year delivery | Level annual credit schedule, summed total credits |
| Equity modeling | Credit-price-to-equity, 99.99% LP / 0.01% GP split |
| Investor IRR | Newton-Raphson IRR with arbitrary cash-flow vectors |
| Compliance tracker | Year-by-year set-aside and AMI verification over 15-year period |
| Recapture (IRC §42(j)) | Declining recapture schedule, interest penalty, bond-disposition analysis |
| Result objects | CreditResult, RecaptureEvent with .summary() methods |
Use Cases
- Syndicators & investors — Quickly model credit delivery and investor return sensitivity.
- Developers & consultants — Validate qualified basis before submitting state tax credit applications.
- Compliance officers — Track annual set-aside and AMI tests; flag violation years automatically.
- Asset managers — Model recapture exposure for portfolio risk reporting.
- Policy researchers — Batch-analyze LIHTC economics across geographies and deal types.
API Reference
Core Functions
eligible_basis(deal) # total_dev_cost × adjustment factor
applicable_fraction(deal) # min(unit_fraction, floor_area_fraction)
boosted_basis(deal) # eligible_basis × 1.30 if QCT/DDA
qualified_basis(deal) # boosted_basis × applicable_fraction
annual_credit(deal) # qualified_basis × applicable_percentage
total_credits_10yr(deal) # annual_credit × 10
credit_price_to_equity(deal, price)
build_credit_result(deal) # → CreditResult with .summary()
investor_irr(cash_flows) # Newton-Raphson IRR
gp_lp_split(equity, lp_pct) # → (gp_equity, lp_equity)
build_investor_cash_flows(equity, annual_credit, residual_value)
ComplianceTracker(deal)
.track_year(year, low_income_units)
.set_aside_compliance(year)
.ami_verification(household_income, ami, limit_pct)
.any_violation()
.violation_years()
.summary()
recapture_amount(deal, violation_year) # → RecaptureEvent
accelerated_credits(deal) # 15-year at-risk schedule
bond_disposition(deal, disposition_year) # § 42(j)(6) analysis
License
MIT © Jay Patel
Metadata
Release files for lihtc-calc 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lihtc_calc-0.1.0.tar.gz | 15.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lihtc_calc-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.9 kB
Release files / lihtc_calc-0.1.0.tar.gz
| Download URL | lihtc_calc-0.1.0.tar.gz |
|---|---|
| Size | 15.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f3024dd7102382796268d8d20771b93d95ea65d098c0783922470623238a8423
|
|
BLAKE2b-256 checksum How to use checksums |
0b71a947e985cd6e48fe00575a2b5d4828a70473759cee8928e8cd3b86f9843f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.12
|
Release files / lihtc_calc-0.1.0-py3-none-any.whl
| Download URL | lihtc_calc-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0d4e99f0f80a23e23457443344a119fed14f401d06a214bf38e0f7f5b8473084
|
|
BLAKE2b-256 checksum How to use checksums |
57d5d05a94161739c329c65cfdd1cd031ef59cd9b28e11c06a54d59f8811778a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.12
|