// Portfolio Analysis Page // Detailed view of individual agent portfolios const dataLoader = new DataLoader(); let allAgentsData = {}; let currentAgent = null; let allocationChart = null; // Initialize the page async function init() { showLoading(); try { // Load all agents data console.log('Loading all agents data...'); allAgentsData = await dataLoader.loadAllAgentsData(); console.log('Data loaded:', allAgentsData); // Populate agent selector populateAgentSelector(); // Load first agent by default const firstAgent = Object.keys(allAgentsData)[0]; if (firstAgent) { currentAgent = firstAgent; await loadAgentPortfolio(firstAgent); } // Set up event listeners setupEventListeners(); } catch (error) { console.error('Error initializing page:', error); alert('Failed to load portfolio data. Please check console for details.'); } finally { hideLoading(); } } // Populate agent selector dropdown function populateAgentSelector() { const select = document.getElementById('agentSelect'); select.innerHTML = ''; Object.keys(allAgentsData).forEach(agentName => { const option = document.createElement('option'); option.value = agentName; // Use text only for dropdown options (HTML select doesn't support images well) option.textContent = dataLoader.getAgentDisplayName(agentName); select.appendChild(option); }); } // Load and display portfolio for selected agent async function loadAgentPortfolio(agentName) { showLoading(); try { currentAgent = agentName; const data = allAgentsData[agentName]; // Update performance metrics updateMetrics(data); // Update holdings table await updateHoldingsTable(agentName); // Update allocation chart await updateAllocationChart(agentName); // Update trade history updateTradeHistory(agentName); } catch (error) { console.error('Error loading portfolio:', error); } finally { hideLoading(); } } // Update performance metrics function updateMetrics(data) { const totalAsset = data.currentValue; const totalReturn = data.return; const latestPosition = data.positions && data.positions.length > 0 ? data.positions[data.positions.length - 1] : null; const cashPosition = latestPosition && latestPosition.positions ? latestPosition.positions.CASH || 0 : 0; const totalTrades = data.positions ? data.positions.filter(p => p.this_action).length : 0; document.getElementById('totalAsset').textContent = dataLoader.formatCurrency(totalAsset); document.getElementById('totalReturn').textContent = dataLoader.formatPercent(totalReturn); document.getElementById('totalReturn').className = `metric-value ${totalReturn >= 0 ? 'positive' : 'negative'}`; document.getElementById('cashPosition').textContent = dataLoader.formatCurrency(cashPosition); document.getElementById('totalTrades').textContent = totalTrades; } // Update holdings table async function updateHoldingsTable(agentName) { const holdings = dataLoader.getCurrentHoldings(agentName); const tableBody = document.getElementById('holdingsTableBody'); tableBody.innerHTML = ''; if (!holdings) { return; } const data = allAgentsData[agentName]; if (!data || !data.assetHistory || data.assetHistory.length === 0) { return; } const latestDate = data.assetHistory[data.assetHistory.length - 1].date; const totalValue = data.currentValue; // Get all stocks with non-zero holdings const stocks = Object.entries(holdings) .filter(([symbol, shares]) => symbol !== 'CASH' && shares > 0); // Sort by market value (descending) const holdingsData = await Promise.all( stocks.map(async ([symbol, shares]) => { const price = await dataLoader.getClosingPrice(symbol, latestDate); const marketValue = price ? shares * price : 0; return { symbol, shares, price, marketValue }; }) ); holdingsData.sort((a, b) => b.marketValue - a.marketValue); // Create table rows holdingsData.forEach(holding => { const weight = (holding.marketValue / totalValue * 100).toFixed(2); const row = document.createElement('tr'); row.innerHTML = `
No trade history available.
'; return; } // Show latest 20 trades const recentTrades = trades.slice(0, 20); recentTrades.forEach(trade => { const tradeItem = document.createElement('div'); tradeItem.className = 'trade-item'; const icon = trade.action === 'buy' ? '📈' : '📉'; const iconClass = trade.action === 'buy' ? 'buy' : 'sell'; const actionText = trade.action === 'buy' ? 'Bought' : 'Sold'; tradeItem.innerHTML = `