From 732c5b49412bf8ae1c2fb4e1a4cf5339dd376465 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Wed, 10 Dec 2025 14:39:06 +0200 Subject: [PATCH] fix live updates --- ANNOTATE/data/annotations/annotations_db.json | 1 + ANNOTATE/web/static/js/chart_manager.js | 13 +- CHART_UPDATES_FIX.md | 125 ++++++++++++++++++ core/orchestrator.py | 8 +- test_chart_updates.html | 91 +++++++++++++ test_live_updates_api.py | 60 +++++++++ 6 files changed, 290 insertions(+), 8 deletions(-) create mode 100644 CHART_UPDATES_FIX.md create mode 100644 test_chart_updates.html create mode 100644 test_live_updates_api.py diff --git a/ANNOTATE/data/annotations/annotations_db.json b/ANNOTATE/data/annotations/annotations_db.json index e69de29..0637a08 100644 --- a/ANNOTATE/data/annotations/annotations_db.json +++ b/ANNOTATE/data/annotations/annotations_db.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/ANNOTATE/web/static/js/chart_manager.js b/ANNOTATE/web/static/js/chart_manager.js index 52e4160..08c752d 100644 --- a/ANNOTATE/web/static/js/chart_manager.js +++ b/ANNOTATE/web/static/js/chart_manager.js @@ -773,9 +773,14 @@ class ChartManager { const volumeColor = candle.close >= candle.open ? '#10b981' : '#ef4444'; Plotly.extendTraces(plotId, { x: [[formattedTimestamp]], - y: [[candle.volume]], - marker: { color: [[volumeColor]] } + y: [[candle.volume]] }, [1]).then(() => { + // Update volume color separately using restyle + const currentTrace = plotElement.data[1]; + if (currentTrace && currentTrace.marker && currentTrace.marker.color) { + const newColors = [...currentTrace.marker.color, volumeColor]; + Plotly.restyle(plotId, {'marker.color': [newColors]}, [1]); + } console.log(`[${timeframe}] Volume trace extended successfully`); }).catch(err => { console.error(`[${timeframe}] Error extending volume trace:`, err); @@ -4393,7 +4398,6 @@ class ChartManager { this.liveMetricsOverlay = null; } -} // Debug method to manually trigger pivot recalculation debugRecalculatePivots(timeframe) { @@ -4424,4 +4428,5 @@ class ChartManager { } }); console.log('========================'); - } \ No newline at end of file + } +} \ No newline at end of file diff --git a/CHART_UPDATES_FIX.md b/CHART_UPDATES_FIX.md new file mode 100644 index 0000000..57a8a36 --- /dev/null +++ b/CHART_UPDATES_FIX.md @@ -0,0 +1,125 @@ +# Chart Updates Fix - JavaScript Errors Resolved + +## Issues Fixed + +### 1. JavaScript Syntax Error ✅ +**Error**: `Uncaught SyntaxError: Unexpected token '{' (at chart_manager.js:4399:39)` +**Cause**: Debug methods were added outside the ChartManager class + +**Fix**: Moved debug methods inside the class before the closing brace +```javascript +class ChartManager { + // ... existing methods + + // Debug methods moved inside class + debugRecalculatePivots(timeframe) { ... } + debugPivotStatus() { ... } +} // ← Proper class closing +``` + +### 2. Plotly extendTraces Marker Error ✅ +**Error**: `attribute marker must be an array of length equal to indices array length` +**Cause**: Incorrect marker.color format in volume trace extension + +**Before (Broken):** +```javascript +Plotly.extendTraces(plotId, { + x: [[formattedTimestamp]], + y: [[candle.volume]], + marker: { color: [[volumeColor]] } // ❌ Wrong format +}, [1]); +``` + +**After (Fixed):** +```javascript +Plotly.extendTraces(plotId, { + x: [[formattedTimestamp]], + y: [[candle.volume]] + // ✅ No marker in extendTraces +}, [1]).then(() => { + // ✅ Update color separately with restyle + const currentTrace = plotElement.data[1]; + if (currentTrace && currentTrace.marker && currentTrace.marker.color) { + const newColors = [...currentTrace.marker.color, volumeColor]; + Plotly.restyle(plotId, {'marker.color': [newColors]}, [1]); + } +}); +``` + +### 3. Empty Annotations File ✅ +**Error**: `Expecting value: line 1 column 1 (char 0)` +**Cause**: Empty annotations JSON file + +**Fix**: Created proper empty JSON array structure +```json +[] +``` + +## Root Cause Analysis + +### Plotly extendTraces Limitation +The issue was that `Plotly.extendTraces()` has specific requirements for marker arrays: +- When extending traces, marker properties must match the exact structure +- For volume bars, the marker.color array must have the same length as the data being added +- The `[[volumeColor]]` format was incorrect for this use case + +### Solution Approach +Instead of trying to extend traces with marker colors, the fix: +1. **Extends traces without marker data** - Adds new data points cleanly +2. **Updates colors separately** - Uses `Plotly.restyle()` to update the entire color array +3. **Maintains color consistency** - Preserves existing colors and adds new ones + +## Expected Results + +### Live Chart Updates Should Now: +- ✅ **Add new candles** without JavaScript errors +- ✅ **Update volume colors** correctly (green for up, red for down) +- ✅ **Maintain chart performance** with proper Plotly API usage +- ✅ **Show live data** from the unified WebSocket → DataProvider pipeline + +### Console Should Show: +``` +[1m] Successfully added new candle. Total candles: 152 +[1m] Volume trace extended successfully +✅ Chart update fix working correctly! +``` + +Instead of: +``` +❌ Error adding new candle: attribute marker must be an array... +``` + +## Files Modified + +### JavaScript: +- `ANNOTATE/web/static/js/chart_manager.js` - Fixed extendTraces marker issue and syntax error + +### Data: +- `ANNOTATE/data/annotations/annotations_db.json` - Created proper empty JSON structure + +### Test: +- `test_chart_updates.html` - Test file to verify the fix works + +## Testing + +The fix can be verified by: +1. **Opening ANNOTATE dashboard** - Should load without JavaScript errors +2. **Watching live updates** - Charts should update smoothly with new candles +3. **Checking console** - No more Plotly marker errors +4. **Volume colors** - Should show green/red based on price direction + +## Technical Details + +### Plotly API Correct Usage: +- **extendTraces()** - For adding new data points to existing traces +- **restyle()** - For updating trace properties like colors, styles +- **relayout()** - For updating layout properties like axes, titles + +### Volume Color Logic: +```javascript +const volumeColor = candle.close >= candle.open ? '#10b981' : '#ef4444'; +// Green for bullish candles (close >= open) +// Red for bearish candles (close < open) +``` + +The chart updates should now work smoothly with live data! 🎯 \ No newline at end of file diff --git a/core/orchestrator.py b/core/orchestrator.py index aa0406a..c4e06c7 100644 --- a/core/orchestrator.py +++ b/core/orchestrator.py @@ -3441,10 +3441,10 @@ class TradingOrchestrator: except Exception as e: logger.error(f"Error getting trend training stats: {e}") return {} - - def store_model_trend_prediction(self, model_type: str, symbol: str, timeframe: str, - predicted_trend: str, confidence: float, - target_price: float = None, horizon_minutes: int = 60): + + def store_model_trend_prediction(self, model_type: str, symbol: str, timeframe: str, + predicted_trend: str, confidence: float, + target_price: float = None, horizon_minutes: int = 60): """ Store a trend prediction from a model for later validation diff --git a/test_chart_updates.html b/test_chart_updates.html new file mode 100644 index 0000000..b2c8ff6 --- /dev/null +++ b/test_chart_updates.html @@ -0,0 +1,91 @@ + + + + Chart Updates Test + + + +
+ + + + \ No newline at end of file diff --git a/test_live_updates_api.py b/test_live_updates_api.py new file mode 100644 index 0000000..8fdab95 --- /dev/null +++ b/test_live_updates_api.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +""" +Test script to check live updates API +""" + +import requests +import json +import time +from datetime import datetime + +def test_live_updates(): + """Test the live-updates-batch API""" + + print("Testing live-updates-batch API...") + print("-" * 50) + + url = "http://localhost:8051/api/live-updates-batch" + + payload = { + "symbol": "ETH/USDT", + "timeframes": ["1s", "1m"] + } + + # Make 3 requests with 3 second intervals to see if data changes + for i in range(3): + try: + print(f"\n=== Request {i+1} at {datetime.now().strftime('%H:%M:%S')} ===") + + response = requests.post(url, json=payload, timeout=10) + + if response.status_code == 200: + data = response.json() + + print(f"Success: {data.get('success')}") + print(f"Server time: {data.get('server_time')}") + + if data.get('success') and data.get('chart_updates'): + for timeframe, update in data['chart_updates'].items(): + candle = update.get('candle', {}) + timestamp = candle.get('timestamp', 'N/A') + close_price = candle.get('close', 'N/A') + is_confirmed = update.get('is_confirmed', False) + + print(f" {timeframe}: {timestamp} | Close: {close_price} | Confirmed: {is_confirmed}") + else: + print(f" Error: {data.get('error', 'Unknown error')}") + else: + print(f" HTTP Error: {response.status_code}") + print(f" Response: {response.text}") + + except Exception as e: + print(f" Request failed: {e}") + + if i < 2: # Don't sleep after last request + time.sleep(3) + + print("\nTest completed!") + +if __name__ == "__main__": + test_live_updates() \ No newline at end of file