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

Popular posts from this blog

Nifty 30,000: The JP Morgan Blueprint for the Indo-US "Trade Bull Run" 🚀🇮🇳🇺🇸

NISM Series XV Research Analyst: Complete Study Material & Notes by Dhaval Visariya

NISM 15 Research Analyst Mock Test 1: 600 MCQ Series (2026 Updated)