Foreign Exchange Market Insights Dashboard

Foreign Exchange Market Insights Dashboard

Analyze currency trends, correlations, and historical performance.

${currentRate.toFixed(4)}

${change.toFixed(4)} (${changePct.toFixed(2)}%) ${change >= 0 ? '' : ''}
`; // Render chart const ctx = document.getElementById('historical-chart').getContext('2d'); if (historicalChart) historicalChart.destroy(); historicalChart = new Chart(ctx, { type: 'line', data: { labels: Array.from({length: timePeriods}, (_, i) => `Day ${i + 1}`), datasets: [{ label: `Exchange Rate for ${selectedPair}`, data: exchangeRateSeries, borderColor: '#3B82F6', backgroundColor: 'rgba(59, 130, 246, 0.1)', fill: true, tension: 0.1 }] }, options: { responsive: true, maintainAspectRatio: false } }); }; const renderCorrelationMatrix = (matrix, currencies) => { let table = ''; table += ''; currencies.forEach(c => table += ``); table += ''; currencies.forEach(c1 => { table += ``; currencies.forEach(c2 => { const val = matrix[c1][c2]; const absVal = Math.abs(val); let cellClass = 'correlation-low'; if (c1 === c2) cellClass = 'correlation-perfect'; else if (absVal >= 0.7) cellClass = 'correlation-high'; else if (absVal >= 0.4) cellClass = 'correlation-medium'; table += ``; }); table += ''; }); table += '
 ${c}
${c1}${val.toFixed(2)}
'; correlationContainer.innerHTML = table; }; // --- CALCULATION LOGIC --- const calculateCorrelationMatrix = () => { const currencies = Object.keys(currencyData); const matrix = {}; const mean = (arr) => arr.reduce((a, b) => a + b) / arr.length; const stdDev = (arr, avg) => Math.sqrt(arr.map(x => Math.pow(x - avg, 2)).reduce((a, b) => a + b) / arr.length); currencies.forEach(c1 => { matrix[c1] = {}; const series1 = currencyData[c1]; const mean1 = mean(series1); const stdDev1 = stdDev(series1, mean1); currencies.forEach(c2 => { if (c1 === c2) { matrix[c1][c2] = 1; return; } const series2 = currencyData[c2]; const mean2 = mean(series2); const stdDev2 = stdDev(series2, mean2); let covariance = 0; for (let i = 0; i < timePeriods; i++) { covariance += (series1[i] - mean1) * (series2[i] - mean2); } covariance /= timePeriods; const correlation = covariance / (stdDev1 * stdDev2); matrix[c1][c2] = isNaN(correlation) ? 0 : correlation; }); }); return { matrix, currencies: currencies }; }; // --- EVENT HANDLERS & UPDATERS --- const updateAndRenderAll = () => { renderPairSelector(); renderDashboard(); const { matrix, currencies } = calculateCorrelationMatrix(); renderCorrelationMatrix(matrix, currencies); }; pairSelector.addEventListener('change', renderDashboard); updateDashboardBtn.addEventListener('click', () => { updateAndRenderAll(); switchTab('dashboard'); // Go to dashboard after updating }); configTableBody.addEventListener('change', e => { const target = e.target; const currency = target.closest('tr').dataset.currency; if (target.classList.contains('currency-value-input')) { const period = parseInt(target.dataset.period); currencyData[currency][period] = parseFloat(target.value); } }); configTableBody.addEventListener('focusout', e => { if (e.target.classList.contains('currency-name-input')) { const oldName = e.target.closest('tr').dataset.currency; const newName = e.target.value.toUpperCase(); if (oldName !== newName && newName && !currencyData[newName]) { const data = currencyData[oldName]; delete currencyData[oldName]; currencyData[newName] = data; renderConfigTable(); // Re-render to update dataset attributes } else { e.target.value = oldName; // Revert if invalid or duplicate } } }); configTableBody.addEventListener('click', e => { if (e.target.classList.contains('remove-currency-btn')) { const currencyToRemove = e.target.closest('tr').dataset.currency; delete currencyData[currencyToRemove]; renderConfigTable(); } }); addCurrencyBtn.addEventListener('click', () => { let newName = 'NEW'; let counter = 1; while(currencyData[newName]) { newName = `NEW${counter++}`; } currencyData[newName] = Array(timePeriods).fill(0); renderConfigTable(); }); downloadPdfBtn.addEventListener('click', async () => { const pdfContainer = document.getElementById('pdf-container'); pdfContainer.classList.remove('hidden'); // Clone chart and matrix into a temporary container for clean capture const chartCanvas = document.getElementById('historical-chart'); const matrixEl = document.getElementById('correlation-matrix-container'); pdfContainer.innerHTML = `

Forex Insights Report: ${pairSelector.value}

Currency Correlation Matrix

${matrixEl.innerHTML}
`; await new Promise(resolve => setTimeout(resolve, 100)); // Allow DOM to update html2canvas(pdfContainer.firstElementChild, { scale: 2 }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const margin = 40; const contentWidth = pdfWidth - margin * 2; const canvasAspectRatio = canvas.width / canvas.height; const contentHeight = contentWidth / canvasAspectRatio; const finalHeight = contentHeight > pdfHeight - margin*2 ? pdfHeight - margin*2 : contentHeight; pdf.addImage(imgData, 'PNG', margin, margin, contentWidth, finalHeight); pdf.save('Forex-Insights-Report.pdf'); pdfContainer.innerHTML = ''; pdfContainer.classList.add('hidden'); }); }); // --- INITIALIZATION --- initialize(); });
Scroll to Top