Browse Source

Refactor bot initialization and polling mechanism to streamline the process. Removed unnecessary keep_running_future and updated logging for clarity. Adjusted stats command to simplify session information retrieval. Enhanced chat ID bot to utilize the new polling method.

Carles Sentis 6 days ago
parent
commit
7aeed104c2

+ 7 - 35
src/bot/core.py

@@ -350,8 +350,6 @@ For support or issues, check the logs or contact the administrator.
         # Set up handlers
         # Set up handlers
         self.setup_handlers()
         self.setup_handlers()
 
 
-        keep_running_future = asyncio.Future() # Future to keep the bot alive
-
         try:
         try:
             logger.info("🚀 Initializing bot application (v20.x style)...")
             logger.info("🚀 Initializing bot application (v20.x style)...")
             await self.application.initialize()
             await self.application.initialize()
@@ -371,37 +369,18 @@ For support or issues, check the logs or contact the administrator.
             logger.info("▶️ Starting PTB application's internal tasks (update processing, job queue).")
             logger.info("▶️ Starting PTB application's internal tasks (update processing, job queue).")
             await self.application.start() # This is non-blocking and starts the Application's processing loop.
             await self.application.start() # This is non-blocking and starts the Application's processing loop.
 
 
-            if self.application.updater:
-                logger.info(f"▶️ Activating PTB updater to fetch updates (drop_pending_updates={Config.TELEGRAM_DROP_PENDING_UPDATES}).")
-                # updater.start_polling is an async method that starts fetching updates and populates the application's update_queue.
-                # It needs to run as a background task, managed by the existing event loop.
-                # We don't await it directly here if we want other code (like keep_running_future) to proceed.
-                # However, for graceful shutdown, we'll manage its lifecycle.
-                # For this structure, we expect the main script to keep the event loop running.
-                await self.application.updater.start_polling(drop_pending_updates=Config.TELEGRAM_DROP_PENDING_UPDATES)
-            else:
-                logger.error("❌ Critical: Application updater is not initialized. Bot cannot receive Telegram updates.")
-                # If updater is critical, we might want to stop here or raise an error.
-                # For now, we'll let keep_running_future potentially handle the stop.
-                if not keep_running_future.done():
-                    keep_running_future.set_exception(RuntimeError("Updater not available"))
-
-
-            logger.info("✅ Bot is initialized and updater is polling. Awaiting stop signal via keep_running_future or Ctrl+C.")
-            await keep_running_future 
-                    
+            logger.info(f"▶️ Starting polling (drop_pending_updates={Config.TELEGRAM_DROP_PENDING_UPDATES})...")
+            await self.application.run_polling(drop_pending_updates=Config.TELEGRAM_DROP_PENDING_UPDATES)
+
+            logger.info("✅ Bot is initialized and polling. Awaiting stop signal or Ctrl+C.")
+            # No need for keep_running_future with run_polling
+        
         except (KeyboardInterrupt, SystemExit) as e: # Added SystemExit here
         except (KeyboardInterrupt, SystemExit) as e: # Added SystemExit here
             logger.info(f"🛑 Bot run interrupted by {type(e).__name__}. Initiating shutdown (v20.x style)...")
             logger.info(f"🛑 Bot run interrupted by {type(e).__name__}. Initiating shutdown (v20.x style)...")
-            if not keep_running_future.done():
-                keep_running_future.set_exception(e if isinstance(e, SystemExit) else KeyboardInterrupt())
         except asyncio.CancelledError:
         except asyncio.CancelledError:
             logger.info("🛑 Bot run task cancelled. Initiating shutdown (v20.x style)...")
             logger.info("🛑 Bot run task cancelled. Initiating shutdown (v20.x style)...")
-            if not keep_running_future.done():
-                keep_running_future.cancel()
         except Exception as e:
         except Exception as e:
             logger.error(f"❌ Unhandled error in bot run loop (v20.x style): {e}", exc_info=True)
             logger.error(f"❌ Unhandled error in bot run loop (v20.x style): {e}", exc_info=True)
-            if not keep_running_future.done():
-                keep_running_future.set_exception(e)
         finally:
         finally:
             logger.info("🔌 Starting graceful shutdown sequence in TelegramTradingBot.run (v20.x style)...")
             logger.info("🔌 Starting graceful shutdown sequence in TelegramTradingBot.run (v20.x style)...")
             try:
             try:
@@ -410,18 +389,11 @@ For support or issues, check the logs or contact the administrator.
                 logger.info("Market monitor stopped.")
                 logger.info("Market monitor stopped.")
 
 
                 if self.application:
                 if self.application:
-                    # Stop the updater first if it's running
-                    if self.application.updater and self.application.updater.running:
-                        logger.info("Stopping PTB updater polling...")
-                        await self.application.updater.stop()
-                        logger.info("PTB updater polling stopped.")
-                    
-                    # Then stop the application's own processing
+                    # Stop the application's own processing
                     if self.application.running: # Check if application was started
                     if self.application.running: # Check if application was started
                         logger.info("Stopping PTB application components (handlers, job queue)...")
                         logger.info("Stopping PTB application components (handlers, job queue)...")
                         await self.application.stop() 
                         await self.application.stop() 
                         logger.info("PTB application components stopped.")
                         logger.info("PTB application components stopped.")
