Portfolio Diversification Analyzer

Portfolio Diversification Analyzer

Enter the percentage of your portfolio allocated to each asset class. The total must sum to 100%.

%
%
%
%
%
Total Allocated: 0.00%

Your Portfolio Allocation

Diversification Analysis

Enter your portfolio allocations above and click "Analyze Diversification" to get insights.

Concentrated: Your portfolio has a significant allocation to ${leadingAsset} (${maxPercentage.toFixed(1)}%). While not extremely concentrated, you might consider further diversification to reduce asset-specific risk.

`; analysisResult.classList.add('concentrated'); } else if (diversifiedCount >= 3 && maxPercentage < 40) { analysisText.innerHTML = `

Well Diversified: Your portfolio shows a good level of diversification across multiple asset classes, with no single asset class dominating. This generally indicates a more balanced risk profile.

`; analysisResult.classList.add('well-diversified'); } else { analysisText.innerHTML = `

Needs Attention: Your portfolio is not adequately diversified across a sufficient number of asset classes. Consider allocating to more distinct types of investments.

`; analysisResult.classList.add('concentrated'); // Use concentrated as a default for "needs attention" } } // --- Event Listeners --- // Listen to all input changes to update total percentage instantly assetClasses.forEach(asset => { if (asset.input) { // Robust null check asset.input.addEventListener('input', updateTotals); } }); if (calculateButton) { // Robust null check calculateButton.type = "button"; // Ensure button type is "button" calculateButton.addEventListener('click', function() { const data = assetClasses.map(asset => ({ name: asset.name, value: parseFloat(asset.input.value) || 0, color: asset.color })); drawPieChart(data); analyzeDiversification(data); }); } if (resetButton) { // Robust null check resetButton.type = "button"; // Ensure button type is "button" resetButton.addEventListener('click', function() { // Reset all inputs to 0 assetClasses.forEach(asset => { if (asset.input) { // Robust null check asset.input.value = "0"; } }); // Set initial values for demo (optional, or truly reset to 0) if (stocksInput) stocksInput.value = "50"; if (bondsInput) bondsInput.value = "30"; if (realEstateInput) realEstateInput.value = "10"; if (commoditiesInput) commoditiesInput.value = "5"; if (cashInput) cashInput.value = "5"; updateTotals(); // Recalculate total percentage // Clear chart and analysis if (pieChartSvg) pieChartSvg.innerHTML = ''; if (chartLegend) chartLegend.innerHTML = ''; if (analysisText) { analysisText.textContent = 'Enter your portfolio allocations above and click "Analyze Diversification" to get insights.'; analysisResult.classList.remove('well-diversified', 'concentrated', 'highly-concentrated'); analysisResult.classList.add('analysis-result'); // Ensure base class is present } }); } // PDF Download Functionality if (downloadPdfButton) { // Robust null check downloadPdfButton.type = "button"; // Ensure button type is "button" downloadPdfButton.addEventListener('click', function() { if (!diversificationAnalyzerTool) return; // Robust null check // Create a container for the PDF content const pdfContentWrapper = document.createElement('div'); pdfContentWrapper.className = 'pdf-output-content'; // Add title const pdfTitle = document.createElement('h2'); pdfTitle.textContent = "Portfolio Diversification Analysis"; pdfContentWrapper.appendChild(pdfTitle); // Add a table of inputs const inputTableTitle = document.createElement('h3'); inputTableTitle.textContent = "Your Asset Allocation"; pdfContentWrapper.appendChild(inputTableTitle); const inputTable = document.createElement('table'); inputTable.className = 'input-table-for-pdf'; inputTable.innerHTML = ` Asset Class Allocated Percentage `; const inputTableBody = inputTable.querySelector('tbody'); assetClasses.forEach(asset => { const row = document.createElement('tr'); row.innerHTML = `${asset.name}${(parseFloat(asset.input.value) || 0).toFixed(1)}%`; inputTableBody.appendChild(row); }); const totalRow = document.createElement('tr'); totalRow.innerHTML = `Total${(parseFloat(totalPercentageValue.textContent) || 0).toFixed(1)}%`; inputTableBody.appendChild(totalRow); pdfContentWrapper.appendChild(inputTable); // Add the pie chart const chartTitle = document.createElement('h3'); chartTitle.textContent = "Visual Representation"; pdfContentWrapper.appendChild(chartTitle); const chartContainer = document.createElement('div'); chartContainer.className = 'pie-chart-container-pdf'; const svgClone = pieChartSvg.cloneNode(true); // Clone the SVG svgClone.classList.remove('pie-chart-svg'); // Remove interactive styling if any svgClone.style.transform = 'rotate(-90deg)'; // Ensure correct orientation in PDF svgClone.style.borderRadius = '50%'; svgClone.style.boxShadow = 'none'; // Remove box shadow for PDF chartContainer.appendChild(svgClone); pdfContentWrapper.appendChild(chartContainer); // Add the legend for the chart const legendClone = chartLegend.cloneNode(true); legendClone.classList.add('chart-legend-pdf'); // Use PDF specific legend styles pdfContentWrapper.appendChild(legendClone); // Add the analysis result const analysisTitle = document.createElement('h3'); analysisTitle.textContent = "Diversification Analysis"; pdfContentWrapper.appendChild(analysisTitle); const analysisResultClone = analysisResult.cloneNode(true); analysisResultClone.id = ''; // Remove ID to prevent duplication analysisResultClone.classList.add('analysis-result-pdf'); // Apply PDF specific styles analysisResultClone.style.boxShadow = 'none'; // Remove shadow analysisResultClone.style.borderLeftColor = analysisResult.style.borderLeftColor; // Keep original color analysisResultClone.querySelector('h3').remove(); // Remove inner H3 as we added one above pdfContentWrapper.appendChild(analysisResultClone); // html2pdf options const options = { margin: 10, filename: 'portfolio_diversification_analysis.pdf', image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2 }, jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }, pagebreak: { avoid: ['input', '.buttons-container', '.total-percentage-info', '.chart-legend'] } // Elements to avoid breaking }; html2pdf().from(pdfContentWrapper).set(options).save(); }); } // Initial calculations and rendering updateTotals(); const initialData = assetClasses.map(asset => ({ name: asset.name, value: parseFloat(asset.input.value) || 0, color: asset.color })); drawPieChart(initialData); analyzeDiversification(initialData); });
Scroll to Top