/** * View detailed strategy information in a modal */ function viewStrategyDetails(index) { console.log('🔍 viewStrategyDetails called with index:', index); console.log('📊 appData.foundStrategies:', appData?.foundStrategies); if (!appData || !appData.foundStrategies) { console.error('❌ appData or foundStrategies is undefined!'); alert('Error: Strategy data not available'); return; } if (index < 0 || index >= appData.foundStrategies.length) { console.error('❌ Invalid index:', index, 'Length:', appData.foundStrategies.length); alert('Error: Invalid strategy index'); return; } const strategy = appData.foundStrategies[index]; if (!strategy || !strategy.metrics) { console.error('❌ Invalid strategy at index:', index); alert('Error: Strategy data is corrupted'); return; } const m = strategy.metrics; // Additional validation for required metrics if (!m.profitFactor || !m.winRate || !m.totalTrades) { console.error('❌ Missing required metrics:', m); alert('Error: Strategy metrics are incomplete'); return; } // Create modal if it doesn't exist let modal = document.getElementById('strategy-modal'); if (!modal) { modal = document.createElement('div'); modal.id = 'strategy-modal'; modal.className = 'modal'; document.body.appendChild(modal); } const name = `FxMath_${String(index + 1).padStart(3, '0')}_PF${(m.profitFactor || 0).toFixed(2).replace('.', '_')}_WR${Math.round(m.winRate || 0)}`; modal.innerHTML = ` `; modal.style.display = 'flex'; // Draw equity chart setTimeout(() => { const ctx = document.getElementById('equity-chart').getContext('2d'); new Chart(ctx, { type: 'line', data: { labels: m.equity.map((_, i) => i), datasets: [{ label: 'Account Balance', data: m.equity, borderColor: '#667eea', backgroundColor: 'rgba(102, 126, 234, 0.1)', tension: 0.4, fill: true, pointRadius: 0 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { backgroundColor: '#1a1f3a', titleColor: '#fff', bodyColor: '#a0aec0', borderColor: '#2d3748', borderWidth: 1 } }, scales: { y: { beginAtZero: false, grid: { color: '#2d3748' }, ticks: { color: '#a0aec0' } }, x: { grid: { color: '#2d3748' }, ticks: { color: '#a0aec0' } } } } }); // Render hourly performance chart if data exists if (m.hourlyStats) { const hourlyCanvas = document.getElementById('hourly-chart'); if (hourlyCanvas) { new Chart(hourlyCanvas, { type: 'bar', data: { labels: Array.from({ length: 24 }, (_, i) => `${String(i).padStart(2, '0')}:00`), datasets: [{ label: 'Profit/Loss', data: m.hourlyStats.map(h => h.profit), backgroundColor: m.hourlyStats.map(h => h.profit >= 0 ? 'rgba(72, 187, 120, 0.6)' : 'rgba(245, 101, 101, 0.6)'), borderColor: m.hourlyStats.map(h => h.profit >= 0 ? 'rgba(72, 187, 120, 1)' : 'rgba(245, 101, 101, 1)'), borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { callbacks: { label: function (context) { const hour = context.dataIndex; const stats = m.hourlyStats[hour]; return [ `Profit: $${stats.profit.toFixed(2)}`, `Trades: ${stats.trades}`, `Wins: ${stats.wins} | Losses: ${stats.losses}` ]; } } } }, scales: { y: { beginAtZero: true, grid: { color: 'rgba(255, 255, 255, 0.1)' }, ticks: { color: '#a0aec0' } }, x: { grid: { display: false }, ticks: { color: '#a0aec0', maxRotation: 45, minRotation: 45 } } } } }); } } }, 100); } /** * Close strategy modal */ function closeStrategyModal() { const modal = document.getElementById('strategy-modal'); if (modal) { modal.style.display = 'none'; } } // Close modal when clicking outside window.onclick = function (event) { const modal = document.getElementById('strategy-modal'); if (event.target === modal) { closeStrategyModal(); } } // Explicitly expose functions to global scope for inline onclick handlers window.viewStrategyDetails = viewStrategyDetails; window.closeStrategyModal = closeStrategyModal;