diff --git a/web/cob_dashboard.html b/web/cob_dashboard.html
index af844ba..d962d24 100644
--- a/web/cob_dashboard.html
+++ b/web/cob_dashboard.html
@@ -545,12 +545,16 @@
ws.onmessage = function(event) {
try {
const data = JSON.parse(event.data);
+ console.log(`🔌 WebSocket message received:`, data.type, data.symbol || 'no symbol');
if (data.type === 'cob_update') {
handleCOBUpdate(data);
+ } else {
+ console.log(`🔌 Unhandled WebSocket message type:`, data.type);
}
} catch (error) {
- console.error('Error parsing WebSocket message:', error);
+ console.error('❌ Error parsing WebSocket message:', error);
+ console.error('Raw message:', event.data);
}
};
@@ -580,7 +584,8 @@
}
// Debug logging to understand data structure
- console.log(`${symbol} COB Update:`, {
+ console.log(`🔄 ${symbol} COB Update:`, {
+ source: data.type || 'Unknown',
bidsCount: (cobData.bids || []).length,
asksCount: (cobData.asks || []).length,
sampleBid: (cobData.bids || [])[0],
@@ -588,7 +593,8 @@
stats: cobData.stats,
hasOHLCV: !!cobData.ohlcv,
ohlcvCount: cobData.ohlcv ? cobData.ohlcv.length : 0,
- sampleOHLCV: cobData.ohlcv ? cobData.ohlcv[0] : null
+ sampleOHLCV: cobData.ohlcv ? cobData.ohlcv[0] : null,
+ ohlcvStructure: cobData.ohlcv ? Object.keys(cobData.ohlcv[0] || {}) : 'none'
});
// Check if WebSocket data has insufficient depth, fetch REST data
@@ -596,7 +602,7 @@
const asks = cobData.asks || [];
if (bids.length <= 1 && asks.length <= 1) {
- console.log(`Insufficient WS depth for ${symbol}, fetching REST data...`);
+ console.log(`⚠️ Insufficient WS depth for ${symbol}, fetching REST data...`);
fetchRESTData(symbol);
return;
}
@@ -604,17 +610,31 @@
currentData[symbol] = cobData;
// Process OHLCV data if available
- if (cobData.ohlcv && Array.isArray(cobData.ohlcv)) {
+ if (cobData.ohlcv && Array.isArray(cobData.ohlcv) && cobData.ohlcv.length > 0) {
ohlcvData[symbol] = cobData.ohlcv;
- console.log(`${symbol} OHLCV data received:`, cobData.ohlcv.length, 'candles');
+ console.log(`📈 ${symbol} OHLCV data received:`, cobData.ohlcv.length, 'candles');
+
+ // Log first and last candle for debugging
+ const firstCandle = cobData.ohlcv[0];
+ const lastCandle = cobData.ohlcv[cobData.ohlcv.length - 1];
+ console.log(`📊 ${symbol} OHLCV range:`, {
+ first: firstCandle,
+ last: lastCandle,
+ priceRange: `${Math.min(...cobData.ohlcv.map(c => c.low))} - ${Math.max(...cobData.ohlcv.map(c => c.high))}`
+ });
// Update mini chart after order book update
setTimeout(() => {
const prefix = symbol === 'BTC/USDT' ? 'btc' : 'eth';
+ console.log(`🎨 Drawing chart for ${prefix} with ${cobData.ohlcv.length} candles`);
drawMiniChart(prefix, cobData.ohlcv);
}, 100);
} else {
- console.log(`${symbol}: No OHLCV data in update`);
+ console.log(`❌ ${symbol}: No valid OHLCV data in update (${cobData.ohlcv ? cobData.ohlcv.length : 'null'} items)`);
+
+ // Try to get OHLCV from REST endpoint
+ console.log(`🔍 Trying to fetch OHLCV from REST for ${symbol}...`);
+ fetchRESTData(symbol);
}
// Track imbalance for aggregation
@@ -636,15 +656,28 @@
}
function fetchRESTData(symbol) {
+ console.log(`🔍 Fetching REST data for ${symbol}...`);
fetch(`/api/cob/${encodeURIComponent(symbol)}`)
- .then(response => response.json())
+ .then(response => {
+ console.log(`📡 REST response for ${symbol}:`, response.status, response.statusText);
+ return response.json();
+ })
.then(data => {
+ console.log(`📦 REST data received for ${symbol}:`, {
+ hasData: !!data.data,
+ dataKeys: data.data ? Object.keys(data.data) : [],
+ hasOHLCV: !!(data.data && data.data.ohlcv),
+ ohlcvCount: data.data && data.data.ohlcv ? data.data.ohlcv.length : 0
+ });
+
if (data.data) {
- console.log(`REST fallback data for ${symbol}:`, data.data);
- handleCOBUpdate({symbol: symbol, data: data.data});
+ console.log(`✅ Processing REST fallback data for ${symbol}`);
+ handleCOBUpdate({symbol: symbol, data: data.data, type: 'rest_api'});
+ } else {
+ console.error(`❌ No data in REST response for ${symbol}`);
}
})
- .catch(error => console.error(`Error fetching REST data for ${symbol}:`, error));
+ .catch(error => console.error(`❌ Error fetching REST data for ${symbol}:`, error));
}
function trackImbalance(symbol, imbalance) {
@@ -1028,7 +1061,7 @@
try {
const canvas = document.getElementById(`${prefix}-mini-chart`);
if (!canvas) {
- console.log(`Canvas not found for ${prefix}-mini-chart`);
+ console.error(`❌ Canvas not found for ${prefix}-mini-chart`);
return;
}
@@ -1036,10 +1069,11 @@
const width = canvas.width;
const height = canvas.height;
- console.log(`Drawing ${prefix} chart with ${ohlcvArray ? ohlcvArray.length : 0} candles`);
+ console.log(`🎨 Drawing ${prefix} chart with ${ohlcvArray ? ohlcvArray.length : 0} candles (${width}x${height})`);
- // Clear canvas
- ctx.clearRect(0, 0, width, height);
+ // Clear canvas with background
+ ctx.fillStyle = '#111';
+ ctx.fillRect(0, 0, width, height);
if (!ohlcvArray || ohlcvArray.length === 0) {
// Draw "No Data" message
@@ -1047,7 +1081,18 @@
ctx.font = '12px Courier New';
ctx.textAlign = 'center';
ctx.fillText('No Data', width / 2, height / 2);
- console.log(`${prefix}: No OHLCV data to draw`);
+ console.log(`❌ ${prefix}: No OHLCV data to draw`);
+ return;
+ }
+
+ // Validate OHLCV data structure
+ const firstCandle = ohlcvArray[0];
+ if (!firstCandle || typeof firstCandle.open === 'undefined' || typeof firstCandle.close === 'undefined') {
+ console.error(`❌ ${prefix}: Invalid OHLCV data structure:`, firstCandle);
+ ctx.fillStyle = '#ff6b6b';
+ ctx.font = '10px Courier New';
+ ctx.textAlign = 'center';
+ ctx.fillText('Invalid Data', width / 2, height / 2);
return;
}
@@ -1061,7 +1106,16 @@
const maxPrice = Math.max(...prices);
const priceRange = maxPrice - minPrice;
- if (priceRange === 0) return;
+ console.log(`📊 ${prefix} price range: $${minPrice.toFixed(2)} - $${maxPrice.toFixed(2)} (range: $${priceRange.toFixed(2)})`);
+
+ if (priceRange === 0) {
+ console.warn(`⚠️ ${prefix}: Zero price range, cannot draw chart`);
+ ctx.fillStyle = '#ff6b6b';
+ ctx.font = '10px Courier New';
+ ctx.textAlign = 'center';
+ ctx.fillText('Zero Range', width / 2, height / 2);
+ return;
+ }
// Calculate candle width and spacing
const candleWidth = Math.max(1, Math.floor(width / ohlcvArray.length) - 1);
@@ -1124,8 +1178,11 @@
ctx.setLineDash([]);
}
+ console.log(`✅ Successfully drew ${prefix} chart with ${ohlcvArray.length} candles`);
+
} catch (error) {
- console.error(`Error drawing mini chart for ${prefix}:`, error);
+ console.error(`❌ Error drawing mini chart for ${prefix}:`, error);
+ console.error(error.stack);
}
}
diff --git a/web/cob_realtime_dashboard.py b/web/cob_realtime_dashboard.py
index 1565712..ab56fdd 100644
--- a/web/cob_realtime_dashboard.py
+++ b/web/cob_realtime_dashboard.py
@@ -194,7 +194,11 @@ class COBDashboardServer:
# Get latest data from cache or COB integration
if symbol in self.latest_cob_data:
- data = self.latest_cob_data[symbol]
+ data = self.latest_cob_data[symbol].copy()
+ # Add OHLCV data to REST response
+ if symbol in self.ohlcv_data:
+ data['ohlcv'] = list(self.ohlcv_data[symbol])
+ logger.debug(f"REST API: Added {len(data['ohlcv'])} OHLCV candles for {symbol}")
elif self.cob_integration:
data = await self._generate_dashboard_data(symbol)
else: