fixed dash updates (wip)

This commit is contained in:
Dobromir Popov 2025-05-24 12:10:27 +03:00
parent fb5350bb50
commit d7f8d1af69
4 changed files with 347 additions and 781 deletions

View File

@ -62,12 +62,12 @@ class DataProvider:
logger.info(f"DataProvider initialized for symbols: {self.symbols}") logger.info(f"DataProvider initialized for symbols: {self.symbols}")
logger.info(f"Timeframes: {self.timeframes}") logger.info(f"Timeframes: {self.timeframes}")
def get_historical_data(self, symbol: str, timeframe: str, limit: int = 1000, def get_historical_data(self, symbol: str, timeframe: str, limit: int = 1000, refresh: bool = False) -> Optional[pd.DataFrame]:
refresh: bool = False) -> Optional[pd.DataFrame]:
"""Get historical OHLCV data for a symbol and timeframe""" """Get historical OHLCV data for a symbol and timeframe"""
try: try:
# Check cache first # If refresh=True, always fetch fresh data (skip cache for real-time updates)
if not refresh and self.cache_enabled: if not refresh:
if self.cache_enabled:
cached_data = self._load_from_cache(symbol, timeframe) cached_data = self._load_from_cache(symbol, timeframe)
if cached_data is not None and len(cached_data) >= limit * 0.8: if cached_data is not None and len(cached_data) >= limit * 0.8:
logger.info(f"Using cached data for {symbol} {timeframe}") logger.info(f"Using cached data for {symbol} {timeframe}")

View File

@ -22,7 +22,7 @@ from typing import Dict, List, Optional
from core.config import get_config, setup_logging from core.config import get_config, setup_logging
from core.data_provider import DataProvider from core.data_provider import DataProvider
from core.enhanced_orchestrator import EnhancedTradingOrchestrator, TradingAction, TimeframePrediction from core.enhanced_orchestrator import EnhancedTradingOrchestrator, TradingAction, TimeframePrediction
from web.scalping_dashboard_fixed import ScalpingDashboard from web.scalping_dashboard import ScalpingDashboard
# Setup logging # Setup logging
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)

View File

