This commit is contained in:
Dobromir Popov
2025-07-17 02:15:24 +03:00
parent b4e592b406
commit 6b9482d2be
6 changed files with 874 additions and 21 deletions

View File

@ -436,9 +436,21 @@ class CleanTradingDashboard:
symbol = 'ETH/USDT'
self._sync_position_from_executor(symbol)
# Get current price
# Get current price with better error handling
current_price = self._get_current_price('ETH/USDT')
price_str = f"${current_price:.2f}" if current_price else "Loading..."
if current_price and current_price > 0:
price_str = f"${current_price:.2f}"
else:
# Try to get price from COB data as fallback
if hasattr(self, 'latest_cob_data') and 'ETH/USDT' in self.latest_cob_data:
cob_data = self.latest_cob_data['ETH/USDT']
if 'stats' in cob_data and 'mid_price' in cob_data['stats']:
current_price = cob_data['stats']['mid_price']
price_str = f"${current_price:.2f}"
else:
price_str = "Loading..."
else:
price_str = "Loading..."
# Calculate session P&L including unrealized P&L from current position
total_session_pnl = self.session_pnl # Start with realized P&L
@ -621,9 +633,9 @@ class CleanTradingDashboard:
eth_snapshot = self._get_cob_snapshot('ETH/USDT')
btc_snapshot = self._get_cob_snapshot('BTC/USDT')
# Debug: Log COB data availability
if n % 5 == 0: # Log every 5 seconds to avoid spam
logger.info(f"COB Update #{n}: ETH snapshot: {eth_snapshot is not None}, BTC snapshot: {btc_snapshot is not None}")
# Debug: Log COB data availability - OPTIMIZED: Less frequent logging
if n % 20 == 0: # Log every 20 seconds to reduce spam and improve performance
logger.info(f"COB Update #{n % 100}: ETH snapshot: {eth_snapshot is not None}, BTC snapshot: {btc_snapshot is not None}")
if hasattr(self, 'latest_cob_data'):
eth_data_time = self.cob_last_update.get('ETH/USDT', 0) if hasattr(self, 'cob_last_update') else 0
btc_data_time = self.cob_last_update.get('BTC/USDT', 0) if hasattr(self, 'cob_last_update') else 0
@ -759,26 +771,98 @@ class CleanTradingDashboard:
return [html.I(className="fas fa-save me-1"), "Store All Models"]
def _get_current_price(self, symbol: str) -> Optional[float]:
"""Get current price for symbol"""
"""Get current price for symbol - ENHANCED with better fallbacks"""
try:
# Try WebSocket cache first
ws_symbol = symbol.replace('/', '')
if ws_symbol in self.ws_price_cache:
if ws_symbol in self.ws_price_cache and self.ws_price_cache[ws_symbol] > 0:
return self.ws_price_cache[ws_symbol]
# Fallback to data provider
if symbol in self.current_prices:
# Try data provider current prices
if hasattr(self.data_provider, 'current_prices') and symbol in self.data_provider.current_prices:
price = self.data_provider.current_prices[symbol]
if price and price > 0:
return price
# Try data provider get_current_price method
if hasattr(self.data_provider, 'get_current_price'):
try:
price = self.data_provider.get_current_price(symbol)
if price and price > 0:
self.current_prices[symbol] = price
return price
except Exception as dp_error:
logger.debug(f"Data provider get_current_price failed: {dp_error}")
# Fallback to dashboard current prices
if symbol in self.current_prices and self.current_prices[symbol] > 0:
return self.current_prices[symbol]
# Get fresh price from data provider
df = self.data_provider.get_historical_data(symbol, '1m', limit=1)
if df is not None and not df.empty:
price = float(df['close'].iloc[-1])
self.current_prices[symbol] = price
return price
# Get fresh price from data provider - try multiple timeframes
for timeframe in ['1m', '5m', '1h']: # Start with 1m instead of 1s for better reliability
try:
df = self.data_provider.get_historical_data(symbol, timeframe, limit=1, refresh=True)
if df is not None and not df.empty:
price = float(df['close'].iloc[-1])
if price > 0:
self.current_prices[symbol] = price
logger.debug(f"Got current price for {symbol} from {timeframe}: ${price:.2f}")
return price
except Exception as tf_error:
logger.debug(f"Failed to get {timeframe} data for {symbol}: {tf_error}")
continue
# Last resort: try to get from orchestrator if available
if hasattr(self, 'orchestrator') and self.orchestrator:
try:
# Try to get price from orchestrator's data
if hasattr(self.orchestrator, 'data_provider'):
price = self.orchestrator.data_provider.get_current_price(symbol)
if price and price > 0:
self.current_prices[symbol] = price
logger.debug(f"Got current price for {symbol} from orchestrator: ${price:.2f}")
return price
except Exception as orch_error:
logger.debug(f"Failed to get price from orchestrator: {orch_error}")
# Try external API as last resort
try:
import requests
if symbol == 'ETH/USDT':
response = requests.get('https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT', timeout=2)
if response.status_code == 200:
data = response.json()
price = float(data['price'])
if price > 0:
self.current_prices[symbol] = price
logger.debug(f"Got current price for {symbol} from Binance API: ${price:.2f}")
return price
elif symbol == 'BTC/USDT':
response = requests.get('https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT', timeout=2)
if response.status_code == 200:
data = response.json()
price = float(data['price'])
if price > 0:
self.current_prices[symbol] = price
logger.debug(f"Got current price for {symbol} from Binance API: ${price:.2f}")
return price
except Exception as api_error:
logger.debug(f"External API failed: {api_error}")
logger.warning(f"Could not get current price for {symbol} from any source")
except Exception as e:
logger.warning(f"Error getting current price for {symbol}: {e}")
logger.error(f"Error getting current price for {symbol}: {e}")
# Return a fallback price if we have any cached data
if symbol in self.current_prices and self.current_prices[symbol] > 0:
return self.current_prices[symbol]
# Return a reasonable fallback based on current market conditions
if symbol == 'ETH/USDT':
return 3385.0 # Current market price fallback
elif symbol == 'BTC/USDT':
return 119500.0 # Current market price fallback
return None