UNPKG

mortgage

Version:

Project with different functions to calculate: -The minimun payment of a mortgage -The loan lenght of a mortgage -Calculate the new loan lenght adding an extra payment -The amortization table of the payoffs -Calculate simple interest and amortiz

267 lines (266 loc) 11.2 kB
"use strict"; /* * Monthly Payment * * Function to calculate the fixed monthly payment required to amortize a loan * over a term of months. * * P = L[c(1 + c)^n]/[(1 + c)^n - 1] * * P = L[(c/t)(1 + c/t)n]/[(1 + c/t)n - 1] * * @param {number} Loan Amount (L) * @param {number} Interest rate annually (c) * @param {number} Loan length express in months (n) * @param {number} Number of times interest compounds, default 12 (t) * @returns {number} Monthly Payment */ Object.defineProperty(exports, "__esModule", { value: true }); exports.getMortgagePayoff = exports.getLoanLength = exports.getTotalAmortizingInterest = exports.getTotalInterest = exports.getSimpleInterest = exports.getLoanBalance = exports.getMonthlyPayment = void 0; exports.getMonthlyPayment = function (loan, interestRate, loanLength, timesInterestCompounds) { if (timesInterestCompounds === void 0) { timesInterestCompounds = 12; } if (loan < 0) throw new Error('Please provide a valid loan'); if (interestRate < 0) throw new Error('Please provide a valid interest rate'); if (loanLength < 0) throw new Error('Please provide a valid loan length'); if (timesInterestCompounds <= 0) throw new Error('Please provide a valid number of times interest compounds'); var interest = interestRate / timesInterestCompounds; return loan * ((interest * Math.pow(1 + interest, loanLength)) / (Math.pow(1 + interest, loanLength) - 1)); }; /* * Loan Balance * * Function to calculate the remaining loan balance of a fixed payment loan after a period of months * * B = L[(1 + c)n - (1 + c)p]/[(1 + c)n - 1] * * B = L[(1 + c/t)^n - (1 + c/t)^p]/[(1 + c/t)^n - 1] * * @param {number} Loan Amount (L) * @param {number} Interest rate annually (c) * @param {number} Loan length express in months (n) * @param {number} Period of elapsed months (p) * @param {number} Number of times interest compounds, default 12 (t) * @returns {number} Monthly Payment */ exports.getLoanBalance = function (loan, interestRate, loanLength, periodElapsedMonths, timesInterestCompounds) { if (timesInterestCompounds === void 0) { timesInterestCompounds = 12; } if (loan < 0) throw new Error('Please provide a valid loan'); if (interestRate < 0) throw new Error('Please provide a valid interest rate'); if (loanLength < 0) throw new Error('Please provide a valid loan length'); if (timesInterestCompounds <= 0) throw new Error('Please provide a valid number of times interest compounds'); if (periodElapsedMonths < 0) throw new Error('Please provide a valid number of Period of elapsed months'); var interest = interestRate / timesInterestCompounds; return (loan * ((Math.pow(1 + interest, loanLength) - Math.pow(1 + interest, periodElapsedMonths)) / (Math.pow(1 + interest, loanLength) - 1))); }; /* * Simple Interest * * Function to calculate the remaining loan balance of a fixed payment loan after a period of months * * i = L (c) * * i = L (c/t) * * @param {number} Balance / Loan in the first operation (L) * @param {number} Interest rate annually (c) * @param {number} Number of times interest compounds, default 12 (t) * @returns {number} interest */ exports.getSimpleInterest = function (balance, interestRate, timesInterestCompounds) { if (timesInterestCompounds === void 0) { timesInterestCompounds = 12; } if (balance < 0) throw new Error('Please provide a valid loan/balance'); if (interestRate < 0) throw new Error('Please provide a valid interest rate'); if (timesInterestCompounds <= 0) throw new Error('Please provide a valid number of times interest compounds'); return balance * (interestRate / timesInterestCompounds); }; /* * Total interest * * Function to calculate the total interest of a loan with the minimum monthly payment * * @param {number} Loan amount * @param {number} loan length * @param {number} Interest rate annually (c) * @param {number} Number of times interest compounds, default 12 (t) * @returns {number} Total interest */ exports.getTotalInterest = function (loan, interestRate, loanLength, timesInterestCompounds) { if (timesInterestCompounds === void 0) { timesInterestCompounds = 12; } if (loan < 0) throw new Error('Please provide a valid loan'); if (interestRate < 0) throw new Error('Please provide a valid interest rate'); if (loanLength < 0) throw new Error('Please provide a valid loan length'); if (timesInterestCompounds <= 0) throw new Error('Please provide a valid number of times interest compounds'); return exports.getMonthlyPayment(loan, interestRate, loanLength, timesInterestCompounds) * loanLength - loan; }; /* * Calculate Total Amortizing Interest using a constant payment * * @param {number} loan/balance amount * @param {number} Interest rate * @param {number} mountly payment * @param {number} Number of times interest compounds, default 12 (t) * @returns {number} Total Interest */ exports.getTotalAmortizingInterest = function (balance, interestRate, mountlyPayment, timesInterestCompounds) { if (timesInterestCompounds === void 0) { timesInterestCompounds = 12; } if (balance < 0) throw new Error('Please provide a valid loan/balance'); if (interestRate < 0) throw new Error('Please provide a valid interest rate'); if (mountlyPayment < 0) throw new Error('Please provide a valid mountly payment'); if (timesInterestCompounds <= 0) throw new Error('Please provide a valid number of times interest compounds'); var interest = 0; var amortizingInterest = 0; while (balance > 0) { interest = (interestRate / timesInterestCompounds) * balance; amortizingInterest += interest; balance -= mountlyPayment - interest; } return amortizingInterest; }; /* * Calculate loan length * * @param {number} loan amount * @param {number} Interest rate * @param {number} mountly payment * @param {number} Number of times interest compounds, default 12 (t) * @returns {number} Total Interest */ exports.getLoanLength = function (loan, interestRate, mountlyPayment, timesInterestCompounds) { if (timesInterestCompounds === void 0) { timesInterestCompounds = 12; } if (loan < 0) throw new Error('Please provide a valid loan/balance'); if (interestRate < 0) throw new Error('Please provide a valid interest rate'); if (mountlyPayment < 0) throw new Error('Please provide a valid mountly payment'); if (timesInterestCompounds <= 0) throw new Error('Please provide a valid number of times interest compounds'); var monthlyInterestRate = interestRate / timesInterestCompounds; // i = monthly interest rate var loanLength = -(Math.log(-((monthlyInterestRate * loan) / mountlyPayment) + 1) / Math.log(1 + monthlyInterestRate)); return Math.ceil(parseFloat(loanLength.toFixed(5))); }; /* * Calculate the Payoff Results * * @param {number} Loan Amount * @param {number} Interest rate annually * @param {number} Loan length express in months * @param {number} Extra payment add to the principal * @param {number} Date to start the payoff in milliseconds * @param {number} Number of times interest compounds, default 12 (t) * @returns {object} Payoff Results */ exports.getMortgagePayoff = function (loan, interestRate, loanLength, extraPrincipal, initialDate, timesInterestCompounds) { if (extraPrincipal === void 0) { extraPrincipal = 0; } if (initialDate === void 0) { initialDate = Date.now(); } if (timesInterestCompounds === void 0) { timesInterestCompounds = 12; } if (loan < 0) throw new Error('Please provide a valid loan'); if (interestRate < 0) throw new Error('Please provide a valid interest rate'); if (loanLength < 0) throw new Error('Please provide a valid Loan Length'); if (extraPrincipal < 0) throw new Error('Please provide a valid extra payment'); if (timesInterestCompounds <= 0) throw new Error('Please provide a valid number of times interest compounds'); var payoffGrid = []; var remainingLoan = loan; var defaultLoanLength = loanLength; var defaultInitialDate = initialDate; var date = new Date(initialDate); if (isNaN(date.getTime())) throw new Error('Please provide a valid date'); var mountlyPayment = exports.getMonthlyPayment(loan, interestRate, loanLength, timesInterestCompounds); var defaultTotalInterest = exports.getTotalInterest(loan, interestRate, loanLength, timesInterestCompounds); var newLoanLength = exports.getLoanLength(loan, interestRate, mountlyPayment + extraPrincipal); var results = { mountlyPayment: mountlyPayment, extraPrincipal: extraPrincipal, interestRate: interestRate, defaultTotalInterest: defaultTotalInterest, totalInterestWithSavings: exports.getTotalAmortizingInterest(loan, interestRate, mountlyPayment, timesInterestCompounds), loan: loan, defaultLoanLength: loanLength, loanLength: newLoanLength, startDate: new Date(initialDate), endDate: getEndDate(defaultInitialDate, newLoanLength), defaultEndDate: getEndDate(defaultInitialDate, defaultLoanLength), data: {}, }; /* * Payoff grid */ for (var i = 0; i < loanLength; i++) { var dateRow = date; var interestRow = exports.getSimpleInterest(remainingLoan, interestRate); var principal = mountlyPayment - interestRow; var principalExtra = principal + extraPrincipal; var balance = remainingLoan - principalExtra; /* * Stop Condition */ if (remainingLoan + interestRow < mountlyPayment + extraPrincipal) { payoffGrid.push({ date: dateRow, interest: interestRow, principal: principal, principalExtra: principalExtra + balance, balance: 0, }); remainingLoan = balance = 0; break; } /* * Add row to the payoff Grid */ payoffGrid.push({ date: dateRow, interest: interestRow, principal: principal, principalExtra: principalExtra, balance: balance, }); /* * Update conditions for next iteration */ remainingLoan = balance; date.setMonth(date.getMonth() + 1); } results.data = payoffGrid; return results; }; /* * Calculate end date of the loan * * @param {number} date in milliseconds * @param {number} loan Length * @returns {string} end date of the loan */ function getEndDate(startDate, loanLength) { var date = new Date(startDate); date.setMonth(date.getMonth() + loanLength - 1); return date; }