From 24aeefda9df19cbf63767ea3d706487f3a54c8f3 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Sat, 22 Nov 2025 23:17:44 +0200 Subject: [PATCH] UI --- ANNOTATE/web/static/js/chart_manager.js | 65 ++++++++++++++++++- .../templates/components/training_panel.html | 48 +++++++++----- 2 files changed, 94 insertions(+), 19 deletions(-) diff --git a/ANNOTATE/web/static/js/chart_manager.js b/ANNOTATE/web/static/js/chart_manager.js index 9c18b7b..9f3be71 100644 --- a/ANNOTATE/web/static/js/chart_manager.js +++ b/ANNOTATE/web/static/js/chart_manager.js @@ -622,7 +622,27 @@ class ChartManager { if (data.pivot_markers && Object.keys(data.pivot_markers).length > 0) { const xMin = data.timestamps[0]; - const xMax = data.timestamps[data.timestamps.length - 1]; + let xMax = data.timestamps[data.timestamps.length - 1]; + + // Extend xMax to include ghost candle predictions if they exist + if (this.ghostCandleHistory && this.ghostCandleHistory[timeframe] && this.ghostCandleHistory[timeframe].length > 0) { + const ghosts = this.ghostCandleHistory[timeframe]; + const furthestGhost = ghosts[ghosts.length - 1]; + if (furthestGhost && furthestGhost.targetTime) { + const ghostTime = new Date(furthestGhost.targetTime); + const currentMax = new Date(xMax); + if (ghostTime > currentMax) { + const year = ghostTime.getUTCFullYear(); + const month = String(ghostTime.getUTCMonth() + 1).padStart(2, '0'); + const day = String(ghostTime.getUTCDate()).padStart(2, '0'); + const hours = String(ghostTime.getUTCHours()).padStart(2, '0'); + const minutes = String(ghostTime.getUTCMinutes()).padStart(2, '0'); + const seconds = String(ghostTime.getUTCSeconds()).padStart(2, '0'); + xMax = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + console.log(`[${timeframe}] Pivot lines extended to include ${ghosts.length} ghost candles (to ${xMax})`); + } + } + } // Process each timestamp that has pivot markers Object.entries(data.pivot_markers).forEach(([timestamp, pivots]) => { @@ -1041,7 +1061,26 @@ class ChartManager { if (data.pivot_markers && Object.keys(data.pivot_markers).length > 0) { const xMin = data.timestamps[0]; - const xMax = data.timestamps[data.timestamps.length - 1]; + let xMax = data.timestamps[data.timestamps.length - 1]; + + // Extend xMax to include ghost candle predictions if they exist + if (this.ghostCandleHistory && this.ghostCandleHistory[timeframe] && this.ghostCandleHistory[timeframe].length > 0) { + const ghosts = this.ghostCandleHistory[timeframe]; + const furthestGhost = ghosts[ghosts.length - 1]; + if (furthestGhost && furthestGhost.targetTime) { + const ghostTime = new Date(furthestGhost.targetTime); + const currentMax = new Date(xMax); + if (ghostTime > currentMax) { + const year = ghostTime.getUTCFullYear(); + const month = String(ghostTime.getUTCMonth() + 1).padStart(2, '0'); + const day = String(ghostTime.getUTCDate()).padStart(2, '0'); + const hours = String(ghostTime.getUTCHours()).padStart(2, '0'); + const minutes = String(ghostTime.getUTCMinutes()).padStart(2, '0'); + const seconds = String(ghostTime.getUTCSeconds()).padStart(2, '0'); + xMax = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + } + } + } // Process each timestamp that has pivot markers Object.entries(data.pivot_markers).forEach(([timestamp, pivots]) => { @@ -1977,7 +2016,27 @@ class ChartManager { if (data.pivot_markers && Object.keys(data.pivot_markers).length > 0) { const xMin = data.timestamps[0]; - const xMax = data.timestamps[data.timestamps.length - 1]; + let xMax = data.timestamps[data.timestamps.length - 1]; + + // Extend xMax to include ghost candle predictions if they exist + if (this.ghostCandleHistory && this.ghostCandleHistory[timeframe] && this.ghostCandleHistory[timeframe].length > 0) { + const ghosts = this.ghostCandleHistory[timeframe]; + const furthestGhost = ghosts[ghosts.length - 1]; + if (furthestGhost && furthestGhost.targetTime) { + const ghostTime = new Date(furthestGhost.targetTime); + const currentMax = new Date(xMax); + if (ghostTime > currentMax) { + const year = ghostTime.getUTCFullYear(); + const month = String(ghostTime.getUTCMonth() + 1).padStart(2, '0'); + const day = String(ghostTime.getUTCDate()).padStart(2, '0'); + const hours = String(ghostTime.getUTCHours()).padStart(2, '0'); + const minutes = String(ghostTime.getUTCMinutes()).padStart(2, '0'); + const seconds = String(ghostTime.getUTCSeconds()).padStart(2, '0'); + xMax = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + console.log(`[${timeframe}] Pivot lines extended to include ${ghosts.length} ghost candles (to ${xMax})`); + } + } + } // Process each timestamp that has pivot markers Object.entries(data.pivot_markers).forEach(([timestamp, pivots]) => { diff --git a/ANNOTATE/web/templates/components/training_panel.html b/ANNOTATE/web/templates/components/training_panel.html index d3402c9..62c056f 100644 --- a/ANNOTATE/web/templates/components/training_panel.html +++ b/ANNOTATE/web/templates/components/training_panel.html @@ -1124,6 +1124,16 @@ function updatePredictionHistory() { const historyDiv = document.getElementById('prediction-history'); + + // Filter out invalid predictions (cleanup any that got through) + predictionHistory = predictionHistory.filter(pred => { + return pred.action && + ['BUY', 'SELL', 'HOLD'].includes(pred.action) && + !isNaN(pred.confidence) && + pred.confidence > 0 && + pred.timestamp; + }); + if (predictionHistory.length === 0) { historyDiv.innerHTML = '
No predictions yet...
'; return; @@ -1148,7 +1158,7 @@ pred.action === 'SELL' ? 'text-danger' : 'text-secondary'; const confidence = (pred.confidence * 100).toFixed(1); const price = (pred.predicted_price && !isNaN(pred.predicted_price)) ? pred.predicted_price.toFixed(2) : '--'; - const timeframe = pred.timeframe || '1m'; + const timeframe = pred.timeframe || '1s'; return `
@@ -1177,11 +1187,15 @@ if (data.success && data.signals.length > 0) { // Update Accuracy Metrics in Header if (data.metrics) { - document.getElementById('metric-accuracy').textContent = (data.metrics.accuracy * 100).toFixed(1) + '%'; - // If you want to show these in the live banner too: + console.log('[Metrics Update]', data.metrics); + const accuracyPct = (data.metrics.accuracy * 100).toFixed(1); + const lossVal = data.metrics.loss ? data.metrics.loss.toFixed(4) : '--'; + + document.getElementById('metric-accuracy').textContent = accuracyPct + '%'; + + // Update live banner with metrics const banner = document.getElementById('inference-status'); if (banner) { - // Check if we already have a metrics div, if not create one let metricsDiv = document.getElementById('live-banner-metrics'); if (!metricsDiv) { metricsDiv = document.createElement('div'); @@ -1190,8 +1204,9 @@ banner.querySelector('.small').appendChild(metricsDiv); } metricsDiv.innerHTML = ` - Acc: ${(data.metrics.accuracy * 100).toFixed(1)}% - Loss: ${data.metrics.loss ? data.metrics.loss.toFixed(4) : '--'} + Acc: ${accuracyPct}% + Loss: ${lossVal} + PnL: +$${pnlTracker.totalPnL.toFixed(2)} `; } } @@ -1219,16 +1234,7 @@ const currentPrice = latest.price || latest.current_price; // Add to prediction history (keep last 15) - const newPrediction = { - timestamp: timestamp, - action: latest.action, - confidence: latest.confidence, - predicted_price: latest.predicted_price, - current_price: currentPrice, - timeframe: appState.currentTimeframes ? appState.currentTimeframes[0] : '1m' - }; - - // Strengthen filter: only add valid signals + // Only create prediction if we have valid data const validActions = ['BUY', 'SELL', 'HOLD']; if (latest.action && validActions.includes(latest.action) && @@ -1237,9 +1243,19 @@ currentPrice && !isNaN(currentPrice)) { + const newPrediction = { + timestamp: timestamp, + action: latest.action, + confidence: latest.confidence, + predicted_price: latest.predicted_price, + current_price: currentPrice, + timeframe: appState.currentTimeframes ? appState.currentTimeframes[0] : '1s' + }; + // Update PnL tracking updatePnLTracking(latest.action, currentPrice, timestamp); + // Add to history predictionHistory.unshift(newPrediction); if (predictionHistory.length > 15) { predictionHistory = predictionHistory.slice(0, 15);