Based on your preferences, this AI-powered optimizer suggests an asset allocation designed to align with a ${riskTolerance} risk tolerance.
- Estimated Portfolio Risk: ${estimatedRisk}
- Estimated Portfolio Return: ${estimatedReturn}
Key Diversification Principles:
International diversification aims to reduce overall portfolio risk by investing in a variety of assets across different countries and regions. This strategy typically works because:
- Different economies and markets don't always move in sync.
- Specific regional or asset class downturns can be offset by gains elsewhere.
- Exposure to emerging markets can offer higher growth potential, albeit with higher volatility.
`;
if (selectedAssets.includes('equitiesEmerging')) {
insightsText += `
Focus on Emerging Markets:
You have opted to include Emerging Market Equities. These markets can provide significant growth opportunities due to their rapidly expanding economies and younger demographics. However, they typically come with higher volatility due to factors like geopolitical risks, currency fluctuations, and less mature regulatory environments. Your allocation to these assets has been adjusted based on your risk tolerance.
`;
}
if (riskTolerance === 'Conservative') {
insightsText += `
For Conservative Investors:
Your portfolio emphasizes capital preservation and stable returns. This typically means a higher allocation to less volatile assets like government bonds and developed market equities, and a lower exposure to higher-risk assets such as high-yield bonds or a very limited exposure to commodities and emerging markets. The goal is to minimize significant drawdowns while still capturing some global growth.
`;
} else if (riskTolerance === 'Moderate') {
insightsText += `
For Moderate Investors:
Your balanced portfolio seeks a blend of growth and stability. It includes a healthy mix of developed and emerging market equities, along with bonds and potentially some alternative assets like REITs or commodities. This approach aims for solid long-term growth without taking on excessive risk, allowing for participation in higher-growth areas while moderating overall volatility.
`;
} else { // Aggressive
insightsText += `
For Aggressive Investors:
Your portfolio is geared towards maximizing long-term returns and is designed to withstand higher levels of market volatility. This typically involves a larger allocation to equities, especially emerging market equities, and potentially a greater weighting in commodities or high-yield bonds. While offering higher growth potential, be prepared for more significant fluctuations in portfolio value.
`;
}
insightsText += `
Next Steps:
- Review the suggested allocation and ensure it aligns with your comfort level.
- Consider consulting a qualified financial advisor to discuss your specific financial situation and investment goals.
- Regularly review and rebalance your portfolio to maintain your desired asset allocation.
- Conduct thorough due diligence on any specific investment products you consider.
`;
insightsContentDiv.innerHTML = insightsText;
}
/**
* Generates a PDF report of the tool's inputs and calculated results.
*/
async function generatePdf() {
// Show loading spinner
pdfSpinner.classList.remove('hidden');
downloadPdfBtn.disabled = true; // Disable button during PDF generation
// Ensure the portfolio is optimized and displayed
optimizePortfolio();
// Create a temporary div to render PDF content into
const pdfContentDiv = document.createElement('div');
pdfContentDiv.className = 'pdf-content-hidden'; // Hidden and styled for print
document.body.appendChild(pdfContentDiv);
// Add title to PDF content
const title = document.createElement('h1');
title.className = 'text-2xl font-bold text-gray-800 text-center mb-6';
title.textContent = 'AI-Powered International Portfolio Diversification Report';
pdfContentDiv.appendChild(title);
// --- Section: Your Preferences ---
const preferencesSectionTitle = document.createElement('h2');
preferencesSectionTitle.className = 'text-xl font-semibold text-gray-800 mb-4';
preferencesSectionTitle.textContent = 'Your Preferences';
pdfContentDiv.appendChild(preferencesSectionTitle);
const preferencesTable = document.createElement('table');
preferencesTable.className = 'w-full text-left border-collapse mb-6';
preferencesTable.innerHTML = `
| Preference |
Value |
`;
const preferencesTableBody = preferencesTable.querySelector('tbody');
pdfContentDiv.appendChild(preferencesTable);
// Add risk tolerance to preferences table
const riskToleranceValue = document.querySelector('input[name="riskTolerance"]:checked').labels[0].textContent;
let row = preferencesTableBody.insertRow();
let cell1 = row.insertCell();
let cell2 = row.insertCell();
cell1.className = 'py-2 px-4 border-b border-gray-200';
cell2.className = 'py-2 px-4 border-b border-gray-200';
cell1.textContent = 'Risk Tolerance';
cell2.textContent = riskToleranceValue;
// Add selected asset classes to preferences table
const selectedAssets = Array.from(assetCheckboxes)
.filter(cb => cb.checked)
.map(cb => cb.labels[0].textContent);
if (selectedAssets.length > 0) {
row = preferencesTableBody.insertRow();
cell1 = row.insertCell();
cell2 = row.insertCell();
cell1.className = 'py-2 px-4 border-b border-gray-200';
cell2.className = 'py-2 px-4 border-b border-gray-200';
cell1.textContent = 'Selected Asset Classes';
cell2.textContent = selectedAssets.join(', ');
} else {
row = preferencesTableBody.insertRow();
cell1 = row.insertCell();
cell2 = row.insertCell();
cell1.className = 'py-2 px-4 border-b border-gray-200';
cell2.className = 'py-2 px-4 border-b border-gray-200';
cell1.textContent = 'Selected Asset Classes';
cell2.textContent = 'None';
}
// --- Section: Optimized Portfolio ---
const resultsSection = document.createElement('div');
resultsSection.className = 'mt-8 p-6 bg-gray-50 rounded-lg shadow-inner';
resultsSection.innerHTML = `
Optimized Portfolio Allocation
Estimated Portfolio Risk: ${portfolioRiskSpan.textContent}
Estimated Portfolio Return: ${portfolioReturnSpan.textContent}
Suggested Asset Allocation:
`;
pdfContentDiv.appendChild(resultsSection);
const pdfAllocationTable = document.createElement('table');
pdfAllocationTable.className = 'w-full rounded-lg overflow-hidden mt-4';
pdfAllocationTable.innerHTML = `
| Asset Class |
Allocation (%) |
`;
const pdfAllocationTableBody = pdfAllocationTable.querySelector('tbody');
resultsSection.appendChild(pdfAllocationTable);
// Copy rows from live allocation table
const liveAllocationRows = allocationTableBody.querySelectorAll('tr');
if (liveAllocationRows.length > 0) {
liveAllocationRows.forEach(liveRow => {
const newRow = pdfAllocationTableBody.insertRow();
const cells = liveRow.querySelectorAll('td');
cells.forEach((cell, index) => {
const newCell = newRow.insertCell();
newCell.className = 'py-2 px-4 border-b border-gray-200';
newCell.textContent = cell.textContent;
});
});
} else {
const noAllocRow = pdfAllocationTableBody.insertRow();
const noAllocCell = noAllocRow.insertCell();
noAllocCell.colSpan = 2;
noAllocCell.className = 'py-2 px-4 text-center text-gray-500';
noAllocCell.textContent = 'No asset allocation generated. Please ensure asset classes are selected.';
}
// --- Section: AI Insights ---
const insightsSection = document.createElement('div');
insightsSection.className = 'mt-8 p-6 bg-blue-50 rounded-lg shadow-inner text-gray-700';
insightsSection.innerHTML = `
AI Insights and Recommendations
${insightsContentDiv.innerHTML}
`;
pdfContentDiv.appendChild(insightsSection);
try {
const canvas = await html2canvas(pdfContentDiv, {
scale: 2, // Increase scale for better resolution in PDF
useCORS: true // Required if you have external images/resources (though none here)
});
const imgData = canvas.toDataURL('image/png');
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({
orientation: 'portrait',
unit: 'px',
format: 'a4'
});
const imgWidth = pdf.internal.pageSize.getWidth() - 40; // Subtract margins (20px each side)
const imgHeight = (canvas.height * imgWidth) / canvas.width;
let position = 20; // Initial Y position with top margin
pdf.addImage(imgData, 'PNG', 20, position, imgWidth, imgHeight);
// Handle multi-page PDF for long content
let heightLeft = imgHeight;
heightLeft -= (pdf.internal.pageSize.getHeight() - 40); // Subtract current page usable height
while (heightLeft >= -5) { // Adjusted condition to catch slightly overflowing content
position = heightLeft - imgHeight + 20; // Calculate position for next page
pdf.addPage();
pdf.addImage(imgData, 'PNG', 20, position, imgWidth, imgHeight);
heightLeft -= (pdf.internal.pageSize.getHeight() - 40);
}
pdf.save('AI_Portfolio_Optimizer_Report.pdf');
} catch (error) {
console.error("Error generating PDF:", error);
// Provide user feedback without alert()
const messageBox = document.createElement('div');
messageBox.textContent = "Failed to generate PDF. Please try again or check console for details.";
messageBox.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #f8d7da;
color: #721c24;
padding: 15px 25px;
border-radius: 8px;
border: 1px solid #f5c6cb;
z-index: 1000;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
font-family: 'Inter', sans-serif;
`;
document.body.appendChild(messageBox);
setTimeout(() => messageBox.remove(), 5000); // Remove after 5 seconds
} finally {
// Hide loading spinner and re-enable button
pdfSpinner.classList.add('hidden');
downloadPdfBtn.disabled = false;
// Remove the temporary PDF content div from the DOM
if (pdfContentDiv.parentNode) {
pdfContentDiv.parentNode.removeChild(pdfContentDiv);
}
}
}
});