#!/usr/bin/env python3 """ Minimal Scalping Dashboard - Test callback functionality without emoji issues """ import logging import sys from pathlib import Path from datetime import datetime import pandas as pd import numpy as np # Add project root to path project_root = Path(__file__).parent sys.path.insert(0, str(project_root)) import dash from dash import dcc, html, Input, Output import plotly.graph_objects as go from core.config import setup_logging from core.data_provider import DataProvider # Setup logging without emojis logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) class MinimalDashboard: """Minimal dashboard to test callback functionality""" def __init__(self): self.data_provider = DataProvider() self.app = dash.Dash(__name__) self.chart_data = {} # Setup layout and callbacks self._setup_layout() self._setup_callbacks() logger.info("Minimal dashboard initialized") def _setup_layout(self): """Setup minimal layout""" self.app.layout = html.Div([ html.H1("Minimal Scalping Dashboard - Callback Test", className="text-center"), # Metrics row html.Div([ html.Div([ html.H3(id="current-time", className="text-center"), html.P("Current Time", className="text-center") ], className="col-md-3"), html.Div([ html.H3(id="update-counter", className="text-center"), html.P("Update Count", className="text-center") ], className="col-md-3"), html.Div([ html.H3(id="eth-price", className="text-center"), html.P("ETH Price", className="text-center") ], className="col-md-3"), html.Div([ html.H3(id="status", className="text-center"), html.P("Status", className="text-center") ], className="col-md-3") ], className="row mb-4"), # Chart html.Div([ dcc.Graph(id="main-chart", style={"height": "400px"}) ]), # Fast refresh interval dcc.Interval( id='fast-interval', interval=1000, # 1 second n_intervals=0 ) ], className="container-fluid") def _setup_callbacks(self): """Setup callbacks with proper scoping""" # Store reference to self for callback access dashboard_instance = self @self.app.callback( [ Output('current-time', 'children'), Output('update-counter', 'children'), Output('eth-price', 'children'), Output('status', 'children'), Output('main-chart', 'figure') ], [Input('fast-interval', 'n_intervals')] ) def update_dashboard(n_intervals): """Update dashboard components""" try: logger.info(f"Callback triggered, interval: {n_intervals}") # Get current time current_time = datetime.now().strftime("%H:%M:%S") # Update counter counter = f"Updates: {n_intervals}" # Try to get ETH price try: eth_price_data = dashboard_instance.data_provider.get_current_price('ETH/USDT') eth_price = f"${eth_price_data:.2f}" if eth_price_data else "Loading..." except Exception as e: logger.warning(f"Error getting ETH price: {e}") eth_price = "Error" # Status status = "Running" if n_intervals > 0 else "Starting" # Create chart try: chart = dashboard_instance._create_chart(n_intervals) except Exception as e: logger.error(f"Error creating chart: {e}") chart = dashboard_instance._create_error_chart() logger.info(f"Callback returning: time={current_time}, counter={counter}, price={eth_price}") return current_time, counter, eth_price, status, chart except Exception as e: logger.error(f"Error in callback: {e}") import traceback logger.error(f"Traceback: {traceback.format_exc()}") # Return safe fallback values return "Error", "Error", "Error", "Error", dashboard_instance._create_error_chart() def _create_chart(self, n_intervals): """Create a simple test chart""" try: # Try to get real data if n_intervals % 5 == 0: # Refresh data every 5 seconds try: df = self.data_provider.get_historical_data('ETH/USDT', '1m', limit=50) if df is not None and not df.empty: self.chart_data = df logger.info(f"Fetched {len(df)} candles for chart") except Exception as e: logger.warning(f"Error fetching data: {e}") # Create chart fig = go.Figure() if hasattr(self, 'chart_data') and not self.chart_data.empty: # Real data chart fig.add_trace(go.Candlestick( x=self.chart_data['timestamp'], open=self.chart_data['open'], high=self.chart_data['high'], low=self.chart_data['low'], close=self.chart_data['close'], name='ETH/USDT' )) title = f"ETH/USDT Real Data - Update #{n_intervals}" else: # Mock data chart x_data = list(range(max(0, n_intervals-20), n_intervals + 1)) y_data = [3500 + 50 * np.sin(i/5) + 10 * np.random.randn() for i in x_data] fig.add_trace(go.Scatter( x=x_data, y=y_data, mode='lines', name='Mock ETH Price', line=dict(color='#00ff88') )) title = f"Mock ETH Data - Update #{n_intervals}" fig.update_layout( title=title, template="plotly_dark", paper_bgcolor='#1e1e1e', plot_bgcolor='#1e1e1e', showlegend=False ) return fig except Exception as e: logger.error(f"Error in _create_chart: {e}") return self._create_error_chart() def _create_error_chart(self): """Create error chart""" fig = go.Figure() fig.add_annotation( text="Error loading chart data", xref="paper", yref="paper", x=0.5, y=0.5, showarrow=False, font=dict(size=16, color="#ff4444") ) fig.update_layout( template="plotly_dark", paper_bgcolor='#1e1e1e', plot_bgcolor='#1e1e1e' ) return fig def run(self, host='127.0.0.1', port=8052, debug=True): """Run the dashboard""" logger.info(f"Starting minimal dashboard at http://{host}:{port}") logger.info("This tests callback functionality without emoji issues") self.app.run(host=host, port=port, debug=debug) def main(): """Main function""" try: dashboard = MinimalDashboard() dashboard.run() except KeyboardInterrupt: logger.info("Dashboard stopped by user") except Exception as e: logger.error(f"Error: {e}") import traceback traceback.print_exc() if __name__ == "__main__": main()