@ -1,11 +1,11 @@
""" """
Ultra-Fast Scalping Dashboard (500x Leverage) Ultra-Fast Scalping Dashboard (500x Leverage) - Real Market Data
Custom dashboard optimized for ultra-fast scalping with: Dashboard using ONLY real market data from APIs with:
- Full-width 1s real-time chart with candlesticks - Main 1s ETH/USDT chart (full width)
- 3 small ETH charts: 1m, 1h, 1d - 4 small charts: 1m ETH, 1h ETH, 1d ETH, 1s BTC
- 1 small BTC 1s chart - 500 candles preloaded at startup
- Real-time metrics for scalping performance - Real-time updates from data provider
""" """
import asyncio import asyncio
@ -17,10 +17,8 @@ from threading import Thread
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
import dash import dash
from dash import dcc, html, Input, Output, State, callback_context from dash import dcc, html, Input, Output
import plotly.graph_objects as go import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
import pandas as pd import pandas as pd
import numpy as np import numpy as np
@ -31,10 +29,10 @@ from core.enhanced_orchestrator import EnhancedTradingOrchestrator, TradingActio
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ScalpingDashboard: 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): 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.config = get_config()
self.data_provider = data_provider or DataProvider() self.data_provider = data_provider or DataProvider()
self.orchestrator = orchestrator or EnhancedTradingOrchestrator(self.data_provider) self.orchestrator = orchestrator or EnhancedTradingOrchestrator(self.data_provider)
@ -44,309 +42,321 @@ class ScalpingDashboard:
self.scalping_metrics = { self.scalping_metrics = {
'total_trades': 0, 'total_trades': 0,
'win_rate': 0.78, 'win_rate': 0.78,
'total_pnl': 247.85, 'total_pnl': 0.0, # Will be updated by runner
'avg_trade_time': 3.2, # seconds 'avg_trade_time': 3.2, # seconds
'leverage': '500x', 'leverage': '500x',
'last_action': None 'last_action': None
} }
# Price data cache for ultra-fast updates # Real market data cache - preload 500 candles for each chart
self.price_cache = { self.market_data = {
'ETH/USDT': {'1s': [], '1m': [], '1h': [], '1d': []}, 'ETH/USDT': {
'BTC/USDT': {'1s': []} '1s': None, # Main chart
'1m': None, # Small chart
'1h': None, # Small chart
'1d': None # Small chart
},
'BTC/USDT': {
'1s': None # Small chart
}
} }
# Create Dash app with custom styling # Initialize real market data
self.app = dash.Dash(__name__, external_stylesheets=[ self._preload_market_data()
'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css' # Create Dash app
]) self.app = dash.Dash(__name__)
# Setup layout and callbacks # Setup layout and callbacks
self._setup_layout() self._setup_layout()
self._setup_callbacks() 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): def _setup_layout(self):
"""Setup the ultra-fast scalping dashboard layout""" """Setup the 5-chart dashboard layout"""
self.app.layout = html.Div([ self.app.layout = html.Div([
# Header with scalping metrics # Header with real-time metrics
html.Div([ html.Div([
html.H1([ html.H1("ULTRA-FAST SCALPING DASHBOARD - 500x LEVERAGE - REAL MARKET DATA",
html.I(className="fas fa-bolt me-3 text-warning"), className="text-center mb-4"),
"ULTRA-FAST SCALPING DASHBOARD",
html.Span(" 500x", className="badge bg-danger ms-3")
], className="text-white mb-2"),
# Real-time metrics row # Real-time metrics row
html.Div([ html.Div([
html.Div([ html.Div([
html.H3(id="live-pnl", className="text-success mb-0"), html.H3(id="live-pnl", className="text-success"),
html.Small("Total P&L", className="text-light opacity-75") html.P("Total P&L")
], className="col-md-2 text-center"), ], className="col-md-2 text-center"),
html.Div([ html.Div([
html.H3(id="win-rate", className="text-info mb-0"), html.H3(id="win-rate", className="text-info"),
html.Small("Win Rate", className="text-light opacity-75") html.P("Win Rate")
], className="col-md-2 text-center"), ], className="col-md-2 text-center"),
html.Div([ html.Div([
html.H3(id="avg-trade-time", className="text-warning mb-0"), html.H3(id="total-trades", className="text-primary"),
html.Small("Avg Trade (sec)", className="text-light opacity-75") html.P("Total Trades")
], className="col-md-2 text-center"), ], className="col-md-2 text-center"),
html.Div([ html.Div([
html.H3(id="total-trades", className="text-primary mb-0"), html.H3(id="last-action", className="text-warning"),
html.Small("Total Trades", className="text-light opacity-75") html.P("Last Action")
], className="col-md-2 text-center"), ], className="col-md-2 text-center"),
html.Div([ html.Div([
html.H3("LIVE", className="text-success mb-0 pulse"), html.H3(id="eth-price", className="text-white"),
html.Small("Status", className="text-light opacity-75") html.P("ETH/USDT Live")
], className="col-md-2 text-center"), ], className="col-md-2 text-center"),
html.Div([ html.Div([
html.H3(id="last-action", className="text-white mb-0"), html.H3(id="btc-price", className="text-white"),
html.Small("Last Action", className="text-light opacity-75") html.P("BTC/USDT Live")
], className="col-md-2 text-center") ], className="col-md-2 text-center")
], className="row") ], className="row mb-4")
], className="bg-dark p-3 mb-3"), ], className="bg-dark p-3 mb-3"),
# Auto-refresh component for ultra-fast updates # Main 1s ETH/USDT chart (full width)
dcc.Interval( html.Div([
id='ultra-fast-interval', html.H4("ETH/USDT 1s Real-Time Chart (Main Trading Signal)",
interval=100, # Update every 100ms for ultra-fast scalping className="text-center mb-3"),
n_intervals=0 dcc.Graph(id="main-eth-1s-chart", style={"height": "500px"})
), ], className="mb-4"),
# Main chart section # Row of 4 small charts
html.Div([ html.Div([
# Full-width 1s chart # ETH/USDT 1m
html.Div([ html.Div([
html.Div([ html.H6("ETH/USDT 1m", className="text-center"),
html.H4([ dcc.Graph(id="eth-1m-chart", style={"height": "250px"})
html.I(className="fas fa-chart-candlestick me-2"),
"ETH/USDT 1s Ultra-Fast Scalping Chart",
html.Span(" LIVE", className="badge bg-success ms-2 pulse")
], className="text-center mb-3"),
dcc.Graph(
id="main-scalping-chart",
style={"height": "500px"},
config={'displayModeBar': False}
)
], className="card-body p-2")
], className="card mb-3")
]),
# Multi-timeframe analysis row
html.Div([
# ETH 1m chart
html.Div([
html.Div([
html.H6("ETH/USDT 1m", className="card-title text-center"),
dcc.Graph(
id="eth-1m-chart",
style={"height": "250px"},
config={'displayModeBar': False}
)
], className="card-body p-2")
], className="col-md-3"), ], className="col-md-3"),
# ETH 1h chart # ETH/USDT 1h
html.Div([ html.Div([
html.Div([ html.H6("ETH/USDT 1h", className="text-center"),
html.H6("ETH/USDT 1h", className="card-title text-center"), dcc.Graph(id="eth-1h-chart", style={"height": "250px"})
dcc.Graph(
id="eth-1h-chart",
style={"height": "250px"},
config={'displayModeBar': False}
)
], className="card-body p-2")
], className="col-md-3"), ], className="col-md-3"),
# ETH 1d chart # ETH/USDT 1d
html.Div([ html.Div([
html.Div([ html.H6("ETH/USDT 1d", className="text-center"),
html.H6("ETH/USDT 1d", className="card-title text-center"), dcc.Graph(id="eth-1d-chart", style={"height": "250px"})
dcc.Graph(
id="eth-1d-chart",
style={"height": "250px"},
config={'displayModeBar': False}
)
], className="card-body p-2")
], className="col-md-3"), ], className="col-md-3"),
# BTC 1s chart # BTC/USDT 1s
html.Div([ html.Div([
html.Div([ html.H6("BTC/USDT 1s", className="text-center"),
html.H6("BTC/USDT 1s", className="card-title text-center"), dcc.Graph(id="btc-1s-chart", style={"height": "250px"})
dcc.Graph(
id="btc-1s-chart",
style={"height": "250px"},
config={'displayModeBar': False}
)
], className="card-body p-2")
], className="col-md-3") ], className="col-md-3")
], className="row g-2"), ], className="row mb-4"),
# Recent actions ticker # Recent actions log
html.Div([ html.Div([
html.Div([ html.H5("Live Trading Actions (Real Market Data)", className="text-center mb-3"),
html.H5([ html.Div(id="actions-log")
html.I(className="fas fa-robot me-2"), ], className="mb-4"),
"Live Trading Actions"
], className="text-center mb-3"),
html.Div(id="live-actions-ticker", className="text-center")
], className="card-body")
], className="card mt-3"),
# Custom CSS for ultra-fast dashboard # Auto-refresh for real-time updates
html.Style(children=""" dcc.Interval(
.pulse { id='market-data-interval',
animation: pulse 1s infinite; interval=1000, # Update every 1 second for real-time feel
} n_intervals=0
@keyframes pulse { )
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
.card {
background: rgba(255, 255, 255, 0.95);
border: none;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
body {
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
font-family: 'Arial', sans-serif;
}
""")
], className="container-fluid") ], className="container-fluid")
def _setup_callbacks(self): def _setup_callbacks(self):
"""Setup ultra-fast dashboard callbacks""" """Setup dashboard callbacks with real market data"""
@self.app.callback( @self.app.callback(
[ [
Output('live-pnl', 'children'), Output('live-pnl', 'children'),
Output('win-rate', 'children'), Output('win-rate', 'children'),
Output('avg-trade-time', 'children'),
Output('total-trades', 'children'), Output('total-trades', 'children'),
Output('last-action', 'children'), Output('last-action', 'children'),
Output('main-scalping-chart', 'figure'), Output('eth-price', 'children'),
Output('btc-price', 'children'),
Output('main-eth-1s-chart', 'figure'),
Output('eth-1m-chart', 'figure'), Output('eth-1m-chart', 'figure'),
Output('eth-1h-chart', 'figure'), Output('eth-1h-chart', 'figure'),
Output('eth-1d-chart', 'figure'), Output('eth-1d-chart', 'figure'),
Output('btc-1s-chart', 'figure'), Output('btc-1s-chart', 'figure'),
Output('live-actions-ticker', 'children') Output('actions-log', 'children')
], ],
[Input('ultra-fast-interval', 'n_intervals')] [Input('market-data-interval', 'n_intervals')]
) )
def update_scalping_dashboard(n_intervals): def update_dashboard_with_real_data(n_intervals):
"""Update all dashboard components for ultra-fast scalping""" """Update all dashboard components with real market data"""
try: try:
# Update metrics # Update metrics
pnl = f"+${self.scalping_metrics['total_pnl']:.2f}" pnl = f"${self.scalping_metrics['total_pnl']:+.2f}"
win_rate = f"{self.scalping_metrics['win_rate']*100:.1f}%" win_rate = f"{self.scalping_metrics['win_rate']*100:.1f}%"
avg_time = f"{self.scalping_metrics['avg_trade_time']:.1f}s"
total_trades = str(self.scalping_metrics['total_trades']) total_trades = str(self.scalping_metrics['total_trades'])
last_action = self.scalping_metrics['last_action'] or "WAITING" last_action = self.scalping_metrics['last_action'] or "WAITING"
# Generate charts # Get current prices from real market data
main_chart = self._create_main_scalping_chart() eth_price = self._get_current_price('ETH/USDT')
eth_1m = self._create_small_chart("ETH/USDT", "1m") btc_price = self._get_current_price('BTC/USDT')
eth_1h = self._create_small_chart("ETH/USDT", "1h")
eth_1d = self._create_small_chart("ETH/USDT", "1d")
btc_1s = self._create_small_chart("BTC/USDT", "1s")
# Create live actions ticker # Refresh market data periodically (every 10 updates)
actions_ticker = self._create_actions_ticker() 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 ( return (
pnl, win_rate, avg_time, total_trades, last_action, pnl, win_rate, total_trades, last_action, eth_price, btc_price,
main_chart, eth_1m, eth_1h, eth_1d, btc_1s, actions_ticker main_eth_chart, eth_1m_chart, eth_1h_chart, eth_1d_chart, btc_1s_chart,
actions_log
) )
except Exception as e: except Exception as e:
logger.error(f"Error updating scalping dashboard: {e}") logger.error(f"Error updating dashboard: {e}")
# Return safe defaults # Return safe defaults
return ( return (
"+$247.85", "78.0%", "3.2s", "0", "WAITING", "$0.00", "0%", "0", "ERROR", "$0", "$0",
{}, {}, {}, {}, {}, "System starting..." {}, {}, {}, {}, {}, "Loading real market data..."
) )
def _create_main_scalping_chart(self) -> go.Figure: def _refresh_market_data(self):
"""Create the main 1s scalping chart with candlesticks""" """Refresh market data from APIs"""
# Generate mock ultra-fast 1s data try:
now = datetime.now() # Get latest data for each chart (last 100 candles for efficiency)
timestamps = [now - timedelta(seconds=i) for i in range(300, 0, -1)] # Last 5 minutes 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)
# Simulate realistic ETH price action around 3000-3100 except Exception as e:
base_price = 3050 logger.warning(f"Error refreshing market data: {e}")
prices = []
current_price = base_price
for i, ts in enumerate(timestamps): def _get_current_price(self, symbol: str) -> str:
# Add realistic price movement with higher volatility for 1s data """Get current price from real market data"""
change = np.random.normal(0, 0.5) # Small random changes try:
current_price += change 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"
# Ensure price stays in reasonable range def _create_real_chart(self, symbol: str, timeframe: str, main_chart: bool = False):
current_price = max(3000, min(3100, current_price)) """Create chart using real market data"""
try:
data = self.market_data[symbol][timeframe]
# OHLC for 1s candle if data is None or data.empty:
open_price = current_price + np.random.normal(0, 0.2) # Return empty chart with message
high_price = max(open_price, current_price) + abs(np.random.normal(0, 0.3)) fig = go.Figure()
low_price = min(open_price, current_price) - abs(np.random.normal(0, 0.3)) fig.add_annotation(
close_price = current_price 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
prices.append({ # Create candlestick chart from real data
'timestamp': ts, fig = go.Figure()
'open': open_price,
'high': high_price,
'low': low_price,
'close': close_price,
'volume': np.random.uniform(50, 200)
})
df = pd.DataFrame(prices) if main_chart:
# Main chart with candlesticks and volume
# Create candlestick chart fig.add_trace(go.Candlestick(
fig = go.Figure(data=[go.Candlestick( x=data['timestamp'],
x=df['timestamp'], open=data['open'],
open=df['open'], high=data['high'],
high=df['high'], low=data['low'],
low=df['low'], close=data['close'],
close=df['close'], name=f"{symbol} {timeframe}",
name="ETH/USDT 1s",
increasing_line_color='#00ff88', increasing_line_color='#00ff88',
decreasing_line_color='#ff4444' decreasing_line_color='#ff4444'
)]) ))
# Add volume bar chart # Add volume as secondary plot
fig.add_trace(go.Bar( fig.add_trace(go.Bar(
x=df['timestamp'], x=data['timestamp'],
y=df['volume'], y=data['volume'],
name="Volume", name="Volume",
yaxis='y2', yaxis='y2',
opacity=0.3, opacity=0.3,
marker_color='lightblue' marker_color='lightblue'
)) ))
# Update layout for ultra-fast scalping # Main chart layout
fig.update_layout( fig.update_layout(
title=f"ETH/USDT 1s Chart - Live Price: ${df['close'].iloc[-1]:.2f}", title=f"{symbol} {timeframe} Real-Time Market Data - Latest: ${data['close'].iloc[-1]:.2f}",
yaxis_title="Price (USDT)", yaxis_title="Price (USDT)",
yaxis2=dict(title="Volume", overlaying='y', side='right'), yaxis2=dict(title="Volume", overlaying='y', side='right'),
xaxis_title="Time",
template="plotly_dark", template="plotly_dark",
showlegend=False, showlegend=False,
margin=dict(l=0, r=0, t=30, b=0),
height=500 height=500
) )
# Add current price line # Add current price line
current_price = df['close'].iloc[-1] current_price = data['close'].iloc[-1]
fig.add_hline( fig.add_hline(
y=current_price, y=current_price,
line_dash="dash", line_dash="dash",
@ -355,80 +365,97 @@ class ScalpingDashboard:
annotation_position="right" annotation_position="right"
) )
return fig 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'
def _create_small_chart(self, symbol: str, timeframe: str) -> go.Figure:
"""Create small timeframe charts"""
# Generate mock data based on timeframe
if timeframe == "1s":
periods = 60 # Last minute
base_price = 67000 if 'BTC' in symbol else 3050
elif timeframe == "1m":
periods = 60 # Last hour
base_price = 67000 if 'BTC' in symbol else 3050
elif timeframe == "1h":
periods = 24 # Last day
base_price = 67000 if 'BTC' in symbol else 3050
else: # 1d
periods = 30 # Last month
base_price = 67000 if 'BTC' in symbol else 3050
# Generate mock price data
prices = []
current_price = base_price
for i in range(periods):
change = np.random.normal(0, base_price * 0.001) # 0.1% volatility
current_price += change
prices.append(current_price)
# Create simple line chart for small displays
fig = go.Figure()
fig.add_trace(go.Scatter( fig.add_trace(go.Scatter(
y=prices, x=data['timestamp'],
y=data['close'],
mode='lines', mode='lines',
name=f"{symbol} {timeframe}", name=f"{symbol} {timeframe}",
line=dict(color='#00ff88' if prices[-1] > prices[0] else '#ff4444', width=2) line=dict(color=line_color, width=2)
)) ))
# Minimal layout for small charts # Small chart layout
fig.update_layout( fig.update_layout(
template="plotly_dark", template="plotly_dark",
showlegend=False, showlegend=False,
margin=dict(l=10, r=10, t=10, b=10), margin=dict(l=10, r=10, t=30, b=10),
xaxis=dict(showticklabels=False), height=250,
yaxis=dict(showticklabels=False), title=f"{symbol} {timeframe}: ${data['close'].iloc[-1]:.2f}"
height=250
) )
# Add price change indicator # Add price change annotation
price_change = ((prices[-1] - prices[0]) / prices[0]) * 100 change_color = "green" if price_change >= 0 else "red"
color = "green" if price_change > 0 else "red"
fig.add_annotation( fig.add_annotation(
text=f"{price_change:+.2f}%", text=f"{price_change:+.2f}%",
xref="paper", yref="paper", xref="paper", yref="paper",
x=0.95, y=0.95, x=0.95, y=0.95,
showarrow=False, showarrow=False,
font=dict(color=color, size=12, weight="bold"), font=dict(color=change_color, size=12, weight="bold"),
bgcolor="rgba(0,0,0,0.5)" bgcolor="rgba(0,0,0,0.7)"
) )
return fig return fig
def _create_actions_ticker(self) -> html.Div: except Exception as e:
"""Create live actions ticker""" logger.error(f"Error creating chart for {symbol} {timeframe}: {e}")
recent_actions = self.recent_decisions[-5:] if self.recent_decisions else [] # 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
if not recent_actions: def _create_actions_log(self):
return html.P("Waiting for trading signals...", className="text-muted") """Create trading actions log"""
if not self.recent_decisions:
return html.P("Waiting for trading signals from real market data...", className="text-muted text-center")
ticker_items = [] for action in recent_actions: color = "success" if action.action == "BUY" else "danger" if action.action == "SELL" else "warning" ticker_items.append( html.Span([ html.I(className=f"fas fa-{'arrow-up' if action.action == 'BUY' else 'arrow-down' if action.action == 'SELL' else 'minus'} me-1"), f"{action.action} {action.symbol} @ ${action.price:.2f} ({action.confidence:.1%})" ], className=f"badge bg-{color} me-3") ) return html.Div(ticker_items) def add_trading_decision(self, decision: TradingAction): """Add a new trading decision to the dashboard""" self.recent_decisions.append(decision) if len(self.recent_decisions) > 50: self.recent_decisions.pop(0) # Update metrics self.scalping_metrics['total_trades'] += 1 self.scalping_metrics['last_action'] = f"{decision.action} {decision.symbol}" # PnL will be updated directly by the scalping runner when trades close # This allows for real PnL tracking instead of simulation log_items = []
for action in self.recent_decisions[-5:]: # Show last 5 actions
log_items.append(
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 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): def run(self, host: str = '127.0.0.1', port: int = 8050, debug: bool = False):
"""Run the ultra-fast scalping dashboard""" """Run the real market data dashboard"""
logger.info(f"Starting Ultra-Fast Scalping Dashboard at http://{host}:{port}") logger.info(f"🚀 Starting Real Market Data Dashboard at http://{host}:{port}")
self.app.run_server(host=host, port=port, debug=debug) 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")
def create_scalping_dashboard(data_provider: DataProvider = None, orchestrator: EnhancedTradingOrchestrator = None) -> ScalpingDashboard: self.app.run(host=host, port=port, debug=debug)
"""Create and return a scalping dashboard instance"""
def create_scalping_dashboard(data_provider=None, orchestrator=None):
"""Create dashboard instance with real market data"""
return ScalpingDashboard(data_provider, orchestrator) return ScalpingDashboard(data_provider, orchestrator)

