This commit is contained in:
Dobromir Popov
2025-05-26 23:04:52 +03:00
parent 374da1b8ac
commit 392dbb4b61
7 changed files with 894 additions and 17 deletions

View File

@ -757,4 +757,203 @@ class EnhancedScalpingDashboard:
html.H6(f"{symbol[:3]}/USDT", className="text-warning"),
html.P(f"Ticks: {tick_count}", className="text-white"),
html.P(f"Duration: {duration:.1f}m", className="text-white"),
html.P
html.P(f"Candles: {candle_count}", className="text-white")
], className="mb-3")
)
return html.Div(details)
except Exception as e:
logger.error(f"Error creating cache details: {e}")
return html.P(f"Cache Error: {str(e)}", className="text-danger")
def _create_system_performance(self, avg_duration: float):
"""Create system performance display"""
try:
session_duration = datetime.now() - self.trading_session.start_time
session_hours = session_duration.total_seconds() / 3600
win_rate = self.trading_session.get_win_rate()
performance_info = [
html.P(f"Callback: {avg_duration:.1f}ms", className="text-white"),
html.P(f"Session: {session_hours:.1f}h", className="text-white"),
html.P(f"Win Rate: {win_rate:.1%}", className="text-success" if win_rate > 0.5 else "text-warning"),
html.P(f"Trades: {self.trading_session.total_trades}", className="text-white")
]
return html.Div(performance_info)
except Exception as e:
logger.error(f"Error creating system performance: {e}")
return html.P(f"Performance Error: {str(e)}", className="text-danger")
def _create_trading_log(self):
"""Create trading log display"""
try:
recent_trades = self.trading_session.trade_history[-5:] # Last 5 trades
if not recent_trades:
return html.P("No trades yet...", className="text-muted text-center")
log_entries = []
for trade in reversed(recent_trades): # Most recent first
timestamp = trade['timestamp'].strftime("%H:%M:%S")
action = trade['action']
symbol = trade['symbol']
price = trade['price']
pnl = trade.get('pnl', 0)
confidence = trade['confidence']
color_class = "text-success" if action == 'BUY' else "text-danger" if action == 'SELL' else "text-muted"
pnl_class = "text-success" if pnl > 0 else "text-danger" if pnl < 0 else "text-muted"
log_entries.append(
html.Div([
html.Span(f"{timestamp} ", className="text-info"),
html.Span(f"{action} ", className=color_class),
html.Span(f"{symbol} ", className="text-warning"),
html.Span(f"${price:.2f} ", className="text-white"),
html.Span(f"({confidence:.1%}) ", className="text-muted"),
html.Span(f"P&L: ${pnl:+.2f}", className=pnl_class)
], className="mb-1")
)
return html.Div(log_entries)
except Exception as e:
logger.error(f"Error creating trading log: {e}")
return html.P(f"Log Error: {str(e)}", className="text-danger")
def _start_real_time_streaming(self):
"""Start real-time data streaming"""
try:
# Subscribe to data provider
self.data_provider_subscriber_id = self.data_provider.subscribe(
callback=self._handle_market_tick,
symbols=['ETHUSDT', 'BTCUSDT']
)
# Start streaming
self.streaming = True
# Start background thread for orchestrator
orchestrator_thread = Thread(target=self._run_orchestrator, daemon=True)
orchestrator_thread.start()
logger.info("Real-time streaming started")
logger.info(f"Subscriber ID: {self.data_provider_subscriber_id}")
except Exception as e:
logger.error(f"Error starting real-time streaming: {e}")
def _handle_market_tick(self, tick: MarketTick):
"""Handle incoming market tick"""
try:
with self.data_lock:
# Update live prices
symbol_display = f"{tick.symbol[:3]}/{tick.symbol[3:]}"
self.live_prices[symbol_display] = tick.price
# Add to tick cache (15-minute window)
self.tick_cache.add_tick(tick.symbol, tick)
# Process tick for 1s candle aggregation
self.candle_aggregator.process_tick(tick.symbol, tick)
except Exception as e:
logger.error(f"Error handling market tick: {e}")
def _run_orchestrator(self):
"""Run trading orchestrator in background"""
try:
while self.streaming:
try:
# Get recent ticks for model training
eth_ticks = self.tick_cache.get_recent_ticks('ETHUSDT', minutes=15)
btc_ticks = self.tick_cache.get_recent_ticks('BTCUSDT', minutes=15)
if eth_ticks:
# Make trading decision
decision = self.orchestrator.make_trading_decision(
symbol='ETH/USDT',
current_price=eth_ticks[-1].price,
market_data={'recent_ticks': eth_ticks}
)
if decision and decision.action != 'HOLD':
# Execute trade
trade_result = self.trading_session.execute_trade(
decision, eth_ticks[-1].price
)
if trade_result:
self.recent_decisions.append(decision)
if len(self.recent_decisions) > 50:
self.recent_decisions.pop(0)
logger.info(f"TRADE EXECUTED: {decision.action} {decision.symbol} "
f"@ ${eth_ticks[-1].price:.2f} | "
f"Confidence: {decision.confidence:.1%}")
time.sleep(1) # Check every second
except Exception as e:
logger.error(f"Error in orchestrator loop: {e}")
time.sleep(5) # Wait longer on error
except Exception as e:
logger.error(f"Error in orchestrator thread: {e}")
def run(self, host: str = '127.0.0.1', port: int = 8051, debug: bool = False):
"""Run the enhanced dashboard"""
try:
logger.info(f"Starting Enhanced Scalping Dashboard at http://{host}:{port}")
logger.info("Features: 1s OHLCV bars, 15min tick cache, enhanced volume display")
self.app.run_server(
host=host,
port=port,
debug=debug,
use_reloader=False # Prevent issues with threading
)
except Exception as e:
logger.error(f"Error running dashboard: {e}")
raise
finally:
self.streaming = False
if self.data_provider_subscriber_id:
self.data_provider.unsubscribe(self.data_provider_subscriber_id)
def main():
"""Main function to run enhanced dashboard"""
import logging
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
try:
# Initialize components
data_provider = DataProvider()
orchestrator = EnhancedTradingOrchestrator(data_provider)
# Create and run dashboard
dashboard = EnhancedScalpingDashboard(
data_provider=data_provider,
orchestrator=orchestrator
)
dashboard.run(host='127.0.0.1', port=8051, debug=False)
except KeyboardInterrupt:
logger.info("Dashboard stopped by user")
except Exception as e:
logger.error(f"Error running enhanced dashboard: {e}")
raise
if __name__ == "__main__":
main()