calcufly-finance 1.0.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -0
  3. package/index.js +528 -0
  4. package/package.json +17 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 CalcuFly (https://calcufly.com)
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,57 @@
1
+ # calcufly-finance
2
+
3
+ Professional finance calculator functions for Node.js. Mortgage, loan, investment, retirement, tax, ROI and more.
4
+
5
+ Part of the [CalcuFly](https://calcufly.com) calculator suite — 600+ free online calculators.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install calcufly-finance
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```javascript
16
+ const finance = require('calcufly-finance');
17
+
18
+ // Mortgage calculation
19
+ const mortgage = finance.mortgage(300000, 6.5, 30);
20
+ console.log(mortgage.monthlyPayment); // 1896.20
21
+
22
+ // Compound interest
23
+ const growth = finance.compoundInterest(10000, 7, 10);
24
+ console.log(growth.futureValue); // 20096.61
25
+
26
+ // ROI
27
+ const roi = finance.roi(5000, 7500);
28
+ console.log(roi.roiPercent); // 50%
29
+ ```
30
+
31
+ ## API Reference
32
+
33
+ | Function | Description |
34
+ |----------|-------------|
35
+ | `mortgage(principal, rate, years)` | Monthly mortgage payment |
36
+ | `compoundInterest(principal, rate, years, n)` | Compound interest growth |
37
+ | `simpleInterest(principal, rate, years)` | Simple interest |
38
+ | `loanPayment(principal, rate, years)` | Loan monthly payment |
39
+ | `amortizationSchedule(principal, rate, years)` | Full amortization table |
40
+ | `roi(initial, final)` | Return on investment |
41
+ | `profitMargin(revenue, cost)` | Gross profit margin |
42
+ | `breakEven(fixed, price, cost)` | Break-even analysis |
43
+ | `futureValue(pv, rate, years)` | Future value of money |
44
+ | `presentValue(fv, rate, years)` | Present value of money |
45
+ | `ruleOf72(rate)` | Years to double investment |
46
+ | `retirementSavings(...)` | Retirement planning |
47
+ | `fireNumber(expenses, rate)` | FIRE movement target |
48
+ | `tipCalculator(bill, tipPct, people)` | Tip splitting |
49
+ | `discountPrice(price, pct)` | Discount calculation |
50
+ | `inflationAdjust(amount, rate, years)` | Inflation adjustment |
51
+ | `depreciationStraightLine(cost, salvage, life)` | Depreciation schedule |
52
+
53
+ Try these calculations online at **[CalcuFly.com](https://calcufly.com)** — free, no signup required.
54
+
55
+ ## License
56
+
57
+ MIT — [CalcuFly](https://calcufly.com)
package/index.js ADDED
@@ -0,0 +1,528 @@
1
+ /**
2
+ * calcufly-finance
3
+ * Professional finance calculator functions
4
+ * https://calcufly.com
5
+ *
6
+ * Try these calculations online at https://calcufly.com
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /**
12
+ * Calculate monthly mortgage payment and totals.
13
+ * @param {number} principal - Loan amount
14
+ * @param {number} annualRate - Annual interest rate (e.g. 6.5 for 6.5%)
15
+ * @param {number} years - Loan term in years
16
+ * @returns {{ monthlyPayment: number, totalPayment: number, totalInterest: number }}
17
+ */
18
+ function mortgage(principal, annualRate, years) {
19
+ const r = annualRate / 100 / 12;
20
+ const n = years * 12;
21
+ if (r === 0) {
22
+ const monthlyPayment = principal / n;
23
+ return { monthlyPayment, totalPayment: principal, totalInterest: 0 };
24
+ }
25
+ const monthlyPayment = principal * (r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1);
26
+ const totalPayment = monthlyPayment * n;
27
+ const totalInterest = totalPayment - principal;
28
+ return {
29
+ monthlyPayment: parseFloat(monthlyPayment.toFixed(2)),
30
+ totalPayment: parseFloat(totalPayment.toFixed(2)),
31
+ totalInterest: parseFloat(totalInterest.toFixed(2)),
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Calculate compound interest.
37
+ * @param {number} principal - Initial amount
38
+ * @param {number} rate - Annual interest rate (e.g. 5 for 5%)
39
+ * @param {number} years - Time in years
40
+ * @param {number} [n=12] - Compounding periods per year
41
+ * @returns {{ futureValue: number, totalInterest: number }}
42
+ */
43
+ function compoundInterest(principal, rate, years, n = 12) {
44
+ const r = rate / 100;
45
+ const futureValue = principal * Math.pow(1 + r / n, n * years);
46
+ const totalInterest = futureValue - principal;
47
+ return {
48
+ futureValue: parseFloat(futureValue.toFixed(2)),
49
+ totalInterest: parseFloat(totalInterest.toFixed(2)),
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Calculate simple interest.
55
+ * @param {number} principal - Initial amount
56
+ * @param {number} rate - Annual interest rate (e.g. 5 for 5%)
57
+ * @param {number} years - Time in years
58
+ * @returns {{ interest: number, total: number }}
59
+ */
60
+ function simpleInterest(principal, rate, years) {
61
+ const interest = principal * (rate / 100) * years;
62
+ const total = principal + interest;
63
+ return {
64
+ interest: parseFloat(interest.toFixed(2)),
65
+ total: parseFloat(total.toFixed(2)),
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Calculate loan payment (same formula as mortgage but named generically).
71
+ * @param {number} principal - Loan amount
72
+ * @param {number} annualRate - Annual interest rate (e.g. 6 for 6%)
73
+ * @param {number} years - Loan term in years
74
+ * @returns {{ monthlyPayment: number, totalPayment: number, totalInterest: number }}
75
+ */
76
+ function loanPayment(principal, annualRate, years) {
77
+ return mortgage(principal, annualRate, years);
78
+ }
79
+
80
+ /**
81
+ * Generate a full amortization schedule.
82
+ * @param {number} principal - Loan amount
83
+ * @param {number} annualRate - Annual interest rate (e.g. 6 for 6%)
84
+ * @param {number} years - Loan term in years
85
+ * @returns {Array<{ month: number, payment: number, principal: number, interest: number, balance: number }>}
86
+ */
87
+ function amortizationSchedule(principal, annualRate, years) {
88
+ const r = annualRate / 100 / 12;
89
+ const n = years * 12;
90
+ const schedule = [];
91
+ let balance = principal;
92
+
93
+ const monthlyPayment = r === 0
94
+ ? principal / n
95
+ : principal * (r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1);
96
+
97
+ for (let month = 1; month <= n; month++) {
98
+ const interestPayment = balance * r;
99
+ const principalPayment = monthlyPayment - interestPayment;
100
+ balance -= principalPayment;
101
+ schedule.push({
102
+ month,
103
+ payment: parseFloat(monthlyPayment.toFixed(2)),
104
+ principal: parseFloat(principalPayment.toFixed(2)),
105
+ interest: parseFloat(interestPayment.toFixed(2)),
106
+ balance: parseFloat(Math.max(0, balance).toFixed(2)),
107
+ });
108
+ }
109
+ return schedule;
110
+ }
111
+
112
+ /**
113
+ * Calculate the effective APR including fees.
114
+ * @param {number} principal - Loan amount
115
+ * @param {number} totalFees - Total fees/closing costs
116
+ * @param {number} rate - Nominal annual rate (e.g. 6 for 6%)
117
+ * @param {number} years - Loan term in years
118
+ * @returns {number} effectiveAPR as a percentage
119
+ */
120
+ function apr(principal, totalFees, rate, years) {
121
+ const adjustedPrincipal = principal - totalFees;
122
+ const r = rate / 100 / 12;
123
+ const n = years * 12;
124
+ const monthlyPayment = principal * (r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1);
125
+
126
+ // Newton-Raphson to find APR
127
+ let guess = rate / 100 / 12;
128
+ for (let i = 0; i < 1000; i++) {
129
+ const f = monthlyPayment * (1 - Math.pow(1 + guess, -n)) / guess - adjustedPrincipal;
130
+ const fPrime = monthlyPayment * (
131
+ (Math.pow(1 + guess, -n) - 1) / (guess * guess) +
132
+ n * Math.pow(1 + guess, -n - 1) / guess
133
+ );
134
+ const next = guess - f / fPrime;
135
+ if (Math.abs(next - guess) < 1e-10) break;
136
+ guess = next;
137
+ }
138
+ return parseFloat((guess * 12 * 100).toFixed(4));
139
+ }
140
+
141
+ /**
142
+ * Calculate effective Annual Percentage Yield.
143
+ * @param {number} nominalRate - Nominal annual rate (e.g. 5 for 5%)
144
+ * @param {number} compoundingPeriods - Number of compounding periods per year
145
+ * @returns {number} effectiveAPY as a percentage
146
+ */
147
+ function apy(nominalRate, compoundingPeriods) {
148
+ const r = nominalRate / 100;
149
+ const effectiveAPY = (Math.pow(1 + r / compoundingPeriods, compoundingPeriods) - 1) * 100;
150
+ return parseFloat(effectiveAPY.toFixed(4));
151
+ }
152
+
153
+ /**
154
+ * Calculate Return on Investment.
155
+ * @param {number} initialInvestment - Amount invested
156
+ * @param {number} finalValue - Final value of investment
157
+ * @returns {{ roi: number, roiPercent: number }}
158
+ */
159
+ function roi(initialInvestment, finalValue) {
160
+ const roiValue = finalValue - initialInvestment;
161
+ const roiPercent = (roiValue / initialInvestment) * 100;
162
+ return {
163
+ roi: parseFloat(roiValue.toFixed(2)),
164
+ roiPercent: parseFloat(roiPercent.toFixed(2)),
165
+ };
166
+ }
167
+
168
+ /**
169
+ * Calculate gross profit margin.
170
+ * @param {number} revenue - Total revenue
171
+ * @param {number} cost - Cost of goods sold
172
+ * @returns {{ grossMargin: number, grossMarginPercent: number }}
173
+ */
174
+ function profitMargin(revenue, cost) {
175
+ const grossMargin = revenue - cost;
176
+ const grossMarginPercent = (grossMargin / revenue) * 100;
177
+ return {
178
+ grossMargin: parseFloat(grossMargin.toFixed(2)),
179
+ grossMarginPercent: parseFloat(grossMarginPercent.toFixed(2)),
180
+ };
181
+ }
182
+
183
+ /**
184
+ * Calculate markup percentage.
185
+ * @param {number} cost - Cost of item
186
+ * @param {number} sellingPrice - Selling price
187
+ * @returns {{ markup: number, markupPercent: number }}
188
+ */
189
+ function markup(cost, sellingPrice) {
190
+ const markupValue = sellingPrice - cost;
191
+ const markupPercent = (markupValue / cost) * 100;
192
+ return {
193
+ markup: parseFloat(markupValue.toFixed(2)),
194
+ markupPercent: parseFloat(markupPercent.toFixed(2)),
195
+ };
196
+ }
197
+
198
+ /**
199
+ * Calculate break-even point.
200
+ * @param {number} fixedCosts - Total fixed costs
201
+ * @param {number} pricePerUnit - Selling price per unit
202
+ * @param {number} costPerUnit - Variable cost per unit
203
+ * @returns {{ breakEvenUnits: number, breakEvenRevenue: number }}
204
+ */
205
+ function breakEven(fixedCosts, pricePerUnit, costPerUnit) {
206
+ const contributionMargin = pricePerUnit - costPerUnit;
207
+ const breakEvenUnits = fixedCosts / contributionMargin;
208
+ const breakEvenRevenue = breakEvenUnits * pricePerUnit;
209
+ return {
210
+ breakEvenUnits: parseFloat(breakEvenUnits.toFixed(2)),
211
+ breakEvenRevenue: parseFloat(breakEvenRevenue.toFixed(2)),
212
+ };
213
+ }
214
+
215
+ /**
216
+ * Calculate future value of a present sum.
217
+ * @param {number} presentValue - Current amount
218
+ * @param {number} rate - Annual interest rate (e.g. 5 for 5%)
219
+ * @param {number} years - Time in years
220
+ * @returns {number} futureValue
221
+ */
222
+ function futureValue(presentValue, rate, years) {
223
+ const fv = presentValue * Math.pow(1 + rate / 100, years);
224
+ return parseFloat(fv.toFixed(2));
225
+ }
226
+
227
+ /**
228
+ * Calculate present value of a future sum.
229
+ * @param {number} fv - Future value
230
+ * @param {number} rate - Annual discount rate (e.g. 5 for 5%)
231
+ * @param {number} years - Time in years
232
+ * @returns {number} presentValue
233
+ */
234
+ function presentValue(fv, rate, years) {
235
+ const pv = fv / Math.pow(1 + rate / 100, years);
236
+ return parseFloat(pv.toFixed(2));
237
+ }
238
+
239
+ /**
240
+ * Estimate years to double an investment using the Rule of 72.
241
+ * @param {number} rate - Annual interest rate (e.g. 6 for 6%)
242
+ * @returns {number} yearsToDouble
243
+ */
244
+ function ruleOf72(rate) {
245
+ return parseFloat((72 / rate).toFixed(2));
246
+ }
247
+
248
+ /**
249
+ * Sort debts using the Debt Snowball method (lowest balance first).
250
+ * @param {Array<{ name: string, balance: number, minPayment: number }>} debts
251
+ * @returns {Array} Sorted payoff order with debt info
252
+ */
253
+ function debtSnowball(debts) {
254
+ return [...debts]
255
+ .sort((a, b) => a.balance - b.balance)
256
+ .map((d, i) => ({ ...d, payoffOrder: i + 1 }));
257
+ }
258
+
259
+ /**
260
+ * Sort debts using the Debt Avalanche method (highest interest rate first).
261
+ * @param {Array<{ name: string, balance: number, minPayment: number, rate: number }>} debts
262
+ * @returns {Array} Sorted payoff order with debt info
263
+ */
264
+ function debtAvalanche(debts) {
265
+ return [...debts]
266
+ .sort((a, b) => b.rate - a.rate)
267
+ .map((d, i) => ({ ...d, payoffOrder: i + 1 }));
268
+ }
269
+
270
+ /**
271
+ * Estimate retirement savings at retirement age.
272
+ * @param {number} currentAge - Current age
273
+ * @param {number} retirementAge - Target retirement age
274
+ * @param {number} currentSavings - Current savings balance
275
+ * @param {number} monthlyContribution - Monthly contribution amount
276
+ * @param {number} annualReturn - Expected annual return rate (e.g. 7 for 7%)
277
+ * @returns {{ totalAtRetirement: number }}
278
+ */
279
+ function retirementSavings(currentAge, retirementAge, currentSavings, monthlyContribution, annualReturn) {
280
+ const years = retirementAge - currentAge;
281
+ const months = years * 12;
282
+ const r = annualReturn / 100 / 12;
283
+
284
+ const futureCurrentSavings = currentSavings * Math.pow(1 + r, months);
285
+ const futureContributions = r === 0
286
+ ? monthlyContribution * months
287
+ : monthlyContribution * (Math.pow(1 + r, months) - 1) / r;
288
+
289
+ const totalAtRetirement = futureCurrentSavings + futureContributions;
290
+ return { totalAtRetirement: parseFloat(totalAtRetirement.toFixed(2)) };
291
+ }
292
+
293
+ /**
294
+ * Calculate FIRE (Financial Independence, Retire Early) number.
295
+ * @param {number} annualExpenses - Annual living expenses
296
+ * @param {number} [withdrawalRate=0.04] - Safe withdrawal rate (e.g. 0.04 for 4%)
297
+ * @returns {number} requiredSavings
298
+ */
299
+ function fireNumber(annualExpenses, withdrawalRate = 0.04) {
300
+ const required = annualExpenses / withdrawalRate;
301
+ return parseFloat(required.toFixed(2));
302
+ }
303
+
304
+ /**
305
+ * Convert annual salary to hourly rate.
306
+ * @param {number} annualSalary - Annual salary amount
307
+ * @param {number} [hoursPerWeek=40] - Hours worked per week
308
+ * @param {number} [weeksPerYear=52] - Weeks worked per year
309
+ * @returns {number} hourlyRate
310
+ */
311
+ function salaryToHourly(annualSalary, hoursPerWeek = 40, weeksPerYear = 52) {
312
+ const hourlyRate = annualSalary / (hoursPerWeek * weeksPerYear);
313
+ return parseFloat(hourlyRate.toFixed(2));
314
+ }
315
+
316
+ /**
317
+ * Convert hourly rate to annual salary.
318
+ * @param {number} hourlyRate - Hourly pay rate
319
+ * @param {number} [hoursPerWeek=40] - Hours worked per week
320
+ * @param {number} [weeksPerYear=52] - Weeks worked per year
321
+ * @returns {number} annualSalary
322
+ */
323
+ function hourlyToSalary(hourlyRate, hoursPerWeek = 40, weeksPerYear = 52) {
324
+ const annualSalary = hourlyRate * hoursPerWeek * weeksPerYear;
325
+ return parseFloat(annualSalary.toFixed(2));
326
+ }
327
+
328
+ /**
329
+ * Calculate tip and split a restaurant bill.
330
+ * @param {number} billAmount - Total bill amount
331
+ * @param {number} tipPercent - Tip percentage (e.g. 18 for 18%)
332
+ * @param {number} [numPeople=1] - Number of people splitting the bill
333
+ * @returns {{ tipAmount: number, totalAmount: number, perPerson: number }}
334
+ */
335
+ function tipCalculator(billAmount, tipPercent, numPeople = 1) {
336
+ const tipAmount = billAmount * (tipPercent / 100);
337
+ const totalAmount = billAmount + tipAmount;
338
+ const perPerson = totalAmount / numPeople;
339
+ return {
340
+ tipAmount: parseFloat(tipAmount.toFixed(2)),
341
+ totalAmount: parseFloat(totalAmount.toFixed(2)),
342
+ perPerson: parseFloat(perPerson.toFixed(2)),
343
+ };
344
+ }
345
+
346
+ /**
347
+ * Calculate discounted price.
348
+ * @param {number} originalPrice - Original price
349
+ * @param {number} discountPercent - Discount percentage (e.g. 20 for 20%)
350
+ * @returns {{ discount: number, finalPrice: number }}
351
+ */
352
+ function discountPrice(originalPrice, discountPercent) {
353
+ const discount = originalPrice * (discountPercent / 100);
354
+ const finalPrice = originalPrice - discount;
355
+ return {
356
+ discount: parseFloat(discount.toFixed(2)),
357
+ finalPrice: parseFloat(finalPrice.toFixed(2)),
358
+ };
359
+ }
360
+
361
+ /**
362
+ * Adjust an amount for inflation over time.
363
+ * @param {number} amount - Original amount
364
+ * @param {number} inflationRate - Annual inflation rate (e.g. 3 for 3%)
365
+ * @param {number} years - Number of years
366
+ * @returns {number} adjustedAmount (future purchasing cost equivalent)
367
+ */
368
+ function inflationAdjust(amount, inflationRate, years) {
369
+ const adjusted = amount * Math.pow(1 + inflationRate / 100, years);
370
+ return parseFloat(adjusted.toFixed(2));
371
+ }
372
+
373
+ /**
374
+ * Calculate net cash flow from inflows and outflows.
375
+ * @param {number[]} inflows - Array of inflow amounts
376
+ * @param {number[]} outflows - Array of outflow amounts
377
+ * @returns {{ netCashFlow: number, totalInflows: number, totalOutflows: number }}
378
+ */
379
+ function cashFlow(inflows, outflows) {
380
+ const totalInflows = inflows.reduce((sum, v) => sum + v, 0);
381
+ const totalOutflows = outflows.reduce((sum, v) => sum + v, 0);
382
+ const netCashFlow = totalInflows - totalOutflows;
383
+ return {
384
+ netCashFlow: parseFloat(netCashFlow.toFixed(2)),
385
+ totalInflows: parseFloat(totalInflows.toFixed(2)),
386
+ totalOutflows: parseFloat(totalOutflows.toFixed(2)),
387
+ };
388
+ }
389
+
390
+ /**
391
+ * Calculate straight-line depreciation schedule.
392
+ * @param {number} cost - Original asset cost
393
+ * @param {number} salvageValue - Estimated salvage/residual value
394
+ * @param {number} usefulLife - Useful life in years
395
+ * @returns {{ annualDepreciation: number, schedule: Array<{ year: number, depreciation: number, bookValue: number }> }}
396
+ */
397
+ function depreciationStraightLine(cost, salvageValue, usefulLife) {
398
+ const annualDepreciation = (cost - salvageValue) / usefulLife;
399
+ const schedule = [];
400
+ let bookValue = cost;
401
+ for (let year = 1; year <= usefulLife; year++) {
402
+ bookValue -= annualDepreciation;
403
+ schedule.push({
404
+ year,
405
+ depreciation: parseFloat(annualDepreciation.toFixed(2)),
406
+ bookValue: parseFloat(Math.max(salvageValue, bookValue).toFixed(2)),
407
+ });
408
+ }
409
+ return {
410
+ annualDepreciation: parseFloat(annualDepreciation.toFixed(2)),
411
+ schedule,
412
+ };
413
+ }
414
+
415
+ /**
416
+ * Calculate net present value of a series of cash flows.
417
+ * @param {number} discountRate - Annual discount rate (e.g. 10 for 10%)
418
+ * @param {number[]} cashFlows - Array of cash flows (index 0 = year 0, typically negative)
419
+ * @returns {number} npv
420
+ */
421
+ function npv(discountRate, cashFlows) {
422
+ const r = discountRate / 100;
423
+ const result = cashFlows.reduce((acc, cf, t) => acc + cf / Math.pow(1 + r, t), 0);
424
+ return parseFloat(result.toFixed(2));
425
+ }
426
+
427
+ /**
428
+ * Calculate Internal Rate of Return using Newton-Raphson.
429
+ * @param {number[]} cashFlows - Array of cash flows (index 0 is typically negative initial investment)
430
+ * @returns {number} irr as a percentage
431
+ */
432
+ function irr(cashFlows) {
433
+ let rate = 0.1;
434
+ for (let i = 0; i < 1000; i++) {
435
+ let npvVal = 0;
436
+ let npvDerivative = 0;
437
+ for (let t = 0; t < cashFlows.length; t++) {
438
+ npvVal += cashFlows[t] / Math.pow(1 + rate, t);
439
+ npvDerivative -= t * cashFlows[t] / Math.pow(1 + rate, t + 1);
440
+ }
441
+ const next = rate - npvVal / npvDerivative;
442
+ if (Math.abs(next - rate) < 1e-10) break;
443
+ rate = next;
444
+ }
445
+ return parseFloat((rate * 100).toFixed(4));
446
+ }
447
+
448
+ /**
449
+ * Calculate debt-to-income ratio.
450
+ * @param {number} monthlyDebtPayments - Total monthly debt payments
451
+ * @param {number} grossMonthlyIncome - Gross monthly income
452
+ * @returns {{ dtiRatio: number, dtiPercent: number }}
453
+ */
454
+ function debtToIncome(monthlyDebtPayments, grossMonthlyIncome) {
455
+ const dtiRatio = monthlyDebtPayments / grossMonthlyIncome;
456
+ const dtiPercent = dtiRatio * 100;
457
+ return {
458
+ dtiRatio: parseFloat(dtiRatio.toFixed(4)),
459
+ dtiPercent: parseFloat(dtiPercent.toFixed(2)),
460
+ };
461
+ }
462
+
463
+ /**
464
+ * Calculate savings goal progress and time to reach goal.
465
+ * @param {number} goalAmount - Target savings amount
466
+ * @param {number} currentSavings - Current savings balance
467
+ * @param {number} monthlyContribution - Monthly savings contribution
468
+ * @param {number} annualReturn - Expected annual return rate (e.g. 5 for 5%)
469
+ * @returns {{ monthsToGoal: number, progressPercent: number }}
470
+ */
471
+ function savingsGoal(goalAmount, currentSavings, monthlyContribution, annualReturn) {
472
+ const r = annualReturn / 100 / 12;
473
+ const progressPercent = (currentSavings / goalAmount) * 100;
474
+ let balance = currentSavings;
475
+ let months = 0;
476
+ const maxMonths = 600;
477
+ while (balance < goalAmount && months < maxMonths) {
478
+ balance = balance * (1 + r) + monthlyContribution;
479
+ months++;
480
+ }
481
+ return {
482
+ monthsToGoal: months >= maxMonths ? null : months,
483
+ progressPercent: parseFloat(progressPercent.toFixed(2)),
484
+ };
485
+ }
486
+
487
+ /**
488
+ * Calculate currency exchange.
489
+ * @param {number} amount - Amount to convert
490
+ * @param {number} exchangeRate - Exchange rate (units of target currency per 1 unit of source)
491
+ * @returns {number} convertedAmount
492
+ */
493
+ function currencyConvert(amount, exchangeRate) {
494
+ return parseFloat((amount * exchangeRate).toFixed(2));
495
+ }
496
+
497
+ module.exports = {
498
+ mortgage,
499
+ compoundInterest,
500
+ simpleInterest,
501
+ loanPayment,
502
+ amortizationSchedule,
503
+ apr,
504
+ apy,
505
+ roi,
506
+ profitMargin,
507
+ markup,
508
+ breakEven,
509
+ futureValue,
510
+ presentValue,
511
+ ruleOf72,
512
+ debtSnowball,
513
+ debtAvalanche,
514
+ retirementSavings,
515
+ fireNumber,
516
+ salaryToHourly,
517
+ hourlyToSalary,
518
+ tipCalculator,
519
+ discountPrice,
520
+ inflationAdjust,
521
+ cashFlow,
522
+ depreciationStraightLine,
523
+ npv,
524
+ irr,
525
+ debtToIncome,
526
+ savingsGoal,
527
+ currencyConvert,
528
+ };
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "calcufly-finance",
3
+ "version": "1.0.0",
4
+ "description": "Professional finance calculator functions - mortgage, loan, investment, retirement, tax calculations. By CalcuFly.com",
5
+ "main": "index.js",
6
+ "keywords": ["finance", "calculator", "mortgage", "loan", "investment", "compound-interest", "amortization", "retirement", "tax", "roi", "apr", "apy", "debt", "savings", "budget"],
7
+ "author": "CalcuFly <contact@calcufly.com>",
8
+ "license": "MIT",
9
+ "homepage": "https://calcufly.com",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/mansouewalks-bit2/calcufly-finance"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/mansouewalks-bit2/calcufly-finance/issues"
16
+ }
17
+ }