diff --git a/ANNOTATE/web/static/css/annotation_ui.css b/ANNOTATE/web/static/css/annotation_ui.css index d9c5809..044f14c 100644 --- a/ANNOTATE/web/static/css/annotation_ui.css +++ b/ANNOTATE/web/static/css/annotation_ui.css @@ -413,3 +413,40 @@ .annotation-mode-inactive { border: 2px solid var(--text-muted); } + + +/* Prediction Toggle Buttons */ +.btn-group .btn.active { + background-color: rgba(var(--bs-success-rgb), 0.2); + border-color: var(--bs-success); + color: var(--bs-success); +} + +.btn-group .btn-outline-success.active { + background-color: rgba(16, 185, 129, 0.2); + border-color: #10b981; + color: #10b981; +} + +.btn-group .btn-outline-warning.active { + background-color: rgba(251, 191, 36, 0.2); + border-color: #fbbf24; + color: #fbbf24; +} + +.btn-group .btn-outline-info.active { + background-color: rgba(59, 130, 246, 0.2); + border-color: #3b82f6; + color: #3b82f6; +} + +.btn-group .btn-outline-primary.active { + background-color: rgba(99, 102, 241, 0.2); + border-color: #6366f1; + color: #6366f1; +} + +/* Spacing between button groups */ +.d-flex.gap-3 { + gap: 1rem !important; +} diff --git a/ANNOTATE/web/static/js/chart_manager.js b/ANNOTATE/web/static/js/chart_manager.js index 485d9e9..82f9011 100644 --- a/ANNOTATE/web/static/js/chart_manager.js +++ b/ANNOTATE/web/static/js/chart_manager.js @@ -21,6 +21,14 @@ class ChartManager { this.predictionHistory = []; // Store last 20 predictions with fading this.maxPredictions = 20; // Maximum number of predictions to display + // Prediction display toggles (all enabled by default) + this.displayToggles = { + ghostCandles: true, + trendLines: true, + actions: true, + pivots: true + }; + // Helper to ensure all timestamps are in UTC this.normalizeTimestamp = (timestamp) => { if (!timestamp) return null; @@ -32,6 +40,121 @@ class ChartManager { console.log('ChartManager initialized with timeframes:', timeframes); } + // Toggle methods for prediction display - NON-DESTRUCTIVE + // These methods only update visibility without redrawing or resetting view + toggleGhostCandles(enabled) { + this.displayToggles.ghostCandles = enabled; + console.log('Ghost candles display:', enabled); + + // Update visibility of ghost candle traces without redrawing + this.timeframes.forEach(tf => { + const plotElement = document.getElementById(`plot-${tf}`); + if (plotElement && plotElement.data) { + // Find ghost candle traces (they have name 'Ghost Prediction') + const updates = {}; + plotElement.data.forEach((trace, idx) => { + if (trace.name === 'Ghost Prediction') { + if (!updates.visible) updates.visible = []; + updates.visible[idx] = enabled; + } + }); + + if (Object.keys(updates).length > 0) { + // Update trace visibility without resetting view + const indices = Object.keys(updates.visible).map(Number); + Plotly.restyle(plotElement, { visible: enabled }, indices); + } + } + }); + } + + toggleTrendLines(enabled) { + this.displayToggles.trendLines = enabled; + console.log('Trend lines display:', enabled); + + // Update visibility of trend line shapes without redrawing + this.timeframes.forEach(tf => { + const plotElement = document.getElementById(`plot-${tf}`); + if (plotElement && plotElement.layout && plotElement.layout.shapes) { + // Filter shapes to show/hide trend lines (yellow dotted lines) + const updatedShapes = plotElement.layout.shapes.map(shape => { + // Trend lines are yellow dotted lines + if (shape.line && shape.line.dash === 'dot' && + shape.line.color && shape.line.color.includes('255, 255, 0')) { + return { ...shape, visible: enabled }; + } + return shape; + }); + + // Update layout without resetting view + Plotly.relayout(plotElement, { shapes: updatedShapes }); + } + }); + } + + toggleActions(enabled) { + this.displayToggles.actions = enabled; + console.log('Action predictions display:', enabled); + + // Update visibility of action annotations without redrawing + this.timeframes.forEach(tf => { + const plotElement = document.getElementById(`plot-${tf}`); + if (plotElement && plotElement.layout && plotElement.layout.annotations) { + // Filter annotations to show/hide action predictions + const updatedAnnotations = plotElement.layout.annotations.map(ann => { + // Action annotations have specific text patterns (BUY, SELL, HOLD) + if (ann.text && (ann.text.includes('BUY') || ann.text.includes('SELL') || ann.text.includes('HOLD'))) { + return { ...ann, visible: enabled }; + } + return ann; + }); + + // Update layout without resetting view + Plotly.relayout(plotElement, { annotations: updatedAnnotations }); + } + }); + } + + togglePivots(enabled) { + this.displayToggles.pivots = enabled; + console.log('Pivot points display:', enabled); + + // Update visibility of pivot shapes and annotations without redrawing + this.timeframes.forEach(tf => { + const plotElement = document.getElementById(`plot-${tf}`); + if (plotElement && plotElement.layout) { + const updates = {}; + + // Hide/show pivot shapes (horizontal lines) + if (plotElement.layout.shapes) { + updates.shapes = plotElement.layout.shapes.map(shape => { + // Pivot lines are horizontal lines with specific colors + if (shape.type === 'line' && shape.y0 === shape.y1) { + return { ...shape, visible: enabled }; + } + return shape; + }); + } + + // Hide/show pivot annotations (L1, L2, etc.) + if (plotElement.layout.annotations) { + updates.annotations = plotElement.layout.annotations.map(ann => { + // Pivot annotations have text like 'L1H', 'L2L', etc. + if (ann.text && /L\d+[HL]/.test(ann.text)) { + return { ...ann, visible: enabled }; + } + return ann; + }); + } + + // Update layout without resetting view + if (Object.keys(updates).length > 0) { + Plotly.relayout(plotElement, updates); + } + } + }); + } + /** * Start auto-updating charts */ @@ -2847,7 +2970,7 @@ class ChartManager { this._addTransformerPrediction(fadedPred, predictionShapes, predictionAnnotations); // Add trend vector visualization (shorter projection to avoid zoom issues) - if (pred.trend_vector) { + if (pred.trend_vector && this.displayToggles.trendLines) { this._addTrendPrediction(pred.trend_vector, predictionShapes, predictionAnnotations); } @@ -2933,8 +3056,10 @@ class ChartManager { } // 4. Add all ghost candles from history to traces (with accuracy if validated) - for (const ghost of this.ghostCandleHistory[timeframe]) { - this._addGhostCandlePrediction(ghost.candle, timeframe, predictionTraces, ghost.targetTime, ghost.accuracy); + if (this.displayToggles.ghostCandles) { + for (const ghost of this.ghostCandleHistory[timeframe]) { + this._addGhostCandlePrediction(ghost.candle, timeframe, predictionTraces, ghost.targetTime, ghost.accuracy); + } } // 5. Store as "Last Prediction" for shadow rendering diff --git a/ANNOTATE/web/templates/components/chart_panel.html b/ANNOTATE/web/templates/components/chart_panel.html index d3207d3..dd43d27 100644 --- a/ANNOTATE/web/templates/components/chart_panel.html +++ b/ANNOTATE/web/templates/components/chart_panel.html @@ -4,22 +4,41 @@ Multi-Timeframe Charts -