From d0cf04536cbcf47998763b378ed8eb8aa4e5003e Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 4 Jul 2025 02:24:18 +0300 Subject: [PATCH] fix dash actions --- config.yaml | 8 +- core/orchestrator.py | 31 +++++- core/trading_executor.py | 8 ++ debug/test_orchestrator_predictions.py | 101 ++++++++++++++++++++ debug/test_trading_execution.py | 125 +++++++++++++++++++++++++ utils/checkpoint_manager.py | 6 +- web/clean_dashboard.py | 40 +++++++- 7 files changed, 309 insertions(+), 10 deletions(-) create mode 100644 debug/test_orchestrator_predictions.py create mode 100644 debug/test_trading_execution.py diff --git a/config.yaml b/config.yaml index c74694a..4fcc1d6 100644 --- a/config.yaml +++ b/config.yaml @@ -81,8 +81,8 @@ orchestrator: # Model weights for decision combination cnn_weight: 0.7 # Weight for CNN predictions rl_weight: 0.3 # Weight for RL decisions - confidence_threshold: 0.20 # Lowered from 0.35 for low-volatility markets - confidence_threshold_close: 0.10 # Lowered from 0.15 for easier exits + confidence_threshold: 0.05 # Very low threshold for training and simulation + confidence_threshold_close: 0.05 # Very low threshold for easier exits decision_frequency: 30 # Seconds between decisions (faster) # Multi-symbol coordination @@ -154,7 +154,7 @@ trading: # MEXC Trading API Configuration mexc_trading: enabled: true - trading_mode: live # simulation, testnet, live + trading_mode: simulation # simulation, testnet, live # FIXED: Meaningful position sizes for learning base_position_usd: 25.0 # $25 base position (was $1) @@ -165,7 +165,7 @@ mexc_trading: max_daily_trades: 100 max_daily_loss_usd: 200.0 max_concurrent_positions: 3 - min_trade_interval_seconds: 30 + min_trade_interval_seconds: 5 # Reduced for testing and training # Order configuration order_type: market # market or limit diff --git a/core/orchestrator.py b/core/orchestrator.py index 30f0d34..493c975 100644 --- a/core/orchestrator.py +++ b/core/orchestrator.py @@ -299,7 +299,36 @@ class TradingOrchestrator: self.model_states['decision']['current_loss'] = 0.0089 self.model_states['decision']['best_loss'] = 0.0065 - logger.info("ML models initialization completed") + # CRITICAL: Register models with the model registry + logger.info("Registering models with model registry...") + + # Register RL Agent + if self.rl_agent: + try: + self.register_model(self.rl_agent, weight=0.3) + logger.info("RL Agent registered successfully") + except Exception as e: + logger.error(f"Failed to register RL Agent: {e}") + + # Register CNN Model + if self.cnn_model: + try: + self.register_model(self.cnn_model, weight=0.7) + logger.info("CNN Model registered successfully") + except Exception as e: + logger.error(f"Failed to register CNN Model: {e}") + + # Register Extrema Trainer + if self.extrema_trainer: + try: + self.register_model(self.extrema_trainer, weight=0.2) + logger.info("Extrema Trainer registered successfully") + except Exception as e: + logger.error(f"Failed to register Extrema Trainer: {e}") + + # Show registered models count + registered_count = len(self.model_registry.models) if self.model_registry else 0 + logger.info(f"ML models initialization completed - {registered_count} models registered") except Exception as e: logger.error(f"Error initializing ML models: {e}") diff --git a/core/trading_executor.py b/core/trading_executor.py index 5fae3d3..f12bc0d 100644 --- a/core/trading_executor.py +++ b/core/trading_executor.py @@ -230,6 +230,14 @@ class TradingExecutor: # Get available balance for the quote asset available_balance = self.exchange.get_balance(quote_asset) + # If USDC balance is insufficient, check USDT as fallback (for MEXC compatibility) + if available_balance < required_capital and quote_asset == 'USDC': + usdt_balance = self.exchange.get_balance('USDT') + if usdt_balance >= required_capital: + available_balance = usdt_balance + quote_asset = 'USDT' # Use USDT instead + logger.info(f"BALANCE CHECK: Using USDT fallback balance for {symbol}") + logger.info(f"BALANCE CHECK: Symbol: {symbol}, Action: {action}, Required: ${required_capital:.2f} {quote_asset}, Available: ${available_balance:.2f} {quote_asset}") if available_balance < required_capital: diff --git a/debug/test_orchestrator_predictions.py b/debug/test_orchestrator_predictions.py new file mode 100644 index 0000000..c96e214 --- /dev/null +++ b/debug/test_orchestrator_predictions.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +""" +Test script to debug orchestrator prediction issues +""" + +import sys +import os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +from core.orchestrator import TradingOrchestrator +from core.data_provider import DataProvider +import asyncio +import logging + +# Set up logging +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger(__name__) + +async def test_orchestrator_predictions(): + """Test orchestrator prediction generation""" + + logger.info("=" * 60) + logger.info("TESTING ORCHESTRATOR PREDICTIONS") + logger.info("=" * 60) + + # Initialize components + logger.info("1. Initializing orchestrator...") + data_provider = DataProvider() + orchestrator = TradingOrchestrator(data_provider) + + # Check configuration + logger.info("2. Checking orchestrator configuration...") + logger.info(f" Confidence threshold: {orchestrator.confidence_threshold}") + logger.info(f" Confidence threshold close: {orchestrator.confidence_threshold_close}") + logger.info(f" Model weights: {orchestrator.model_weights}") + + # Check registered models + logger.info("3. Checking registered models...") + if hasattr(orchestrator, 'model_registry'): + # Check what methods are available + registry_methods = [method for method in dir(orchestrator.model_registry) if not method.startswith('_')] + logger.info(f" Model registry methods: {registry_methods}") + + # Check if we have models + if hasattr(orchestrator, 'rl_agent'): + logger.info(f" RL Agent available: {orchestrator.rl_agent is not None}") + if hasattr(orchestrator, 'cnn_model'): + logger.info(f" CNN Model available: {orchestrator.cnn_model is not None}") + if hasattr(orchestrator, 'extrema_trainer'): + logger.info(f" Extrema Trainer available: {orchestrator.extrema_trainer is not None}") + else: + logger.info(" No model registry found") + + # Test prediction generation + logger.info("4. Testing prediction generation...") + symbol = 'ETH/USDT' + + try: + # Get all predictions + predictions = await orchestrator._get_all_predictions(symbol) + logger.info(f" Total predictions: {len(predictions)}") + + for i, pred in enumerate(predictions): + logger.info(f" Prediction {i+1}: {pred.action} (confidence: {pred.confidence:.3f}, model: {pred.model_name})") + + # Test decision making + logger.info("5. Testing decision making...") + for i in range(3): # Test multiple decisions + decision = await orchestrator.make_trading_decision(symbol) + if decision: + logger.info(f" Decision {i+1}: {decision.action} (confidence: {decision.confidence:.3f})") + logger.info(f" Reasoning: {decision.reasoning}") + else: + logger.info(f" Decision {i+1}: None") + + # Wait a bit between decisions + await asyncio.sleep(1) + + # Test fallback prediction + logger.info("6. Testing fallback prediction...") + current_price = data_provider.get_current_price(symbol) + if current_price: + fallback = await orchestrator._generate_fallback_prediction(symbol, current_price) + if fallback: + logger.info(f" Fallback prediction: {fallback.action} (confidence: {fallback.confidence:.3f})") + else: + logger.info(" No fallback prediction generated") + else: + logger.info(" No current price available for fallback test") + + except Exception as e: + logger.error(f" Error testing predictions: {e}") + import traceback + traceback.print_exc() + + logger.info("=" * 60) + logger.info("TEST COMPLETE") + logger.info("=" * 60) + +if __name__ == "__main__": + asyncio.run(test_orchestrator_predictions()) \ No newline at end of file diff --git a/debug/test_trading_execution.py b/debug/test_trading_execution.py new file mode 100644 index 0000000..bc178c7 --- /dev/null +++ b/debug/test_trading_execution.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +""" +Test script to debug trading execution issues +""" + +import sys +import os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +from core.trading_executor import TradingExecutor +from core.orchestrator import TradingOrchestrator +from core.data_provider import DataProvider +import logging + +# Set up logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +def test_trading_execution(): + """Test trading execution in simulation mode""" + + logger.info("=" * 60) + logger.info("TESTING TRADING EXECUTION") + logger.info("=" * 60) + + # Initialize components + logger.info("1. Initializing components...") + data_provider = DataProvider() + orchestrator = TradingOrchestrator(data_provider) + trading_executor = TradingExecutor() + + # Check trading executor status + logger.info("2. Checking trading executor status...") + logger.info(f" Trading enabled: {trading_executor.trading_enabled}") + logger.info(f" Trading mode: {trading_executor.trading_mode}") + logger.info(f" Simulation mode: {trading_executor.simulation_mode}") + logger.info(f" Exchange connected: {trading_executor.exchange is not None}") + + # Check account balance + logger.info("3. Checking account balance...") + try: + balance = trading_executor.get_account_balance() + logger.info(f" Account balance: {balance}") + except Exception as e: + logger.error(f" Error getting balance: {e}") + + # Test manual trade execution + logger.info("4. Testing manual trade execution...") + symbol = 'ETH/USDT' + action = 'BUY' + quantity = 0.01 + + try: + logger.info(f" Executing: {action} {quantity} {symbol}") + result = trading_executor.execute_trade(symbol, action, quantity) + logger.info(f" Result: {result}") + + if result: + # Check positions + positions = trading_executor.get_positions() + logger.info(f" Positions after trade: {positions}") + + except Exception as e: + logger.error(f" Error executing trade: {e}") + import traceback + traceback.print_exc() + + # Test orchestrator decision making + logger.info("5. Testing orchestrator decisions...") + try: + import asyncio + + async def test_decision(): + decision = await orchestrator.make_trading_decision(symbol) + if decision: + logger.info(f" Decision: {decision.action} (confidence: {decision.confidence:.3f})") + + # Test executing the decision + if decision.action != 'HOLD': + result = trading_executor.execute_signal( + symbol=decision.symbol, + action=decision.action, + confidence=decision.confidence, + current_price=decision.price + ) + logger.info(f" Execution result: {result}") + else: + logger.info(" No decision made") + + asyncio.run(test_decision()) + + except Exception as e: + logger.error(f" Error testing orchestrator: {e}") + import traceback + traceback.print_exc() + + # Check safety conditions + logger.info("6. Testing safety conditions...") + try: + # Check if safety conditions are blocking trades + symbol_test = 'ETH/USDT' + action_test = 'BUY' + + # Access private method for testing (not ideal but for debugging) + if hasattr(trading_executor, '_check_safety_conditions'): + safety_ok = trading_executor._check_safety_conditions(symbol_test, action_test) + logger.info(f" Safety conditions OK for {action_test} {symbol_test}: {safety_ok}") + + # Check individual safety conditions + config = trading_executor.mexc_config + logger.info(f" Emergency stop: {config.get('emergency_stop', False)}") + logger.info(f" Allowed symbols: {config.get('allowed_symbols', [])}") + logger.info(f" Daily loss: {trading_executor.daily_loss} / {config.get('max_daily_loss_usd', 5.0)}") + logger.info(f" Daily trades: {trading_executor.daily_trades} / {config.get('max_trades_per_hour', 2) * 24}") + logger.info(f" Concurrent positions: {len(trading_executor.positions)} / {config.get('max_concurrent_positions', 1)}") + + except Exception as e: + logger.error(f" Error checking safety conditions: {e}") + + logger.info("=" * 60) + logger.info("TEST COMPLETE") + logger.info("=" * 60) + +if __name__ == "__main__": + test_trading_execution() \ No newline at end of file diff --git a/utils/checkpoint_manager.py b/utils/checkpoint_manager.py index 7821e5e..5d2b078 100644 --- a/utils/checkpoint_manager.py +++ b/utils/checkpoint_manager.py @@ -124,7 +124,7 @@ class CheckpointManager: self._rotate_checkpoints(model_name) self._save_metadata() - logger.info(f"Saved checkpoint: {checkpoint_id} (score: {performance_score:.4f})") + logger.debug(f"Saved checkpoint: {checkpoint_id} (score: {performance_score:.4f})") return metadata except Exception as e: @@ -232,7 +232,7 @@ class CheckpointManager: # Save more frequently during active training (every 5th attempt instead of 10th) if random.random() < 0.2: # 20% chance to save anyway - logger.info(f"Saving checkpoint for {model_name} - periodic save during active training") + logger.debug(f"Saving checkpoint for {model_name} - periodic save during active training") return True return False @@ -268,7 +268,7 @@ class CheckpointManager: file_path = Path(checkpoint.file_path) if file_path.exists(): file_path.unlink() - logger.info(f"Rotated out checkpoint: {checkpoint.checkpoint_id}") + logger.debug(f"Rotated out checkpoint: {checkpoint.checkpoint_id}") except Exception as e: logger.error(f"Error removing rotated checkpoint {checkpoint.checkpoint_id}: {e}") diff --git a/web/clean_dashboard.py b/web/clean_dashboard.py index 2f12ab4..c43222d 100644 --- a/web/clean_dashboard.py +++ b/web/clean_dashboard.py @@ -4850,17 +4850,19 @@ class CleanTradingDashboard: logger.error(f"Error initiating orchestrator connection: {e}") async def _on_trading_decision(self, decision): - """Handle trading decision from orchestrator.""" + """Handle trading decision from orchestrator and execute through trading executor.""" try: # Handle both object and dict formats if hasattr(decision, 'action'): action = getattr(decision, 'action', 'HOLD') symbol = getattr(decision, 'symbol', 'ETH/USDT') confidence = getattr(decision, 'confidence', 0.0) + price = getattr(decision, 'price', None) else: action = decision.get('action', 'HOLD') symbol = decision.get('symbol', 'ETH/USDT') confidence = decision.get('confidence', 0.0) + price = decision.get('price', None) if action == 'HOLD': return @@ -4886,11 +4888,45 @@ class CleanTradingDashboard: dashboard_decision['timestamp'] = datetime.now() dashboard_decision['executed'] = False + logger.info(f"[ORCHESTRATOR SIGNAL] Received: {action} for {symbol} (confidence: {confidence:.3f})") + + # EXECUTE THE DECISION THROUGH TRADING EXECUTOR + if self.trading_executor and confidence > 0.5: # Only execute high confidence signals + try: + logger.info(f"[ORCHESTRATOR EXECUTION] Attempting to execute {action} for {symbol} via trading executor...") + success = self.trading_executor.execute_signal( + symbol=symbol, + action=action, + confidence=confidence, + current_price=price + ) + + if success: + dashboard_decision['executed'] = True + dashboard_decision['execution_time'] = datetime.now() + logger.info(f"[ORCHESTRATOR EXECUTION] SUCCESS: {action} executed for {symbol}") + + # Sync position from trading executor after execution + self._sync_position_from_executor(symbol) + + else: + logger.warning(f"[ORCHESTRATOR EXECUTION] FAILED: {action} execution blocked for {symbol}") + dashboard_decision['execution_failure'] = True + + except Exception as e: + logger.error(f"[ORCHESTRATOR EXECUTION] ERROR: Failed to execute {action} for {symbol}: {e}") + dashboard_decision['execution_error'] = str(e) + else: + if not self.trading_executor: + logger.warning("[ORCHESTRATOR EXECUTION] No trading executor available") + elif confidence <= 0.5: + logger.info(f"[ORCHESTRATOR EXECUTION] Low confidence signal ignored: {action} for {symbol} (confidence: {confidence:.3f})") + + # Store decision in dashboard self.recent_decisions.append(dashboard_decision) if len(self.recent_decisions) > 200: self.recent_decisions.pop(0) - logger.info(f"[ORCHESTRATOR SIGNAL] Received: {action} for {symbol} (confidence: {confidence:.3f})") except Exception as e: logger.error(f"Error handling trading decision: {e}")