Investing in real estate is one of the most popular ways to build long-term wealth. However, the difference between a profitable investment and a financial burden often comes down to the numbers. This Rental Property ROI Calculator is designed to help investors analyze the potential returns of a real estate deal by looking at critical metrics like Cash Flow, Cash on Cash Return, and Cap Rate.
What is Cash on Cash Return?
Cash on Cash Return is essentially a metric that calculates the cash income earned on the cash invested in a property. Unlike total return on investment (ROI), which might include appreciation or loan paydown, Cash on Cash focuses strictly on the liquid cash flow relative to the actual dollars you put into the deal (Down Payment + Closing Costs + Repairs).
Formula:Annual Pre-Tax Cash Flow / Total Cash Invested
For example, if you invest $50,000 cash to buy a property and it generates $5,000 in positive cash flow per year, your Cash on Cash Return is 10%. This is a vital metric because it allows you to compare real estate returns directly against other investment vehicles like stocks or bonds.
Calculating Monthly Cash Flow
Cash flow is the net amount of cash moving into or out of your business every month. In real estate terms, it is calculated by taking your Gross Rental Income and subtracting all Operating Expenses and Debt Service (Mortgage Payments).
Operating Expenses: These include property taxes, insurance, HOA fees, maintenance reserves, vacancy reserves, and property management fees.
Debt Service: This is your monthly principal and interest payment to the lender.
Positive cash flow ensures the property pays for itself and provides you with income. Negative cash flow means you are feeding the property money every month to keep it afloat, which is a risky position for most investors.
What is a "Good" Cap Rate?
The Capitalization Rate (Cap Rate) measures the natural rate of return of a real estate investment assuming it was bought entirely with cash (no loan). It helps compare the profitability of similar properties regardless of how they are financed.
While a "good" Cap Rate varies by market, generally:
4% – 5%: Common in high-demand, low-risk areas (Class A properties).
6% – 8%: A solid target for most balanced rental markets.
8% – 10%+: Often found in riskier neighborhoods or older properties requiring more maintenance.
How to Use This Calculator
To get the most accurate results, ensure you are realistic with your expense estimates. New investors often overlook vacancy rates (periods where the property sits empty) and maintenance costs (inevitable repairs). A general rule of thumb is to set aside 5-10% of monthly rent for maintenance and another 5% for vacancy.
function calculateROI() {
// 1. Get Inputs
var purchasePrice = parseFloat(document.getElementById('purchasePrice').value);
var downPaymentPercent = parseFloat(document.getElementById('downPaymentPercent').value);
var interestRate = parseFloat(document.getElementById('interestRate').value);
var loanTerm = parseFloat(document.getElementById('loanTerm').value);
var closingCosts = parseFloat(document.getElementById('closingCosts').value);
var monthlyRent = parseFloat(document.getElementById('monthlyRent').value);
var annualTax = parseFloat(document.getElementById('annualTax').value);
var annualInsurance = parseFloat(document.getElementById('annualInsurance').value);
var monthlyHOA = parseFloat(document.getElementById('monthlyHOA').value);
var vacancyRate = parseFloat(document.getElementById('vacancyRate').value);
// Validation
if (isNaN(purchasePrice) || isNaN(monthlyRent)) {
alert("Please enter valid numbers for Purchase Price and Rental Income.");
return;
}
// 2. Initial Investment Calculation
var downPaymentAmount = purchasePrice * (downPaymentPercent / 100);
var loanAmount = purchasePrice – downPaymentAmount;
var totalInitialInvestment = downPaymentAmount + closingCosts;
// 3. Mortgage Payment Calculation (Principal & Interest)
var monthlyRate = (interestRate / 100) / 12;
var numberOfPayments = loanTerm * 12;
var monthlyPI = 0;
if (interestRate > 0) {
monthlyPI = loanAmount * (monthlyRate * Math.pow(1 + monthlyRate, numberOfPayments)) / (Math.pow(1 + monthlyRate, numberOfPayments) – 1);
} else {
monthlyPI = loanAmount / numberOfPayments;
}
// 4. Monthly Expenses Calculation
var monthlyTax = annualTax / 12;
var monthlyInsurance = annualInsurance / 12;
var monthlyVacancyMaint = monthlyRent * (vacancyRate / 100);
// Total Operating Expenses (Excluding Mortgage)
var totalOperatingExpenses = monthlyTax + monthlyInsurance + monthlyHOA + monthlyVacancyMaint;
// Total Outflow (Expenses + Mortgage)
var totalMonthlyOutflow = totalOperatingExpenses + monthlyPI;
// 5. Cash Flow Calculation
var monthlyCashFlow = monthlyRent – totalMonthlyOutflow;
var annualCashFlow = monthlyCashFlow * 12;
// 6. Return Metrics
var cocReturn = 0;
if (totalInitialInvestment > 0) {
cocReturn = (annualCashFlow / totalInitialInvestment) * 100;
}
// Cap Rate = (Net Operating Income / Current Market Value)
// NOI = Annual Rent – Annual Operating Expenses (Excluding Mortgage)
var annualNOI = (monthlyRent * 12) – (totalOperatingExpenses * 12);
var capRate = (annualNOI / purchasePrice) * 100;
// 7. Display Results
document.getElementById('resTotalInvestment').innerText = formatCurrency(totalInitialInvestment);
document.getElementById('resMortgage').innerText = formatCurrency(monthlyPI);
document.getElementById('resTotalExpenses').innerText = formatCurrency(totalMonthlyOutflow);
var resMonthlyCF = document.getElementById('resMonthlyCashFlow');
resMonthlyCF.innerText = formatCurrency(monthlyCashFlow);
styleResult(resMonthlyCF, monthlyCashFlow);
var resAnnualCF = document.getElementById('resAnnualCashFlow');
resAnnualCF.innerText = formatCurrency(annualCashFlow);
styleResult(resAnnualCF, annualCashFlow);
var resCoC = document.getElementById('resCoC');
resCoC.innerText = cocReturn.toFixed(2) + "%";
styleResult(resCoC, cocReturn);
document.getElementById('resCapRate').innerText = capRate.toFixed(2) + "%";
document.getElementById('resultsBox').style.display = 'block';
}
function formatCurrency(num) {
return "$" + num.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
}
function styleResult(element, value) {
if (value < 0) {
element.style.color = "#c0392b"; // Red for negative
} else {
element.style.color = "#27ae60"; // Green for positive
}
}