Переглянути джерело

Add sync_status command and enhance order synchronization diagnostics

- Introduced the /sync_status command to provide users with detailed synchronization diagnostics, including the status of the monitoring coordinator and exchange order sync.
- Enhanced error handling and user feedback in the sync command, ensuring better communication of synchronization issues.
- Improved the initialization process for exchange order sync by checking multiple sources for trading stats, increasing reliability.
- Added detailed logging for diagnostics to aid in troubleshooting synchronization issues.
Carles Sentis 1 тиждень тому
батько
коміт
740173cc85

+ 1 - 0
src/bot/core.py

@@ -160,6 +160,7 @@ class TelegramTradingBot:
         self.application.add_handler(CommandHandler("version", self.management_commands.version_command))
         self.application.add_handler(CommandHandler("keyboard", self.management_commands.keyboard_command))
         self.application.add_handler(CommandHandler("sync", self.management_commands.sync_command))
+        self.application.add_handler(CommandHandler("sync_status", self.management_commands.sync_status_command))
         self.application.add_handler(CommandHandler("deposit", self.management_commands.deposit_command))
         self.application.add_handler(CommandHandler("withdrawal", self.management_commands.withdrawal_command))
         

+ 147 - 3
src/commands/management_commands.py

@@ -564,12 +564,28 @@ Will trigger when {token} price moves {alarm['direction']} {target_price_str}
 
             await self._reply(update, "🔄 Starting order synchronization...")
 
-            # Get exchange order sync from monitoring coordinator
+            # Get monitoring coordinator
             monitoring_coordinator = getattr(self.trading_engine, 'monitoring_coordinator', None)
-            if not monitoring_coordinator or not monitoring_coordinator.exchange_order_sync:
-                await self._reply(update, "❌ Order synchronization not available. Please restart the bot.")
+            if not monitoring_coordinator:
+                await self._reply(update, "❌ Monitoring coordinator not available. Please restart the bot.")
                 return
 
+            # Check if exchange order sync is available, if not try to initialize it
+            if not monitoring_coordinator.exchange_order_sync:
+                await self._reply(update, "⚠️ Exchange order sync not initialized. Attempting to initialize...")
+                
+                # Try to initialize the sync manually
+                try:
+                    await self._initialize_exchange_order_sync(monitoring_coordinator)
+                    if not monitoring_coordinator.exchange_order_sync:
+                        await self._reply(update, "❌ Failed to initialize exchange order sync. Please restart the bot.")
+                        return
+                    await self._reply(update, "✅ Exchange order sync initialized successfully.")
+                except Exception as e:
+                    logger.error(f"Failed to initialize exchange order sync: {e}")
+                    await self._reply(update, f"❌ Failed to initialize exchange order sync: {str(e)}")
+                    return
+
             # Run synchronization
             sync_results = monitoring_coordinator.exchange_order_sync.sync_exchange_orders_to_database()
             
@@ -581,6 +597,29 @@ Will trigger when {token} price moves {alarm['direction']} {target_price_str}
             logger.error(f"Error in sync command: {e}", exc_info=True)
             await self._reply(update, "❌ Error during synchronization.")
 
+    async def _initialize_exchange_order_sync(self, monitoring_coordinator):
+        """Try to manually initialize exchange order sync."""
+        try:
+            from src.monitoring.exchange_order_sync import ExchangeOrderSync
+            
+            # Get trading stats from trading engine
+            stats = self.trading_engine.get_stats()
+            if not stats:
+                raise Exception("Trading stats not available from trading engine")
+            
+            # Get hyperliquid client
+            hl_client = self.trading_engine.client
+            if not hl_client:
+                raise Exception("Hyperliquid client not available")
+            
+            # Initialize the exchange order sync
+            monitoring_coordinator.exchange_order_sync = ExchangeOrderSync(hl_client, stats)
+            logger.info("✅ Manually initialized exchange order sync")
+            
+        except Exception as e:
+            logger.error(f"Error manually initializing exchange order sync: {e}")
+            raise
+
     async def _format_sync_results(self, sync_results: Dict[str, Any], force: bool) -> str:
         """Format synchronization results for display."""
         
@@ -627,6 +666,111 @@ Will trigger when {token} price moves {alarm['direction']} {target_price_str}
         
         return "\n".join(message_parts)
 
