Multi-Fund Portfolio Growth Projector
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Multi-Fund Portfolio Projector</title>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f6f9; color: #333; margin: 0; padding: 20px; }
.container { max-width: 900px; margin: 0 auto; background: white; padding: 25px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
h2 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
.fund-row { display: grid; grid-template-columns: 2fr 1.5fr 1.5fr 1fr auto; gap: 10px; background: #f8f9fa; padding: 15px; border-radius: 6px; margin-bottom: 15px; align-items: center; border-left: 4px solid #3498db; }
label { font-size: 12px; font-weight: bold; color: #7f8c8d; text-transform: uppercase; display: block; margin-bottom: 5px; }
input, select { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
button { cursor: pointer; padding: 10px 15px; border: none; border-radius: 4px; font-weight: bold; transition: background 0.2s; }
.btn-add { background: #2ecc71; color: white; }
.btn-add:hover { background: #27ae60; }
.btn-remove { background: #e74c3c; color: white; padding: 8px 12px; margin-top: 18px;}
.btn-remove:hover { background: #c0392b; }
.btn-calculate { background: #3498db; color: white; width: 100%; font-size: 16px; margin-top: 15px; padding: 12px; }
.btn-calculate:hover { background: #2980b9; }
.results-section { margin-top: 30px; display: none; }
table { width: 100%; border-collapse: collapse; margin-top: 15px; }
th, td { border: 1px solid #ddd; padding: 12px; text-align: right; }
th { background-color: #34495e; color: white; }
tr:nth-child(even) { background-color: #f9f9f9; }
.total-row { font-weight: bold; background-color: #ecf0f1 !important; }
</style>
</head>
<body>
<div class="container">
<h2>Multi-Fund Portfolio Growth Projector</h2>
<p>Add your funds, specify their Type (SIP or One-Time Lumpsum), Investment Amount, and expected CAGR to project cumulative wealth over 10 or 15 Years.</p>
<div id="funds-container">
<div class="fund-row" id="fund-1">
<div>
<label>Fund Name</label>
<input type="text" class="fund-name" value="Large Cap Fund">
</div>
<div>
<label>Investment Type</label>
<select class="fund-type">
<option value="LUMPSUM">One-Time (Lump sum)</option>
<option value="SIP" selected>Monthly SIP</option>
</select>
</div>
<div>
<label>Amount (₹)</label>
<input type="number" class="fund-amount" value="5000">
</div>
<div>
<label>CAGR (%)</label>
<input type="number" class="fund-cagr" value="12" step="0.1">
</div>
<div>
<button class="btn-remove" onclick="removeFund('fund-1')">✕</button>
</div>
</div>
</div>
<div style="display: flex; gap: 10px;">
<button type="button" class="btn-add" onclick="addFundRow()">+ Add Fund</button>
<button type="button" class="btn-calculate" onclick="calculateProjections()">Project Portfolio Returns</button>
</div>
<div class="results-section" id="results-div">
<h3>Cumulative Portfolio Projections</h3>
<table>
<thead>
<tr>
<th style="text-align: left;">End of Year</th>
<th>Total Invested (₹)</th>
<th>Projected Portfolio Value (₹)</th>
<th>Estimated Wealth Gain (₹)</th>
</tr>
</thead>
<tbody id="projection-table-body">
</tbody>
</table>
</div>
</div>
<script>
let fundCount = 1;
function addFundRow() {
fundCount++;
const container = document.getElementById('funds-container');
const newRow = document.createElement('div');
newRow.className = 'fund-row';
newRow.id = `fund-${fundCount}`;
newRow.innerHTML = `
<div>
<label>Fund Name</label>
<input type="text" class="fund-name" value="Fund ${fundCount}">
</div>
<div>
<label>Investment Type</label>
<select class="fund-type">
<option value="LUMPSUM">One-Time (Lump sum)</option>
<option value="SIP" selected>Monthly SIP</option>
</select>
</div>
<div>
<label>Amount (₹)</label>
<input type="number" class="fund-amount" value="5000">
</div>
<div>
<label>CAGR (%)</label>
<input type="number" class="fund-cagr" value="12" step="0.1">
</div>
<div>
<button class="btn-remove" onclick="removeFund('fund-${fundCount}')">✕</button>
</div>
`;
container.appendChild(newRow);
}
function removeFund(id) {
const row = document.getElementById(id);
if (document.querySelectorAll('.fund-row').length > 1) {
row.remove();
} else {
alert("Keep at least one fund to compute projections.");
}
}
function calculateProjections() {
const rows = document.querySelectorAll('.fund-row');
const years = [10, 15];
const tbody = document.getElementById('projection-table-body');
tbody.innerHTML = '';
// Generate data year-by-year from 1 to 15
for (let year = 1; year <= 15; year++) {
let totalInvested = 0;
let totalFutureValue = 0;
rows.forEach(row => {
const type = row.querySelector('.fund-type').value;
const amt = parseFloat(row.querySelector('.fund-amount').value) || 0;
const cagr = (parseFloat(row.querySelector('.fund-cagr').value) || 0) / 100;
if (type === 'LUMPSUM') {
totalInvested += amt;
// Formula: FV = P * (1 + r)^n
totalFutureValue += amt * Math.pow(1 + cagr, year);
} else if (type === 'SIP') {
totalInvested += amt * 12 * year;
// Formula: FV = P * [((1 + i)^n - 1) / i] * (1 + i)
const monthlyRate = cagr / 12;
const months = year * 12;
if (monthlyRate > 0) {
totalFutureValue += amt * ((Math.pow(1 + monthlyRate, months) - 1) / monthlyRate) * (1 + monthlyRate);
} else {
totalFutureValue += amt * months;
}
}
});
const wealthGain = totalFutureValue - totalInvested;
// Highlight years 10 and 15
const isTargetYear = (year === 10 || year === 15);
const rowClass = isTargetYear ? 'class="total-row"' : '';
const tr = document.createElement('tr');
if (isTargetYear) tr.className = 'total-row';
tr.innerHTML = `
<td style="text-align: left; font-weight: ${isTargetYear ? 'bold' : 'normal'};">Year ${year} ${isTargetYear ? '★' : ''}</td>
<td>₹${Math.round(totalInvested).toLocaleString('en-IN')}</td>
<td><strong>₹${Math.round(totalFutureValue).toLocaleString('en-IN')}</strong></td>
<td style="color: #27ae60;">₹${Math.round(wealthGain).toLocaleString('en-IN')}</td>
`;
tbody.appendChild(tr);
}
document.getElementById('results-div').style.display = 'block';
document.getElementById('results-div').scrollIntoView({ behavior: 'smooth' });
}
</script>
</body>
</html>
Dhaval Visariya
AMFI Registered Distributor (ARN-327925) | Software Developer & Finance Enthusiast
Connect with me:
LinkedIn |
Telegram |
YouTube |
GitHub |
Medium
Disclaimer: I am an AMFI Registered Mutual Fund Distributor. Views expressed here are for educational purposes. Mutual Fund investments are subject to market risks, read all scheme related documents carefully.
📧 Contact: info.apollofinancialservices@gmail.com
Comments
Post a Comment