mortgage-utils 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.4
2
+ Name: mortgage-utils
3
+ Version: 1.0.0
4
+ Summary: Lightweight Python utility library for mortgage calculations — DTI, amortization, affordability, LTV.
5
+ Author-email: Sanjeev Kumar <contact@ournethelps.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://ournethelps.com
8
+ Project-URL: Repository, https://github.com/sanjeevkumardev/mortgage-utils-py
9
+ Project-URL: Bug Tracker, https://github.com/sanjeevkumardev/mortgage-utils-py/issues
10
+ Keywords: mortgage,calculator,dti,debt-to-income,amortization,affordability,ltv,fintech,real-estate,home-loan,mortgage-broker
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Office/Business :: Financial
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+
25
+ # mortgage-utils
26
+
27
+ > Lightweight Python utility library for mortgage calculations - DTI, amortization, affordability, and LTV.
28
+
29
+ Built by **[OurNetHelps](https://ournethelps.com)** - mortgage tools for US mortgage brokers.
30
+
31
+ ---
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install mortgage-utils
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Features
42
+
43
+ - DTI Calculator - front-end and back-end debt-to-income ratio
44
+ - Amortization - monthly payment and full amortization schedule
45
+ - Affordability - maximum loan amount based on income and debts
46
+ - LTV - loan-to-value ratio with PMI threshold detection
47
+ - Zero dependencies
48
+ - Python 3.8 and above
49
+
50
+ ---
51
+
52
+ ## Usage
53
+
54
+ ### DTI (Debt-to-Income)
55
+
56
+ ```python
57
+ from mortgage_utils import front_end_dti, back_end_dti, dti_report
58
+
59
+ # Front-End DTI
60
+ front = front_end_dti(monthly_housing_cost=1800, gross_monthly_income=7000)
61
+ print(front)
62
+ # {'ratio': 0.2571, 'percentage': 25.71, 'status': 'good', ...}
63
+
64
+ # Back-End DTI
65
+ back = back_end_dti(
66
+ monthly_housing_cost=1800,
67
+ monthly_debts=500,
68
+ gross_monthly_income=7000
69
+ )
70
+ print(back)
71
+ # {'ratio': 0.3286, 'percentage': 32.86, 'status': 'good', ...}
72
+
73
+ # Full DTI Report
74
+ report = dti_report(
75
+ monthly_housing_cost=1800,
76
+ monthly_debts=500,
77
+ gross_monthly_income=7000
78
+ )
79
+ print(report['qualified']) # True
80
+ print(report['summary']) # "Front-End: 25.71% | Back-End: 32.86%"
81
+ ```
82
+
83
+ ### Amortization
84
+
85
+ ```python
86
+ from mortgage_utils import monthly_payment, amortization_schedule
87
+
88
+ # Monthly Payment
89
+ result = monthly_payment(
90
+ loan_amount=300000,
91
+ annual_interest_rate=6.5,
92
+ loan_term_years=30
93
+ )
94
+ print(result['monthly_payment']) # 1896.20
95
+ print(result['total_interest']) # 382632.0
96
+
97
+ # Full Amortization Schedule
98
+ schedule = amortization_schedule(300000, 6.5, 30)
99
+ print(schedule[0])
100
+ # {'month': 1, 'payment': 1896.20, 'principal': 271.2, 'interest': 1625.0, 'balance': 299728.8}
101
+ ```
102
+
103
+ ### Affordability
104
+
105
+ ```python
106
+ from mortgage_utils import max_affordable_loan, loan_to_value
107
+
108
+ # Max Affordable Loan
109
+ result = max_affordable_loan(
110
+ gross_monthly_income=8000,
111
+ monthly_debts=500,
112
+ annual_interest_rate=6.5,
113
+ loan_term_years=30
114
+ )
115
+ print(result['estimated_loan_amount']) # max loan amount
116
+ print(result['max_monthly_payment']) # max monthly payment
117
+
118
+ # LTV Ratio
119
+ ltv = loan_to_value(loan_amount=320000, property_value=400000)
120
+ print(ltv['percentage']) # 80.0
121
+ print(ltv['requires_pmi']) # False
122
+ ```
123
+
124
+ ---
125
+
126
+ ## API Reference
127
+
128
+ ### `front_end_dti(monthly_housing_cost, gross_monthly_income)`
129
+ Returns front-end DTI with status (good / caution / high).
130
+
131
+ ### `back_end_dti(monthly_housing_cost, monthly_debts, gross_monthly_income)`
132
+ Returns back-end DTI including all monthly debts.
133
+
134
+ ### `dti_report(monthly_housing_cost, monthly_debts, gross_monthly_income)`
135
+ Returns full DTI report with qualified boolean and summary.
136
+
137
+ ### `monthly_payment(loan_amount, annual_interest_rate, loan_term_years)`
138
+ Returns monthly P&I payment, total payment, and total interest.
139
+
140
+ ### `amortization_schedule(loan_amount, annual_interest_rate, loan_term_years)`
141
+ Returns list of monthly payment breakdowns.
142
+
143
+ ### `max_affordable_loan(gross_monthly_income, monthly_debts, annual_interest_rate, loan_term_years, max_dti=43.0)`
144
+ Returns max affordable loan amount based on income and DTI threshold.
145
+
146
+ ### `loan_to_value(loan_amount, property_value)`
147
+ Returns LTV ratio, percentage, down payment, and PMI requirement flag.
148
+
149
+ ---
150
+
151
+ ## DTI Status Thresholds
152
+
153
+ | Status | Front-End DTI | Back-End DTI |
154
+ |--------|--------------|--------------|
155
+ | good | 28% or less | 36% or less |
156
+ | caution | 29% to 36% | 37% to 43% |
157
+ | high | Above 36% | Above 43% |
158
+
159
+ ---
160
+
161
+ ## Related
162
+
163
+ - [OurNetHelps](https://ournethelps.com) - mortgage tools for US mortgage brokers
164
+ - [mortgage-utils on NPM](https://www.npmjs.com/package/mortgage-utils) - JavaScript version
165
+ - [Live Mortgage Calculator](https://huggingface.co/spaces/sanjeevkumardev/mortgage-suite)
166
+
167
+ ---
168
+
169
+ ## License
170
+
171
+ MIT © [Sanjeev Kumar](https://ournethelps.com)
@@ -0,0 +1,147 @@
1
+ # mortgage-utils
2
+
3
+ > Lightweight Python utility library for mortgage calculations - DTI, amortization, affordability, and LTV.
4
+
5
+ Built by **[OurNetHelps](https://ournethelps.com)** - mortgage tools for US mortgage brokers.
6
+
7
+ ---
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install mortgage-utils
13
+ ```
14
+
15
+ ---
16
+
17
+ ## Features
18
+
19
+ - DTI Calculator - front-end and back-end debt-to-income ratio
20
+ - Amortization - monthly payment and full amortization schedule
21
+ - Affordability - maximum loan amount based on income and debts
22
+ - LTV - loan-to-value ratio with PMI threshold detection
23
+ - Zero dependencies
24
+ - Python 3.8 and above
25
+
26
+ ---
27
+
28
+ ## Usage
29
+
30
+ ### DTI (Debt-to-Income)
31
+
32
+ ```python
33
+ from mortgage_utils import front_end_dti, back_end_dti, dti_report
34
+
35
+ # Front-End DTI
36
+ front = front_end_dti(monthly_housing_cost=1800, gross_monthly_income=7000)
37
+ print(front)
38
+ # {'ratio': 0.2571, 'percentage': 25.71, 'status': 'good', ...}
39
+
40
+ # Back-End DTI
41
+ back = back_end_dti(
42
+ monthly_housing_cost=1800,
43
+ monthly_debts=500,
44
+ gross_monthly_income=7000
45
+ )
46
+ print(back)
47
+ # {'ratio': 0.3286, 'percentage': 32.86, 'status': 'good', ...}
48
+
49
+ # Full DTI Report
50
+ report = dti_report(
51
+ monthly_housing_cost=1800,
52
+ monthly_debts=500,
53
+ gross_monthly_income=7000
54
+ )
55
+ print(report['qualified']) # True
56
+ print(report['summary']) # "Front-End: 25.71% | Back-End: 32.86%"
57
+ ```
58
+
59
+ ### Amortization
60
+
61
+ ```python
62
+ from mortgage_utils import monthly_payment, amortization_schedule
63
+
64
+ # Monthly Payment
65
+ result = monthly_payment(
66
+ loan_amount=300000,
67
+ annual_interest_rate=6.5,
68
+ loan_term_years=30
69
+ )
70
+ print(result['monthly_payment']) # 1896.20
71
+ print(result['total_interest']) # 382632.0
72
+
73
+ # Full Amortization Schedule
74
+ schedule = amortization_schedule(300000, 6.5, 30)
75
+ print(schedule[0])
76
+ # {'month': 1, 'payment': 1896.20, 'principal': 271.2, 'interest': 1625.0, 'balance': 299728.8}
77
+ ```
78
+
79
+ ### Affordability
80
+
81
+ ```python
82
+ from mortgage_utils import max_affordable_loan, loan_to_value
83
+
84
+ # Max Affordable Loan
85
+ result = max_affordable_loan(
86
+ gross_monthly_income=8000,
87
+ monthly_debts=500,
88
+ annual_interest_rate=6.5,
89
+ loan_term_years=30
90
+ )
91
+ print(result['estimated_loan_amount']) # max loan amount
92
+ print(result['max_monthly_payment']) # max monthly payment
93
+
94
+ # LTV Ratio
95
+ ltv = loan_to_value(loan_amount=320000, property_value=400000)
96
+ print(ltv['percentage']) # 80.0
97
+ print(ltv['requires_pmi']) # False
98
+ ```
99
+
100
+ ---
101
+
102
+ ## API Reference
103
+
104
+ ### `front_end_dti(monthly_housing_cost, gross_monthly_income)`
105
+ Returns front-end DTI with status (good / caution / high).
106
+
107
+ ### `back_end_dti(monthly_housing_cost, monthly_debts, gross_monthly_income)`
108
+ Returns back-end DTI including all monthly debts.
109
+
110
+ ### `dti_report(monthly_housing_cost, monthly_debts, gross_monthly_income)`
111
+ Returns full DTI report with qualified boolean and summary.
112
+
113
+ ### `monthly_payment(loan_amount, annual_interest_rate, loan_term_years)`
114
+ Returns monthly P&I payment, total payment, and total interest.
115
+
116
+ ### `amortization_schedule(loan_amount, annual_interest_rate, loan_term_years)`
117
+ Returns list of monthly payment breakdowns.
118
+
119
+ ### `max_affordable_loan(gross_monthly_income, monthly_debts, annual_interest_rate, loan_term_years, max_dti=43.0)`
120
+ Returns max affordable loan amount based on income and DTI threshold.
121
+
122
+ ### `loan_to_value(loan_amount, property_value)`
123
+ Returns LTV ratio, percentage, down payment, and PMI requirement flag.
124
+
125
+ ---
126
+
127
+ ## DTI Status Thresholds
128
+
129
+ | Status | Front-End DTI | Back-End DTI |
130
+ |--------|--------------|--------------|
131
+ | good | 28% or less | 36% or less |
132
+ | caution | 29% to 36% | 37% to 43% |
133
+ | high | Above 36% | Above 43% |
134
+
135
+ ---
136
+
137
+ ## Related
138
+
139
+ - [OurNetHelps](https://ournethelps.com) - mortgage tools for US mortgage brokers
140
+ - [mortgage-utils on NPM](https://www.npmjs.com/package/mortgage-utils) - JavaScript version
141
+ - [Live Mortgage Calculator](https://huggingface.co/spaces/sanjeevkumardev/mortgage-suite)
142
+
143
+ ---
144
+
145
+ ## License
146
+
147
+ MIT © [Sanjeev Kumar](https://ournethelps.com)
@@ -0,0 +1,30 @@
1
+ """
2
+ mortgage-utils
3
+ --------------
4
+ Lightweight Python utility library for mortgage calculations.
5
+ Built by OurNetHelps: https://ournethelps.com
6
+
7
+ Modules:
8
+ dti: front_end_dti, back_end_dti, dti_report
9
+ amortization: monthly_payment, amortization_schedule
10
+ affordability: max_affordable_loan, loan_to_value
11
+ """
12
+
13
+ from .dti import front_end_dti, back_end_dti, dti_report
14
+ from .amortization import monthly_payment, amortization_schedule
15
+ from .affordability import max_affordable_loan, loan_to_value
16
+
17
+ __version__ = "1.0.0"
18
+ __author__ = "Sanjeev Kumar"
19
+ __email__ = "contact@ournethelps.com"
20
+ __url__ = "https://ournethelps.com"
21
+
22
+ __all__ = [
23
+ "front_end_dti",
24
+ "back_end_dti",
25
+ "dti_report",
26
+ "monthly_payment",
27
+ "amortization_schedule",
28
+ "max_affordable_loan",
29
+ "loan_to_value",
30
+ ]
@@ -0,0 +1,100 @@
1
+ """
2
+ Affordability and LTV Calculations
3
+ ------------------------------------
4
+ Built by OurNetHelps: https://ournethelps.com
5
+ """
6
+
7
+
8
+ def max_affordable_loan(
9
+ gross_monthly_income: float,
10
+ monthly_debts: float,
11
+ annual_interest_rate: float,
12
+ loan_term_years: int,
13
+ max_dti: float = 43.0,
14
+ ) -> dict:
15
+ """
16
+ Calculate maximum affordable loan based on income and debts.
17
+
18
+ Args:
19
+ gross_monthly_income: Borrower's gross monthly income
20
+ monthly_debts: Existing monthly debt obligations
21
+ annual_interest_rate: Annual interest rate (e.g. 6.5 for 6.5%)
22
+ loan_term_years: Loan term in years
23
+ max_dti: Maximum back-end DTI allowed (default 43%)
24
+
25
+ Returns:
26
+ dict with max_monthly_payment, estimated_loan_amount, max_dti_used
27
+
28
+ Raises:
29
+ ValueError: If gross_monthly_income is zero or negative
30
+ """
31
+ if gross_monthly_income <= 0:
32
+ raise ValueError("Gross monthly income must be greater than zero.")
33
+
34
+ max_monthly_debt = (gross_monthly_income * max_dti) / 100
35
+ max_monthly_payment = round(max_monthly_debt - monthly_debts, 2)
36
+
37
+ if max_monthly_payment <= 0:
38
+ return {
39
+ "max_monthly_payment": 0,
40
+ "estimated_loan_amount": 0,
41
+ "max_dti_used": max_dti,
42
+ "message": "Existing debts exceed the maximum DTI threshold.",
43
+ }
44
+
45
+ monthly_rate = annual_interest_rate / 100 / 12
46
+ n = loan_term_years * 12
47
+
48
+ if monthly_rate == 0:
49
+ estimated_loan = max_monthly_payment * n
50
+ else:
51
+ estimated_loan = (
52
+ max_monthly_payment
53
+ * ((1 + monthly_rate) ** n - 1)
54
+ / (monthly_rate * (1 + monthly_rate) ** n)
55
+ )
56
+
57
+ return {
58
+ "max_monthly_payment": max_monthly_payment,
59
+ "estimated_loan_amount": round(estimated_loan, 2),
60
+ "max_dti_used": max_dti,
61
+ "gross_monthly_income": gross_monthly_income,
62
+ "monthly_debts": monthly_debts,
63
+ }
64
+
65
+
66
+ def loan_to_value(loan_amount: float, property_value: float) -> dict:
67
+ """
68
+ Calculate LTV (Loan-to-Value Ratio).
69
+
70
+ Args:
71
+ loan_amount: Total loan amount in dollars
72
+ property_value: Appraised property value in dollars
73
+
74
+ Returns:
75
+ dict with ltv, percentage, requires_pmi, down_payment, status, guideline
76
+
77
+ Raises:
78
+ ValueError: If property_value is zero or negative
79
+ """
80
+ if property_value <= 0:
81
+ raise ValueError("Property value must be greater than zero.")
82
+
83
+ ltv = loan_amount / property_value
84
+ percentage = round(ltv * 100, 2)
85
+
86
+ if percentage <= 80:
87
+ status = "good"
88
+ elif percentage <= 95:
89
+ status = "caution"
90
+ else:
91
+ status = "high"
92
+
93
+ return {
94
+ "ltv": round(ltv, 4),
95
+ "percentage": percentage,
96
+ "requires_pmi": percentage > 80,
97
+ "down_payment": round(property_value - loan_amount, 2),
98
+ "status": status,
99
+ "guideline": "LTV 80% or less avoids PMI requirement",
100
+ }
@@ -0,0 +1,99 @@
1
+ """
2
+ Amortization Calculations
3
+ --------------------------
4
+ Monthly payment and full amortization schedule.
5
+
6
+ Built by OurNetHelps: https://ournethelps.com
7
+ """
8
+
9
+
10
+ def monthly_payment(
11
+ loan_amount: float,
12
+ annual_interest_rate: float,
13
+ loan_term_years: int,
14
+ ) -> dict:
15
+ """
16
+ Calculate monthly mortgage payment (Principal + Interest only).
17
+
18
+ Args:
19
+ loan_amount: Total loan amount in dollars
20
+ annual_interest_rate: Annual interest rate (e.g. 6.5 for 6.5%)
21
+ loan_term_years: Loan term in years (e.g. 30)
22
+
23
+ Returns:
24
+ dict with monthly_payment, total_payment, total_interest,
25
+ loan_amount, annual_interest_rate, loan_term_years
26
+
27
+ Raises:
28
+ ValueError: If loan_amount or loan_term_years is invalid
29
+ """
30
+ if loan_amount <= 0:
31
+ raise ValueError("Loan amount must be greater than zero.")
32
+ if annual_interest_rate < 0:
33
+ raise ValueError("Interest rate cannot be negative.")
34
+ if loan_term_years <= 0:
35
+ raise ValueError("Loan term must be greater than zero.")
36
+
37
+ monthly_rate = annual_interest_rate / 100 / 12
38
+ n = loan_term_years * 12
39
+
40
+ if monthly_rate == 0:
41
+ payment = loan_amount / n
42
+ else:
43
+ payment = (
44
+ loan_amount
45
+ * (monthly_rate * (1 + monthly_rate) ** n)
46
+ / ((1 + monthly_rate) ** n - 1)
47
+ )
48
+
49
+ total_payment = payment * n
50
+ total_interest = total_payment - loan_amount
51
+
52
+ return {
53
+ "monthly_payment": round(payment, 2),
54
+ "total_payment": round(total_payment, 2),
55
+ "total_interest": round(total_interest, 2),
56
+ "loan_amount": loan_amount,
57
+ "annual_interest_rate": annual_interest_rate,
58
+ "loan_term_years": loan_term_years,
59
+ }
60
+
61
+
62
+ def amortization_schedule(
63
+ loan_amount: float,
64
+ annual_interest_rate: float,
65
+ loan_term_years: int,
66
+ ) -> list:
67
+ """
68
+ Generate full amortization schedule.
69
+
70
+ Args:
71
+ loan_amount: Total loan amount in dollars
72
+ annual_interest_rate: Annual interest rate (e.g. 6.5 for 6.5%)
73
+ loan_term_years: Loan term in years
74
+
75
+ Returns:
76
+ List of dicts with month, payment, principal, interest, balance
77
+ """
78
+ result = monthly_payment(loan_amount, annual_interest_rate, loan_term_years)
79
+ payment = result["monthly_payment"]
80
+ monthly_rate = annual_interest_rate / 100 / 12
81
+ n = loan_term_years * 12
82
+
83
+ balance = loan_amount
84
+ schedule = []
85
+
86
+ for month in range(1, n + 1):
87
+ interest_payment = round(balance * monthly_rate, 2)
88
+ principal_payment = round(payment - interest_payment, 2)
89
+ balance = max(0, round(balance - principal_payment, 2))
90
+
91
+ schedule.append({
92
+ "month": month,
93
+ "payment": round(payment, 2),
94
+ "principal": principal_payment,
95
+ "interest": interest_payment,
96
+ "balance": balance,
97
+ })
98
+
99
+ return schedule
@@ -0,0 +1,119 @@
1
+ """
2
+ DTI (Debt-to-Income) Calculations
3
+ ----------------------------------
4
+ Used by mortgage brokers to assess borrower qualification.
5
+ Standard guidelines: Front-end DTI <= 28%, Back-end DTI <= 43%
6
+
7
+ Built by OurNetHelps: https://ournethelps.com
8
+ """
9
+
10
+
11
+ def _get_front_status(pct: float) -> str:
12
+ if pct <= 28:
13
+ return "good"
14
+ elif pct <= 36:
15
+ return "caution"
16
+ return "high"
17
+
18
+
19
+ def _get_back_status(pct: float) -> str:
20
+ if pct <= 36:
21
+ return "good"
22
+ elif pct <= 43:
23
+ return "caution"
24
+ return "high"
25
+
26
+
27
+ def front_end_dti(monthly_housing_cost: float, gross_monthly_income: float) -> dict:
28
+ """
29
+ Calculate Front-End DTI (Housing Ratio).
30
+ Only includes housing-related costs vs gross income.
31
+
32
+ Args:
33
+ monthly_housing_cost: PITI (Principal + Interest + Tax + Insurance)
34
+ gross_monthly_income: Borrower's gross monthly income
35
+
36
+ Returns:
37
+ dict with ratio, percentage, status, label, guideline
38
+
39
+ Raises:
40
+ ValueError: If gross_monthly_income is zero or negative
41
+ """
42
+ if gross_monthly_income <= 0:
43
+ raise ValueError("Gross monthly income must be greater than zero.")
44
+
45
+ ratio = monthly_housing_cost / gross_monthly_income
46
+ percentage = round(ratio * 100, 2)
47
+
48
+ return {
49
+ "ratio": round(ratio, 4),
50
+ "percentage": percentage,
51
+ "status": _get_front_status(percentage),
52
+ "label": "Front-End DTI",
53
+ "guideline": "Recommended: 28% or less",
54
+ }
55
+
56
+
57
+ def back_end_dti(
58
+ monthly_housing_cost: float,
59
+ monthly_debts: float,
60
+ gross_monthly_income: float,
61
+ ) -> dict:
62
+ """
63
+ Calculate Back-End DTI (Total Debt Ratio).
64
+ Includes all monthly debt obligations vs gross income.
65
+
66
+ Args:
67
+ monthly_housing_cost: PITI (Principal + Interest + Tax + Insurance)
68
+ monthly_debts: All other monthly debts (car, student loans, credit cards)
69
+ gross_monthly_income: Borrower's gross monthly income
70
+
71
+ Returns:
72
+ dict with ratio, percentage, total_monthly_debt, status, label, guideline
73
+
74
+ Raises:
75
+ ValueError: If gross_monthly_income is zero or negative
76
+ """
77
+ if gross_monthly_income <= 0:
78
+ raise ValueError("Gross monthly income must be greater than zero.")
79
+
80
+ total_debt = monthly_housing_cost + monthly_debts
81
+ ratio = total_debt / gross_monthly_income
82
+ percentage = round(ratio * 100, 2)
83
+
84
+ return {
85
+ "ratio": round(ratio, 4),
86
+ "percentage": percentage,
87
+ "total_monthly_debt": round(total_debt, 2),
88
+ "status": _get_back_status(percentage),
89
+ "label": "Back-End DTI",
90
+ "guideline": "Recommended: 43% or less (FHA allows up to 50%)",
91
+ }
92
+
93
+
94
+ def dti_report(
95
+ monthly_housing_cost: float,
96
+ monthly_debts: float,
97
+ gross_monthly_income: float,
98
+ ) -> dict:
99
+ """
100
+ Full DTI Report - returns both front-end and back-end DTI.
101
+
102
+ Args:
103
+ monthly_housing_cost: PITI monthly housing cost
104
+ monthly_debts: All other monthly debt obligations
105
+ gross_monthly_income: Borrower's gross monthly income
106
+
107
+ Returns:
108
+ dict with front_end, back_end, qualified, summary
109
+ """
110
+ front = front_end_dti(monthly_housing_cost, gross_monthly_income)
111
+ back = back_end_dti(monthly_housing_cost, monthly_debts, gross_monthly_income)
112
+ qualified = front["status"] != "high" and back["status"] != "high"
113
+
114
+ return {
115
+ "front_end": front,
116
+ "back_end": back,
117
+ "qualified": qualified,
118
+ "summary": f"Front-End: {front['percentage']}% | Back-End: {back['percentage']}%",
119
+ }
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.4
2
+ Name: mortgage-utils
3
+ Version: 1.0.0
4
+ Summary: Lightweight Python utility library for mortgage calculations — DTI, amortization, affordability, LTV.
5
+ Author-email: Sanjeev Kumar <contact@ournethelps.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://ournethelps.com
8
+ Project-URL: Repository, https://github.com/sanjeevkumardev/mortgage-utils-py
9
+ Project-URL: Bug Tracker, https://github.com/sanjeevkumardev/mortgage-utils-py/issues
10
+ Keywords: mortgage,calculator,dti,debt-to-income,amortization,affordability,ltv,fintech,real-estate,home-loan,mortgage-broker
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Office/Business :: Financial
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+
25
+ # mortgage-utils
26
+
27
+ > Lightweight Python utility library for mortgage calculations - DTI, amortization, affordability, and LTV.
28
+
29
+ Built by **[OurNetHelps](https://ournethelps.com)** - mortgage tools for US mortgage brokers.
30
+
31
+ ---
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install mortgage-utils
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Features
42
+
43
+ - DTI Calculator - front-end and back-end debt-to-income ratio
44
+ - Amortization - monthly payment and full amortization schedule
45
+ - Affordability - maximum loan amount based on income and debts
46
+ - LTV - loan-to-value ratio with PMI threshold detection
47
+ - Zero dependencies
48
+ - Python 3.8 and above
49
+
50
+ ---
51
+
52
+ ## Usage
53
+
54
+ ### DTI (Debt-to-Income)
55
+
56
+ ```python
57
+ from mortgage_utils import front_end_dti, back_end_dti, dti_report
58
+
59
+ # Front-End DTI
60
+ front = front_end_dti(monthly_housing_cost=1800, gross_monthly_income=7000)
61
+ print(front)
62
+ # {'ratio': 0.2571, 'percentage': 25.71, 'status': 'good', ...}
63
+
64
+ # Back-End DTI
65
+ back = back_end_dti(
66
+ monthly_housing_cost=1800,
67
+ monthly_debts=500,
68
+ gross_monthly_income=7000
69
+ )
70
+ print(back)
71
+ # {'ratio': 0.3286, 'percentage': 32.86, 'status': 'good', ...}
72
+
73
+ # Full DTI Report
74
+ report = dti_report(
75
+ monthly_housing_cost=1800,
76
+ monthly_debts=500,
77
+ gross_monthly_income=7000
78
+ )
79
+ print(report['qualified']) # True
80
+ print(report['summary']) # "Front-End: 25.71% | Back-End: 32.86%"
81
+ ```
82
+
83
+ ### Amortization
84
+
85
+ ```python
86
+ from mortgage_utils import monthly_payment, amortization_schedule
87
+
88
+ # Monthly Payment
89
+ result = monthly_payment(
90
+ loan_amount=300000,
91
+ annual_interest_rate=6.5,
92
+ loan_term_years=30
93
+ )
94
+ print(result['monthly_payment']) # 1896.20
95
+ print(result['total_interest']) # 382632.0
96
+
97
+ # Full Amortization Schedule
98
+ schedule = amortization_schedule(300000, 6.5, 30)
99
+ print(schedule[0])
100
+ # {'month': 1, 'payment': 1896.20, 'principal': 271.2, 'interest': 1625.0, 'balance': 299728.8}
101
+ ```
102
+
103
+ ### Affordability
104
+
105
+ ```python
106
+ from mortgage_utils import max_affordable_loan, loan_to_value
107
+
108
+ # Max Affordable Loan
109
+ result = max_affordable_loan(
110
+ gross_monthly_income=8000,
111
+ monthly_debts=500,
112
+ annual_interest_rate=6.5,
113
+ loan_term_years=30
114
+ )
115
+ print(result['estimated_loan_amount']) # max loan amount
116
+ print(result['max_monthly_payment']) # max monthly payment
117
+
118
+ # LTV Ratio
119
+ ltv = loan_to_value(loan_amount=320000, property_value=400000)
120
+ print(ltv['percentage']) # 80.0
121
+ print(ltv['requires_pmi']) # False
122
+ ```
123
+
124
+ ---
125
+
126
+ ## API Reference
127
+
128
+ ### `front_end_dti(monthly_housing_cost, gross_monthly_income)`
129
+ Returns front-end DTI with status (good / caution / high).
130
+
131
+ ### `back_end_dti(monthly_housing_cost, monthly_debts, gross_monthly_income)`
132
+ Returns back-end DTI including all monthly debts.
133
+
134
+ ### `dti_report(monthly_housing_cost, monthly_debts, gross_monthly_income)`
135
+ Returns full DTI report with qualified boolean and summary.
136
+
137
+ ### `monthly_payment(loan_amount, annual_interest_rate, loan_term_years)`
138
+ Returns monthly P&I payment, total payment, and total interest.
139
+
140
+ ### `amortization_schedule(loan_amount, annual_interest_rate, loan_term_years)`
141
+ Returns list of monthly payment breakdowns.
142
+
143
+ ### `max_affordable_loan(gross_monthly_income, monthly_debts, annual_interest_rate, loan_term_years, max_dti=43.0)`
144
+ Returns max affordable loan amount based on income and DTI threshold.
145
+
146
+ ### `loan_to_value(loan_amount, property_value)`
147
+ Returns LTV ratio, percentage, down payment, and PMI requirement flag.
148
+
149
+ ---
150
+
151
+ ## DTI Status Thresholds
152
+
153
+ | Status | Front-End DTI | Back-End DTI |
154
+ |--------|--------------|--------------|
155
+ | good | 28% or less | 36% or less |
156
+ | caution | 29% to 36% | 37% to 43% |
157
+ | high | Above 36% | Above 43% |
158
+
159
+ ---
160
+
161
+ ## Related
162
+
163
+ - [OurNetHelps](https://ournethelps.com) - mortgage tools for US mortgage brokers
164
+ - [mortgage-utils on NPM](https://www.npmjs.com/package/mortgage-utils) - JavaScript version
165
+ - [Live Mortgage Calculator](https://huggingface.co/spaces/sanjeevkumardev/mortgage-suite)
166
+
167
+ ---
168
+
169
+ ## License
170
+
171
+ MIT © [Sanjeev Kumar](https://ournethelps.com)
@@ -0,0 +1,11 @@
1
+ README.md
2
+ pyproject.toml
3
+ mortgage_utils/__init__.py
4
+ mortgage_utils/affordability.py
5
+ mortgage_utils/amortization.py
6
+ mortgage_utils/dti.py
7
+ mortgage_utils.egg-info/PKG-INFO
8
+ mortgage_utils.egg-info/SOURCES.txt
9
+ mortgage_utils.egg-info/dependency_links.txt
10
+ mortgage_utils.egg-info/top_level.txt
11
+ tests/test_mortgage_utils.py
@@ -0,0 +1 @@
1
+ mortgage_utils
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "mortgage-utils"
7
+ version = "1.0.0"
8
+ description = "Lightweight Python utility library for mortgage calculations — DTI, amortization, affordability, LTV."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ authors = [
12
+ { name = "Sanjeev Kumar", email = "contact@ournethelps.com" }
13
+ ]
14
+ keywords = [
15
+ "mortgage",
16
+ "calculator",
17
+ "dti",
18
+ "debt-to-income",
19
+ "amortization",
20
+ "affordability",
21
+ "ltv",
22
+ "fintech",
23
+ "real-estate",
24
+ "home-loan",
25
+ "mortgage-broker",
26
+ ]
27
+ classifiers = [
28
+ "Development Status :: 5 - Production/Stable",
29
+ "Intended Audience :: Developers",
30
+ "License :: OSI Approved :: MIT License",
31
+ "Programming Language :: Python :: 3",
32
+ "Programming Language :: Python :: 3.8",
33
+ "Programming Language :: Python :: 3.9",
34
+ "Programming Language :: Python :: 3.10",
35
+ "Programming Language :: Python :: 3.11",
36
+ "Programming Language :: Python :: 3.12",
37
+ "Topic :: Office/Business :: Financial",
38
+ "Topic :: Software Development :: Libraries :: Python Modules",
39
+ ]
40
+ requires-python = ">=3.8"
41
+ dependencies = []
42
+
43
+ [project.urls]
44
+ Homepage = "https://ournethelps.com"
45
+ Repository = "https://github.com/sanjeevkumardev/mortgage-utils-py"
46
+ "Bug Tracker" = "https://github.com/sanjeevkumardev/mortgage-utils-py/issues"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,85 @@
1
+ """
2
+ Tests for mortgage-utils Python package
3
+ Built by OurNetHelps — https://ournethelps.com
4
+ """
5
+ import sys
6
+ sys.path.insert(0, '..')
7
+
8
+ from mortgage_utils import (
9
+ front_end_dti, back_end_dti, dti_report,
10
+ monthly_payment, amortization_schedule,
11
+ max_affordable_loan, loan_to_value,
12
+ )
13
+
14
+ passed = 0
15
+ failed = 0
16
+
17
+ def test(name, condition, expected=None, got=None):
18
+ global passed, failed
19
+ if condition:
20
+ print(f" ✅ {name}")
21
+ passed += 1
22
+ else:
23
+ print(f" ❌ {name} — expected {expected}, got {got}")
24
+ failed += 1
25
+
26
+ print("\n📦 mortgage-utils Python — Test Suite\n")
27
+
28
+ # DTI Tests
29
+ print("🔢 DTI Calculations")
30
+
31
+ r = front_end_dti(1800, 7000)
32
+ test("front_end_dti percentage", r['percentage'] == 25.71, 25.71, r['percentage'])
33
+ test("front_end_dti status good", r['status'] == 'good', 'good', r['status'])
34
+
35
+ r = front_end_dti(2500, 5000)
36
+ test("front_end_dti status high", r['status'] == 'high', 'high', r['status'])
37
+
38
+ r = back_end_dti(1800, 500, 7000)
39
+ test("back_end_dti percentage", r['percentage'] == 32.86, 32.86, r['percentage'])
40
+ test("back_end_dti status good", r['status'] == 'good', 'good', r['status'])
41
+
42
+ r = dti_report(1800, 500, 7000)
43
+ test("dti_report qualified", r['qualified'] == True, True, r['qualified'])
44
+ test("dti_report front_end", r['front_end']['percentage'] == 25.71, 25.71, r['front_end']['percentage'])
45
+ test("dti_report back_end", r['back_end']['percentage'] == 32.86, 32.86, r['back_end']['percentage'])
46
+
47
+ r = dti_report(3000, 1500, 6000)
48
+ test("dti_report not qualified", r['qualified'] == False, False, r['qualified'])
49
+
50
+ # Amortization Tests
51
+ print("\n🏠 Amortization Calculations")
52
+
53
+ r = monthly_payment(300000, 6.5, 30)
54
+ test("monthly_payment amount", r['monthly_payment'] == 1896.20, 1896.20, r['monthly_payment'])
55
+ test("monthly_payment total_interest positive", r['total_interest'] > 0)
56
+
57
+ r = monthly_payment(120000, 0, 10)
58
+ test("monthly_payment zero interest", r['monthly_payment'] == 1000.0, 1000.0, r['monthly_payment'])
59
+
60
+ schedule = amortization_schedule(300000, 6.5, 30)
61
+ test("amortization schedule length", len(schedule) == 360, 360, len(schedule))
62
+ test("amortization first month", schedule[0]['month'] == 1)
63
+ test("amortization balance reduces", schedule[0]['balance'] < 300000)
64
+
65
+ # Affordability Tests
66
+ print("\n💰 Affordability and LTV")
67
+
68
+ r = max_affordable_loan(8000, 500, 6.5, 30)
69
+ test("max_affordable_loan positive", r['estimated_loan_amount'] > 0)
70
+ test("max_affordable_loan payment", r['max_monthly_payment'] == 2940.0, 2940.0, r['max_monthly_payment'])
71
+
72
+ r = max_affordable_loan(5000, 3000, 6.5, 30)
73
+ test("max_affordable_loan debts exceed", r['estimated_loan_amount'] == 0, 0, r['estimated_loan_amount'])
74
+
75
+ r = loan_to_value(320000, 400000)
76
+ test("ltv percentage", r['percentage'] == 80.0, 80.0, r['percentage'])
77
+ test("ltv no pmi at 80", r['requires_pmi'] == False, False, r['requires_pmi'])
78
+ test("ltv down payment", r['down_payment'] == 80000.0, 80000.0, r['down_payment'])
79
+
80
+ r = loan_to_value(380000, 400000)
81
+ test("ltv pmi required above 80", r['requires_pmi'] == True, True, r['requires_pmi'])
82
+
83
+ print(f"\n📊 Results: {passed} passed, {failed} failed\n")
84
+ if failed > 0:
85
+ sys.exit(1)