Преглед на файлове

Refactor datetime handling in Telegram bot state management - Introduced a helper function to safely convert datetime objects to ISO strings, improving error handling for invalid datetime values. Updated state saving and trade processing logic to maintain datetime objects for comparisons, enhancing reliability in trade tracking.

Carles Sentis преди 5 дни
родител
ревизия
22125440b9
променени са 1 файла, в които са добавени 29 реда и са изтрити 11 реда
  1. 29 11
      src/telegram_bot.py

+ 29 - 11
src/telegram_bot.py

@@ -113,12 +113,29 @@ class TelegramTradingBot:
     def _save_bot_state(self):
         """Save bot state to disk."""
         try:
+            # Helper function to safely convert datetime to ISO string
+            def safe_datetime_to_iso(dt):
+                if dt is None:
+                    return None
+                try:
+                    # Handle both datetime objects and strings
+                    if isinstance(dt, str):
+                        # If it's already a string, validate it's a valid ISO format
+                        datetime.fromisoformat(dt.replace('Z', '+00:00'))
+                        return dt
+                    else:
+                        # Convert datetime object to ISO string
+                        return dt.isoformat()
+                except (ValueError, AttributeError) as e:
+                    logger.warning(f"⚠️ Invalid datetime value, using None: {dt} - {e}")
+                    return None
+            
             state_data = {
                 'pending_stop_losses': self.pending_stop_losses,
                 'last_known_orders': list(self.last_known_orders),  # Convert set to list for JSON
                 'last_known_positions': self.last_known_positions,
-                'last_processed_trade_time': self.last_processed_trade_time.isoformat() if self.last_processed_trade_time else None,
-                'last_deposit_withdrawal_check': self.last_deposit_withdrawal_check.isoformat() if self.last_deposit_withdrawal_check else None,
+                'last_processed_trade_time': safe_datetime_to_iso(self.last_processed_trade_time),
+                'last_deposit_withdrawal_check': safe_datetime_to_iso(self.last_deposit_withdrawal_check),
                 'last_updated': datetime.now().isoformat(),
                 'version': self.version
             }
@@ -2627,7 +2644,7 @@ This will place a limit {exit_side} order at ${profit_price:,.2f} to capture pro
             # Initialize last processed time if first run
             if self.last_processed_trade_time is None:
                 # Set to current time minus 1 hour to catch recent activity
-                self.last_processed_trade_time = (datetime.now() - timedelta(hours=1)).isoformat()
+                self.last_processed_trade_time = datetime.now() - timedelta(hours=1)
             
             # Filter for new trades since last check
             new_trades = []
@@ -2638,18 +2655,19 @@ This will place a limit {exit_side} order at ${profit_price:,.2f} to capture pro
                 if fill_time:
                     # Convert timestamps to comparable format
                     try:
-                        # Convert fill_time to string if it's not already
+                        # Convert fill_time to datetime object for comparison
                         if isinstance(fill_time, (int, float)):
                             # Assume it's a unix timestamp
-                            fill_time_str = datetime.fromtimestamp(fill_time / 1000 if fill_time > 1e10 else fill_time).isoformat()
+                            fill_datetime = datetime.fromtimestamp(fill_time / 1000 if fill_time > 1e10 else fill_time)
                         else:
-                            fill_time_str = str(fill_time)
+                            # Try to parse as ISO string
+                            fill_datetime = datetime.fromisoformat(str(fill_time).replace('Z', '+00:00'))
                         
-                        # Compare as strings
-                        if fill_time_str > self.last_processed_trade_time:
+                        # Compare datetime objects
+                        if fill_datetime > self.last_processed_trade_time:
                             new_trades.append(fill)
-                            if fill_time_str > latest_trade_time:
-                                latest_trade_time = fill_time_str
+                            if fill_datetime > latest_trade_time:
+                                latest_trade_time = fill_datetime
                     except Exception as timestamp_error:
                         logger.warning(f"⚠️ Error processing timestamp {fill_time}: {timestamp_error}")
                         continue
@@ -2661,7 +2679,7 @@ This will place a limit {exit_side} order at ${profit_price:,.2f} to capture pro
             for trade in new_trades:
                 await self._process_external_trade(trade)
             
-            # Update last processed time
+            # Update last processed time (keep as datetime object)
             self.last_processed_trade_time = latest_trade_time
             
             # Save state after updating last processed time