better dash
This commit is contained in:
parent
cf825239cd
commit
3c23e4ec42
@ -1,10 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Scalping Dashboard Runner - 100% REAL MARKET DATA ONLY
|
||||
Run Ultra-Fast Scalping Dashboard (500x Leverage)
|
||||
|
||||
CRITICAL: This dashboard uses EXCLUSIVELY real market data.
|
||||
NO synthetic, mock, or simulated data is allowed.
|
||||
All trading decisions come from real market analysis.
|
||||
This script starts the custom scalping dashboard with:
|
||||
- Full-width 1s ETH/USDT candlestick chart
|
||||
- 3 small ETH charts: 1m, 1h, 1d
|
||||
- 1 small BTC 1s chart
|
||||
- Ultra-fast 100ms updates for scalping
|
||||
- Real-time PnL tracking and logging
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
@ -48,6 +48,14 @@ class TradingDashboard:
|
||||
self.current_prices = {}
|
||||
self.last_update = datetime.now()
|
||||
|
||||
# Trading session tracking
|
||||
self.session_start = datetime.now()
|
||||
self.session_trades = []
|
||||
self.session_pnl = 0.0
|
||||
self.current_position = None # {'side': 'BUY', 'price': 3456.78, 'size': 0.1, 'timestamp': datetime}
|
||||
self.total_realized_pnl = 0.0
|
||||
self.total_fees = 0.0
|
||||
|
||||
# Create Dash app
|
||||
self.app = dash.Dash(__name__, external_stylesheets=[
|
||||
'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css',
|
||||
@ -76,7 +84,7 @@ class TradingDashboard:
|
||||
# Auto-refresh component
|
||||
dcc.Interval(
|
||||
id='interval-component',
|
||||
interval=5000, # Update every 5 seconds for better real-time feel
|
||||
interval=1000, # Update every 1 second for real-time tick updates
|
||||
n_intervals=0
|
||||
),
|
||||
|
||||
@ -189,24 +197,30 @@ class TradingDashboard:
|
||||
symbol = self.config.symbols[0] if self.config.symbols else "ETH/USDT"
|
||||
|
||||
try:
|
||||
# Try to get fresh current price from latest data
|
||||
fresh_data = self.data_provider.get_historical_data(symbol, '1m', limit=1, refresh=True)
|
||||
# Try to get fresh current price from latest data - OPTIMIZED FOR SPEED
|
||||
fresh_data = self.data_provider.get_historical_data(symbol, '1s', limit=5, refresh=True)
|
||||
if fresh_data is not None and not fresh_data.empty:
|
||||
current_price = float(fresh_data['close'].iloc[-1])
|
||||
logger.debug(f"Got fresh price for {symbol}: ${current_price:.2f}")
|
||||
logger.debug(f"[TICK] Fresh price for {symbol}: ${current_price:.2f}")
|
||||
else:
|
||||
# Fallback to cached data
|
||||
cached_data = self.data_provider.get_historical_data(symbol, '1m', limit=1, refresh=False)
|
||||
if cached_data is not None and not cached_data.empty:
|
||||
base_price = float(cached_data['close'].iloc[-1])
|
||||
# Apply small realistic price movement for demo
|
||||
current_price = self._simulate_price_update(symbol, base_price)
|
||||
logger.debug(f"Simulated price update for {symbol}: ${current_price:.2f} (base: ${base_price:.2f})")
|
||||
# Quick fallback to 1m data
|
||||
fresh_data = self.data_provider.get_historical_data(symbol, '1m', limit=1, refresh=True)
|
||||
if fresh_data is not None and not fresh_data.empty:
|
||||
current_price = float(fresh_data['close'].iloc[-1])
|
||||
logger.debug(f"[TICK] Fresh 1m price for {symbol}: ${current_price:.2f}")
|
||||
else:
|
||||
current_price = None
|
||||
logger.warning(f"No price data available for {symbol}")
|
||||
# Use cached data with simulation
|
||||
cached_data = self.data_provider.get_historical_data(symbol, '1m', limit=1, refresh=False)
|
||||
if cached_data is not None and not cached_data.empty:
|
||||
base_price = float(cached_data['close'].iloc[-1])
|
||||
# Apply small realistic price movement for demo
|
||||
current_price = self._simulate_price_update(symbol, base_price)
|
||||
logger.debug(f"[SIM] Simulated price update for {symbol}: ${current_price:.2f} (base: ${base_price:.2f})")
|
||||
else:
|
||||
current_price = None
|
||||
logger.warning(f"[ERROR] No price data available for {symbol}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Error getting price for {symbol}: {e}")
|
||||
logger.warning(f"[ERROR] Error getting price for {symbol}: {e}")
|
||||
current_price = None
|
||||
|
||||
# Get model performance metrics with fallback
|
||||
@ -233,10 +247,12 @@ class TradingDashboard:
|
||||
wins += 1
|
||||
|
||||
# Format outputs with safe defaults and update indicators
|
||||
update_time = datetime.now().strftime("%H:%M:%S")
|
||||
update_time = datetime.now().strftime("%H:%M:%S.%f")[:-3] # Include milliseconds
|
||||
price_text = f"${current_price:.2f}" if current_price else "No Data"
|
||||
if current_price:
|
||||
price_text += f" @ {update_time}"
|
||||
# Add tick indicator and precise timestamp (no emojis to avoid Unicode issues)
|
||||
tick_indicator = "[LIVE]" if (datetime.now().microsecond // 100000) % 2 else "[TICK]" # Alternating indicator
|
||||
price_text += f" {tick_indicator} @ {update_time}"
|
||||
pnl_text = f"${total_pnl:.2f}"
|
||||
pnl_class = "text-success mb-1" if total_pnl >= 0 else "text-danger mb-1"
|
||||
win_rate_text = f"{(wins/total_trades*100):.1f}%" if total_trades > 0 else "0.0%"
|
||||
@ -348,30 +364,31 @@ class TradingDashboard:
|
||||
|
||||
for tf in timeframes_to_try:
|
||||
try:
|
||||
# FORCE FRESH DATA on each update for real-time charts
|
||||
df = self.data_provider.get_historical_data(symbol, tf, limit=200, refresh=True)
|
||||
# FORCE FRESH DATA on each update for real-time charts - OPTIMIZED FOR SPEED
|
||||
limit = 100 if tf == '1s' else 50 if tf == '1m' else 30 # Smaller data for faster updates
|
||||
df = self.data_provider.get_historical_data(symbol, tf, limit=limit, refresh=True)
|
||||
if df is not None and not df.empty and len(df) > 5:
|
||||
actual_timeframe = tf
|
||||
logger.info(f"✅ Got FRESH {len(df)} candles for {symbol} {tf}")
|
||||
logger.info(f"[FRESH] Got {len(df)} candles for {symbol} {tf}")
|
||||
break
|
||||
else:
|
||||
logger.warning(f"⚠️ No fresh data for {symbol} {tf}")
|
||||
logger.warning(f"[WARN] No fresh data for {symbol} {tf}")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Error getting fresh {symbol} {tf} data: {e}")
|
||||
logger.warning(f"[ERROR] Error getting fresh {symbol} {tf} data: {e}")
|
||||
continue
|
||||
|
||||
# If still no fresh data, try cached data as fallback
|
||||
if df is None or df.empty:
|
||||
logger.warning(f"⚠️ No fresh data, trying cached data for {symbol}")
|
||||
logger.warning(f"[WARN] No fresh data, trying cached data for {symbol}")
|
||||
for tf in timeframes_to_try:
|
||||
try:
|
||||
df = self.data_provider.get_historical_data(symbol, tf, limit=200, refresh=False)
|
||||
if df is not None and not df.empty and len(df) > 5:
|
||||
actual_timeframe = tf
|
||||
logger.info(f"✅ Got cached {len(df)} candles for {symbol} {tf}")
|
||||
logger.info(f"[CACHED] Got {len(df)} candles for {symbol} {tf}")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Error getting cached {symbol} {tf} data: {e}")
|
||||
logger.warning(f"[ERROR] Error getting cached {symbol} {tf} data: {e}")
|
||||
continue
|
||||
|
||||
# If still no data, create empty chart
|
||||
@ -427,11 +444,11 @@ class TradingDashboard:
|
||||
))
|
||||
|
||||
# Update layout with current timestamp
|
||||
current_time = datetime.now().strftime("%H:%M:%S")
|
||||
current_time = datetime.now().strftime("%H:%M:%S.%f")[:-3] # Include milliseconds
|
||||
latest_price = df['close'].iloc[-1] if not df.empty else 0
|
||||
|
||||
fig.update_layout(
|
||||
title=f"{symbol} Price Chart ({actual_timeframe.upper()}) - {len(df)} candles | ${latest_price:.2f} @ {current_time}",
|
||||
title=f"{symbol} LIVE CHART ({actual_timeframe.upper()}) | ${latest_price:.2f} | {len(df)} candles | {current_time}",
|
||||
template="plotly_dark",
|
||||
height=400,
|
||||
xaxis_rangeslider_visible=False,
|
||||
|
Loading…
x
Reference in New Issue
Block a user