View File

@ -1,461 +0,0 @@
"""
Ultra-Fast Scalping Dashboard (500x Leverage) - Real Market Data
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
import json
import logging
import time
from datetime import datetime, timedelta
from threading import Thread
from typing import Dict, List, Optional, Any
import dash
from dash import dcc, html, Input, Output
import plotly.graph_objects as go
import pandas as pd
import numpy as np
from core.config import get_config
from core.data_provider import DataProvider
from core.enhanced_orchestrator import EnhancedTradingOrchestrator, TradingAction
logger = logging.getLogger(__name__)
class ScalpingDashboard:
"""Real market data scalping dashboard for 500x leverage trading"""
def __init__(self, data_provider: DataProvider = None, orchestrator: EnhancedTradingOrchestrator = None):
"""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)
# Dashboard state
self.recent_decisions = []
self.scalping_metrics = {
'total_trades': 0,
'win_rate': 0.78,
'total_pnl': 0.0, # Will be updated by runner
'avg_trade_time': 3.2, # seconds
'leverage': '500x',
'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__)
# Setup layout and callbacks
self._setup_layout()
self._setup_callbacks()
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 5-chart dashboard layout"""
self.app.layout = html.Div([
# Header with real-time metrics
html.Div([
html.H1("ULTRA-FAST SCALPING DASHBOARD - 500x LEVERAGE - REAL MARKET DATA",
className="text-center mb-4"),
# Real-time metrics row
html.Div([
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.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.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"),
# Recent actions log
html.Div([
html.H5("Live Trading Actions (Real Market Data)", className="text-center mb-3"),
html.Div(id="actions-log")
], className="mb-4"),
# Auto-refresh for real-time updates
dcc.Interval(
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 with real market data"""
@self.app.callback(
[
Output('live-pnl', 'children'),
Output('win-rate', 'children'),
Output('total-trades', 'children'),
Output('last-action', 'children'),
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('market-data-interval', 'n_intervals')]
)
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}"
win_rate = f"{self.scalping_metrics['win_rate']*100:.1f}%"
total_trades = str(self.scalping_metrics['total_trades'])
last_action = self.scalping_metrics['last_action'] or "WAITING"
# 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, 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 safe defaults
return (
"$0.00", "0%", "0", "ERROR", "$0", "$0",
{}, {}, {}, {}, {}, "Loading real market data..."
)
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 trading actions log"""
if not self.recent_decisions:
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:]: # Show last 5 actions
log_items.append(
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 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 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 with real market data"""
return ScalpingDashboard(data_provider, orchestrator)