moneyfunx 3.0.9 → 3.0.10
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/build/lib/debt/payments.d.ts +2 -2
- package/build/lib/debt/payments.d.ts.map +1 -1
- package/build/lib/debt/payments.js +22 -16
- package/build/lib/investment/contributions.d.ts +7 -7
- package/build/lib/investment/contributions.d.ts.map +1 -1
- package/build/lib/investment/contributions.js +18 -13
- package/package.json +1 -1
|
@@ -32,8 +32,8 @@ export declare function determineCarryover(loan: Loan, loanPayment: number, loan
|
|
|
32
32
|
*
|
|
33
33
|
* @param {Loan} loan The loan to amortize payments for
|
|
34
34
|
* @param {number} principal The amount borrowed
|
|
35
|
-
* @param {number} payment The amount to pay to the loan's balance each period
|
|
36
|
-
* @param {number} numPayments The number of periods to make payments to the loan
|
|
35
|
+
* @param {number|null} payment The amount to pay to the loan's balance each period
|
|
36
|
+
* @param {number|null} numPayments The number of periods to make payments to the loan
|
|
37
37
|
* @param {number} startPeriod An initial offset of periods to 'fast-forward' the state of the loan to prior to calculation of each period
|
|
38
38
|
* @param {number} carryover An additional amount to pay towards a loan, used when a residual amount is available from paying off the previous loan this period
|
|
39
39
|
* @returns {PaymentRecord[]} The amortization schedule for the number of payments of payment made to the loan from the provided start period
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["../../../src/lib/debt/payments.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["../../../src/lib/debt/payments.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EACV,aAAa,EAEb,oBAAoB,EACrB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,KAAK,EAAE,EACd,OAAO,EAAE,MAAM,GACd,MAAM,CAYR;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,OAAO,GACrB,MAAM,CAOR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,WAAW,GAAE,MAAU,EACvB,SAAS,GAAE,MAAU,GACpB,aAAa,EAAE,CA2BjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,EAAE,MAAM,EACf,aAAa,GAAE,OAAe,GAC7B,oBAAoB,CA0ItB"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
6
|
import * as errors from '../errors.js';
|
|
7
|
+
import { TOTALS } from '../constants.js';
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
9
10
|
* Calculates the extra amount in a payment after all loans' minimum payments are met
|
|
@@ -45,27 +46,24 @@ export function determineCarryover(loan, loanPayment, loanFinalPayment, reduceMi
|
|
|
45
46
|
*
|
|
46
47
|
* @param {Loan} loan The loan to amortize payments for
|
|
47
48
|
* @param {number} principal The amount borrowed
|
|
48
|
-
* @param {number} payment The amount to pay to the loan's balance each period
|
|
49
|
-
* @param {number} numPayments The number of periods to make payments to the loan
|
|
49
|
+
* @param {number|null} payment The amount to pay to the loan's balance each period
|
|
50
|
+
* @param {number|null} numPayments The number of periods to make payments to the loan
|
|
50
51
|
* @param {number} startPeriod An initial offset of periods to 'fast-forward' the state of the loan to prior to calculation of each period
|
|
51
52
|
* @param {number} carryover An additional amount to pay towards a loan, used when a residual amount is available from paying off the previous loan this period
|
|
52
53
|
* @returns {PaymentRecord[]} The amortization schedule for the number of payments of payment made to the loan from the provided start period
|
|
53
54
|
*/
|
|
54
55
|
export function amortizePayments(loan, principal, payment, numPayments, startPeriod = 0, carryover = 0) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (numPayments === null) {
|
|
60
|
-
numPayments = loan.numPaymentsToZero(payment);
|
|
61
|
-
}
|
|
56
|
+
// Strict null check handling
|
|
57
|
+
let actualPayment = (payment !== null) ? payment : loan.minPayment;
|
|
58
|
+
actualPayment = loan.validatePayment(actualPayment);
|
|
59
|
+
let actualNumPayments = (numPayments !== null) ? numPayments : loan.numPaymentsToZero(actualPayment);
|
|
62
60
|
const amortizationSchedule = [];
|
|
63
61
|
let principalRemaining = principal;
|
|
64
|
-
for (let period = 0; period <
|
|
62
|
+
for (let period = 0; period < actualNumPayments; period++) {
|
|
65
63
|
const interestThisPeriod = loan.accrueInterest(principalRemaining);
|
|
66
|
-
const principalThisPeriod = Math.min((period ===
|
|
67
|
-
?
|
|
68
|
-
:
|
|
64
|
+
const principalThisPeriod = Math.min((period === actualNumPayments - 1
|
|
65
|
+
? actualPayment + carryover
|
|
66
|
+
: actualPayment) - interestThisPeriod, principalRemaining);
|
|
69
67
|
principalRemaining -= principalThisPeriod;
|
|
70
68
|
amortizationSchedule.push({
|
|
71
69
|
period: startPeriod + period + 1,
|
|
@@ -110,11 +108,14 @@ export function payLoans(loans, payment, reduceMinimum = false) {
|
|
|
110
108
|
const firstLoanPrincipalRemaining = loanPrincipalsRemaining[firstLoan.id];
|
|
111
109
|
const periodsToPay = firstLoan.numPaymentsToZero(firstLoanPayment, firstLoanPrincipalRemaining);
|
|
112
110
|
const firstLoanAmortizedPayments = amortizePayments(firstLoan, firstLoanPrincipalRemaining, firstLoanPayment, periodsToPay, periodsElapsed);
|
|
113
|
-
|
|
111
|
+
// Calculate final payment logic
|
|
112
|
+
const finalPrincipal = firstLoan.principalRemaining(periodsToPay - 1, firstLoanPayment, firstLoanPrincipalRemaining);
|
|
113
|
+
const firstLoanFinalPayment = finalPrincipal + firstLoan.accrueInterest(finalPrincipal);
|
|
114
114
|
paymentSchedule[firstLoan.id].amortizationSchedule = [
|
|
115
115
|
...paymentSchedule[firstLoan.id].amortizationSchedule,
|
|
116
116
|
...firstLoanAmortizedPayments
|
|
117
117
|
];
|
|
118
|
+
// Merge into totals
|
|
118
119
|
totalAmortizationSchedule = [
|
|
119
120
|
...totalAmortizationSchedule,
|
|
120
121
|
...firstLoanAmortizedPayments
|
|
@@ -132,6 +133,7 @@ export function payLoans(loans, payment, reduceMinimum = false) {
|
|
|
132
133
|
...paymentSchedule[loan.id].amortizationSchedule,
|
|
133
134
|
...loanAmortizedPayments,
|
|
134
135
|
];
|
|
136
|
+
// Safe map for totals
|
|
135
137
|
totalAmortizationSchedule = totalAmortizationSchedule.map((element) => {
|
|
136
138
|
const matchedInnerElement = loanAmortizedPayments.find((innerElement) => innerElement.period === element.period);
|
|
137
139
|
return (matchedInnerElement != null)
|
|
@@ -144,7 +146,11 @@ export function payLoans(loans, payment, reduceMinimum = false) {
|
|
|
144
146
|
}
|
|
145
147
|
: element;
|
|
146
148
|
});
|
|
147
|
-
|
|
149
|
+
// Update remaining principals for next iteration
|
|
150
|
+
const currentLoanSchedule = paymentSchedule[loan.id].amortizationSchedule;
|
|
151
|
+
if (currentLoanSchedule.length > 0) {
|
|
152
|
+
loanPrincipalsRemaining[loan.id] = currentLoanSchedule[currentLoanSchedule.length - 1].principalRemaining;
|
|
153
|
+
}
|
|
148
154
|
});
|
|
149
155
|
periodsElapsed += periodsToPay;
|
|
150
156
|
}
|
|
@@ -155,7 +161,7 @@ export function payLoans(loans, payment, reduceMinimum = false) {
|
|
|
155
161
|
totalLifetimeInterest += loanLifetimeInterest;
|
|
156
162
|
totalLifetimePrincipal += loan.currentBalance;
|
|
157
163
|
}
|
|
158
|
-
paymentSchedule
|
|
164
|
+
paymentSchedule[TOTALS] = {
|
|
159
165
|
lifetimeInterest: totalLifetimeInterest,
|
|
160
166
|
lifetimePrincipal: totalLifetimePrincipal,
|
|
161
167
|
amortizationSchedule: totalAmortizationSchedule,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
6
|
import type { Instrument } from '../investment/instrument.js';
|
|
7
|
-
import { ContributionRecord, InstrumentsContributionSchedule } from '../investment/contributionTypes.js';
|
|
7
|
+
import type { ContributionRecord, InstrumentsContributionSchedule } from '../investment/contributionTypes.js';
|
|
8
8
|
/**
|
|
9
9
|
*
|
|
10
10
|
* @param {IInstrument[]} instruments The instruments to allocate maximum contributions
|
|
@@ -19,8 +19,8 @@ export declare function determineExtraContribution(instruments: Instrument[], co
|
|
|
19
19
|
* @param {number} contribution The amount to contribute to the instrument's balance
|
|
20
20
|
* @param {number[int]} startPeriod The initial offset for period values
|
|
21
21
|
* @param {boolean} accrueBeforeContribution A flag for ordering operations of accrual (A) and contribution (C)
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* true: A -> C
|
|
23
|
+
* false: C -> A
|
|
24
24
|
* @returns {ContributionRecord} The amortized contribution
|
|
25
25
|
*/
|
|
26
26
|
export declare function amortizeContribution(instrument: Instrument, currentBalance: number, contribution: number, startPeriod?: number, accrueBeforeContribution?: boolean): ContributionRecord;
|
|
@@ -34,8 +34,8 @@ export declare function amortizeContribution(instrument: Instrument, currentBala
|
|
|
34
34
|
* @param {number} numContributions The number of periods to make contributions to the instrument
|
|
35
35
|
* @param {number[int]} startPeriod The inital offset for period values
|
|
36
36
|
* @param {boolean} accrueBeforeContribution A flag for ordering operations of accrual (A) and contribution (C)
|
|
37
|
-
*
|
|
38
|
-
*
|
|
37
|
+
* true: A -> C
|
|
38
|
+
* false: C -> A
|
|
39
39
|
* @returns {ContributionRecord[]} The amortized contributions
|
|
40
40
|
*/
|
|
41
41
|
export declare function amortizeContributions(instrument: Instrument, initialBalance: number, contribution: number, numContributions: number, startPeriod?: number, accrueBeforeContribution?: boolean): ContributionRecord[];
|
|
@@ -45,8 +45,8 @@ export declare function amortizeContributions(instrument: Instrument, initialBal
|
|
|
45
45
|
* @param {number} contribution The total amount to contirbute each period
|
|
46
46
|
* @param {number[int]} numContributions The number of periods to contribute
|
|
47
47
|
* @param {boolean} accrueBeforeContribution A flag for ordering operations of accrual (A) and contribution (C)
|
|
48
|
-
*
|
|
49
|
-
*
|
|
48
|
+
* true: A -> C
|
|
49
|
+
* false: C -> A
|
|
50
50
|
* @returns {InstrumentsContributionSchedule} The amortized contributions for all instruments
|
|
51
51
|
*/
|
|
52
52
|
export declare function contributeInstruments(instruments: Instrument[], contribution: number, numContributions: number, accrueBeforeContribution?: boolean): InstrumentsContributionSchedule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contributions.d.ts","sourceRoot":"","sources":["../../../src/lib/investment/contributions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"contributions.d.ts","sourceRoot":"","sources":["../../../src/lib/investment/contributions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EACV,kBAAkB,EAClB,+BAA+B,EAGhC,MAAM,oCAAoC,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,UAAU,EAAE,EACzB,YAAY,EAAE,MAAM,GACnB,MAAM,CAMR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,WAAW,GAAE,MAAU,EACvB,wBAAwB,GAAE,OAAc,GACvC,kBAAkB,CAkBpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,WAAW,GAAE,MAAU,EACvB,wBAAwB,GAAE,OAAc,GACvC,kBAAkB,EAAE,CAoBtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,UAAU,EAAE,EACzB,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,wBAAwB,GAAE,OAAc,GACvC,+BAA+B,CA+FjC"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* This file containts functions for computing detailed information on contributing to investments
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
|
+
import { TOTALS } from '../constants.js';
|
|
6
7
|
/**
|
|
7
8
|
*
|
|
8
9
|
* @param {IInstrument[]} instruments The instruments to allocate maximum contributions
|
|
@@ -21,26 +22,27 @@ export function determineExtraContribution(instruments, contribution) {
|
|
|
21
22
|
* @param {number} contribution The amount to contribute to the instrument's balance
|
|
22
23
|
* @param {number[int]} startPeriod The initial offset for period values
|
|
23
24
|
* @param {boolean} accrueBeforeContribution A flag for ordering operations of accrual (A) and contribution (C)
|
|
24
|
-
*
|
|
25
|
-
*
|
|
25
|
+
* true: A -> C
|
|
26
|
+
* false: C -> A
|
|
26
27
|
* @returns {ContributionRecord} The amortized contribution
|
|
27
28
|
*/
|
|
28
29
|
export function amortizeContribution(instrument, currentBalance, contribution, startPeriod = 0, accrueBeforeContribution = true) {
|
|
29
30
|
let interestThisPeriod;
|
|
31
|
+
let newBalance = currentBalance;
|
|
30
32
|
if (accrueBeforeContribution) {
|
|
31
|
-
interestThisPeriod = instrument.accrueInterest(
|
|
32
|
-
|
|
33
|
+
interestThisPeriod = instrument.accrueInterest(newBalance);
|
|
34
|
+
newBalance += contribution + interestThisPeriod;
|
|
33
35
|
}
|
|
34
36
|
else {
|
|
35
|
-
|
|
36
|
-
interestThisPeriod = instrument.accrueInterest(
|
|
37
|
-
|
|
37
|
+
newBalance += contribution;
|
|
38
|
+
interestThisPeriod = instrument.accrueInterest(newBalance);
|
|
39
|
+
newBalance += interestThisPeriod;
|
|
38
40
|
}
|
|
39
41
|
return {
|
|
40
42
|
period: startPeriod + 1,
|
|
41
43
|
contribution: contribution,
|
|
42
44
|
growth: interestThisPeriod,
|
|
43
|
-
currentBalance,
|
|
45
|
+
currentBalance: newBalance,
|
|
44
46
|
};
|
|
45
47
|
}
|
|
46
48
|
;
|
|
@@ -54,8 +56,8 @@ export function amortizeContribution(instrument, currentBalance, contribution, s
|
|
|
54
56
|
* @param {number} numContributions The number of periods to make contributions to the instrument
|
|
55
57
|
* @param {number[int]} startPeriod The inital offset for period values
|
|
56
58
|
* @param {boolean} accrueBeforeContribution A flag for ordering operations of accrual (A) and contribution (C)
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
+
* true: A -> C
|
|
60
|
+
* false: C -> A
|
|
59
61
|
* @returns {ContributionRecord[]} The amortized contributions
|
|
60
62
|
*/
|
|
61
63
|
export function amortizeContributions(instrument, initialBalance, contribution, numContributions, startPeriod = 0, accrueBeforeContribution = true) {
|
|
@@ -66,6 +68,8 @@ export function amortizeContributions(instrument, initialBalance, contribution,
|
|
|
66
68
|
const periodicContribution = instrument.validateContribution(contribution, ytd);
|
|
67
69
|
const record = amortizeContribution(instrument, currentBalance, periodicContribution, period + startPeriod, accrueBeforeContribution);
|
|
68
70
|
currentBalance = record.currentBalance;
|
|
71
|
+
// Reset YTD every 12 periods, assuming monthly periodicity matching periodsPerYear
|
|
72
|
+
// NOTE: This logic assumes period 0 is the start of a year.
|
|
69
73
|
period % 12 === 0 ? ytd = 0 : ytd += periodicContribution;
|
|
70
74
|
contributionSchedule.push(record);
|
|
71
75
|
}
|
|
@@ -78,8 +82,8 @@ export function amortizeContributions(instrument, initialBalance, contribution,
|
|
|
78
82
|
* @param {number} contribution The total amount to contirbute each period
|
|
79
83
|
* @param {number[int]} numContributions The number of periods to contribute
|
|
80
84
|
* @param {boolean} accrueBeforeContribution A flag for ordering operations of accrual (A) and contribution (C)
|
|
81
|
-
*
|
|
82
|
-
*
|
|
85
|
+
* true: A -> C
|
|
86
|
+
* false: C -> A
|
|
83
87
|
* @returns {InstrumentsContributionSchedule} The amortized contributions for all instruments
|
|
84
88
|
*/
|
|
85
89
|
export function contributeInstruments(instruments, contribution, numContributions, accrueBeforeContribution = true) {
|
|
@@ -126,6 +130,7 @@ export function contributeInstruments(instruments, contribution, numContribution
|
|
|
126
130
|
contributionSchedules[instrument.id].lifetimeGrowth = instrumentLifetimeGrowth;
|
|
127
131
|
totalLifetimeContribution += instrumentLifetimeContribution;
|
|
128
132
|
totalLifetimeGrowth += instrumentLifetimeGrowth;
|
|
133
|
+
// Merge totals safely
|
|
129
134
|
totalAmortizationSchedule = totalAmortizationSchedule.length
|
|
130
135
|
? (totalAmortizationSchedule.map((element) => {
|
|
131
136
|
const matchedInnerElement = instrumentSchedule.find((innerElement) => innerElement.period === element.period);
|
|
@@ -141,7 +146,7 @@ export function contributeInstruments(instruments, contribution, numContribution
|
|
|
141
146
|
}))
|
|
142
147
|
: instrumentSchedule;
|
|
143
148
|
}
|
|
144
|
-
contributionSchedules
|
|
149
|
+
contributionSchedules[TOTALS] = {
|
|
145
150
|
lifetimeContribution: totalLifetimeContribution,
|
|
146
151
|
lifetimeGrowth: totalLifetimeGrowth,
|
|
147
152
|
amortizationSchedule: totalAmortizationSchedule,
|