Browse Source

Increment BOT_VERSION to 2.2.132 and add diagnostic logging in MarketMonitor for unmatched fills.

- Updated BOT_VERSION for the upcoming release.
- Introduced a diagnostic block in MarketMonitor to log discrepancies when fills do not match expected open positions, enhancing debugging capabilities.
- Improved logging details for better visibility into potential issues with trade lifecycle management.
Carles Sentis 2 days ago
parent
commit
f20b05cba1
2 changed files with 51 additions and 1 deletions
  1. 50 0
      src/monitoring/market_monitor.py
  2. 1 1
      trading_bot.py

+ 50 - 0
src/monitoring/market_monitor.py

@@ -927,6 +927,56 @@ class MarketMonitor:
 
                     # Original Fallback logic if still not processed
                     if not fill_processed_this_iteration:
+                        # ---- START DIAGNOSTIC BLOCK ----
+                        # Log details if this fill *should* have matched an open lifecycle but didn't.
+                        # This condition checks if a position count recently changed, suggesting a closure.
+                        # We access _update_cached_data's effect by checking self.last_known_positions vs current from cache.
+                        # Note: This is an approximation. A more robust check might involve tracking position count changes more directly.
+                        
+                        # Get current positions from cache (reflects state after _update_cached_data this cycle)
+                        current_positions_from_cache_map = {
+                            pos.get('symbol'): pos for pos in (self.cached_positions or [])
+                            if pos.get('symbol') and abs(float(pos.get('contracts', 0))) > 1e-9
+                        }
+                        # Get DB's view of open positions
+                        all_open_positions_in_db = stats.get_open_positions() # Fetches all with status='position_opened'
+                        db_open_symbols = {pos_db.get('symbol') for pos_db in all_open_positions_in_db}
+
+                        # Check if the fill's symbol *should* have been in the DB as open,
+                        # but wasn't found by get_trade_by_symbol_and_status(full_symbol, 'position_opened')
+                        if full_symbol in db_open_symbols:
+                            # This is the critical contradiction: DB says it's open via get_open_positions,
+                            # but get_trade_by_symbol_and_status(full_symbol, ...) failed.
+                            # This should ideally not happen if queries are consistent.
+                            logger.error(f"🚨 DIAGNOSTIC: Contradiction for {full_symbol}! get_open_positions() includes it, but get_trade_by_symbol_and_status('{full_symbol}', 'position_opened') failed to find it within _check_external_trades context for fill {trade_id}. This needs investigation into TradingStats symbol querying.")
+                        
+                        # More general diagnostic: if a position disappeared from exchange but we couldn't match this fill
+                        # This is a heuristic. A position count change was logged by _update_cached_data.
+                        # If len(current_positions_from_cache_map) < len(self.last_known_positions_before_update_this_cycle) 
+                        # (hypothetical variable, self.last_known_positions is already updated)
+                        # For now, we just log if get_trade_by_symbol_and_status failed.
+                        
+                        potential_match_failure_logged = False
+                        if not stats.get_trade_by_symbol_and_status(full_symbol, 'position_opened'): # Re-check to be sure
+                            logger.warning(f"⚠️ DIAGNOSTIC for UNMATCHED FILL {trade_id} ({full_symbol}):")
+                            logger.warning(f"   Fill details: Side={side_from_fill}, Amount={amount_from_fill}, Price={price_from_fill}")
+                            logger.warning(f"   Attempted lookup with full_symbol='{full_symbol}' and status='position_opened' found NO active lifecycle.")
+                            if all_open_positions_in_db:
+                                logger.warning(f"   However, DB currently has these 'position_opened' lifecycles (symbol - lifecycle_id):")
+                                for db_pos in all_open_positions_in_db:
+                                    logger.warning(f"     - '{db_pos.get('symbol')}' - ID: {db_pos.get('trade_lifecycle_id')}")
+                                # Check for near matches (e.g. base token match)
+                                base_token_fill = full_symbol.split('/')[0].split(':')[0]
+                                near_matches = [db_s for db_s in db_open_symbols if base_token_fill in db_s]
+                                if near_matches:
+                                    logger.warning(f"   Possible near matches in DB for base token '{base_token_fill}': {near_matches}")
+                                else:
+                                    logger.warning(f"   No near matches found in DB for base token '{base_token_fill}'.")
+                            else:
+                                logger.warning("   DB has NO 'position_opened' lifecycles at all right now.")
+                            potential_match_failure_logged = True
+                        # ---- END DIAGNOSTIC BLOCK ----
+                        
                         linked_order_db_id = None
                         if exchange_order_id_from_fill:
                             order_in_db = stats.get_order_by_exchange_id(exchange_order_id_from_fill)

+ 1 - 1
trading_bot.py

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