Skip to main content

lihtc-calc

PyPI version Python 3.9+ License: MIT

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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lihtc_calc-0.1.0.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lihtc_calc-0.1.0-py3-none-any.whl (14.3 kB view details)

Uploaded Python 3

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

Hashes for lihtc_calc-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f3024dd7102382796268d8d20771b93d95ea65d098c0783922470623238a8423
MD5 81fa8eee3d5082300421d6573182651c
BLAKE2b-256 0b71a947e985cd6e48fe00575a2b5d4828a70473759cee8928e8cd3b86f9843f

See more details on using hashes here.

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

Hashes for lihtc_calc-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0d4e99f0f80a23e23457443344a119fed14f401d06a214bf38e0f7f5b8473084
MD5 9c02c518fd1960458d8d564c3a93385b
BLAKE2b-256 57d5d05a94161739c329c65cfdd1cd031ef59cd9b28e11c06a54d59f8811778a

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page