Investment Portfolio Analyzer

Investment Portfolio Analyzer

Analyze your investment allocation, diversity, and performance.

Add Your Assets

$

Current Holdings

Your portfolio is empty. Add assets above.

Your portfolio analysis will appear here.

Add your assets on the left and click "Analyze Portfolio".

${asset.name}

${formatCurrency(asset.value)} - ${asset.type}

`; listEl.appendChild(row); }); } } window.analyzePortfolio = function() { if (portfolio.length === 0) { alert('Please add at least one asset to your portfolio before analyzing.'); return; } const totalValue = portfolio.reduce((sum, asset) => sum + asset.value, 0); // Update summary cards document.getElementById('totalValue').textContent = formatCurrency(totalValue); document.getElementById('numHoldings').textContent = portfolio.length; const largestHolding = portfolio.reduce((max, asset) => asset.value > max.value ? asset : max, {value:0}); const largestHoldingEl = document.getElementById('largestHolding'); largestHoldingEl.textContent = largestHolding.name; largestHoldingEl.title = `${largestHolding.name} (${formatCurrency(largestHolding.value)})`; // Generate analysis table const tableContainer = document.getElementById('analysisTableContainer'); let tableHTML = ``; portfolio.sort((a,b) => b.value - a.value).forEach(asset => { const percentage = totalValue > 0 ? (asset.value / totalValue * 100).toFixed(2) : 0; tableHTML += ``; }); tableHTML += `
Asset Value % of Portfolio
${asset.name} ${formatCurrency(asset.value)} ${percentage}%
`; tableContainer.innerHTML = tableHTML; // --- Chart Data Preparation --- const typeAllocation = portfolio.reduce((acc, asset) => { acc[asset.type] = (acc[asset.type] || 0) + asset.value; return acc; }, {}); const sectorAllocation = portfolio.reduce((acc, asset) => { if (asset.sector && asset.sector !== 'N/A') { acc[asset.sector] = (acc[asset.sector] || 0) + asset.value; } return acc; }, {}); renderCharts(typeAllocation, sectorAllocation); document.getElementById('analysis-dashboard').classList.remove('hidden'); document.getElementById('analysis-placeholder').classList.add('hidden'); } function renderCharts(typeData, sectorData) { const chartColors = ['#4f46e5', '#7c3aed', '#db2777', '#f59e0b', '#10b981', '#3b82f6', '#ef4444', '#6b7280']; const doughnutOptions = { responsive: true, plugins: { legend: { position: 'bottom', labels: { padding: 15, font: { size: 11 } } } } }; const typeCtx = document.getElementById('assetTypeChart').getContext('2d'); if (assetTypeChart) assetTypeChart.destroy(); assetTypeChart = new Chart(typeCtx, { type: 'doughnut', data: { labels: Object.keys(typeData), datasets: [{ data: Object.values(typeData), backgroundColor: chartColors }] }, options: doughnutOptions }); const sectorCtx = document.getElementById('sectorAllocationChart').getContext('2d'); if (sectorAllocationChart) sectorAllocationChart.destroy(); sectorAllocationChart = new Chart(sectorCtx, { type: 'doughnut', data: { labels: Object.keys(sectorData), datasets: [{ data: Object.values(sectorData), backgroundColor: chartColors.slice().reverse() }] }, options: doughnutOptions }); } window.generatePdf = function() { if (!assetTypeChart || !sectorAllocationChart) { alert("Please analyze your portfolio first to generate a report."); return; } const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pageW = pdf.internal.pageSize.getWidth(); const margin = 15; let yPos = 20; pdf.setFont("helvetica", "bold"); pdf.setFontSize(22); pdf.setTextColor('#312e81'); // indigo-900 pdf.text("Investment Portfolio Analysis", pageW / 2, yPos, { align: 'center' }); yPos += 8; pdf.setFontSize(10); pdf.setTextColor(100, 116, 139); pdf.text(`Report Generated: ${new Date().toLocaleDateString('en-US')}`, pageW / 2, yPos, { align: 'center' }); yPos += 15; // --- Summary Section --- pdf.setFontSize(16); pdf.setFont("helvetica", "bold"); pdf.setTextColor(17, 24, 39); pdf.text("Portfolio Snapshot", margin, yPos); yPos += 8; pdf.setFontSize(11); pdf.setFont("helvetica", "normal"); pdf.text(`Total Value: ${document.getElementById('totalValue').textContent}`, margin, yPos); pdf.text(`Total Holdings: ${document.getElementById('numHoldings').textContent}`, pageW/2, yPos); yPos += 15; // --- Charts --- const chartW = (pageW - margin * 3) / 2; const chartH = chartW; pdf.text("Asset Allocation", margin + chartW/2, yPos, { align: 'center' }); pdf.text("Sector Allocation", margin * 2 + chartW + chartW/2, yPos, { align: 'center' }); yPos += 5; const chartImg1 = assetTypeChart.canvas.toDataURL('image/png', 1.0); const chartImg2 = sectorAllocationChart.canvas.toDataURL('image/png', 1.0); pdf.addImage(chartImg1, 'PNG', margin, yPos, chartW, chartH); pdf.addImage(chartImg2, 'PNG', margin * 2 + chartW, yPos, chartW, chartH); yPos += chartH + 15; // --- Detailed Table --- const totalValue = portfolio.reduce((sum, asset) => sum + asset.value, 0); const tableData = portfolio.map(asset => [ asset.name, formatCurrency(asset.value), `${(asset.value / totalValue * 100).toFixed(2)}%`, asset.type, asset.sector ]); pdf.autoTable({ startY: yPos, head: [['Asset', 'Value', '% of Portfolio', 'Type', 'Sector']], body: tableData, theme: 'grid', headStyles: { fillColor: '#4338ca' }, // indigo-700 margin: { left: margin, right: margin } }); pdf.save('Investment-Portfolio-Analysis.pdf'); } // Initial setup populateWithSampleData(); });
Scroll to Top