"""Aplicação de Análise de Mercado com IA para Scalping - Versão Refatorada.""" from typing import Dict, Any, Optional import gradio as gr from datetime import datetime # Importar módulos refatorados try: from config.config import AppConfig from src.analysis.market_analysis import TechnicalAnalysisEngine from src.analysis.sentiment_analysis import SentimentAnalysisEngine from src.ui.gradio_interface import GradioInterface from src.utils.utils import LogUtils, ValidationUtils from src.core.log_parser import VampireBotLogParser from src.analysis.fibonacci_analysis import AdvancedFibonacciEngine from src.core.advanced_market_processing import AdvancedMarketProcessor from src.integrations.real_time_integration import RealTimeIntegration, BotEvent from src.core.performance_monitor import PerformanceMonitor, measure_analysis_time from src.utils.request_logger import log_requests_responses, enable_logging, disable_logging # Sistema de logging avançado from src.core.database_logger import get_logger, initialize_logger, LogLevel, LogCategory from src.utils.logging_decorators import log_execution, log_api_call, log_ai_model_usage, LoggingContext, quick_log from src.ui.log_viewer import create_log_viewer_interface # Inicializar o sistema de logging db_logger = initialize_logger("logs/application.db") except ImportError: # Fallback para modo standalone se módulos não existirem print("⚠️ Módulos refatorados não encontrados. Executando em modo standalone.") AppConfig = None TechnicalAnalysisEngine = None SentimentAnalysisEngine = None GradioInterface = None LogUtils = None ValidationUtils = None VampireBotLogParser = None AdvancedFibonacciEngine = None AdvancedMarketProcessor = None RealTimeIntegration = None BotEvent = None PerformanceMonitor = None measure_analysis_time = None log_requests_responses = None enable_logging = None disable_logging = None # Fallback para sistema de logging get_logger = None initialize_logger = None LogLevel = None LogCategory = None log_execution = None log_api_call = None log_ai_model_usage = None LoggingContext = None quick_log = None create_log_viewer_interface = None db_logger = None # Engines de análise technical_engine = None sentiment_engine = None real_time_integration = None model_info = {'available': False, 'description': 'IA Indisponível'} # Estado global para eventos em tempo real recent_events = [] max_events_display = 50 # Monitor de performance global performance_monitor = PerformanceMonitor() if PerformanceMonitor else None # Inicializar engines def initialize_engines(): """Inicializa engines de análise técnica e de sentimento.""" global technical_engine, sentiment_engine, model_info try: # Log do início da inicialização if quick_log: quick_log("Iniciando inicialização dos engines", LogLevel.INFO, LogCategory.SYSTEM) # Habilitar logging de requisições/respostas if enable_logging: enable_logging() print("🔍 Sistema de logging de requisições habilitado") if TechnicalAnalysisEngine and SentimentAnalysisEngine: # Inicializar engine de análise técnica technical_engine = TechnicalAnalysisEngine() if LogUtils: LogUtils.log_analysis_result({'action': 'ENGINE_INIT', 'confidence': 100}) # Inicializar engine de análise de sentimento sentiment_engine = SentimentAnalysisEngine() # Obter informações do modelo de IA model_info = sentiment_engine.get_model_info() if LogUtils: LogUtils.log_model_status(model_info) # Log de sucesso if quick_log: quick_log("Engines inicializados com sucesso", LogLevel.INFO, LogCategory.SYSTEM, metadata={'engines': ['Technical Analysis', 'Sentiment Analysis']}) # Log evento do sistema if db_logger: db_logger.log_system_event( event_type="INITIALIZATION", event_name="ENGINES_STARTED", description="Todos os engines foram inicializados com sucesso", severity="INFO", metadata=model_info ) print("✅ Engines inicializadas com sucesso") else: # Fallback para modo standalone initialize_standalone_mode() except Exception as e: # Log de erro if quick_log: quick_log(f"Erro ao inicializar engines: {e}", LogLevel.ERROR, LogCategory.SYSTEM) if db_logger: db_logger.log_system_event( event_type="ERROR", event_name="ENGINES_INITIALIZATION_FAILED", description=f"Falha na inicialização dos engines: {str(e)}", severity="ERROR", metadata={'error': str(e)} ) print(f"Erro na inicialização: {str(e)}") # Fallback para modo básico initialize_standalone_mode() def initialize_standalone_mode(): """Inicializa modo standalone com funcionalidades básicas.""" global model_info # Importações opcionais para IA try: from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline import torch TRANSFORMERS_AVAILABLE = True except ImportError: TRANSFORMERS_AVAILABLE = False print("⚠️ Transformers não disponível. Executando sem IA.") # Lista de modelos alternativos (do mais específico para o mais geral) FINANCIAL_MODELS = [ { "name": "ProsusAI/finbert", "description": "FinBERT - Modelo especializado em sentimento financeiro", "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"} }, { "name": "mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis", "description": "DistilRoBERTa - Modelo leve para notícias financeiras", "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"} }, { "name": "soleimanian/financial-roberta-large-sentiment", "description": "Financial RoBERTa - Modelo robusto para textos financeiros", "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"} }, { "name": "cardiffnlp/twitter-roberta-base-sentiment-latest", "description": "RoBERTa - Modelo geral de sentimento (fallback)", "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"} } ] # Inicializar modelo de sentimento sentiment_pipeline = None current_model_info = None if TRANSFORMERS_AVAILABLE: for model_config in FINANCIAL_MODELS: try: print(f"🔄 Tentando carregar: {model_config['description']}") sentiment_pipeline = pipeline( "sentiment-analysis", model=model_config["name"], return_all_scores=True ) current_model_info = model_config print(f"✅ {model_config['description']} carregado com sucesso!") break except Exception as e: print(f"❌ Falha ao carregar {model_config['name']}: {e}") continue if sentiment_pipeline is None: print("❌ Nenhum modelo de sentimento pôde ser carregado.") TRANSFORMERS_AVAILABLE = False else: print("⚠️ Transformers não disponível. Executando sem análise de sentimento IA.") # Atualizar model_info global if current_model_info: model_info = {'available': True, 'description': current_model_info['description']} else: model_info = {'available': False, 'description': 'IA Indisponível'} def parse_market_data(text): """Extrai dados de mercado do texto de entrada usando engines ou fallback.""" if technical_engine and hasattr(technical_engine, 'parse_market_data'): return technical_engine.parse_market_data(text) # Fallback para modo standalone import re try: # Regex patterns para extrair dados price_match = re.search(r'P:([0-9,]+\.?\d*)', text) variation_match = re.search(r'\(([\+\-]\d+\.?\d*%?)\)', text) rsi_match = re.search(r'RSI:(\d+)', text) ema_match = re.search(r'EMA:(ALTA|BAIXA)', text) bb_match = re.search(r'BB:(DENTRO|SOBRE|ABAIXO|ACIMA)', text) vol_match = re.search(r'Vol:([0-9\.]+)', text) # Extrair valores price = float(price_match.group(1).replace(',', '')) if price_match else 0 variation_str = variation_match.group(1) if variation_match else "0" variation = float(variation_str.replace('%', '').replace('+', '')) if variation_str != "0" else 0 rsi = int(rsi_match.group(1)) if rsi_match else 50 ema_trend = ema_match.group(1) if ema_match else "NEUTRO" bb_position = bb_match.group(1) if bb_match else "DENTRO" volume = float(vol_match.group(1)) if vol_match else 0 return { 'price': price, 'variation': variation, 'rsi': rsi, 'ema_trend': ema_trend, 'bb_position': bb_position, 'volume': volume } except Exception as e: return None @log_requests_responses("analyze_sentiment") if log_requests_responses else lambda f: f @log_ai_model_usage("sentiment_analysis") if log_ai_model_usage else lambda f: f def analyze_sentiment(text): """Analisa o sentimento do texto usando engines ou fallback.""" if sentiment_engine and hasattr(sentiment_engine, 'analyze_sentiment'): return sentiment_engine.analyze_sentiment(text) # Fallback para modo standalone import re # Verificar se temos pipeline carregado no modo standalone if 'sentiment_pipeline' in globals() and sentiment_pipeline is not None: try: # Limpar e preparar o texto para análise clean_text = re.sub(r'[^\w\s\+\-\%\.]', ' ', text) clean_text = clean_text[:512] # Limitar tamanho para o modelo result = sentiment_pipeline(clean_text) # Processar resultado baseado no modelo if isinstance(result, list) and len(result) > 0: # Se return_all_scores=True, pegar o resultado com maior score if isinstance(result[0], list): predictions = result[0] best_prediction = max(predictions, key=lambda x: x['score']) else: best_prediction = result[0] # Mapear label usando o mapeamento do modelo atual label = best_prediction['label'] confidence = best_prediction['score'] # Usar mapeamento específico do modelo ou fallback genérico if 'current_model_info' in globals() and current_model_info and label in current_model_info['labels']: sentiment_label = current_model_info['labels'][label] else: # Fallback para mapeamento genérico label_lower = label.lower() if 'neg' in label_lower: sentiment_label = 'NEGATIVO' elif 'pos' in label_lower: sentiment_label = 'POSITIVO' else: sentiment_label = 'NEUTRO' return { 'sentiment': label.lower(), 'confidence': confidence, 'label': sentiment_label } except Exception as e: print(f"Erro na análise de sentimento: {e}") # Fallback padrão return { 'sentiment': 'neutral', 'confidence': 0.5, 'label': 'NEUTRO' } @measure_analysis_time if measure_analysis_time else lambda f: f @log_execution(LogCategory.MARKET_ANALYSIS, log_performance=True) if log_execution else lambda f: f def analyze_scalping_signals(market_data, original_text=""): """Analisa sinais para scalping usando engines ou fallback.""" if technical_engine and hasattr(technical_engine, 'analyze_scalping_signals'): return technical_engine.analyze_scalping_signals(market_data, original_text) # Fallback para modo standalone if not market_data: return { 'action': 'AGUARDAR', 'confidence': 0, 'signals': [], 'market_data': {}, 'sentiment': {'label': 'NEUTRO', 'confidence': 0.5} } # Análise de sentimento com FinBERT sentiment_analysis = analyze_sentiment(original_text) price = market_data['price'] variation = market_data['variation'] rsi = market_data['rsi'] ema_trend = market_data['ema_trend'] bb_position = market_data['bb_position'] volume = market_data['volume'] # Pontuação de confiança confidence_score = 0 signals = [] action = 'AGUARDAR' # === ANÁLISE RSI === if rsi <= 30: # Oversold signals.append("RSI em zona de sobrevenda ({}): COMPRA".format(rsi)) confidence_score += 25 if action == 'AGUARDAR': action = 'COMPRAR' elif rsi >= 70: # Overbought signals.append("RSI em zona de sobrecompra ({}): VENDA".format(rsi)) confidence_score += 25 if action == 'AGUARDAR': action = 'VENDER' elif 45 <= rsi <= 55: signals.append("RSI neutro ({}): aguardar confirmação".format(rsi)) # === ANÁLISE EMA === if ema_trend == 'ALTA': signals.append("Tendência EMA ALTA: viés de COMPRA") confidence_score += 15 if action == 'VENDER': confidence_score -= 10 # Conflito elif action == 'AGUARDAR': action = 'COMPRAR' elif ema_trend == 'BAIXA': signals.append("Tendência EMA BAIXA: viés de VENDA") confidence_score += 15 if action == 'COMPRAR': confidence_score -= 10 # Conflito elif action == 'AGUARDAR': action = 'VENDER' # === ANÁLISE BOLLINGER BANDS === if bb_position == 'ABAIXO': signals.append("Preço abaixo da banda inferior: COMPRA (reversão)") confidence_score += 20 if action == 'AGUARDAR': action = 'COMPRAR' elif bb_position == 'ACIMA' or bb_position == 'SOBRE': signals.append("Preço acima da banda superior: VENDA (reversão)") confidence_score += 20 if action == 'AGUARDAR': action = 'VENDER' elif bb_position == 'DENTRO': signals.append("Preço dentro das bandas: aguardar breakout") confidence_score += 5 # === ANÁLISE DE MOMENTUM (Variação) === if abs(variation) >= 0.05: # Movimento significativo if variation > 0: signals.append("Momentum positivo (+{:.2f}%): seguir tendência".format(variation)) confidence_score += 10 if action == 'VENDER': confidence_score -= 5 else: signals.append("Momentum negativo ({:.2f}%): seguir tendência".format(variation)) confidence_score += 10 if action == 'COMPRAR': confidence_score -= 5 # === ANÁLISE DE VOLUME === if volume > 1.0: # Volume alto signals.append("Volume alto ({:.1f}x): confirma movimento".format(volume)) confidence_score += 10 elif volume < 0.5: # Volume baixo signals.append("Volume baixo ({:.1f}x): cuidado com falsos sinais".format(volume)) confidence_score -= 5 # === ANÁLISE DE SENTIMENTO IA (FinBERT) === sentiment_label = sentiment_analysis['label'] sentiment_conf = sentiment_analysis['confidence'] if sentiment_label == 'POSITIVO': signals.append("🤖 IA Sentimento: POSITIVO ({:.1f}%): viés de COMPRA".format(sentiment_conf * 100)) confidence_score += int(sentiment_conf * 20) # Até 20 pontos if action == 'AGUARDAR': action = 'COMPRAR' elif action == 'VENDER': confidence_score -= 10 # Conflito com sentimento elif sentiment_label == 'NEGATIVO': signals.append("🤖 IA Sentimento: NEGATIVO ({:.1f}%): viés de VENDA".format(sentiment_conf * 100)) confidence_score += int(sentiment_conf * 20) # Até 20 pontos if action == 'AGUARDAR': action = 'VENDER' elif action == 'COMPRAR': confidence_score -= 10 # Conflito com sentimento else: signals.append("🤖 IA Sentimento: NEUTRO ({:.1f}%): sem viés claro".format(sentiment_conf * 100)) # === REGRAS ESPECÍFICAS DE SCALPING === # Scalping: RSI extremo + EMA contrária = reversão forte if (rsi <= 25 and ema_trend == 'BAIXA') or (rsi >= 75 and ema_trend == 'ALTA'): signals.append("🚨 SINAL FORTE: RSI extremo com EMA contrária - REVERSÃO") confidence_score += 30 # Scalping: RSI + BB alinhados if rsi <= 35 and bb_position == 'ABAIXO': signals.append("🎯 SETUP PERFEITO: RSI baixo + BB abaixo - COMPRA FORTE") confidence_score += 35 action = 'COMPRAR' elif rsi >= 65 and (bb_position == 'ACIMA' or bb_position == 'SOBRE'): signals.append("🎯 SETUP PERFEITO: RSI alto + BB acima - VENDA FORTE") confidence_score += 35 action = 'VENDER' # Limitar confiança confidence_score = min(confidence_score, 95) confidence_score = max(confidence_score, 10) return { 'action': action, 'confidence': confidence_score, 'signals': signals, 'market_data': market_data, 'sentiment': sentiment_analysis } def generate_trading_response(analysis): """Gera resposta formatada para trading com análise de sentimento IA""" action = analysis['action'] confidence = analysis['confidence'] signals = analysis.get('signals', []) market_data = analysis.get('market_data', {}) sentiment = analysis.get('sentiment', {'label': 'NEUTRO', 'confidence': 0.5}) # Emojis e cores baseados na ação if action == 'COMPRAR': emoji = "🟢" action_emoji = "📈" color = "verde" direction = "LONG" elif action == 'VENDER': emoji = "🔴" action_emoji = "📉" color = "vermelho" direction = "SHORT" else: emoji = "🟡" action_emoji = "⏸️" color = "amarelo" direction = "NEUTRO" # Emojis para sentimento sentiment_emojis = { 'POSITIVO': '😊💚', 'NEGATIVO': '😟💔', 'NEUTRO': '😐💛' } # Barra de confiança confidence_bars = "█" * int(confidence / 10) + "░" * (10 - int(confidence / 10)) # Classificação de confiança if confidence >= 80: conf_level = "MUITO ALTA" elif confidence >= 65: conf_level = "ALTA" elif confidence >= 50: conf_level = "MODERADA" else: conf_level = "BAIXA" # Timestamp timestamp = datetime.now().strftime("%H:%M:%S") response = f"""{emoji} **ANÁLISE SCALPING - WIN M1/M5** **⏰ Timestamp:** {timestamp} **📊 Instrumento:** WINV25 **🎯 DECISÃO DE TRADING:** • **Ação:** {action} {action_emoji} • **Direção:** {direction} • **Confiança:** {confidence:.0f}% ({conf_level}) • **Visual:** {confidence_bars} **🤖 ANÁLISE DE SENTIMENTO IA (FinBERT):** • **Sentimento:** {sentiment_emojis.get(sentiment['label'], '😐💛')} **{sentiment['label']}** ({sentiment['confidence']*100:.1f}%) **📈 DADOS DE MERCADO:** • **Preço:** {market_data.get('price', 'N/A'):,.0f} • **Variação:** {market_data.get('variation', 0):+.2f}% • **RSI:** {market_data.get('rsi', 'N/A')} • **EMA:** {market_data.get('ema_trend', 'N/A')} • **Bollinger:** {market_data.get('bb_position', 'N/A')} • **Volume:** {market_data.get('volume', 0):.1f}x **🔍 ANÁLISE TÉCNICA + IA:**""" for i, signal in enumerate(signals[:5], 1): # Máximo 5 sinais response += f"\n{i}. {signal}" # Recomendações específicas response += f"\n\n**⚡ RECOMENDAÇÕES SCALPING:**" if action == 'COMPRAR': response += f""" • **Stop Loss:** -{market_data.get('price', 0) * 0.0007:.0f} pts (0.07%) • **Take Profit:** +{market_data.get('price', 0) * 0.0015:.0f} pts (0.15%) • **Timeframe:** M1/M5 • **Risk/Reward:** 1:2""" elif action == 'VENDER': response += f""" • **Stop Loss:** +{market_data.get('price', 0) * 0.0007:.0f} pts (0.07%) • **Take Profit:** -{market_data.get('price', 0) * 0.0015:.0f} pts (0.15%) • **Timeframe:** M1/M5 • **Risk/Reward:** 1:2""" else: response += """ • **Aguardar:** Setup mais definido • **Monitorar:** Rompimentos de suporte/resistência • **Observar:** Confluência de sinais técnicos""" if confidence < 60: response += f"\n\n⚠️ **ATENÇÃO:** Confiança {conf_level} - Aguarde confirmação adicional!" response += f"\n\n---\n*🤖 Análise Scalping Automatizada - {timestamp}*" return response @log_requests_responses("process_trading_analysis") if log_requests_responses else lambda f: f @log_api_call("process_trading_analysis") if log_api_call else lambda f: f def process_trading_analysis(text): """Função principal que processa a análise de trading usando engines ou fallback.""" # Validação de entrada if ValidationUtils and hasattr(ValidationUtils, 'validate_text_input'): if not ValidationUtils.validate_text_input(text): return "⚠️ **Erro:** Entrada de texto inválida ou muito curta." else: # Fallback validation if not text or not text.strip(): return "⚠️ **Erro:** Nenhum dado de mercado fornecido para análise." try: # Verificar se é um log do bot if 'VAMPIRE TRADING BOT' in text or 'FIBONACCI AVANÇADO' in text: if VampireBotLogParser: log_parser = VampireBotLogParser() return log_parser.process_bot_log(text) else: # Fallback para processamento de log return process_bot_log_fallback(text) # Parse dos dados de mercado market_data = parse_market_data(text) if not market_data: return "⚠️ **Erro:** Não foi possível extrair dados válidos do texto fornecido." # Análise dos sinais de scalping analysis = analyze_scalping_signals(market_data, text) # Log da análise se disponível if LogUtils and hasattr(LogUtils, 'log_analysis_result'): LogUtils.log_analysis_result(analysis) # Gerar resposta formatada para a interface return generate_trading_response(analysis) except Exception as e: error_msg = f"Erro durante a análise: {str(e)}" if LogUtils and hasattr(LogUtils, 'log_error'): LogUtils.log_error(error_msg, "PROCESS_ANALYSIS") return f"❌ **Erro:** {error_msg}" def process_bot_log_fallback(text): """Processamento fallback para logs do bot quando VampireBotLogParser não está disponível.""" try: # Extrair informações básicas do log import re # Buscar por padrões específicos do bot fibonacci_match = re.search(r'FIBONACCI AVANÇADO.*?Nível: ([\d.]+)', text, re.DOTALL) action_match = re.search(r'(COMPRAR|VENDER|AGUARDAR)', text) confidence_match = re.search(r'Confiança: (\d+)%', text) if fibonacci_match or action_match: response = "🤖 **ANÁLISE DE LOG DO BOT DETECTADA**\n\n" if action_match: action = action_match.group(1) response += f"**Ação Recomendada:** {action}\n" if confidence_match: confidence = confidence_match.group(1) response += f"**Confiança:** {confidence}%\n" if fibonacci_match: fib_level = fibonacci_match.group(1) response += f"**Nível Fibonacci:** {fib_level}\n" response += "\n⚠️ **Nota:** Processamento básico de log. Para análise completa, instale os módulos avançados." return response # Se não conseguir extrair dados do log, processar como entrada normal return process_trading_analysis_basic(text) except Exception as e: return f"❌ **Erro no processamento do log:** {str(e)}" def process_trading_analysis_basic(text): """Processamento básico quando não há log do bot.""" market_data = parse_market_data(text) if not market_data: return "⚠️ **Erro:** Não foi possível extrair dados válidos do texto fornecido." analysis = analyze_scalping_signals(market_data, text) return generate_trading_response(analysis) # Função principal de análise para a interface @log_requests_responses("main_analysis_function") if log_requests_responses else lambda f: f @log_api_call("main_analysis_function") if log_api_call else lambda f: f def main_analysis_function(text: str) -> str: """Função principal de análise que será usada pela interface.""" result = process_trading_analysis(text) # Se o resultado é uma string (erro ou resposta formatada), retornar diretamente if isinstance(result, str): return result # Se é um dicionário (análise estruturada), formatar para string if isinstance(result, dict): return generate_trading_response(result) return "❌ **Erro:** Resultado de análise inválido." # Criar e configurar interface def create_interface(): """Cria interface usando a nova arquitetura modular.""" if GradioInterface: # Usar interface refatorada interface = GradioInterface( analysis_function=main_analysis_function, model_info=model_info ) return interface.create_interface() else: # Fallback para interface simples return create_fallback_interface() def create_fallback_interface(): """Cria interface simples para modo standalone.""" example_data = AppConfig.EXAMPLE_INPUT if AppConfig else """IBOV: 129.847 (+0,85%) RSI: 65 EMA 9: Tendência de alta Bollinger: Preço próximo à banda superior Volume: 2.3x da média Notícias: Mercado otimista com dados do PIB""" with gr.Blocks(title="📈 Análise de Mercado IA") as interface: gr.HTML("""
Sistema de análise técnica para scalping
Status do Monitor: {monitor_status}
Total de Eventos: {total_events}
Modelo IA: {model_info.get('description', 'N/A')}
Memória Disponível: {current_metrics.memory_available:.2f} GB
Uso do Disco: {current_metrics.disk_usage:.1f}%
Última atualização: {current_metrics.timestamp.strftime('%H:%M:%S')}
Total de Análises: {bot_stats.total_analyses}
Sucessos: {bot_stats.successful_analyses}
Falhas: {bot_stats.failed_analyses}
Taxa de Sucesso: {success_rate:.1f}%
Tempo Médio: {bot_stats.average_analysis_time:.2f}s
Alertas Fibonacci: {bot_stats.fibonacci_alerts_count}
Última Atualização:
{bot_stats.last_update.strftime('%H:%M:%S') if bot_stats.last_update else 'N/A'}