LIHTC transaction calculator — qualified basis, applicable fraction, 4%/9% credit, 15-year compliance, recapture, and investor IRR
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lihtc_calc-0.1.0.tar.gz.
File metadata
- Download URL: lihtc_calc-0.1.0.tar.gz
- Upload date:
- Size: 15.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3024dd7102382796268d8d20771b93d95ea65d098c0783922470623238a8423
|
|
| MD5 |
81fa8eee3d5082300421d6573182651c
|
|
| BLAKE2b-256 |
0b71a947e985cd6e48fe00575a2b5d4828a70473759cee8928e8cd3b86f9843f
|
File details
Details for the file lihtc_calc-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lihtc_calc-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d4e99f0f80a23e23457443344a119fed14f401d06a214bf38e0f7f5b8473084
|
|
| MD5 |
9c02c518fd1960458d8d564c3a93385b
|
|
| BLAKE2b-256 |
57d5d05a94161739c329c65cfdd1cd031ef59cd9b28e11c06a54d59f8811778a
|