mortctl 0.1.0
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.
- package/README.md +234 -0
- package/dist/commands/eligible.d.ts +6 -0
- package/dist/commands/eligible.d.ts.map +1 -0
- package/dist/commands/eligible.js +115 -0
- package/dist/commands/eligible.js.map +1 -0
- package/dist/commands/limits.d.ts +6 -0
- package/dist/commands/limits.d.ts.map +1 -0
- package/dist/commands/limits.js +89 -0
- package/dist/commands/limits.js.map +1 -0
- package/dist/commands/ltv.d.ts +6 -0
- package/dist/commands/ltv.d.ts.map +1 -0
- package/dist/commands/ltv.js +96 -0
- package/dist/commands/ltv.js.map +1 -0
- package/dist/commands/payment.d.ts +6 -0
- package/dist/commands/payment.d.ts.map +1 -0
- package/dist/commands/payment.js +98 -0
- package/dist/commands/payment.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/calculations.d.ts +52 -0
- package/dist/lib/calculations.d.ts.map +1 -0
- package/dist/lib/calculations.js +270 -0
- package/dist/lib/calculations.js.map +1 -0
- package/dist/lib/eligibility.d.ts +33 -0
- package/dist/lib/eligibility.d.ts.map +1 -0
- package/dist/lib/eligibility.js +296 -0
- package/dist/lib/eligibility.js.map +1 -0
- package/dist/types.d.ts +179 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/jest.config.js +8 -0
- package/package.json +46 -0
- package/src/commands/eligible.ts +121 -0
- package/src/commands/limits.ts +91 -0
- package/src/commands/ltv.ts +97 -0
- package/src/commands/payment.ts +100 -0
- package/src/index.ts +32 -0
- package/src/lib/calculations.ts +314 -0
- package/src/lib/eligibility.ts +343 -0
- package/src/types.ts +216 -0
- package/tests/calculations.test.ts +154 -0
- package/tsconfig.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# mortctl
|
|
2
|
+
|
|
3
|
+
Mortgage underwriting calculations and eligibility. Part of the **LendCtl Suite**.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **LTV Calculation** — LTV, CLTV, HCLTV with PMI estimates
|
|
8
|
+
- **Program Eligibility** — Conventional, FHA, VA, USDA, Jumbo
|
|
9
|
+
- **Payment Breakdown** — Full PITI calculation
|
|
10
|
+
- **Loan Limits** — 2026 conforming limits by county
|
|
11
|
+
- **PMI Estimation** — Based on LTV and credit score
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g mortctl
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or use directly with npx:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx mortctl --help
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Calculate LTV
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
mortctl ltv --property-value 400000 --down-payment 80000
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Output:
|
|
34
|
+
```
|
|
35
|
+
═══════════════════════════════════════════════════════════════
|
|
36
|
+
LTV CALCULATION
|
|
37
|
+
═══════════════════════════════════════════════════════════════
|
|
38
|
+
|
|
39
|
+
Property Value: $400,000
|
|
40
|
+
Loan Amount: $320,000
|
|
41
|
+
Down Payment: $80,000 (20.0%)
|
|
42
|
+
|
|
43
|
+
LTV RATIOS
|
|
44
|
+
───────────────────────────────────────────────────────────────
|
|
45
|
+
LTV: 80.00%
|
|
46
|
+
|
|
47
|
+
PMI: Not required (LTV ≤ 80%)
|
|
48
|
+
═══════════════════════════════════════════════════════════════
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Check Program Eligibility
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
mortctl eligible \
|
|
55
|
+
--property-value 400000 \
|
|
56
|
+
--loan-amount 380000 \
|
|
57
|
+
--credit-score 720
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Output:
|
|
61
|
+
```
|
|
62
|
+
═══════════════════════════════════════════════════════════════
|
|
63
|
+
LOAN PROGRAM ELIGIBILITY
|
|
64
|
+
═══════════════════════════════════════════════════════════════
|
|
65
|
+
|
|
66
|
+
Property Value: $400,000
|
|
67
|
+
Loan Amount: $380,000
|
|
68
|
+
LTV: 95.0%
|
|
69
|
+
Credit Score: 720
|
|
70
|
+
|
|
71
|
+
PROGRAM ELIGIBILITY
|
|
72
|
+
───────────────────────────────────────────────────────────────
|
|
73
|
+
✓ CONVENTIONAL
|
|
74
|
+
Min down: $12,000
|
|
75
|
+
⚠ LTV >95% requires additional eligibility criteria
|
|
76
|
+
|
|
77
|
+
✓ FHA
|
|
78
|
+
Min down: $14,000
|
|
79
|
+
|
|
80
|
+
✗ VA
|
|
81
|
+
✗ VA loans require veteran/military eligibility
|
|
82
|
+
|
|
83
|
+
✗ USDA
|
|
84
|
+
✗ USDA loans require rural/eligible suburban location
|
|
85
|
+
|
|
86
|
+
✗ JUMBO
|
|
87
|
+
✗ Loan amount is within conforming limits - use conventional
|
|
88
|
+
|
|
89
|
+
───────────────────────────────────────────────────────────────
|
|
90
|
+
💡 RECOMMENDED: FHA
|
|
91
|
+
═══════════════════════════════════════════════════════════════
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Calculate Monthly Payment
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
mortctl payment \
|
|
98
|
+
--loan-amount 320000 \
|
|
99
|
+
--rate 6.5 \
|
|
100
|
+
--property-value 400000
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Show Loan Limits
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Baseline limits
|
|
107
|
+
mortctl limits
|
|
108
|
+
|
|
109
|
+
# Specific county
|
|
110
|
+
mortctl limits --county "Los Angeles" --state CA
|
|
111
|
+
|
|
112
|
+
# List all high-cost counties
|
|
113
|
+
mortctl limits --list-high-cost
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Commands
|
|
117
|
+
|
|
118
|
+
### `mortctl ltv`
|
|
119
|
+
Calculate loan-to-value ratios with PMI estimates.
|
|
120
|
+
|
|
121
|
+
Options:
|
|
122
|
+
- `--property-value <amount>` - Property value (required)
|
|
123
|
+
- `--loan-amount <amount>` - Loan amount
|
|
124
|
+
- `--down-payment <amount>` - Down payment (alternative to loan-amount)
|
|
125
|
+
- `--second-lien <amount>` - Second mortgage amount
|
|
126
|
+
- `--heloc <amount>` - HELOC amount
|
|
127
|
+
- `--credit-score <score>` - Credit score for PMI estimate
|
|
128
|
+
|
|
129
|
+
### `mortctl eligible`
|
|
130
|
+
Check eligibility for all loan programs.
|
|
131
|
+
|
|
132
|
+
Options:
|
|
133
|
+
- `--property-value <amount>` - Property value (required)
|
|
134
|
+
- `--loan-amount <amount>` - Loan amount (required)
|
|
135
|
+
- `--credit-score <score>` - Credit score (required)
|
|
136
|
+
- `--property-type <type>` - single-family, condo, etc.
|
|
137
|
+
- `--occupancy <type>` - primary, second-home, investment
|
|
138
|
+
- `--veteran` - Veteran/military eligibility
|
|
139
|
+
- `--rural` - Rural/USDA eligible location
|
|
140
|
+
|
|
141
|
+
### `mortctl payment`
|
|
142
|
+
Calculate monthly payment with full PITI breakdown.
|
|
143
|
+
|
|
144
|
+
Options:
|
|
145
|
+
- `--loan-amount <amount>` - Loan amount (required)
|
|
146
|
+
- `--rate <percent>` - Interest rate (required)
|
|
147
|
+
- `--term <years>` - Loan term (default: 30)
|
|
148
|
+
- `--property-value <amount>` - For tax/insurance estimates
|
|
149
|
+
- `--taxes <amount>` - Annual property taxes
|
|
150
|
+
- `--insurance <amount>` - Annual homeowners insurance
|
|
151
|
+
- `--hoa <amount>` - Monthly HOA dues
|
|
152
|
+
|
|
153
|
+
### `mortctl limits`
|
|
154
|
+
Show conforming loan limits.
|
|
155
|
+
|
|
156
|
+
Options:
|
|
157
|
+
- `--county <name>` - County name
|
|
158
|
+
- `--state <abbr>` - State abbreviation
|
|
159
|
+
- `--units <n>` - Number of units (1-4)
|
|
160
|
+
- `--list-high-cost` - List all high-cost counties
|
|
161
|
+
|
|
162
|
+
## Programmatic Usage
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import {
|
|
166
|
+
calculateLtv,
|
|
167
|
+
calculatePmi,
|
|
168
|
+
calculatePaymentBreakdown,
|
|
169
|
+
checkAllEligibility,
|
|
170
|
+
findBestProgram,
|
|
171
|
+
getConformingLimit
|
|
172
|
+
} from 'mortctl';
|
|
173
|
+
|
|
174
|
+
// Calculate LTV
|
|
175
|
+
const ltv = calculateLtv(400000, 320000);
|
|
176
|
+
console.log(`LTV: ${ltv.ltv}%, PMI required: ${ltv.pmiRequired}`);
|
|
177
|
+
|
|
178
|
+
// Calculate PMI
|
|
179
|
+
const pmi = calculatePmi({ ltv: 95, creditScore: 720, loanAmount: 380000 });
|
|
180
|
+
console.log(`Monthly PMI: $${pmi.monthlyAmount}`);
|
|
181
|
+
|
|
182
|
+
// Check eligibility
|
|
183
|
+
const eligibility = checkAllEligibility({
|
|
184
|
+
propertyValue: 400000,
|
|
185
|
+
loanAmount: 380000,
|
|
186
|
+
creditScore: 720,
|
|
187
|
+
// ... other scenario options
|
|
188
|
+
});
|
|
189
|
+
const recommended = findBestProgram(eligibility);
|
|
190
|
+
console.log(`Recommended program: ${recommended}`);
|
|
191
|
+
|
|
192
|
+
// Get loan limits
|
|
193
|
+
const limit = getConformingLimit('Los Angeles, CA', 1);
|
|
194
|
+
console.log(`Conforming limit: $${limit}`);
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## 2026 Loan Limits
|
|
198
|
+
|
|
199
|
+
| Type | Limit |
|
|
200
|
+
|------|-------|
|
|
201
|
+
| Conforming (baseline) | $766,550 |
|
|
202
|
+
| High-cost ceiling | $1,149,825 |
|
|
203
|
+
| FHA floor | $498,257 |
|
|
204
|
+
| FHA ceiling | $1,149,825 |
|
|
205
|
+
|
|
206
|
+
Multi-unit multipliers:
|
|
207
|
+
- 2-unit: 1.28x baseline
|
|
208
|
+
- 3-unit: 1.55x baseline
|
|
209
|
+
- 4-unit: 1.92x baseline
|
|
210
|
+
|
|
211
|
+
## PMI Rate Factors
|
|
212
|
+
|
|
213
|
+
PMI rates vary by:
|
|
214
|
+
- **LTV**: Higher LTV = higher rate
|
|
215
|
+
- **Credit Score**: Higher score = lower rate
|
|
216
|
+
- **Property Type**: Single-family vs condo
|
|
217
|
+
- **Occupancy**: Primary vs investment
|
|
218
|
+
|
|
219
|
+
Typical range: 0.15% - 1.40% annually
|
|
220
|
+
|
|
221
|
+
## Part of LendCtl Suite
|
|
222
|
+
|
|
223
|
+
mortctl works with other LendCtl tools:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Full underwriting workflow
|
|
227
|
+
finctl analyze -f borrower.json | \
|
|
228
|
+
creditctl analyze --stdin | \
|
|
229
|
+
mortctl eligible --stdin
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
MIT © Avatar Consulting
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eligible.d.ts","sourceRoot":"","sources":["../../src/commands/eligible.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,qBAAqB,IAAI,OAAO,CAgH/C"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* mortctl eligible command - Check loan program eligibility
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createEligibleCommand = createEligibleCommand;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const eligibility_1 = require("../lib/eligibility");
|
|
9
|
+
function createEligibleCommand() {
|
|
10
|
+
const eligible = new commander_1.Command('eligible')
|
|
11
|
+
.description('Check eligibility for loan programs')
|
|
12
|
+
.requiredOption('--property-value <amount>', 'Property value')
|
|
13
|
+
.requiredOption('--loan-amount <amount>', 'Loan amount')
|
|
14
|
+
.requiredOption('--credit-score <score>', 'Credit score')
|
|
15
|
+
.option('--property-type <type>', 'Property type', 'single-family')
|
|
16
|
+
.option('--occupancy <type>', 'Occupancy type', 'primary')
|
|
17
|
+
.option('--purpose <type>', 'Loan purpose', 'purchase')
|
|
18
|
+
.option('--units <n>', 'Number of units', '1')
|
|
19
|
+
.option('--county <name>', 'County for loan limits')
|
|
20
|
+
.option('--state <abbr>', 'State abbreviation')
|
|
21
|
+
.option('--veteran', 'Veteran/military eligibility', false)
|
|
22
|
+
.option('--rural', 'Rural/USDA eligible location', false)
|
|
23
|
+
.option('--first-time', 'First-time homebuyer', false)
|
|
24
|
+
.option('--format <type>', 'Output format (json|table)', 'table')
|
|
25
|
+
.action(async (options) => {
|
|
26
|
+
try {
|
|
27
|
+
const scenario = {
|
|
28
|
+
propertyValue: parseFloat(options.propertyValue),
|
|
29
|
+
loanAmount: parseFloat(options.loanAmount),
|
|
30
|
+
downPayment: parseFloat(options.propertyValue) - parseFloat(options.loanAmount),
|
|
31
|
+
creditScore: parseInt(options.creditScore),
|
|
32
|
+
propertyType: options.propertyType,
|
|
33
|
+
occupancy: options.occupancy,
|
|
34
|
+
purpose: options.purpose,
|
|
35
|
+
units: parseInt(options.units),
|
|
36
|
+
county: options.county,
|
|
37
|
+
state: options.state,
|
|
38
|
+
veteran: options.veteran,
|
|
39
|
+
rural: options.rural,
|
|
40
|
+
firstTimeHomebuyer: options.firstTime,
|
|
41
|
+
interestRate: 6.5, // Default for calculations
|
|
42
|
+
termYears: 30,
|
|
43
|
+
};
|
|
44
|
+
const eligibility = (0, eligibility_1.checkAllEligibility)(scenario);
|
|
45
|
+
const recommended = (0, eligibility_1.findBestProgram)(eligibility);
|
|
46
|
+
if (options.format === 'json') {
|
|
47
|
+
console.log(JSON.stringify({
|
|
48
|
+
scenario: {
|
|
49
|
+
propertyValue: scenario.propertyValue,
|
|
50
|
+
loanAmount: scenario.loanAmount,
|
|
51
|
+
ltv: (scenario.loanAmount / scenario.propertyValue * 100).toFixed(2),
|
|
52
|
+
creditScore: scenario.creditScore,
|
|
53
|
+
},
|
|
54
|
+
eligibility,
|
|
55
|
+
recommendedProgram: recommended,
|
|
56
|
+
}, null, 2));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const ltv = (scenario.loanAmount / scenario.propertyValue * 100);
|
|
60
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
61
|
+
console.log('LOAN PROGRAM ELIGIBILITY');
|
|
62
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
63
|
+
console.log('');
|
|
64
|
+
console.log(`Property Value: $${scenario.propertyValue.toLocaleString()}`);
|
|
65
|
+
console.log(`Loan Amount: $${scenario.loanAmount.toLocaleString()}`);
|
|
66
|
+
console.log(`LTV: ${ltv.toFixed(1)}%`);
|
|
67
|
+
console.log(`Credit Score: ${scenario.creditScore}`);
|
|
68
|
+
console.log(`Property: ${scenario.propertyType}, ${scenario.occupancy}`);
|
|
69
|
+
console.log('');
|
|
70
|
+
console.log('PROGRAM ELIGIBILITY');
|
|
71
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
72
|
+
for (const result of eligibility) {
|
|
73
|
+
const status = result.eligible ? '✓' : '✗';
|
|
74
|
+
const programName = result.program.toUpperCase().padEnd(15);
|
|
75
|
+
console.log(`${status} ${programName}`);
|
|
76
|
+
if (!result.eligible && result.reasons) {
|
|
77
|
+
for (const reason of result.reasons) {
|
|
78
|
+
console.log(` ✗ ${reason}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (result.eligible) {
|
|
82
|
+
if (result.minDownPayment !== undefined) {
|
|
83
|
+
console.log(` Min down: $${result.minDownPayment.toLocaleString()}`);
|
|
84
|
+
}
|
|
85
|
+
if (result.rateAdjustment) {
|
|
86
|
+
const adj = result.rateAdjustment > 0 ? `+${result.rateAdjustment}%` : `${result.rateAdjustment}%`;
|
|
87
|
+
console.log(` Rate adj: ${adj}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (result.warnings) {
|
|
91
|
+
for (const warning of result.warnings) {
|
|
92
|
+
console.log(` ⚠ ${warning}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
console.log('');
|
|
96
|
+
}
|
|
97
|
+
if (recommended) {
|
|
98
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
99
|
+
console.log(`💡 RECOMMENDED: ${recommended.toUpperCase()}`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
103
|
+
console.log('⚠ No programs eligible - review requirements');
|
|
104
|
+
}
|
|
105
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error(`Error: ${error.message}`);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return eligible;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=eligible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eligible.js","sourceRoot":"","sources":["../../src/commands/eligible.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/commands/limits.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,mBAAmB,IAAI,OAAO,CAmF7C"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* mortctl limits command - Show conforming loan limits
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createLimitsCommand = createLimitsCommand;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const calculations_1 = require("../lib/calculations");
|
|
9
|
+
function createLimitsCommand() {
|
|
10
|
+
const limits = new commander_1.Command('limits')
|
|
11
|
+
.description('Show conforming loan limits')
|
|
12
|
+
.option('--county <name>', 'County name (e.g., "Los Angeles")')
|
|
13
|
+
.option('--state <abbr>', 'State abbreviation (e.g., "CA")')
|
|
14
|
+
.option('--units <n>', 'Number of units (1-4)', '1')
|
|
15
|
+
.option('--list-high-cost', 'List all high-cost counties', false)
|
|
16
|
+
.option('--format <type>', 'Output format (json|table)', 'table')
|
|
17
|
+
.action(async (options) => {
|
|
18
|
+
try {
|
|
19
|
+
const units = parseInt(options.units);
|
|
20
|
+
if (options.listHighCost) {
|
|
21
|
+
if (options.format === 'json') {
|
|
22
|
+
console.log(JSON.stringify(calculations_1.HIGH_COST_COUNTIES, null, 2));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
26
|
+
console.log('HIGH-COST COUNTIES (2026)');
|
|
27
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
28
|
+
console.log('');
|
|
29
|
+
for (const [county, limit] of Object.entries(calculations_1.HIGH_COST_COUNTIES)) {
|
|
30
|
+
console.log(`${county.padEnd(30)} $${limit.toLocaleString()}`);
|
|
31
|
+
}
|
|
32
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const countyKey = options.county && options.state
|
|
37
|
+
? `${options.county}, ${options.state}`
|
|
38
|
+
: undefined;
|
|
39
|
+
const conformingLimit = (0, calculations_1.getConformingLimit)(countyKey, units);
|
|
40
|
+
const isHighCost = countyKey && calculations_1.HIGH_COST_COUNTIES[countyKey];
|
|
41
|
+
// Unit multipliers for display
|
|
42
|
+
const unitLimits = {};
|
|
43
|
+
for (let u = 1; u <= 4; u++) {
|
|
44
|
+
unitLimits[u] = (0, calculations_1.getConformingLimit)(countyKey, u);
|
|
45
|
+
}
|
|
46
|
+
const result = {
|
|
47
|
+
year: 2026,
|
|
48
|
+
county: countyKey || 'Baseline (standard counties)',
|
|
49
|
+
isHighCost: !!isHighCost,
|
|
50
|
+
units,
|
|
51
|
+
conformingLimit,
|
|
52
|
+
allUnitLimits: unitLimits,
|
|
53
|
+
baseline: calculations_1.LOAN_LIMITS_2026,
|
|
54
|
+
};
|
|
55
|
+
if (options.format === 'json') {
|
|
56
|
+
console.log(JSON.stringify(result, null, 2));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
60
|
+
console.log('CONFORMING LOAN LIMITS (2026)');
|
|
61
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
62
|
+
console.log('');
|
|
63
|
+
console.log(`Area: ${result.county}`);
|
|
64
|
+
console.log(`High-Cost: ${result.isHighCost ? 'Yes' : 'No'}`);
|
|
65
|
+
console.log('');
|
|
66
|
+
console.log('LIMITS BY UNIT COUNT');
|
|
67
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
68
|
+
console.log(`1-Unit: $${unitLimits[1].toLocaleString()}`);
|
|
69
|
+
console.log(`2-Unit: $${unitLimits[2].toLocaleString()}`);
|
|
70
|
+
console.log(`3-Unit: $${unitLimits[3].toLocaleString()}`);
|
|
71
|
+
console.log(`4-Unit: $${unitLimits[4].toLocaleString()}`);
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log('NATIONAL BASELINE');
|
|
74
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
75
|
+
console.log(`Conforming Floor: $${calculations_1.LOAN_LIMITS_2026.baseline.toLocaleString()}`);
|
|
76
|
+
console.log(`High-Cost Ceiling: $${calculations_1.LOAN_LIMITS_2026.highCost.toLocaleString()}`);
|
|
77
|
+
console.log(`FHA Floor: $${calculations_1.LOAN_LIMITS_2026.fhaFloor.toLocaleString()}`);
|
|
78
|
+
console.log(`FHA Ceiling: $${calculations_1.LOAN_LIMITS_2026.fhaCeiling.toLocaleString()}`);
|
|
79
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.error(`Error: ${error.message}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
return limits;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/commands/limits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ltv.d.ts","sourceRoot":"","sources":["../../src/commands/ltv.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,gBAAgB,IAAI,OAAO,CAyF1C"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* mortctl ltv command - Calculate LTV/CLTV/HCLTV
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createLtvCommand = createLtvCommand;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const calculations_1 = require("../lib/calculations");
|
|
9
|
+
function createLtvCommand() {
|
|
10
|
+
const ltv = new commander_1.Command('ltv')
|
|
11
|
+
.description('Calculate loan-to-value ratios')
|
|
12
|
+
.requiredOption('--property-value <amount>', 'Property value or purchase price')
|
|
13
|
+
.option('--loan-amount <amount>', 'Loan amount (or use --down-payment)')
|
|
14
|
+
.option('--down-payment <amount>', 'Down payment amount')
|
|
15
|
+
.option('--second-lien <amount>', 'Second mortgage/lien amount', '0')
|
|
16
|
+
.option('--heloc <amount>', 'HELOC amount', '0')
|
|
17
|
+
.option('--credit-score <score>', 'Credit score for PMI estimate', '720')
|
|
18
|
+
.option('--format <type>', 'Output format (json|table)', 'table')
|
|
19
|
+
.action(async (options) => {
|
|
20
|
+
try {
|
|
21
|
+
const propertyValue = parseFloat(options.propertyValue);
|
|
22
|
+
let loanAmount;
|
|
23
|
+
if (options.loanAmount) {
|
|
24
|
+
loanAmount = parseFloat(options.loanAmount);
|
|
25
|
+
}
|
|
26
|
+
else if (options.downPayment) {
|
|
27
|
+
loanAmount = propertyValue - parseFloat(options.downPayment);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
console.error('Error: Must specify either --loan-amount or --down-payment');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const secondLien = parseFloat(options.secondLien);
|
|
34
|
+
const heloc = parseFloat(options.heloc);
|
|
35
|
+
const creditScore = parseInt(options.creditScore);
|
|
36
|
+
const ltvResult = (0, calculations_1.calculateLtv)(propertyValue, loanAmount, secondLien, heloc);
|
|
37
|
+
const pmiResult = (0, calculations_1.calculatePmi)({
|
|
38
|
+
ltv: ltvResult.ltv,
|
|
39
|
+
creditScore,
|
|
40
|
+
loanAmount,
|
|
41
|
+
});
|
|
42
|
+
const downPayment = propertyValue - loanAmount;
|
|
43
|
+
const downPaymentPct = (downPayment / propertyValue) * 100;
|
|
44
|
+
if (options.format === 'json') {
|
|
45
|
+
console.log(JSON.stringify({
|
|
46
|
+
propertyValue,
|
|
47
|
+
loanAmount,
|
|
48
|
+
downPayment,
|
|
49
|
+
downPaymentPct: Math.round(downPaymentPct * 100) / 100,
|
|
50
|
+
...ltvResult,
|
|
51
|
+
pmi: pmiResult,
|
|
52
|
+
}, null, 2));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
56
|
+
console.log('LTV CALCULATION');
|
|
57
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log(`Property Value: $${propertyValue.toLocaleString()}`);
|
|
60
|
+
console.log(`Loan Amount: $${loanAmount.toLocaleString()}`);
|
|
61
|
+
console.log(`Down Payment: $${downPayment.toLocaleString()} (${downPaymentPct.toFixed(1)}%)`);
|
|
62
|
+
console.log('');
|
|
63
|
+
console.log('LTV RATIOS');
|
|
64
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
65
|
+
console.log(`LTV: ${ltvResult.ltv.toFixed(2)}%`);
|
|
66
|
+
if (secondLien > 0 || heloc > 0) {
|
|
67
|
+
console.log(`CLTV: ${ltvResult.cltv.toFixed(2)}%`);
|
|
68
|
+
console.log(`HCLTV: ${ltvResult.hcltv.toFixed(2)}%`);
|
|
69
|
+
}
|
|
70
|
+
console.log('');
|
|
71
|
+
if (pmiResult.required) {
|
|
72
|
+
console.log('PMI ESTIMATE');
|
|
73
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
74
|
+
console.log(`PMI Required: Yes`);
|
|
75
|
+
console.log(`Monthly PMI: $${pmiResult.monthlyAmount.toLocaleString()}`);
|
|
76
|
+
console.log(`Annual PMI: $${pmiResult.annualAmount.toLocaleString()}`);
|
|
77
|
+
console.log(`PMI Rate: ${pmiResult.ratePercent}%`);
|
|
78
|
+
console.log(`Auto-Cancel at: ${pmiResult.cancellationLtv}% LTV`);
|
|
79
|
+
if (pmiResult.monthsToCancel) {
|
|
80
|
+
console.log(`Est. Months to Cancel: ~${pmiResult.monthsToCancel}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log('PMI: Not required (LTV ≤ 80%)');
|
|
85
|
+
}
|
|
86
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error(`Error: ${error.message}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return ltv;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=ltv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ltv.js","sourceRoot":"","sources":["../../src/commands/ltv.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../../src/commands/payment.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,oBAAoB,IAAI,OAAO,CA2F9C"}
|