`;
dashboardResultsContainer.innerHTML = `
`;
if (equityChart) equityChart.destroy();
const ctx = document.getElementById('equity-chart').getContext('2d');
equityChart = new Chart(ctx, {
type: 'line',
data: {
labels: historicalData.map(d => d.date),
datasets: [
{
label: 'Strategy Equity',
data: results.equityCurve,
borderColor: '#3B82F6', // blue-500
tension: 0.1, pointRadius: 0
},
{
label: 'Buy & Hold Equity',
data: results.buyAndHoldCurve,
borderColor: '#F59E0B', // amber-500
tension: 0.1, pointRadius: 0
}
]
},
options: {
responsive: true, maintainAspectRatio: true,
plugins: { title: { display: true, text: 'Equity Curve vs. Buy & Hold Benchmark' } },
scales: { y: { ticks: { callback: v => `$${v.toLocaleString()}` } } }
}
});
downloadPdfBtn.disabled = false;
};
// --- PDF DOWNLOAD ---
const handlePdfDownload = () => {
const pdfContent = document.getElementById('pdf-content');
html2canvas(pdfContent, { scale: 2, backgroundColor: '#ffffff' }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({ orientation: 'landscape', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const margin = 40;
const contentWidth = pdfWidth - margin * 2;
const canvasAspectRatio = canvas.width / canvas.height;
const contentHeight = contentWidth / canvasAspectRatio;
pdf.setFontSize(20);
pdf.text("Quantitative Strategy Backtest Report", margin, margin);
pdf.addImage(imgData, 'PNG', margin, margin + 20, contentWidth, contentHeight);
pdf.save('Strategy-Backtest-Report.pdf');
});
};
// --- EVENT LISTENERS ---
window.switchTab = switchTab;
window.navigateTabs = navigateTabs;
runBacktestBtn.addEventListener('click', handleRunBacktest);
downloadPdfBtn.addEventListener('click', handlePdfDownload);
addDataRowBtn.addEventListener('click', () => {
const newId = nextId++;
historicalData.push({ id: newId, date: new Date().toISOString().split('T')[0], close: 0 });
renderDataTable();
const newRow = dataTableBody.querySelector(`[data-id='${newId}']`);
if (newRow) newRow.scrollIntoView();
});
dataTableBody.addEventListener('input', e => {
if (e.target.classList.contains('data-input')) {
const id = parseInt(e.target.closest('tr').dataset.id);
const prop = e.target.dataset.prop;
const value = e.target.type === 'number' ? parseFloat(e.target.value) : e.target.value;
const item = historicalData.find(d => d.id === id);
if (item) item[prop] = value;
}
});
dataTableBody.addEventListener('click', e => {
if (e.target.classList.contains('remove-row-btn')) {
const idToRemove = parseInt(e.target.closest('tr').dataset.id);
historicalData = historicalData.filter(d => d.id !== idToRemove);
renderDataTable();
}
});
// --- INITIALIZATION ---
renderDataTable();
updateNavButtons();
switchTab('dashboard');
});
${createMetricCard('Total Return', formatPercent(results.totalReturn))}
${createMetricCard('Annualized Return', formatPercent(results.annualizedReturn))}
${createMetricCard('Max Drawdown', formatPercent(results.maxDrawdown))}
${createMetricCard('Buy & Hold Return', formatPercent(results.buyAndHoldReturn))}
