financial-calculators-ts 0.4.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/LICENSE +21 -0
- package/README.md +621 -0
- package/dist/calculators/AutoLoan.d.ts +42 -0
- package/dist/calculators/AutoLoan.js +65 -0
- package/dist/calculators/BreakEven.d.ts +43 -0
- package/dist/calculators/BreakEven.js +66 -0
- package/dist/calculators/CompoundInterest.d.ts +43 -0
- package/dist/calculators/CompoundInterest.js +88 -0
- package/dist/calculators/DebtPayoff.d.ts +39 -0
- package/dist/calculators/DebtPayoff.js +72 -0
- package/dist/calculators/DollarCostAveraging.d.ts +41 -0
- package/dist/calculators/DollarCostAveraging.js +67 -0
- package/dist/calculators/InflationAdjustedReturn.d.ts +36 -0
- package/dist/calculators/InflationAdjustedReturn.js +52 -0
- package/dist/calculators/LoanAmortization.d.ts +48 -0
- package/dist/calculators/LoanAmortization.js +86 -0
- package/dist/calculators/PresentValue.d.ts +31 -0
- package/dist/calculators/PresentValue.js +53 -0
- package/dist/calculators/ROI.d.ts +42 -0
- package/dist/calculators/ROI.js +61 -0
- package/dist/calculators/RetirementSavings.d.ts +45 -0
- package/dist/calculators/RetirementSavings.js +81 -0
- package/dist/calculators/RuleOf72.d.ts +36 -0
- package/dist/calculators/RuleOf72.js +45 -0
- package/dist/calculators/SavingsGoal.d.ts +47 -0
- package/dist/calculators/SavingsGoal.js +84 -0
- package/dist/calculators/SimpleInterest.d.ts +26 -0
- package/dist/calculators/SimpleInterest.js +46 -0
- package/dist/calculators/TaxBracket.d.ts +53 -0
- package/dist/calculators/TaxBracket.js +86 -0
- package/dist/calculators/mortgage.d.ts +40 -0
- package/dist/calculators/mortgage.js +87 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +38 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 jklamert
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
# Calculators
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.typescriptlang.org/)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
[](#testing)
|
|
7
|
+
|
|
8
|
+
A TypeScript library of **15 financial calculators** covering interest, loans, investments, taxes, and business analysis. Zero dependencies, fully typed, with strict mode enabled.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Quick Start](#quick-start)
|
|
16
|
+
- [Calculators](#calculators)
|
|
17
|
+
- [Interest & Growth](#interest--growth)
|
|
18
|
+
- [Loans & Debt](#loans--debt)
|
|
19
|
+
- [Investments & Savings](#investments--savings)
|
|
20
|
+
- [Tax & Business](#tax--business)
|
|
21
|
+
- [Scripts](#scripts)
|
|
22
|
+
- [Testing](#testing)
|
|
23
|
+
- [Contributing](#contributing)
|
|
24
|
+
- [License](#license)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install calculators
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or clone and build from source:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone https://github.com/your-username/Calculators.git
|
|
38
|
+
cd Calculators
|
|
39
|
+
npm install
|
|
40
|
+
npm run build
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { Mortgage, CompoundInterest, Compound } from "calculators";
|
|
47
|
+
|
|
48
|
+
// Calculate monthly mortgage payment
|
|
49
|
+
const mortgage = new Mortgage(350000, 70000, 6.5, 30);
|
|
50
|
+
const result = mortgage.calculate();
|
|
51
|
+
console.log(result.monthlyPayment); // 1770.27
|
|
52
|
+
|
|
53
|
+
// Calculate compound interest
|
|
54
|
+
const ci = new CompoundInterest(10000, 5, 10, Compound.Monthly);
|
|
55
|
+
console.log(ci.calculate()); // 16470.09
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Calculators
|
|
59
|
+
|
|
60
|
+
### Interest & Growth
|
|
61
|
+
|
|
62
|
+
#### SimpleInterest
|
|
63
|
+
|
|
64
|
+
Calculates simple interest using `A = P(1 + rt)`.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { SimpleInterest } from "calculators";
|
|
68
|
+
|
|
69
|
+
const si = new SimpleInterest(1000, 5, 3);
|
|
70
|
+
// constructor(principal, ratePercentage, years)
|
|
71
|
+
console.log(si.calculate()); // 1150.00
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
| Parameter | Type | Description |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| `principal` | `number` | Initial amount (must be > 0) |
|
|
77
|
+
| `ratePercentage` | `number` | Annual rate as a percentage, 0-100 |
|
|
78
|
+
| `years` | `number` | Time period in years (>= 0) |
|
|
79
|
+
|
|
80
|
+
**Returns:** `number` — the total amount (principal + interest).
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
#### CompoundInterest
|
|
85
|
+
|
|
86
|
+
Calculates compound interest using `A = P(1 + r/n)^(nt)`.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { CompoundInterest, Compound } from "calculators";
|
|
90
|
+
|
|
91
|
+
const ci = new CompoundInterest(5000, 8, 5, Compound.Quarterly);
|
|
92
|
+
console.log(ci.calculate()); // 7429.74
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
| Parameter | Type | Description |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| `principal` | `number` | Initial amount (must be > 0) |
|
|
98
|
+
| `ratePercentage` | `number` | Annual rate, 0-100 |
|
|
99
|
+
| `years` | `number` | Time period (must be > 0) |
|
|
100
|
+
| `compound` | `Compound` | `Compound.Monthly`, `Compound.Quarterly`, or `Compound.Annually` |
|
|
101
|
+
|
|
102
|
+
**Returns:** `number` — the total amount after compounding.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
#### RuleOf72
|
|
107
|
+
|
|
108
|
+
Estimates the time required to double an investment.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { RuleOf72 } from "calculators";
|
|
112
|
+
|
|
113
|
+
const r72 = new RuleOf72(8);
|
|
114
|
+
const result = r72.calculate();
|
|
115
|
+
console.log(result.estimatedYears); // 9
|
|
116
|
+
console.log(result.exactYears); // 9.01
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
| Parameter | Type | Description |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
|
|
122
|
+
|
|
123
|
+
**Returns:** `RuleOf72Result`
|
|
124
|
+
|
|
125
|
+
| Field | Type | Description |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `estimatedYears` | `number` | 72 / rate (rounded to 2 decimals) |
|
|
128
|
+
| `exactYears` | `number` | ln(2) / ln(1 + rate/100) |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### Loans & Debt
|
|
133
|
+
|
|
134
|
+
#### Mortgage
|
|
135
|
+
|
|
136
|
+
Calculates monthly and yearly mortgage payments.
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { Mortgage } from "calculators";
|
|
140
|
+
|
|
141
|
+
const m = new Mortgage(300000, 60000, 6, 30);
|
|
142
|
+
// constructor(amount, downPayment, ratePercentage, years)
|
|
143
|
+
const result = m.calculate();
|
|
144
|
+
console.log(result.monthlyPayment); // 1438.92
|
|
145
|
+
console.log(result.yearlyPayment); // 17267.04
|
|
146
|
+
console.log(result.totalNumberOfPayments); // 360
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
| Parameter | Type | Description |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| `amount` | `number` | Total property price (must be > 0) |
|
|
152
|
+
| `downPayment` | `number` | Down payment (>= 0, must be < amount) |
|
|
153
|
+
| `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
|
|
154
|
+
| `years` | `number` | Loan term as a positive integer |
|
|
155
|
+
|
|
156
|
+
**Returns:** `MortgageResult`
|
|
157
|
+
|
|
158
|
+
| Field | Type | Description |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `monthlyPayment` | `number` | Monthly payment amount |
|
|
161
|
+
| `yearlyPayment` | `number` | Annual payment amount |
|
|
162
|
+
| `totalNumberOfPayments` | `number` | Total number of monthly payments |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
#### LoanAmortization
|
|
167
|
+
|
|
168
|
+
Generates a full amortization schedule with principal/interest breakdown per payment.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { LoanAmortization } from "calculators";
|
|
172
|
+
|
|
173
|
+
const la = new LoanAmortization(200000, 6, 30);
|
|
174
|
+
const result = la.calculate();
|
|
175
|
+
|
|
176
|
+
console.log(result.monthlyPayment); // 1199.10
|
|
177
|
+
console.log(result.totalInterest); // 231677.04
|
|
178
|
+
console.log(result.schedule[0]);
|
|
179
|
+
// { payment: 1, principal: 199.10, interest: 1000.00, remainingBalance: 199800.90 }
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| Parameter | Type | Description |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `loanAmount` | `number` | Loan principal (must be > 0) |
|
|
185
|
+
| `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
|
|
186
|
+
| `years` | `number` | Loan term as a positive integer (max 100) |
|
|
187
|
+
|
|
188
|
+
**Returns:** `AmortizationResult`
|
|
189
|
+
|
|
190
|
+
| Field | Type | Description |
|
|
191
|
+
|---|---|---|
|
|
192
|
+
| `monthlyPayment` | `number` | Fixed monthly payment |
|
|
193
|
+
| `totalPayments` | `number` | Total number of payments |
|
|
194
|
+
| `totalInterest` | `number` | Total interest paid over the life of the loan |
|
|
195
|
+
| `schedule` | `AmortizationEntry[]` | Per-payment breakdown |
|
|
196
|
+
|
|
197
|
+
Each `AmortizationEntry`:
|
|
198
|
+
|
|
199
|
+
| Field | Type | Description |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `payment` | `number` | Payment number (1-indexed) |
|
|
202
|
+
| `principal` | `number` | Principal portion of the payment |
|
|
203
|
+
| `interest` | `number` | Interest portion of the payment |
|
|
204
|
+
| `remainingBalance` | `number` | Balance remaining after payment |
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
#### AutoLoan
|
|
209
|
+
|
|
210
|
+
Calculates auto loan payments using the standard amortization formula, with term in months.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import { AutoLoan } from "calculators";
|
|
214
|
+
|
|
215
|
+
const al = new AutoLoan(35000, 5000, 4.5, 60);
|
|
216
|
+
// constructor(vehiclePrice, downPayment, ratePercentage, termMonths)
|
|
217
|
+
const result = al.calculate();
|
|
218
|
+
console.log(result.monthlyPayment); // 559.28
|
|
219
|
+
console.log(result.totalInterest); // 3556.80
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
| Parameter | Type | Description |
|
|
223
|
+
|---|---|---|
|
|
224
|
+
| `vehiclePrice` | `number` | Vehicle price (must be > 0) |
|
|
225
|
+
| `downPayment` | `number` | Down payment (>= 0, must be < price) |
|
|
226
|
+
| `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
|
|
227
|
+
| `termMonths` | `number` | Loan term in months (positive integer) |
|
|
228
|
+
|
|
229
|
+
**Returns:** `AutoLoanResult`
|
|
230
|
+
|
|
231
|
+
| Field | Type | Description |
|
|
232
|
+
|---|---|---|
|
|
233
|
+
| `loanAmount` | `number` | Financed amount (price - down payment) |
|
|
234
|
+
| `monthlyPayment` | `number` | Monthly payment |
|
|
235
|
+
| `totalPaid` | `number` | Total of all payments |
|
|
236
|
+
| `totalInterest` | `number` | Total interest paid |
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
#### DebtPayoff
|
|
241
|
+
|
|
242
|
+
Calculates how long it takes to pay off a debt with a fixed monthly payment.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { DebtPayoff } from "calculators";
|
|
246
|
+
|
|
247
|
+
const dp = new DebtPayoff(5000, 18, 200);
|
|
248
|
+
// constructor(balance, ratePercentage, monthlyPayment)
|
|
249
|
+
const result = dp.calculate();
|
|
250
|
+
console.log(result.months); // 32
|
|
251
|
+
console.log(result.totalInterest); // 1313.97
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
| Parameter | Type | Description |
|
|
255
|
+
|---|---|---|
|
|
256
|
+
| `balance` | `number` | Outstanding debt (must be > 0) |
|
|
257
|
+
| `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
|
|
258
|
+
| `monthlyPayment` | `number` | Fixed payment (must exceed monthly interest) |
|
|
259
|
+
|
|
260
|
+
**Returns:** `DebtPayoffResult`
|
|
261
|
+
|
|
262
|
+
| Field | Type | Description |
|
|
263
|
+
|---|---|---|
|
|
264
|
+
| `months` | `number` | Number of months to pay off |
|
|
265
|
+
| `totalPaid` | `number` | Total amount paid |
|
|
266
|
+
| `totalInterest` | `number` | Total interest paid |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### Investments & Savings
|
|
271
|
+
|
|
272
|
+
#### RetirementSavings
|
|
273
|
+
|
|
274
|
+
Projects the future value of retirement savings with regular contributions.
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import { RetirementSavings } from "calculators";
|
|
278
|
+
|
|
279
|
+
const rs = new RetirementSavings(50000, 500, 7, 25);
|
|
280
|
+
// constructor(initialBalance, monthlyContribution, ratePercentage, years)
|
|
281
|
+
const result = rs.calculate();
|
|
282
|
+
console.log(result.futureValue); // 676,570+ (varies by rounding)
|
|
283
|
+
console.log(result.totalContributions); // 150000
|
|
284
|
+
console.log(result.totalInterest); // futureValue - 50000 - 150000
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
| Parameter | Type | Description |
|
|
288
|
+
|---|---|---|
|
|
289
|
+
| `initialBalance` | `number` | Starting balance (>= 0) |
|
|
290
|
+
| `monthlyContribution` | `number` | Monthly contribution (>= 0) |
|
|
291
|
+
| `ratePercentage` | `number` | Annual return rate, 0-100 |
|
|
292
|
+
| `years` | `number` | Investment horizon (must be > 0) |
|
|
293
|
+
|
|
294
|
+
**Returns:** `RetirementResult`
|
|
295
|
+
|
|
296
|
+
| Field | Type | Description |
|
|
297
|
+
|---|---|---|
|
|
298
|
+
| `futureValue` | `number` | Projected total value |
|
|
299
|
+
| `totalContributions` | `number` | Sum of all contributions |
|
|
300
|
+
| `totalInterest` | `number` | Total growth from interest |
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
#### PresentValue
|
|
305
|
+
|
|
306
|
+
Calculates the present value of a future sum: `PV = FV / (1 + r)^n`.
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
import { PresentValue } from "calculators";
|
|
310
|
+
|
|
311
|
+
const pv = new PresentValue(10000, 5, 10);
|
|
312
|
+
// constructor(futureValue, ratePercentage, years)
|
|
313
|
+
console.log(pv.calculate()); // 6139.13
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
| Parameter | Type | Description |
|
|
317
|
+
|---|---|---|
|
|
318
|
+
| `futureValue` | `number` | Future amount (must be > 0) |
|
|
319
|
+
| `ratePercentage` | `number` | Discount rate, 0-100 |
|
|
320
|
+
| `years` | `number` | Time period (must be > 0) |
|
|
321
|
+
|
|
322
|
+
**Returns:** `number` — the present value.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
#### SavingsGoal
|
|
327
|
+
|
|
328
|
+
Calculates the monthly savings needed to reach a financial goal.
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { SavingsGoal } from "calculators";
|
|
332
|
+
|
|
333
|
+
const sg = new SavingsGoal(50000, 10000, 5, 5);
|
|
334
|
+
// constructor(goalAmount, currentSavings, ratePercentage, years)
|
|
335
|
+
const result = sg.calculate();
|
|
336
|
+
console.log(result.monthlySavings); // ~588
|
|
337
|
+
console.log(result.totalContributions); // monthlySavings * 60
|
|
338
|
+
console.log(result.interestEarned); // goal - currentSavings - contributions
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
| Parameter | Type | Description |
|
|
342
|
+
|---|---|---|
|
|
343
|
+
| `goalAmount` | `number` | Target amount (must be > 0) |
|
|
344
|
+
| `currentSavings` | `number` | Current savings (>= 0, must be < goal) |
|
|
345
|
+
| `ratePercentage` | `number` | Annual return rate, 0-100 |
|
|
346
|
+
| `years` | `number` | Time horizon (must be > 0) |
|
|
347
|
+
|
|
348
|
+
**Returns:** `SavingsGoalResult`
|
|
349
|
+
|
|
350
|
+
| Field | Type | Description |
|
|
351
|
+
|---|---|---|
|
|
352
|
+
| `monthlySavings` | `number` | Required monthly savings |
|
|
353
|
+
| `totalContributions` | `number` | Total amount contributed |
|
|
354
|
+
| `interestEarned` | `number` | Total interest earned |
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
#### DollarCostAveraging
|
|
359
|
+
|
|
360
|
+
Simulates periodic fixed-amount investments at varying prices.
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
import { DollarCostAveraging } from "calculators";
|
|
364
|
+
|
|
365
|
+
const prices = [50, 45, 55, 40, 60];
|
|
366
|
+
const dca = new DollarCostAveraging(100, prices);
|
|
367
|
+
// constructor(investmentPerPeriod, prices)
|
|
368
|
+
const result = dca.calculate();
|
|
369
|
+
console.log(result.totalShares);
|
|
370
|
+
console.log(result.averageCostPerShare);
|
|
371
|
+
console.log(result.totalInvested); // 500
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
| Parameter | Type | Description |
|
|
375
|
+
|---|---|---|
|
|
376
|
+
| `investmentPerPeriod` | `number` | Fixed investment amount (must be > 0) |
|
|
377
|
+
| `prices` | `number[]` | Array of prices per period (all must be > 0) |
|
|
378
|
+
|
|
379
|
+
**Returns:** `DCAResult`
|
|
380
|
+
|
|
381
|
+
| Field | Type | Description |
|
|
382
|
+
|---|---|---|
|
|
383
|
+
| `totalInvested` | `number` | Total amount invested |
|
|
384
|
+
| `totalShares` | `number` | Total shares purchased |
|
|
385
|
+
| `averageCostPerShare` | `number` | Average cost per share |
|
|
386
|
+
| `currentValue` | `number` | Value at the final price |
|
|
387
|
+
| `gainLoss` | `number` | Dollar gain or loss (currentValue - totalInvested) |
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
#### ROI
|
|
392
|
+
|
|
393
|
+
Calculates return on investment with optional annualized ROI.
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
import { ROI } from "calculators";
|
|
397
|
+
|
|
398
|
+
const roi = new ROI(10000, 15000, 3);
|
|
399
|
+
// constructor(cost, revenue, years?)
|
|
400
|
+
const result = roi.calculate();
|
|
401
|
+
console.log(result.roi); // 50.00
|
|
402
|
+
console.log(result.annualizedRoi); // 14.47
|
|
403
|
+
console.log(result.netProfit); // 5000.00
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
| Parameter | Type | Description |
|
|
407
|
+
|---|---|---|
|
|
408
|
+
| `cost` | `number` | Initial investment (must be > 0) |
|
|
409
|
+
| `revenue` | `number` | Total return (>= 0) |
|
|
410
|
+
| `years` | `number?` | Optional holding period for annualized ROI |
|
|
411
|
+
|
|
412
|
+
**Returns:** `ROIResult`
|
|
413
|
+
|
|
414
|
+
| Field | Type | Description |
|
|
415
|
+
|---|---|---|
|
|
416
|
+
| `roi` | `number` | ROI as a percentage |
|
|
417
|
+
| `annualizedRoi` | `number?` | Annualized ROI (if years provided) |
|
|
418
|
+
| `netProfit` | `number` | Revenue minus cost |
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
#### InflationAdjustedReturn
|
|
423
|
+
|
|
424
|
+
Calculates the real rate of return after inflation using the Fisher equation.
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
import { InflationAdjustedReturn } from "calculators";
|
|
428
|
+
|
|
429
|
+
const iar = new InflationAdjustedReturn(10, 3);
|
|
430
|
+
// constructor(nominalRatePercentage, inflationRatePercentage)
|
|
431
|
+
const result = iar.calculate();
|
|
432
|
+
console.log(result.realReturn); // 6.80
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
| Parameter | Type | Description |
|
|
436
|
+
|---|---|---|
|
|
437
|
+
| `nominalRatePercentage` | `number` | Nominal return rate, 0-100 |
|
|
438
|
+
| `inflationRatePercentage` | `number` | Inflation rate, 0 to <100 |
|
|
439
|
+
|
|
440
|
+
**Returns:** `InflationAdjustedResult`
|
|
441
|
+
|
|
442
|
+
| Field | Type | Description |
|
|
443
|
+
|---|---|---|
|
|
444
|
+
| `realReturn` | `number` | Real return percentage |
|
|
445
|
+
| `nominalRate` | `number` | Input nominal rate |
|
|
446
|
+
| `inflationRate` | `number` | Input inflation rate |
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
### Tax & Business
|
|
451
|
+
|
|
452
|
+
#### TaxBracket
|
|
453
|
+
|
|
454
|
+
Calculates progressive income tax with bracket breakdown.
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
import { TaxBracket } from "calculators";
|
|
458
|
+
import type { Bracket } from "calculators";
|
|
459
|
+
|
|
460
|
+
const brackets: Bracket[] = [
|
|
461
|
+
{ min: 0, max: 11000, rate: 10 },
|
|
462
|
+
{ min: 11000, max: 44725, rate: 12 },
|
|
463
|
+
{ min: 44725, max: 95375, rate: 22 },
|
|
464
|
+
{ min: 95375, max: 182100, rate: 24 },
|
|
465
|
+
];
|
|
466
|
+
|
|
467
|
+
const tb = new TaxBracket(100000, brackets);
|
|
468
|
+
const result = tb.calculate();
|
|
469
|
+
console.log(result.totalTax); // Total tax owed
|
|
470
|
+
console.log(result.effectiveRate); // Effective tax rate %
|
|
471
|
+
console.log(result.marginalRate); // Highest applicable bracket rate
|
|
472
|
+
console.log(result.brackets); // Per-bracket breakdown
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
| Parameter | Type | Description |
|
|
476
|
+
|---|---|---|
|
|
477
|
+
| `income` | `number` | Taxable income (must be > 0) |
|
|
478
|
+
| `taxBrackets` | `Bracket[]` | Array of tax brackets (non-overlapping) |
|
|
479
|
+
|
|
480
|
+
Each `Bracket`:
|
|
481
|
+
|
|
482
|
+
| Field | Type | Description |
|
|
483
|
+
|---|---|---|
|
|
484
|
+
| `min` | `number` | Bracket lower bound (>= 0) |
|
|
485
|
+
| `max` | `number` | Bracket upper bound (must be > min) |
|
|
486
|
+
| `rate` | `number` | Tax rate for this bracket, 0-100 |
|
|
487
|
+
|
|
488
|
+
**Returns:** `TaxBracketResult`
|
|
489
|
+
|
|
490
|
+
| Field | Type | Description |
|
|
491
|
+
|---|---|---|
|
|
492
|
+
| `totalTax` | `number` | Total tax owed |
|
|
493
|
+
| `effectiveRate` | `number` | Effective tax rate as a percentage |
|
|
494
|
+
| `marginalRate` | `number` | Marginal (highest applicable) tax rate |
|
|
495
|
+
| `brackets` | `BracketBreakdown[]` | Per-bracket tax detail |
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
#### BreakEven
|
|
500
|
+
|
|
501
|
+
Calculates the break-even point in units and revenue.
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
import { BreakEven } from "calculators";
|
|
505
|
+
|
|
506
|
+
const be = new BreakEven(50000, 100, 60);
|
|
507
|
+
// constructor(fixedCosts, pricePerUnit, variableCostPerUnit)
|
|
508
|
+
const result = be.calculate();
|
|
509
|
+
console.log(result.breakEvenUnits); // 1250
|
|
510
|
+
console.log(result.breakEvenRevenue); // 125000
|
|
511
|
+
console.log(result.contributionMargin); // 40
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
| Parameter | Type | Description |
|
|
515
|
+
|---|---|---|
|
|
516
|
+
| `fixedCosts` | `number` | Total fixed costs (must be > 0) |
|
|
517
|
+
| `pricePerUnit` | `number` | Selling price per unit (must be > 0) |
|
|
518
|
+
| `variableCostPerUnit` | `number` | Variable cost per unit (>= 0, must be < price) |
|
|
519
|
+
|
|
520
|
+
**Returns:** `BreakEvenResult`
|
|
521
|
+
|
|
522
|
+
| Field | Type | Description |
|
|
523
|
+
|---|---|---|
|
|
524
|
+
| `breakEvenUnits` | `number` | Units to sell to break even (rounded up) |
|
|
525
|
+
| `breakEvenRevenue` | `number` | Revenue at break-even point |
|
|
526
|
+
| `contributionMargin` | `number` | Price minus variable cost per unit |
|
|
527
|
+
| `contributionMarginRatio` | `number` | Contribution margin as a percentage of price |
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## Scripts
|
|
532
|
+
|
|
533
|
+
| Command | Description |
|
|
534
|
+
|---|---|
|
|
535
|
+
| `npm test` | Run all tests with Jest |
|
|
536
|
+
| `npm run build` | Compile TypeScript to `dist/` |
|
|
537
|
+
| `npm run publish-lib` | Build and publish to npm |
|
|
538
|
+
| `npm run publish-beta` | Build and publish with `beta` tag |
|
|
539
|
+
| `npm run publish-dryrun` | Build and simulate publish |
|
|
540
|
+
| `npm run patch` | Bump patch version |
|
|
541
|
+
| `npm run minor` | Bump minor version |
|
|
542
|
+
| `npm run major` | Bump major version |
|
|
543
|
+
|
|
544
|
+
## Testing
|
|
545
|
+
|
|
546
|
+
The library includes **173 tests** across 15 test suites covering:
|
|
547
|
+
|
|
548
|
+
- Input validation (boundary values, negative inputs, zero values)
|
|
549
|
+
- Mathematical correctness (verified against known financial formulas)
|
|
550
|
+
- Edge cases (rounding precision, exact payoff, single-period calculations)
|
|
551
|
+
- Safety guards (loop limits, maximum term lengths)
|
|
552
|
+
|
|
553
|
+
```bash
|
|
554
|
+
npm test
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## Project Structure
|
|
558
|
+
|
|
559
|
+
```
|
|
560
|
+
Calculators/
|
|
561
|
+
app/
|
|
562
|
+
index.ts # Library entry point (all exports)
|
|
563
|
+
calculators/
|
|
564
|
+
SimpleInterest.ts
|
|
565
|
+
CompoundInterest.ts
|
|
566
|
+
mortgage.ts
|
|
567
|
+
LoanAmortization.ts
|
|
568
|
+
RetirementSavings.ts
|
|
569
|
+
PresentValue.ts
|
|
570
|
+
DebtPayoff.ts
|
|
571
|
+
ROI.ts
|
|
572
|
+
RuleOf72.ts
|
|
573
|
+
InflationAdjustedReturn.ts
|
|
574
|
+
DollarCostAveraging.ts
|
|
575
|
+
AutoLoan.ts
|
|
576
|
+
SavingsGoal.ts
|
|
577
|
+
BreakEven.ts
|
|
578
|
+
TaxBracket.ts
|
|
579
|
+
__tests__/ # Jest test suites (one per calculator)
|
|
580
|
+
dist/ # Compiled output (generated)
|
|
581
|
+
tsconfig.json # Build config (strict mode)
|
|
582
|
+
tsconfig.test.json # Test config (extends build)
|
|
583
|
+
jest.config.js # Jest configuration
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## Contributing
|
|
587
|
+
|
|
588
|
+
1. Fork the repository
|
|
589
|
+
2. Create a feature branch: `git checkout -b feature/my-calculator`
|
|
590
|
+
3. Write tests first (TDD) in `app/__tests__/`
|
|
591
|
+
4. Implement the calculator in `app/calculators/`
|
|
592
|
+
5. Export from `app/index.ts`
|
|
593
|
+
6. Ensure all tests pass: `npm test`
|
|
594
|
+
7. Ensure the build is clean: `npm run build`
|
|
595
|
+
8. Submit a pull request
|
|
596
|
+
|
|
597
|
+
All calculators follow the same pattern:
|
|
598
|
+
|
|
599
|
+
```typescript
|
|
600
|
+
export interface MyCalculatorResult {
|
|
601
|
+
// typed result fields
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export default class MyCalculator {
|
|
605
|
+
constructor(/* parameters */) { /* assign fields */ }
|
|
606
|
+
|
|
607
|
+
_validate() {
|
|
608
|
+
// throw descriptive errors for invalid inputs
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
calculate(): MyCalculatorResult {
|
|
612
|
+
this._validate();
|
|
613
|
+
// computation with toFixed(2) rounding
|
|
614
|
+
return { /* result */ };
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
## License
|
|
620
|
+
|
|
621
|
+
[MIT](https://opensource.org/licenses/MIT)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface AutoLoanResult {
|
|
2
|
+
loanAmount: number;
|
|
3
|
+
monthlyPayment: number;
|
|
4
|
+
totalPaid: number;
|
|
5
|
+
totalInterest: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Auto loan calculator. Uses the standard amortization formula
|
|
9
|
+
* with term specified in months: M = P[r(1+r)^n] / [(1+r)^n - 1].
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const al = new AutoLoan(35000, 5000, 4.5, 60);
|
|
14
|
+
* const result = al.calculate();
|
|
15
|
+
* result.monthlyPayment; // 559.28
|
|
16
|
+
* result.totalInterest; // 3556.80
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export default class AutoLoan {
|
|
20
|
+
vehiclePrice: number;
|
|
21
|
+
downPayment: number;
|
|
22
|
+
rate: number;
|
|
23
|
+
termMonths: number;
|
|
24
|
+
/**
|
|
25
|
+
* @param vehiclePrice - Total vehicle price (must be > 0).
|
|
26
|
+
* @param downPayment - Down payment amount (>= 0, must be less than vehiclePrice).
|
|
27
|
+
* @param ratePercentage - Annual interest rate as a percentage (0 < rate < 100).
|
|
28
|
+
* @param termMonths - Loan term in months (positive integer).
|
|
29
|
+
*/
|
|
30
|
+
constructor(vehiclePrice: number, downPayment: number, ratePercentage: number, termMonths: number);
|
|
31
|
+
/**
|
|
32
|
+
* Validates that all inputs are within acceptable ranges.
|
|
33
|
+
* @throws {Error} If any input is invalid.
|
|
34
|
+
*/
|
|
35
|
+
_validate(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Computes the monthly payment, total paid, and total interest for the auto loan.
|
|
38
|
+
* @returns An {@link AutoLoanResult} with loanAmount, monthlyPayment, totalPaid, and totalInterest.
|
|
39
|
+
* @throws {Error} If any input is invalid.
|
|
40
|
+
*/
|
|
41
|
+
calculate(): AutoLoanResult;
|
|
42
|
+
}
|