From fb5350bb50343206295008d05bfa168b31322c27 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Sat, 24 May 2025 11:42:02 +0300 Subject: [PATCH] new fixed dash --- config.yaml | 10 +- core/data_provider.py | 4 +- web/scalping_dashboard_fixed.py | 420 ++++++++++++++++++++++++++------ 3 files changed, 348 insertions(+), 86 deletions(-) diff --git a/config.yaml b/config.yaml index aeb9253..0881807 100644 --- a/config.yaml +++ b/config.yaml @@ -37,15 +37,7 @@ cnn: epochs: 100 confidence_threshold: 0.6 early_stopping_patience: 10 - model_dir: "models/enhanced_cnn" - # Ultra-fast scalping weights (500x leverage) - timeframe_importance: - "1s": 0.60 # Primary scalping signal - "1m": 0.20 # Short-term confirmation - "1h": 0.15 # Medium-term trend - "1d": 0.05 # Long-term direction (minimal) - -# Enhanced RL Agent Configuration + model_dir: "models/enhanced_cnn" # Ultra-fast scalping weights (500x leverage) timeframe_importance: "1s": 0.60 # Primary scalping signal "1m": 0.20 # Short-term confirmation "1h": 0.15 # Medium-term trend "1d": 0.05 # Long-term direction (minimal)# Enhanced RL Agent Configuration rl: state_size: 100 # Will be calculated dynamically based on features action_space: 3 # BUY, HOLD, SELL diff --git a/core/data_provider.py b/core/data_provider.py index 10ee43d..ab0400b 100644 --- a/core/data_provider.py +++ b/core/data_provider.py @@ -105,9 +105,9 @@ class DataProvider: # Convert symbol format binance_symbol = symbol.replace('/', '').upper() - # Convert timeframe + # Convert timeframe (now includes 1s support) timeframe_map = { - '1m': '1m', '5m': '5m', '15m': '15m', '30m': '30m', + '1s': '1s', '1m': '1m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '4h': '4h', '1d': '1d' } binance_timeframe = timeframe_map.get(timeframe, '1h') diff --git a/web/scalping_dashboard_fixed.py b/web/scalping_dashboard_fixed.py index d8e3126..3f992bf 100644 --- a/web/scalping_dashboard_fixed.py +++ b/web/scalping_dashboard_fixed.py @@ -1,7 +1,11 @@ """ -Ultra-Fast Scalping Dashboard (500x Leverage) - Fixed Version +Ultra-Fast Scalping Dashboard (500x Leverage) - Real Market Data -Simplified dashboard for PnL tracking demonstration +Dashboard using ONLY real market data from APIs with: +- Main 1s ETH/USDT chart (full width) +- 4 small charts: 1m ETH, 1h ETH, 1d ETH, 1s BTC +- 500 candles preloaded at startup +- Real-time updates from data provider """ import asyncio @@ -25,10 +29,10 @@ from core.enhanced_orchestrator import EnhancedTradingOrchestrator, TradingActio logger = logging.getLogger(__name__) class ScalpingDashboard: - """Ultra-fast scalping dashboard optimized for 500x leverage trading""" + """Real market data scalping dashboard for 500x leverage trading""" def __init__(self, data_provider: DataProvider = None, orchestrator: EnhancedTradingOrchestrator = None): - """Initialize the scalping dashboard""" + """Initialize the dashboard with real market data""" self.config = get_config() self.data_provider = data_provider or DataProvider() self.orchestrator = orchestrator or EnhancedTradingOrchestrator(self.data_provider) @@ -44,6 +48,22 @@ class ScalpingDashboard: 'last_action': None } + # Real market data cache - preload 500 candles for each chart + self.market_data = { + 'ETH/USDT': { + '1s': None, # Main chart + '1m': None, # Small chart + '1h': None, # Small chart + '1d': None # Small chart + }, + 'BTC/USDT': { + '1s': None # Small chart + } + } + + # Initialize real market data + self._preload_market_data() + # Create Dash app self.app = dash.Dash(__name__) @@ -51,57 +71,142 @@ class ScalpingDashboard: self._setup_layout() self._setup_callbacks() - logger.info("Ultra-Fast Scalping Dashboard initialized") + logger.info("Ultra-Fast Scalping Dashboard initialized with REAL MARKET DATA") + + def _preload_market_data(self): + """Preload 500 candles for each chart from real market APIs""" + logger.info("🔄 Preloading 500 candles of real market data...") + + try: + # Load ETH/USDT data for main chart and small charts + self.market_data['ETH/USDT']['1s'] = self.data_provider.get_historical_data( + 'ETH/USDT', '1s', limit=500 + ) + self.market_data['ETH/USDT']['1m'] = self.data_provider.get_historical_data( + 'ETH/USDT', '1m', limit=500 + ) + self.market_data['ETH/USDT']['1h'] = self.data_provider.get_historical_data( + 'ETH/USDT', '1h', limit=500 + ) + self.market_data['ETH/USDT']['1d'] = self.data_provider.get_historical_data( + 'ETH/USDT', '1d', limit=500 + ) + + # Load BTC/USDT 1s data for small chart + self.market_data['BTC/USDT']['1s'] = self.data_provider.get_historical_data( + 'BTC/USDT', '1s', limit=500 + ) + + # Log successful data loading + for symbol in self.market_data: + for timeframe, data in self.market_data[symbol].items(): + if data is not None and not data.empty: + logger.info(f"✅ Loaded {len(data)} candles for {symbol} {timeframe}") + logger.info(f" Price range: ${data['close'].min():.2f} - ${data['close'].max():.2f}") + else: + logger.warning(f"⚠️ No data loaded for {symbol} {timeframe}") + + logger.info("✅ Market data preload complete - ready for real-time updates") + + except Exception as e: + logger.error(f"❌ Error preloading market data: {e}") + # Initialize empty DataFrames as fallback + for symbol in self.market_data: + for timeframe in self.market_data[symbol]: + self.market_data[symbol][timeframe] = pd.DataFrame() def _setup_layout(self): - """Setup the dashboard layout""" + """Setup the 5-chart dashboard layout""" self.app.layout = html.Div([ - # Header - html.H1("ULTRA-FAST SCALPING DASHBOARD - 500x LEVERAGE", - className="text-center mb-4"), - - # Metrics row + # Header with real-time metrics html.Div([ - html.Div([ - html.H3(id="live-pnl", className="text-success"), - html.P("Total P&L") - ], className="col-md-3 text-center"), + html.H1("ULTRA-FAST SCALPING DASHBOARD - 500x LEVERAGE - REAL MARKET DATA", + className="text-center mb-4"), + # Real-time metrics row html.Div([ - html.H3(id="win-rate", className="text-info"), - html.P("Win Rate") - ], className="col-md-3 text-center"), + html.Div([ + html.H3(id="live-pnl", className="text-success"), + html.P("Total P&L") + ], className="col-md-2 text-center"), + + html.Div([ + html.H3(id="win-rate", className="text-info"), + html.P("Win Rate") + ], className="col-md-2 text-center"), + + html.Div([ + html.H3(id="total-trades", className="text-primary"), + html.P("Total Trades") + ], className="col-md-2 text-center"), + + html.Div([ + html.H3(id="last-action", className="text-warning"), + html.P("Last Action") + ], className="col-md-2 text-center"), + + html.Div([ + html.H3(id="eth-price", className="text-white"), + html.P("ETH/USDT Live") + ], className="col-md-2 text-center"), + + html.Div([ + html.H3(id="btc-price", className="text-white"), + html.P("BTC/USDT Live") + ], className="col-md-2 text-center") + ], className="row mb-4") + ], className="bg-dark p-3 mb-3"), + + # Main 1s ETH/USDT chart (full width) + html.Div([ + html.H4("ETH/USDT 1s Real-Time Chart (Main Trading Signal)", + className="text-center mb-3"), + dcc.Graph(id="main-eth-1s-chart", style={"height": "500px"}) + ], className="mb-4"), + + # Row of 4 small charts + html.Div([ + # ETH/USDT 1m + html.Div([ + html.H6("ETH/USDT 1m", className="text-center"), + dcc.Graph(id="eth-1m-chart", style={"height": "250px"}) + ], className="col-md-3"), + # ETH/USDT 1h html.Div([ - html.H3(id="total-trades", className="text-primary"), - html.P("Total Trades") - ], className="col-md-3 text-center"), + html.H6("ETH/USDT 1h", className="text-center"), + dcc.Graph(id="eth-1h-chart", style={"height": "250px"}) + ], className="col-md-3"), + # ETH/USDT 1d html.Div([ - html.H3(id="last-action", className="text-warning"), - html.P("Last Action") - ], className="col-md-3 text-center") + html.H6("ETH/USDT 1d", className="text-center"), + dcc.Graph(id="eth-1d-chart", style={"height": "250px"}) + ], className="col-md-3"), + + # BTC/USDT 1s + html.Div([ + html.H6("BTC/USDT 1s", className="text-center"), + dcc.Graph(id="btc-1s-chart", style={"height": "250px"}) + ], className="col-md-3") ], className="row mb-4"), - # Chart - dcc.Graph(id="main-chart", style={"height": "400px"}), - - # Actions log + # Recent actions log html.Div([ - html.H4("Recent Trading Actions"), + html.H5("Live Trading Actions (Real Market Data)", className="text-center mb-3"), html.Div(id="actions-log") - ]), + ], className="mb-4"), - # Auto-refresh + # Auto-refresh for real-time updates dcc.Interval( - id='interval-component', - interval=100, # 100ms + id='market-data-interval', + interval=1000, # Update every 1 second for real-time feel n_intervals=0 ) - ]) + ], className="container-fluid") def _setup_callbacks(self): - """Setup dashboard callbacks""" + """Setup dashboard callbacks with real market data""" @self.app.callback( [ @@ -109,13 +214,19 @@ class ScalpingDashboard: Output('win-rate', 'children'), Output('total-trades', 'children'), Output('last-action', 'children'), - Output('main-chart', 'figure'), + Output('eth-price', 'children'), + Output('btc-price', 'children'), + Output('main-eth-1s-chart', 'figure'), + Output('eth-1m-chart', 'figure'), + Output('eth-1h-chart', 'figure'), + Output('eth-1d-chart', 'figure'), + Output('btc-1s-chart', 'figure'), Output('actions-log', 'children') ], - [Input('interval-component', 'n_intervals')] + [Input('market-data-interval', 'n_intervals')] ) - def update_dashboard(n_intervals): - """Update all dashboard components""" + def update_dashboard_with_real_data(n_intervals): + """Update all dashboard components with real market data""" try: # Update metrics pnl = f"${self.scalping_metrics['total_pnl']:+.2f}" @@ -123,69 +234,228 @@ class ScalpingDashboard: total_trades = str(self.scalping_metrics['total_trades']) last_action = self.scalping_metrics['last_action'] or "WAITING" - # Create simple chart - chart = self._create_simple_chart() + # Get current prices from real market data + eth_price = self._get_current_price('ETH/USDT') + btc_price = self._get_current_price('BTC/USDT') + + # Refresh market data periodically (every 10 updates) + if n_intervals % 10 == 0: + self._refresh_market_data() + + # Create charts with real market data + main_eth_chart = self._create_real_chart('ETH/USDT', '1s', main_chart=True) + eth_1m_chart = self._create_real_chart('ETH/USDT', '1m') + eth_1h_chart = self._create_real_chart('ETH/USDT', '1h') + eth_1d_chart = self._create_real_chart('ETH/USDT', '1d') + btc_1s_chart = self._create_real_chart('BTC/USDT', '1s') # Create actions log actions_log = self._create_actions_log() - return pnl, win_rate, total_trades, last_action, chart, actions_log + return ( + pnl, win_rate, total_trades, last_action, eth_price, btc_price, + main_eth_chart, eth_1m_chart, eth_1h_chart, eth_1d_chart, btc_1s_chart, + actions_log + ) except Exception as e: logger.error(f"Error updating dashboard: {e}") - return "$0.00", "0%", "0", "ERROR", {}, "System starting..." + # Return safe defaults + return ( + "$0.00", "0%", "0", "ERROR", "$0", "$0", + {}, {}, {}, {}, {}, "Loading real market data..." + ) - def _create_simple_chart(self): - """Create a simple price chart""" - # Generate mock price data - times = [datetime.now() - timedelta(seconds=i) for i in range(100, 0, -1)] - prices = [3050 + np.random.normal(0, 2) for _ in times] - - fig = go.Figure() - fig.add_trace(go.Scatter( - x=times, - y=prices, - mode='lines', - name='ETH/USDT 1s', - line=dict(color='green', width=2) - )) - - fig.update_layout( - title="ETH/USDT Ultra-Fast Chart", - xaxis_title="Time", - yaxis_title="Price (USDT)", - template="plotly_dark" - ) - - return fig + def _refresh_market_data(self): + """Refresh market data from APIs""" + try: + # Get latest data for each chart (last 100 candles for efficiency) + for symbol in self.market_data: + for timeframe in self.market_data[symbol]: + latest_data = self.data_provider.get_latest_candles(symbol, timeframe, limit=100) + if latest_data is not None and not latest_data.empty: + # Update our cache with latest data + if self.market_data[symbol][timeframe] is not None: + # Append new data and keep last 500 candles + combined = pd.concat([self.market_data[symbol][timeframe], latest_data]) + combined = combined.drop_duplicates(subset=['timestamp'], keep='last') + self.market_data[symbol][timeframe] = combined.tail(500) + else: + self.market_data[symbol][timeframe] = latest_data.tail(500) + + except Exception as e: + logger.warning(f"Error refreshing market data: {e}") + + def _get_current_price(self, symbol: str) -> str: + """Get current price from real market data""" + try: + data = self.market_data[symbol]['1s'] + if data is not None and not data.empty: + current_price = data['close'].iloc[-1] + return f"${current_price:.2f}" + return "$0.00" + except Exception as e: + logger.warning(f"Error getting current price for {symbol}: {e}") + return "$0.00" + + def _create_real_chart(self, symbol: str, timeframe: str, main_chart: bool = False): + """Create chart using real market data""" + try: + data = self.market_data[symbol][timeframe] + + if data is None or data.empty: + # Return empty chart with message + fig = go.Figure() + fig.add_annotation( + text=f"Loading real market data for {symbol} {timeframe}...", + xref="paper", yref="paper", + x=0.5, y=0.5, showarrow=False, + font=dict(size=16, color="red") + ) + fig.update_layout( + title=f"{symbol} {timeframe} - Real Market Data", + template="plotly_dark", + height=500 if main_chart else 250 + ) + return fig + + # Create candlestick chart from real data + fig = go.Figure() + + if main_chart: + # Main chart with candlesticks and volume + fig.add_trace(go.Candlestick( + x=data['timestamp'], + open=data['open'], + high=data['high'], + low=data['low'], + close=data['close'], + name=f"{symbol} {timeframe}", + increasing_line_color='#00ff88', + decreasing_line_color='#ff4444' + )) + + # Add volume as secondary plot + fig.add_trace(go.Bar( + x=data['timestamp'], + y=data['volume'], + name="Volume", + yaxis='y2', + opacity=0.3, + marker_color='lightblue' + )) + + # Main chart layout + fig.update_layout( + title=f"{symbol} {timeframe} Real-Time Market Data - Latest: ${data['close'].iloc[-1]:.2f}", + yaxis_title="Price (USDT)", + yaxis2=dict(title="Volume", overlaying='y', side='right'), + template="plotly_dark", + showlegend=False, + height=500 + ) + + # Add current price line + current_price = data['close'].iloc[-1] + fig.add_hline( + y=current_price, + line_dash="dash", + line_color="yellow", + annotation_text=f"${current_price:.2f}", + annotation_position="right" + ) + + else: + # Small chart - simple line chart + price_change = ((data['close'].iloc[-1] - data['close'].iloc[0]) / data['close'].iloc[0]) * 100 + line_color = '#00ff88' if price_change >= 0 else '#ff4444' + + fig.add_trace(go.Scatter( + x=data['timestamp'], + y=data['close'], + mode='lines', + name=f"{symbol} {timeframe}", + line=dict(color=line_color, width=2) + )) + + # Small chart layout + fig.update_layout( + template="plotly_dark", + showlegend=False, + margin=dict(l=10, r=10, t=30, b=10), + height=250, + title=f"{symbol} {timeframe}: ${data['close'].iloc[-1]:.2f}" + ) + + # Add price change annotation + change_color = "green" if price_change >= 0 else "red" + fig.add_annotation( + text=f"{price_change:+.2f}%", + xref="paper", yref="paper", + x=0.95, y=0.95, + showarrow=False, + font=dict(color=change_color, size=12, weight="bold"), + bgcolor="rgba(0,0,0,0.7)" + ) + + return fig + + except Exception as e: + logger.error(f"Error creating chart for {symbol} {timeframe}: {e}") + # Return error chart + fig = go.Figure() + fig.add_annotation( + text=f"Error loading {symbol} {timeframe}", + xref="paper", yref="paper", + x=0.5, y=0.5, showarrow=False, + font=dict(size=14, color="red") + ) + fig.update_layout( + template="plotly_dark", + height=500 if main_chart else 250 + ) + return fig def _create_actions_log(self): - """Create actions log""" + """Create trading actions log""" if not self.recent_decisions: - return html.P("No recent actions", className="text-muted") + return html.P("Waiting for trading signals from real market data...", className="text-muted text-center") log_items = [] - for action in self.recent_decisions[-5:]: + for action in self.recent_decisions[-5:]: # Show last 5 actions log_items.append( - html.P(f"{action.action} {action.symbol} @ ${action.price:.2f}") + html.P( + f"🔥 {action.action} {action.symbol} @ ${action.price:.2f} " + f"(Confidence: {action.confidence:.1%}) - Real Market Data", + className="text-center mb-1" + ) ) return html.Div(log_items) def add_trading_decision(self, decision: TradingAction): - """Add a new trading decision""" + """Add a new trading decision based on real market data""" self.recent_decisions.append(decision) if len(self.recent_decisions) > 50: self.recent_decisions.pop(0) self.scalping_metrics['total_trades'] += 1 self.scalping_metrics['last_action'] = f"{decision.action} {decision.symbol}" + + logger.info(f"📊 Added real market trading decision: {decision.action} {decision.symbol} @ ${decision.price:.2f}") def run(self, host: str = '127.0.0.1', port: int = 8050, debug: bool = False): - """Run the dashboard""" - logger.info(f"Starting Dashboard at http://{host}:{port}") - self.app.run_server(host=host, port=port, debug=debug) + """Run the real market data dashboard""" + logger.info(f"🚀 Starting Real Market Data Dashboard at http://{host}:{port}") + logger.info("📊 Dashboard Features:") + logger.info(" • Main 1s ETH/USDT chart with real market data") + logger.info(" • 4 small charts: 1m/1h/1d ETH + 1s BTC") + logger.info(" • 500 candles preloaded from Binance API") + logger.info(" • Real-time updates every second") + logger.info(" • NO GENERATED DATA - 100% real market feeds") + + self.app.run(host=host, port=port, debug=debug) def create_scalping_dashboard(data_provider=None, orchestrator=None): - """Create dashboard instance""" + """Create dashboard instance with real market data""" return ScalpingDashboard(data_provider, orchestrator) \ No newline at end of file