+    async def sync_status_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+        """Handle the /sync_status command to show synchronization diagnostics."""
+        try:
+            if not self._is_authorized(update):
+                await self._reply(update, "❌ Unauthorized access.")
+                return
+
+            # Check monitoring coordinator
+            monitoring_coordinator = getattr(self.trading_engine, 'monitoring_coordinator', None)
+            
+            diagnostic_parts = ["🔍 <b>Synchronization Diagnostics</b>\n"]
+            
+            # Check monitoring coordinator
+            if monitoring_coordinator:
+                diagnostic_parts.append("✅ <b>Monitoring Coordinator:</b> Available")
+                diagnostic_parts.append(f"   • Running: {'Yes' if monitoring_coordinator.is_running else 'No'}")
+                
+                # Check exchange order sync
+                if monitoring_coordinator.exchange_order_sync:
+                    diagnostic_parts.append("✅ <b>Exchange Order Sync:</b> Available")
+                    
+                    # Try to get sync stats
+                    try:
+                        sync_stats = self._get_sync_diagnostics(monitoring_coordinator)
+                        diagnostic_parts.extend(sync_stats)
+                    except Exception as e:
+                        diagnostic_parts.append(f"⚠️ <b>Sync Stats Error:</b> {str(e)}")
+                else:
+                    diagnostic_parts.append("❌ <b>Exchange Order Sync:</b> Not Available")
+                    
+                    # Try to diagnose why
+                    diagnostic_parts.append("\n🔍 <b>Troubleshooting:</b>")
+                    
+                    # Check position tracker
+                    if hasattr(monitoring_coordinator, 'position_tracker'):
+                        diagnostic_parts.append("✅ Position Tracker: Available")
+                        if hasattr(monitoring_coordinator.position_tracker, 'trading_stats'):
+                            if monitoring_coordinator.position_tracker.trading_stats:
+                                diagnostic_parts.append("✅ Position Tracker Trading Stats: Available")
+                            else:
+                                diagnostic_parts.append("❌ Position Tracker Trading Stats: None")
+                        else:
+                            diagnostic_parts.append("❌ Position Tracker Trading Stats: Not Found")
+                    else:
+                        diagnostic_parts.append("❌ Position Tracker: Not Available")
+                    
+                    # Check trading engine stats
+                    stats = self.trading_engine.get_stats()
+                    if stats:
+                        diagnostic_parts.append("✅ Trading Engine Stats: Available")
+                    else:
+                        diagnostic_parts.append("❌ Trading Engine Stats: Not Available")
+                    
+                    # Check hyperliquid client
+                    client = self.trading_engine.client
+                    if client:
+                        diagnostic_parts.append("✅ Hyperliquid Client: Available")
+                    else:
+                        diagnostic_parts.append("❌ Hyperliquid Client: Not Available")
+            else:
+                diagnostic_parts.append("❌ <b>Monitoring Coordinator:</b> Not Available")
+            
+            diagnostic_parts.append("\n💡 <b>Solutions:</b>")
+            diagnostic_parts.append("• Try: /sync force")
+            diagnostic_parts.append("• If that fails, restart the bot")
+            diagnostic_parts.append("• Check logs for detailed error messages")
+            
+            await self._reply(update, "\n".join(diagnostic_parts))
+
+        except Exception as e:
+            logger.error(f"Error in sync_status command: {e}", exc_info=True)
+            await self._reply(update, f"❌ Error getting sync status: {str(e)}")
+
+    def _get_sync_diagnostics(self, monitoring_coordinator):
+        """Get detailed sync diagnostics."""
+        diagnostic_parts = []
+        
+        try:
+            # Test if we can access the sync components
+            sync_manager = monitoring_coordinator.exchange_order_sync
+            
+            if hasattr(sync_manager, 'hl_client'):
+                diagnostic_parts.append("✅ Hyperliquid Client: Connected")
+            else:
+                diagnostic_parts.append("❌ Hyperliquid Client: Missing")
+            
+            if hasattr(sync_manager, 'trading_stats'):
+                diagnostic_parts.append("✅ Trading Stats: Connected")
+                
+                # Try to get a count of database orders
+                try:
+                    db_orders = []
+                    db_orders.extend(sync_manager.trading_stats.get_orders_by_status('open', limit=10))
+                    db_orders.extend(sync_manager.trading_stats.get_orders_by_status('submitted', limit=10))
+                    diagnostic_parts.append(f"✅ Database Orders: {len(db_orders)} found")
+                except Exception as e:
+                    diagnostic_parts.append(f"⚠️ Database Orders: Error ({str(e)})")
+            else:
+                diagnostic_parts.append("❌ Trading Stats: Missing")
+                
+        except Exception as e:
+            diagnostic_parts.append(f"❌ Sync Components: Error ({str(e)})")
+        
+        return diagnostic_parts
+
     async def deposit_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
         """Handle the /deposit command to record a deposit."""
         if not self._is_authorized(update):

+ 26 - 4
src/monitoring/monitoring_coordinator.py

@@ -105,17 +105,39 @@ class MonitoringCoordinator:
     def _init_exchange_order_sync(self):
         """Initialize exchange order synchronization"""
         try:
-            # Get trading stats from position tracker
+            # Try multiple sources for trading stats
+            trading_stats = None
+            
+            # Method 1: Get from position tracker
             if hasattr(self.position_tracker, 'trading_stats') and self.position_tracker.trading_stats:
+                trading_stats = self.position_tracker.trading_stats
+                logger.debug("Found trading stats from position tracker")
+            
+            # Method 2: Get from trading engine (if we have access to it)
+            elif hasattr(self, '_trading_engine') and self._trading_engine:
+                trading_stats = self._trading_engine.get_stats()
+                logger.debug("Found trading stats from trading engine")
+            
+            # Method 3: Try to initialize trading stats directly
+            if not trading_stats:
+                try:
+                    from ..stats.trading_stats import TradingStats
+                    trading_stats = TradingStats()
+                    logger.debug("Initialized trading stats directly")
+                except Exception as e:
+                    logger.warning(f"Could not initialize trading stats directly: {e}")
+            
+            if trading_stats:
                 self.exchange_order_sync = ExchangeOrderSync(
                     self.hl_client, 
-                    self.position_tracker.trading_stats
+                    trading_stats
                 )
                 logger.info("✅ Exchange order sync initialized")
             else:
-                logger.warning("⚠️ Trading stats not available, exchange order sync disabled")
+                logger.warning("⚠️ Trading stats not available from any source, exchange order sync disabled")
+                
         except Exception as e:
-            logger.error(f"Error initializing exchange order sync: {e}")
+            logger.error(f"Error initializing exchange order sync: {e}", exc_info=True)
     
     async def _order_sync_loop(self):
         """Periodic order synchronization loop"""

+ 1 - 1
trading_bot.py

@@ -14,7 +14,7 @@ from datetime import datetime
 from pathlib import Path
 
 # Bot version
-BOT_VERSION = "2.6.311"
+BOT_VERSION = "2.6.312"
 
 # Add src directory to Python path
 sys.path.insert(0, str(Path(__file__).parent / "src"))