`).join('');
};
const renderCharts = (metrics) => {
const chartContexts = {
composition: document.getElementById('composition-chart').getContext('2d'),
volatility: document.getElementById('volatility-chart').getContext('2d'),
riskReturn: document.getElementById('risk-return-chart').getContext('2d'),
};
Object.values(charts).forEach(chart => chart.destroy());
charts.composition = new Chart(chartContexts.composition, {
type: 'doughnut',
data: {
labels: metrics.assets.map(a => a.name),
datasets: [{
data: metrics.assets.map(a => a.value),
backgroundColor: ['#4f46e5', '#10b981', '#f59e0b', '#3b82f6', '#ec4899'],
}]
},
options: { plugins: { legend: { position: 'bottom' } } }
});
charts.volatility = new Chart(chartContexts.volatility, {
type: 'bar',
data: {
labels: metrics.assets.map(a => a.name),
datasets: [{
label: 'Volatility (Std. Dev %)',
data: metrics.assets.map(a => a.volatility),
backgroundColor: '#6366f1',
}]
},
options: { indexAxis: 'y', scales: { x: { beginAtZero: true } } }
});
charts.riskReturn = new Chart(chartContexts.riskReturn, {
type: 'scatter',
data: {
datasets: [{
label: 'Individual Assets',
data: metrics.assets.map(a => ({ x: a.volatility, y: a.expectedReturn })),
backgroundColor: '#10b981'
}, {
label: 'Total Portfolio',
data: [{ x: metrics.volatility, y: metrics.expectedReturn }],
backgroundColor: '#ef4444',
pointRadius: 8,
pointHoverRadius: 10
}]
},
options: {
scales: {
x: { title: { display: true, text: 'Risk (Volatility %)' } },
y: { title: { display: true, text: 'Expected Return %' } }
}
}
});
};
const renderAnalysis = (metrics) => {
const container = document.getElementById('analysis-output');
const highRiskAsset = metrics.assets.reduce((max, a) => a.volatility > max.volatility ? a : max);
const highReturnAsset = metrics.assets.reduce((max, a) => a.expectedReturn > max.expectedReturn ? a : max);
container.innerHTML = `
Portfolio Insights
Performance Summary
The portfolio's expected annual return is ${formatPercent(metrics.expectedReturn)}, with a calculated volatility (risk) of ${formatPercent(metrics.volatility)}. This results in a Sharpe Ratio of ${formatNumber(metrics.sharpeRatio)}, which measures risk-adjusted return. A higher Sharpe Ratio (typically > 1.0) is considered good.
Key Observations
- Highest Return Asset: ${highReturnAsset.name} (${formatPercent(highReturnAsset.expectedReturn)})
- Highest Risk Asset: ${highRiskAsset.name} (${formatPercent(highRiskAsset.volatility)})
- The overall portfolio risk (${formatPercent(metrics.volatility)}) is lower than that of its riskiest component due to diversification.
