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
JavaScript
"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;
}