diff --git a/src/api/dashboard/static/index.html b/src/api/dashboard/static/index.html index 4b66b4a..c2b31aa 100644 --- a/src/api/dashboard/static/index.html +++ b/src/api/dashboard/static/index.html @@ -1254,15 +1254,28 @@ } onVisibleRangeChange() { - if (!this.hasInitialLoad || this.isLoading) return; + if (!this.hasInitialLoad || this.isLoading) { + console.log('Skipping range change:', { hasInitialLoad: this.hasInitialLoad, isLoading: this.isLoading }); + return; + } const visibleRange = this.chart.timeScale().getVisibleLogicalRange(); - if (!visibleRange) return; + if (!visibleRange) { + console.log('No visible range'); + return; + } + + console.log('Visible range:', visibleRange); const data = this.candleSeries.data(); - if (!data || data.length === 0) return; + if (!data || data.length === 0) { + console.log('No data available'); + return; + } - if (visibleRange.from < 10) { + // Load when user scrolls close to the left edge (earlier time) + if (visibleRange.from < 20) { + console.log('Near left edge, loading historical data...'); const oldestCandle = data[0]; if (oldestCandle) { this.loadHistoricalData(oldestCandle.time); @@ -1275,11 +1288,12 @@ this.isLoading = true; try { - const endTime = new Date(beforeTime * 1000); - const startTime = new Date(endTime.getTime() - 24 * 60 * 60 * 1000); + // Fetch candles before the oldest visible candle + // Use end parameter to get candles up to (but not including) the oldest candle + const endTime = new Date((beforeTime - 1) * 1000); // 1 second before oldest const response = await fetch( - `/api/v1/candles?symbol=BTC&interval=${this.currentInterval}&start=${startTime.toISOString()}&end=${endTime.toISOString()}&limit=500` + `/api/v1/candles?symbol=BTC&interval=${this.currentInterval}&end=${endTime.toISOString()}&limit=500` ); const data = await response.json(); @@ -1297,6 +1311,9 @@ this.allData.set(this.currentInterval, mergedData); this.candleSeries.setData(mergedData); + console.log(`Loaded ${chartData.length} historical candles`); + } else { + console.log('No more historical data available'); } } catch (error) { console.error('Error loading historical data:', error); @@ -1750,6 +1767,9 @@ }); } + // Track trade line series for cleanup + window.tradeLineSeries = []; + // Show simulation buy/sell markers on the chart function showSimulationMarkers() { if (!window.lastSimulationResults || !window.dashboard) return; @@ -1757,36 +1777,59 @@ const trades = window.lastSimulationResults.trades; const markers = []; + // Clear existing trade lines + window.tradeLineSeries.forEach(series => { + window.dashboard.chart.removeSeries(series); + }); + window.tradeLineSeries = []; + trades.forEach(trade => { const entryTime = Math.floor(new Date(trade.entryTime).getTime() / 1000); const exitTime = Math.floor(new Date(trade.exitTime).getTime() / 1000); const pnlSymbol = trade.pnl > 0 ? '+' : ''; - // Entry Marker - Buy signal + // Entry Marker - Buy signal (blue arrow and text) markers.push({ time: entryTime, position: 'belowBar', - color: '#26a69a', + color: '#2196f3', shape: 'arrowUp', - text: '🟢 BUY', - size: 2 + text: 'BUY', + size: 1 }); - // Exit Marker - Sell signal with P&L info + // Exit Marker - Sell signal (green for profit, red for loss) markers.push({ time: exitTime, position: 'aboveBar', - color: trade.pnl > 0 ? '#26a69a' : '#ef5350', + color: trade.pnl > 0 ? '#4caf50' : '#f44336', shape: 'arrowDown', - text: (trade.pnl > 0 ? '🟢' : '🔴') + ' SELL ' + pnlSymbol + trade.pnlPct.toFixed(1) + '%', - size: 2 + text: 'SELL ' + pnlSymbol + trade.pnlPct.toFixed(1) + '%', + size: 1 }); + + // Create separate line series for this trade (entry to exit) + const tradeLine = window.dashboard.chart.addLineSeries({ + color: '#2196f3', + lineWidth: 1, + lastValueVisible: false, + title: '', + priceLineVisible: false, + crosshairMarkerVisible: false + }); + + tradeLine.setData([ + { time: entryTime, value: trade.entryPrice }, + { time: exitTime, value: trade.exitPrice } + ]); + + window.tradeLineSeries.push(tradeLine); }); // Sort markers by time markers.sort((a, b) => a.time - b.time); - // Apply to chart + // Apply markers to chart window.dashboard.candleSeries.setMarkers(markers); // Log to console instead of alert @@ -1800,6 +1843,12 @@ function clearSimulationMarkers() { if (window.dashboard) { window.dashboard.candleSeries.setMarkers([]); + + // Remove trade line series + window.tradeLineSeries.forEach(series => { + window.dashboard.chart.removeSeries(series); + }); + window.tradeLineSeries = []; } }