Calculate your mortgage payments, see how extra payments affect your loan payoff time, and generate an amortization schedule.
Loan Summary
Monthly Principal & Interest: —
Total Payments: —
Total Interest Paid: —
Payoff Time: —
Loan Paid Off In: —
Amortization Schedule
(Schedule shown for the first 12 months, and the final few months)
Month
Payment
Principal
Interest
Extra Payment
Principal Paid (Cumulative)
Remaining Balance
Understanding Your Mortgage and Extra Payments
A mortgage is a long-term loan used to purchase real estate. The borrower repays the loan over a set period (the loan term), typically in monthly installments that include both principal and interest. Understanding the components of your mortgage and how to pay it off faster can save you a significant amount of money over the life of the loan.
Key Components of a Mortgage Payment:
Principal: The actual amount borrowed. Each payment reduces the principal balance.
Interest: The cost of borrowing money, calculated as a percentage of the outstanding principal balance. Early in the loan term, a larger portion of your payment goes towards interest.
Loan Term: The total duration of the loan, usually expressed in years (e.g., 15, 30 years).
Interest Rate: The annual percentage charged by the lender. A lower interest rate means less interest paid over time.
How the Mortgage Payment is Calculated:
The standard monthly payment (P&I – Principal and Interest) is calculated using the following formula:
M = P [ i(1 + i)^n ] / [ (1 + i)^n – 1]
Where:
M = Your total monthly mortgage payment (P&I)
P = The principal loan amount
i = Your monthly interest rate (annual rate divided by 12)
n = The total number of payments over the loan's lifetime (loan term in years multiplied by 12)
The Power of Extra Payments:
Even small extra payments made consistently can significantly accelerate your mortgage payoff and reduce the total interest paid. When you make an extra payment, it is applied directly to the principal balance. This reduces the amount of principal on which future interest is calculated, leading to substantial savings over time.
How Extra Payments Work:
Applying Extra Payments: Ensure your lender applies extra payments directly to the principal. Some lenders may apply them to future interest or escrow first, which would not have the desired effect.
Impact on Interest: By reducing the principal balance faster, you pay less interest overall.
Impact on Loan Term: Extra payments shorten the time it takes to pay off your loan, potentially saving you years of payments and interest.
Using This Calculator:
This calculator helps you visualize the impact of extra payments. Input your loan details, and then add an amount for an 'Extra Monthly Payment'. The calculator will show you:
Your standard monthly Principal & Interest payment.
The total number of payments and total interest paid if you only make the standard payment.
How much sooner you can pay off your loan and how much interest you save by making extra payments.
A detailed amortization schedule showing the breakdown of each payment and the remaining balance over time.
When to Make Extra Payments:
Financial Stability: Once you have established an emergency fund and are comfortable with your other financial obligations.
Interest Rate Environment: If your mortgage rate is higher than what you could earn on conservative investments, paying down debt is often a wise move.
Personal Goals: To achieve financial freedom sooner or to be mortgage-free by a certain age.
By understanding your mortgage and utilizing strategies like extra payments, you can take control of your finances and build wealth more effectively.
function calculateMortgage() {
var loanAmount = parseFloat(document.getElementById("loanAmount").value);
var annualInterestRate = parseFloat(document.getElementById("annualInterestRate").value);
var loanTermYears = parseInt(document.getElementById("loanTermYears").value);
var extraMonthlyPayment = parseFloat(document.getElementById("extraMonthlyPayment").value);
// Input validation
if (isNaN(loanAmount) || loanAmount <= 0 ||
isNaN(annualInterestRate) || annualInterestRate < 0 ||
isNaN(loanTermYears) || loanTermYears <= 0 ||
isNaN(extraMonthlyPayment) || extraMonthlyPayment 0) {
monthlyPI = loanAmount * (monthlyInterestRate * Math.pow(1 + monthlyInterestRate, numberOfPayments)) / (Math.pow(1 + monthlyInterestRate, numberOfPayments) – 1);
} else {
monthlyPI = loanAmount / numberOfPayments; // Simple division if interest rate is 0
}
// Calculate total payments and interest for standard payment
var totalPaymentsStandard = monthlyPI * numberOfPayments;
var totalInterestStandard = totalPaymentsStandard – loanAmount;
document.getElementById("monthlyPI").textContent = formatCurrency(monthlyPI);
document.getElementById("totalPayments").textContent = formatCurrency(totalPaymentsStandard);
document.getElementById("totalInterest").textContent = formatCurrency(totalInterestStandard);
// — Calculation with Extra Payments —
var remainingBalance = loanAmount;
var totalPaidWithExtra = 0;
var totalInterestWithExtra = 0;
var monthsWithExtra = 0;
var amortizationData = [];
var currentMonthlyPayment = monthlyPI + extraMonthlyPayment;
// Edge case: if interest rate is 0, it will be infinite loop if extra payment is also 0.
// But we already validated for positive loanAmount and zero/positive rate.
// If rate is 0, monthlyPI is loanAmount/numberOfPayments.
// If extra is 0, it's a standard payment.
// If rate is 0 and extra > 0, it pays off faster.
while (remainingBalance > 0.01) { // Use a small tolerance for floating point issues
monthsWithExtra++;
var interestForMonth = remainingBalance * monthlyInterestRate;
var principalForMonth = currentMonthlyPayment – interestForMonth;
var actualPrincipalPaidThisMonth = principalForMonth;
// Handle cases where the final payment might be smaller
if (remainingBalance – principalForMonth loanTermYears * 12 * 5) { // Safeguard: assume max 5x original term
alert("Calculation may be taking too long. Please check your inputs.");
return;
}
}
// Determine payoff time string
var yearsPayoff = Math.floor(monthsWithExtra / 12);
var monthsPayoff = monthsWithExtra % 12;
var payoffTimeString = "";
if (yearsPayoff > 0) payoffTimeString += yearsPayoff + " year" + (yearsPayoff > 1 ? "s" : "");
if (monthsPayoff > 0) payoffTimeString += (payoffTimeString ? " " : "") + monthsPayoff + " month" + (monthsPayoff > 1 ? "s" : "");
if (payoffTimeString === "") payoffTimeString = "0 months";
document.getElementById("payoffTime").textContent = payoffTimeString;
document.getElementById("finalPayoffAmount").textContent = formatCurrency(totalPaidWithExtra);
// Populate amortization table
populateAmortizationTable(amortizationData, monthlyPI, extraMonthlyPayment);
}
function populateAmortizationTable(data, baseMonthlyPI, configuredExtraPayment) {
var tableBody = document.getElementById("amortizationTable").getElementsByTagName('tbody')[0];
tableBody.innerHTML = "; // Clear previous data
var rowsToShow = 12; // Show first 12 months
var dataLength = data.length;
for (var i = 0; i < dataLength; i++) {
var row = tableBody.insertRow();
var item = data[i];
var principalPaidThisMonth = item.payment – item.interest;
var actualPrincipalPaidThisMonth = principalPaidThisMonth;
if (item.balance < 0.01 && item.month === dataLength) { // Final payment adjustment
actualPrincipalPaidThisMonth = item.payment; // The final payment IS the principal
item.interest = 0; // No interest in the very last principal payment
item.payment = actualPrincipalPaidThisMonth; // The final payment equals remaining principal
}
var cumulativePrincipal = item.principalCumulative;
row.insertCell(0).textContent = item.month;
row.insertCell(1).textContent = formatCurrency(item.payment);
row.insertCell(2).textContent = formatCurrency(actualPrincipalPaidThisMonth);
row.insertCell(3).textContent = formatCurrency(item.interest);
row.insertCell(4).textContent = formatCurrency(configuredExtraPayment); // Show the configured extra payment
row.insertCell(5).textContent = formatCurrency(cumulativePrincipal);
row.insertCell(6).textContent = formatCurrency(item.balance);
// Display first 12 months and last few months
if (i = dataLength – 5) {
// If we've already shown 12, and the next month is not within the last 5, and there are more than 12 months total:
if (i >= rowsToShow && i rowsToShow + 5) {
// Add a row to indicate skipped months if there's a gap
if (i > 0 && data[i-1].month < dataLength – 5 – 1) { // Check if previous item wasn't already one of the last few
var skipRow = tableBody.insertRow();
var skipCell = skipRow.insertCell(0);
skipCell.colSpan = 7;
skipCell.textContent = "…";
skipCell.style.textAlign = "center";
skipCell.style.fontStyle = "italic";
}
}
} else {
// Hide rows between the initial 12 and the final few, except for the ellipsis row
row.style.display = 'none';
}
}
// Ensure the last rows are visible if they were hidden due to the logic above
var numRows = tableBody.rows.length;
for (var i = Math.max(0, numRows – 5); i < numRows; i++) {
if (tableBody.rows[i]) {
tableBody.rows[i].style.display = '';
}
}
}
function formatCurrency(amount) {
if (isNaN(amount) || amount === null) return "–";
return "$" + amount.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
}
// Initial calculation on page load (optional, with default values)
window.onload = function() {
calculateMortgage();
};