-                    
                     # Finally, shutdown the application
                     # Finally, shutdown the application
                     logger.info("Shutting down PTB application (bot, persistence, etc.)...")
                     logger.info("Shutting down PTB application (bot, persistence, etc.)...")
                     await self.application.shutdown()
                     await self.application.shutdown()

+ 4 - 1
src/commands/info/stats.py

@@ -103,7 +103,10 @@ class StatsCommands(InfoCommandsBase):
             formatter = get_formatter()
             formatter = get_formatter()
             s = stats.get_basic_stats()
             s = stats.get_basic_stats()
             perf = stats.get_basic_stats()
             perf = stats.get_basic_stats()
-            session = stats.get_session_info()
+            session = {
+                "bot_started": s.get("start_date", "N/A"),
+                "last_updated": s.get("last_trade", "N/A"),
+            }
 
 
             # Account Overview
             # Account Overview
             account_lines = [
             account_lines = [

+ 21 - 0
tests/test_db_mark_price.py

@@ -0,0 +1,21 @@
+import sys
+import os
+from datetime import datetime
+
+# Adjust path if needed to import TradingStats
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+from src.stats.trading_stats import TradingStats
+
+def print_open_positions_mark_prices():
+    stats = TradingStats()
+    open_positions = stats.get_open_positions()
+    print(f"Found {len(open_positions)} open positions:")
+    for pos in open_positions:
+        symbol = pos.get('symbol', 'N/A')
+        entry_price = pos.get('entry_price', 'N/A')
+        mark_price = pos.get('mark_price', 'N/A')
+        print(f"Symbol: {symbol}, Entry Price: {entry_price}, Mark Price: {mark_price}")
+
+if __name__ == "__main__":
+    print_open_positions_mark_prices() 

+ 49 - 0
tests/test_update_and_check_mark_price.py

@@ -0,0 +1,49 @@
+import sys
+import os
+from datetime import datetime
+
+# Adjust path if needed to import TradingStats and TradingEngine
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+from src.stats.trading_stats import TradingStats
+from src.trading.trading_engine import TradingEngine
+
+def update_db_with_latest_mark_prices():
+    engine = TradingEngine()
+    stats = TradingStats()
+    exchange_positions = engine.get_positions() or []
+    print(f"Fetched {len(exchange_positions)} positions from exchange.")
+    updated = 0
+    for pos in exchange_positions:
+        symbol = pos.get('symbol')
+        mark_price = pos.get('markPrice') or pos.get('markPx')
+        if symbol and mark_price is not None:
+            # Find the open trade in DB
+            open_positions = stats.get_open_positions()
+            for db_pos in open_positions:
+                if db_pos.get('symbol') == symbol:
+                    lifecycle_id = db_pos.get('trade_lifecycle_id')
+                    try:
+                        stats.trade_manager.update_trade_market_data(
+                            lifecycle_id,
+                            mark_price=float(mark_price)
+                        )
+                        updated += 1
+                        print(f"Updated {symbol} (Lifecycle: {lifecycle_id}) with mark_price={mark_price}")
+                    except Exception as e:
+                        print(f"Failed to update {symbol}: {e}")
+    print(f"Updated {updated} positions in DB with latest mark prices.")
+
+def print_open_positions_mark_prices():
+    stats = TradingStats()
+    open_positions = stats.get_open_positions()
+    print(f"\nDB now has {len(open_positions)} open positions:")
+    for pos in open_positions:
+        symbol = pos.get('symbol', 'N/A')
+        entry_price = pos.get('entry_price', 'N/A')
+        mark_price = pos.get('mark_price', 'N/A')
+        print(f"Symbol: {symbol}, Entry Price: {entry_price}, Mark Price: {mark_price}")
+
+if __name__ == "__main__":
+    update_db_with_latest_mark_prices()
+    print_open_positions_mark_prices() 

+ 1 - 1
trading_bot.py

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

+ 1 - 4
utils/get_telegram_chat_id.py

@@ -106,8 +106,7 @@ class ChatIDBot:
             
             
             # Initialize and run
             # Initialize and run
             await self.application.initialize()
             await self.application.initialize()
-            await self.application.start()
-            await self.application.updater.start_polling()
+            await self.application.run_polling()
             
             
             # Keep running until interrupted
             # Keep running until interrupted
             while self.running:
             while self.running:
@@ -121,8 +120,6 @@ class ChatIDBot:
             # Cleanup
             # Cleanup
             try:
             try:
                 if self.application:
                 if self.application:
-                    if self.application.updater.running:
-                        await self.application.updater.stop()
                     await self.application.stop()
                     await self.application.stop()
                     await self.application.shutdown()
                     await self.application.shutdown()
             except Exception as e:
             except Exception as e: