Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import json | |
| import re | |
| import sys | |
| import os | |
| from datetime import datetime | |
| # Adicionar o diretório raiz ao path | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| # Dashboard não disponível - app rodado no Hugging Face Spaces | |
| DASHBOARD_INTEGRATION_AVAILABLE = False | |
| # Importar apenas o sistema de IA para análise | |
| try: | |
| from src.main import ScalpingBot | |
| # Inicializar apenas para usar o sistema de IA | |
| trading_bot = ScalpingBot() | |
| print("✅ Sistema de IA BERT inicializado com sucesso") | |
| # Verificar se o sistema de IA está disponível | |
| if hasattr(trading_bot, 'hf_api') and trading_bot.hf_api: | |
| TRANSFORMERS_AVAILABLE = True | |
| current_model_info = { | |
| "name": "Hugging Face Spaces", | |
| "description": "IA FinBERT via Hugging Face Spaces", | |
| "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"} | |
| } | |
| print("✅ Sistema de IA BERT disponível para análise") | |
| else: | |
| TRANSFORMERS_AVAILABLE = False | |
| print("⚠️ Sistema de IA BERT não disponível") | |
| except ImportError as e: | |
| TRANSFORMERS_AVAILABLE = False | |
| trading_bot = None | |
| current_model_info = None | |
| print(f"⚠️ Sistema de IA não disponível: {e}") | |
| def get_sample_market_data(): | |
| """Retorna dados de exemplo para demonstração""" | |
| return { | |
| 'price': 116500.25, | |
| 'variation': 0.15, | |
| 'rsi': 68.5, | |
| 'ema_trend': 'ALTA', | |
| 'bb_position': 'DENTRO', | |
| 'volume': 1.8, | |
| 'symbol': 'BTCUSD', | |
| 'timestamp': datetime.now().isoformat() | |
| } | |
| def parse_market_data(text): | |
| """Extrai dados de mercado do texto de entrada""" | |
| 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 | |
| def analyze_sentiment_with_bert(market_data): | |
| """Analisa o sentimento usando o sistema de IA BERT com fallback robusto""" | |
| if not TRANSFORMERS_AVAILABLE or not trading_bot or not hasattr(trading_bot, 'hf_api'): | |
| print("⚠️ BERT não disponível - usando sistema robusto") | |
| return analyze_sentiment_robust(market_data) | |
| try: | |
| # Preparar dados para análise de IA | |
| ai_market_data = { | |
| 'symbol': market_data.get('symbol', 'BTCUSD'), | |
| 'current_price': market_data.get('price', 0), | |
| 'rsi': market_data.get('rsi', 50), | |
| 'ema_12': market_data.get('ema_12', 0), | |
| 'ema_26': market_data.get('ema_26', 0), | |
| 'bb_upper': market_data.get('bb_upper', 0), | |
| 'bb_middle': market_data.get('bb_middle', 0), | |
| 'bb_lower': market_data.get('bb_lower', 0), | |
| 'volume_ratio': market_data.get('volume', 1.0), | |
| 'trend': market_data.get('ema_trend', 'NEUTRO'), | |
| 'price_change_pct': market_data.get('variation', 0), | |
| 'timestamp': datetime.now().isoformat() | |
| } | |
| # Enviar para análise de IA | |
| ai_response = trading_bot.hf_api.send_analysis_request(ai_market_data) | |
| if ai_response: | |
| # Parse da resposta | |
| ai_sentiment, ai_confidence, ai_analysis = trading_bot.hf_api.parse_ai_response(ai_response) | |
| # Verificar se o BERT retornou dados estáticos (problema conhecido) | |
| if ("$0.00" in ai_analysis or "RSI: 50" in ai_analysis or | |
| "0.00%" in ai_analysis or "Volume: 0.0x" in ai_analysis): | |
| print("⚠️ BERT retornou dados estáticos - usando sistema robusto") | |
| return analyze_sentiment_robust(market_data) | |
| # Mapear para o formato esperado | |
| sentiment_mapping = { | |
| 'BULLISH': 'POSITIVO', | |
| 'BEARISH': 'NEGATIVO', | |
| 'NEUTRAL': 'NEUTRO', | |
| 'NEUTRO': 'NEUTRO', | |
| 'POSITIVO': 'POSITIVO', | |
| 'NEGATIVO': 'NEGATIVO' | |
| } | |
| sentiment_label = sentiment_mapping.get(ai_sentiment, 'NEUTRO') | |
| print(f"✅ BERT Sentimento: {sentiment_label} ({ai_confidence:.1f}%)") | |
| return { | |
| 'sentiment': ai_sentiment.lower(), | |
| 'confidence': ai_confidence / 100.0 if ai_confidence > 1 else ai_confidence, | |
| 'label': sentiment_label, | |
| 'analysis': ai_analysis | |
| } | |
| print("⚠️ BERT não respondeu - usando sistema robusto") | |
| return analyze_sentiment_robust(market_data) | |
| except Exception as e: | |
| print(f"⚠️ Erro na análise BERT: {e} - usando sistema robusto") | |
| return analyze_sentiment_robust(market_data) | |
| def analyze_sentiment_robust(market_data): | |
| """Sistema de análise robusto que funciona quando o BERT falha""" | |
| try: | |
| # Extrair dados | |
| price = market_data.get('price', 0) | |
| rsi = market_data.get('rsi', 50) | |
| ema_trend = market_data.get('ema_trend', 'NEUTRO') | |
| volume_ratio = market_data.get('volume', 1.0) | |
| price_change_pct = market_data.get('variation', 0) | |
| symbol = market_data.get('symbol', 'BTCUSD') | |
| print(f"📊 Análise Robusta {symbol}: Preço={price}, RSI={rsi}, Trend={ema_trend}") | |
| # Análise de sentimento baseada em indicadores | |
| sentiment_score = 0 | |
| confidence_score = 0 | |
| signals = [] | |
| # === ANÁLISE RSI === | |
| if rsi <= 30: | |
| sentiment_score += 30 # Muito bullish | |
| confidence_score += 25 | |
| signals.append(f"RSI {rsi} - Zona de sobrevenda (COMPRA)") | |
| elif rsi >= 70: | |
| sentiment_score -= 30 # Muito bearish | |
| confidence_score += 25 | |
| signals.append(f"RSI {rsi} - Zona de sobrecompra (VENDA)") | |
| elif 40 <= rsi <= 60: | |
| sentiment_score += 5 # Neutro | |
| confidence_score += 10 | |
| signals.append(f"RSI {rsi} - Zona neutra") | |
| # === ANÁLISE EMA === | |
| if ema_trend == 'ALTA': | |
| sentiment_score += 20 | |
| confidence_score += 15 | |
| signals.append("EMA em tendência de ALTA") | |
| elif ema_trend == 'BAIXA': | |
| sentiment_score -= 20 | |
| confidence_score += 15 | |
| signals.append("EMA em tendência de BAIXA") | |
| # === ANÁLISE DE VOLUME === | |
| if volume_ratio > 1.5: | |
| sentiment_score += 15 | |
| confidence_score += 10 | |
| signals.append(f"Volume alto ({volume_ratio:.1f}x) - Confirma movimento") | |
| elif volume_ratio < 0.8: | |
| sentiment_score -= 5 | |
| confidence_score += 5 | |
| signals.append(f"Volume baixo ({volume_ratio:.1f}x) - Cuidado") | |
| # === ANÁLISE DE MOMENTUM === | |
| if price_change_pct > 0.1: | |
| sentiment_score += 10 | |
| confidence_score += 10 | |
| signals.append(f"Momentum positivo (+{price_change_pct:.2f}%)") | |
| elif price_change_pct < -0.1: | |
| sentiment_score -= 10 | |
| confidence_score += 10 | |
| signals.append(f"Momentum negativo ({price_change_pct:.2f}%)") | |
| # === ANÁLISE DE BOLLINGER BANDS === | |
| bb_position = market_data.get('bb_position', 'DENTRO') | |
| if bb_position == 'ABAIXO': | |
| sentiment_score += 25 | |
| confidence_score += 20 | |
| signals.append("Preço abaixo da banda inferior - Reversão esperada") | |
| elif bb_position == 'ACIMA': | |
| sentiment_score -= 25 | |
| confidence_score += 20 | |
| signals.append("Preço acima da banda superior - Reversão esperada") | |
| # Determinar sentimento final | |
| if sentiment_score >= 30: | |
| sentiment = 'BULLISH' | |
| sentiment_label = 'POSITIVO' | |
| elif sentiment_score <= -30: | |
| sentiment = 'BEARISH' | |
| sentiment_label = 'NEGATIVO' | |
| else: | |
| sentiment = 'NEUTRAL' | |
| sentiment_label = 'NEUTRO' | |
| # Calcular confiança final | |
| confidence = min(95, max(15, confidence_score)) | |
| print(f"✅ Análise Robusta: {sentiment} ({confidence:.1f}%)") | |
| return { | |
| 'sentiment': sentiment.lower(), | |
| 'confidence': confidence / 100.0, | |
| 'label': sentiment_label, | |
| 'analysis': f'Análise robusta: {sentiment} ({confidence:.1f}%) - {len(signals)} sinais', | |
| 'signals': signals, | |
| 'sentiment_score': sentiment_score | |
| } | |
| except Exception as e: | |
| print(f"❌ Erro na análise robusta: {e}") | |
| return { | |
| 'sentiment': 'neutral', | |
| 'confidence': 0.5, | |
| 'label': 'NEUTRO', | |
| 'analysis': f'Erro na análise: {e}', | |
| 'signals': [], | |
| 'sentiment_score': 0 | |
| } | |
| def analyze_scalping_signals(market_data, original_text=""): | |
| """Analisa sinais para scalping baseado em indicadores técnicos e sentimento IA""" | |
| if not market_data: | |
| return { | |
| 'action': 'AGUARDAR', | |
| 'confidence': 0, | |
| 'reason': 'Dados insuficientes para análise', | |
| 'sentiment': {'label': 'NEUTRO', 'confidence': 0.5} | |
| } | |
| # Análise de sentimento com BERT | |
| sentiment_analysis = analyze_sentiment_with_bert(market_data) | |
| 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 - BTCUSD M1/M5** | |
| **⏰ Timestamp:** {timestamp} | |
| **📊 Instrumento:** BTCUSD | |
| **🎯 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'):,.2f} | |
| • **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.9993:.2f} (-0.07%) | |
| • **Take Profit:** ${market_data.get('price', 0) * 1.0015:.2f} (+0.15%) | |
| • **Timeframe:** M1/M5 | |
| • **Risk/Reward:** 1:2""" | |
| elif action == 'VENDER': | |
| response += f""" | |
| • **Stop Loss:** ${market_data.get('price', 0) * 1.0007:.2f} (+0.07%) | |
| • **Take Profit:** ${market_data.get('price', 0) * 0.9985:.2f} (-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 | |
| def process_trading_analysis(text): | |
| """Função principal que processa a análise de trading com BERT""" | |
| if text and text.strip(): | |
| # Parse dos dados de mercado do texto | |
| market_data = parse_market_data(text) | |
| data_source = "Dados Inseridos" | |
| if not market_data: | |
| return "⚠️ **Erro:** Formato de dados inválido. Use o formato: P:preço(variação%) | EMA:ALTA/BAIXA | RSI:valor | BB:posição | Vol:volume" | |
| else: | |
| return "⚠️ **Erro:** Nenhum dado de mercado fornecido. Insira dados no formato correto." | |
| # Análise dos sinais com BERT | |
| analysis = analyze_scalping_signals(market_data, text or f"Dados {data_source}") | |
| # Adicionar informação da fonte de dados | |
| analysis['data_source'] = data_source | |
| analysis['timestamp'] = datetime.now().isoformat() | |
| # Gerar resposta formatada | |
| response = generate_trading_response(analysis) | |
| # Dashboard não disponível - app rodado no Hugging Face Spaces | |
| print(f"✅ Análise BERT concluída - {data_source}") | |
| return response | |
| def get_sample_data_for_ui(): | |
| """Retorna dados de exemplo formatados para a interface""" | |
| sample_data = get_sample_market_data() | |
| formatted_data = f"P:{sample_data['price']}({sample_data['variation']:+.2f}%) | EMA:{sample_data['ema_trend']} | RSI:{sample_data['rsi']:.1f} | BB:{sample_data['bb_position']} | Vol:{sample_data['volume']:.1f}" | |
| return formatted_data | |
| # CSS customizado com Bootstrap 5 integrado | |
| custom_css = """ | |
| @import url('https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css'); | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Poppins:wght@300;400;500;600;700&display=swap'); | |
| :root { | |
| --bs-primary: #00d4ff; | |
| --bs-secondary: #ff6b6b; | |
| --bs-success: #00ff88; | |
| --bs-danger: #ff4757; | |
| --bs-warning: #ffa502; | |
| --bs-dark: #0a0a0a; | |
| --bs-light: #f0f0f0; | |
| --primary-bg: linear-gradient(135deg, #0a0a0a 0%, #1a0a1a 50%, #0a0a0a 100%); | |
| --card-bg: rgba(30, 30, 40, 0.98); | |
| --text-bright: #f0f0f0; | |
| --text-secondary: #c0c0c0; | |
| } | |
| body { | |
| font-family: 'Inter', 'Poppins', -apple-system, BlinkMacSystemFont, sans-serif !important; | |
| background: var(--primary-bg) !important; | |
| color: var(--text-bright) !important; | |
| min-height: 100vh; | |
| } | |
| body::before { | |
| content: ''; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-image: | |
| radial-gradient(circle at 25% 25%, rgba(255, 107, 107, 0.05) 0%, transparent 50%), | |
| radial-gradient(circle at 75% 75%, rgba(78, 205, 196, 0.05) 0%, transparent 50%); | |
| pointer-events: none; | |
| z-index: -1; | |
| } | |
| .gradio-container { | |
| max-width: 100% !important; | |
| padding: 0 !important; | |
| } | |
| .main-header { | |
| background: var(--card-bg); | |
| border: 1px solid rgba(0, 212, 255, 0.2); | |
| backdrop-filter: blur(20px); | |
| box-shadow: 0 25px 50px rgba(0, 0, 0, 0.6); | |
| } | |
| .main-header h1 { | |
| color: #ffffff !important; | |
| font-weight: 700 !important; | |
| font-family: 'Poppins', sans-serif !important; | |
| } | |
| .main-header h2, | |
| .main-header p, | |
| .main-header p *, | |
| .main-header p strong, | |
| .main-header p em, | |
| .main-header .text-white, | |
| .main-header .text-white *, | |
| .main-header .lead, | |
| .main-header .lead * { | |
| color: #ffffff !important; | |
| text-shadow: none !important; | |
| } | |
| .card-custom { | |
| background: var(--card-bg) !important; | |
| border: 1px solid rgba(255, 255, 255, 0.1) !important; | |
| backdrop-filter: blur(20px) !important; | |
| box-shadow: 0 25px 50px rgba(0, 0, 0, 0.6) !important; | |
| } | |
| .form-control { | |
| background: rgba(0, 0, 0, 0.9) !important; | |
| border: 1px solid rgba(0, 212, 255, 0.3) !important; | |
| color: var(--text-bright) !important; | |
| font-family: 'Inter', sans-serif !important; | |
| } | |
| .form-control:focus { | |
| background: rgba(0, 0, 0, 0.9) !important; | |
| border-color: var(--bs-primary) !important; | |
| box-shadow: 0 0 25px rgba(0, 212, 255, 0.3) !important; | |
| color: var(--text-bright) !important; | |
| } | |
| .form-control::placeholder { | |
| color: var(--text-secondary) !important; | |
| opacity: 0.7 !important; | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, var(--bs-primary), #0099cc) !important; | |
| border: none !important; | |
| font-weight: 600 !important; | |
| font-family: 'Inter', sans-serif !important; | |
| box-shadow: 0 4px 12px rgba(0, 212, 255, 0.3) !important; | |
| transition: all 0.3s ease !important; | |
| } | |
| .btn-primary:hover { | |
| transform: translateY(-2px) !important; | |
| box-shadow: 0 6px 16px rgba(0, 212, 255, 0.4) !important; | |
| filter: brightness(1.05) !important; | |
| } | |
| .btn-secondary { | |
| background: rgba(255, 255, 255, 0.1) !important; | |
| border: 1px solid rgba(0, 212, 255, 0.3) !important; | |
| color: var(--text-bright) !important; | |
| font-family: 'Inter', sans-serif !important; | |
| } | |
| .btn-secondary:hover { | |
| background: rgba(255, 255, 255, 0.2) !important; | |
| border-color: rgba(0, 212, 255, 0.5) !important; | |
| color: var(--text-bright) !important; | |
| transform: translateY(-1px) !important; | |
| } | |
| .output-area { | |
| background: rgba(0, 0, 0, 0.85) !important; | |
| border: 1px solid rgba(0, 212, 255, 0.2) !important; | |
| color: var(--text-bright) !important; | |
| font-family: 'Inter', sans-serif !important; | |
| max-height: 600px; | |
| overflow-y: auto; | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); | |
| } | |
| .text-gradient { | |
| color: #ffffff !important; | |
| } | |
| .strategy-card { | |
| background: rgba(0, 0, 0, 0.6); | |
| border: 2px solid rgba(0, 212, 255, 0.2); | |
| backdrop-filter: blur(10px); | |
| box-shadow: 0 0 20px rgba(0, 212, 255, 0.1); | |
| } | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: rgba(255, 255, 255, 0.1); | |
| border-radius: 10px; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: var(--bs-primary); | |
| border-radius: 10px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: var(--bs-secondary); | |
| } | |
| /* Responsividade Mobile */ | |
| @media (max-width: 768px) { | |
| .container-fluid { | |
| padding: 0.5rem !important; | |
| } | |
| .main-header { | |
| padding: 1.5rem !important; | |
| } | |
| .main-header h1 { | |
| font-size: 2rem !important; | |
| } | |
| .main-header h2 { | |
| font-size: 1.2rem !important; | |
| } | |
| .card-custom { | |
| margin-bottom: 1rem !important; | |
| } | |
| .btn-lg { | |
| font-size: 0.9rem !important; | |
| padding: 0.5rem 1rem !important; | |
| } | |
| .form-control { | |
| font-size: 14px !important; | |
| } | |
| .output-area { | |
| font-size: 13px !important; | |
| max-height: 400px !important; | |
| } | |
| .row.g-2 { | |
| margin-top: 0.5rem !important; | |
| } | |
| .btn-sm { | |
| font-size: 0.8rem !important; | |
| padding: 0.25rem 0.5rem !important; | |
| } | |
| } | |
| @media (max-width: 576px) { | |
| .main-header h1 { | |
| font-size: 1.5rem !important; | |
| } | |
| .main-header h2 { | |
| font-size: 1rem !important; | |
| } | |
| .main-header p { | |
| font-size: 0.9rem !important; | |
| } | |
| .card-header h3 { | |
| font-size: 1rem !important; | |
| } | |
| .btn { | |
| font-size: 0.8rem !important; | |
| } | |
| } | |
| /* Melhorias para tablets */ | |
| @media (min-width: 769px) and (max-width: 1024px) { | |
| .container-fluid { | |
| padding: 1rem !important; | |
| } | |
| .main-header { | |
| padding: 2rem !important; | |
| } | |
| } | |
| /* Classes utilitárias responsivas */ | |
| .mobile-view .gradio-container { | |
| padding: 0.5rem !important; | |
| } | |
| .mobile-view .main-header { | |
| margin-bottom: 1rem !important; | |
| } | |
| /* Ajustes para elementos Gradio */ | |
| .gradio-container .gr-textbox, | |
| .gradio-container textarea { | |
| border-radius: 0.375rem !important; | |
| } | |
| .gradio-container .gr-button { | |
| border-radius: 0.375rem !important; | |
| } | |
| .gradio-container .gr-markdown { | |
| border-radius: 0.375rem !important; | |
| } | |
| """ | |
| # Interface Gradio com Bootstrap 5 | |
| with gr.Blocks(css=custom_css, title="🤖 Serviço de Análise BERT - BotCS", theme=gr.themes.Base()) as demo: | |
| # Container principal Bootstrap | |
| gr.HTML(""" | |
| <div class="container-fluid"> | |
| <!-- Cabeçalho principal --> | |
| <div class="row justify-content-center mb-4"> | |
| <div class="col-12"> | |
| <div class="main-header card-custom rounded-4 p-4 text-center"> | |
| <h1 class="display-4 fw-bold mb-3 text-white">🤖 SERVIÇO DE ANÁLISE BERT</h1> | |
| <h2 class="h4 mb-3 text-white">📈 BotCS - Análise de Indicadores com IA FinBERT</h2> | |
| <p class="lead mb-2 text-white"><strong>Serviço especializado em análise de indicadores técnicos com IA</strong></p> | |
| <p class="mb-0 text-white"><em>🎯 RSI • 📊 EMA • 📉 Bollinger Bands • 📈 Volume • ⚡ Momentum • 🤖 FinBERT AI</em></p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| """) | |
| # Layout principal responsivo | |
| with gr.Row(): | |
| # Coluna esquerda - Input | |
| with gr.Column(scale=1): | |
| gr.HTML(""" | |
| <div class="card card-custom rounded-3 mb-3"> | |
| <div class="card-header bg-transparent border-0"> | |
| <h3 class="h5 fw-bold mb-0" style="color: #ffffff !important;">📊 INDICADORES TÉCNICOS</h3> | |
| </div> | |
| </div> | |
| """) | |
| input_text = gr.Textbox( | |
| label="Insira os indicadores técnicos para análise...", | |
| placeholder="Exemplo: P:115510.61(+0.05%) | EMA:ALTA | RSI:28 | BB:ABAIXO | Vol:1.2", | |
| lines=4, | |
| elem_classes=["form-control"] | |
| ) | |
| with gr.Row(): | |
| analyze_btn = gr.Button( | |
| "🤖 ANALISAR COM BERT", | |
| variant="primary", | |
| elem_classes=["btn", "btn-primary", "btn-lg"] | |
| ) | |
| get_sample_data_btn = gr.Button( | |
| "📊 DADOS EXEMPLO", | |
| variant="secondary", | |
| elem_classes=["btn", "btn-info"] | |
| ) | |
| clear_btn = gr.Button( | |
| "🗑️ LIMPAR", | |
| variant="secondary", | |
| elem_classes=["btn", "btn-secondary"] | |
| ) | |
| # Botões de exemplo responsivos | |
| gr.HTML(""" | |
| <div class="row g-2 mt-2"> | |
| <div class="col-12 col-md-4"> | |
| <button class="btn btn-outline-success btn-sm w-100" id="example-buy">📈 Exemplo COMPRA</button> | |
| </div> | |
| <div class="col-12 col-md-4"> | |
| <button class="btn btn-outline-danger btn-sm w-100" id="example-sell">📉 Exemplo VENDA</button> | |
| </div> | |
| <div class="col-12 col-md-4"> | |
| <button class="btn btn-outline-warning btn-sm w-100" id="example-neutral">⏸️ Exemplo NEUTRO</button> | |
| </div> | |
| </div> | |
| """) | |
| example1_btn = gr.Button("📈 Exemplo COMPRA", visible=False) | |
| example2_btn = gr.Button("📉 Exemplo VENDA", visible=False) | |
| example3_btn = gr.Button("⏸️ Exemplo NEUTRO", visible=False) | |
| # Coluna direita - Output | |
| with gr.Column(scale=1): | |
| gr.HTML(""" | |
| <div class="card card-custom rounded-3 mb-3"> | |
| <div class="card-header bg-transparent border-0"> | |
| <h3 class="h5 fw-bold mb-0" style="color: #ffffff !important;">🤖 ANÁLISE BERT - AGUARDANDO INDICADORES</h3> | |
| </div> | |
| </div> | |
| """) | |
| # Seção de instruções destacada | |
| gr.HTML(""" | |
| <div class="alert alert-info border-0 shadow-lg mb-3" style="background: linear-gradient(135deg, rgba(0, 212, 255, 0.15), rgba(255, 107, 107, 0.15)); border: 2px solid rgba(0, 212, 255, 0.3); backdrop-filter: blur(10px);"> | |
| <div class="text-center mb-3"> | |
| <h4 class="fw-bold mb-2" style="color: #ffffff !important;">📋 COMO USAR O SERVIÇO DE ANÁLISE BERT</h4> | |
| </div> | |
| <div class="row"> | |
| <div class="col-12"> | |
| <p class="lead text-light mb-3 text-center" style="color: #ffffff !important;"> | |
| <strong style="color: #ffffff !important;">Insira os indicadores técnicos para análise com IA FinBERT + Sistema Robusto:</strong> | |
| </p> | |
| </div> | |
| </div> | |
| <div class="row g-2"> | |
| <div class="col-12 col-md-6"> | |
| <div class="d-flex align-items-center mb-2"> | |
| <span class="badge bg-success me-2">✅</span> | |
| <span class="text-light" style="color: #ffffff !important;"><strong style="color: #ffffff !important;">Sinal de entrada</strong> (COMPRAR/VENDER/AGUARDAR)</span> | |
| </div> | |
| <div class="d-flex align-items-center mb-2"> | |
| <span class="badge bg-success me-2">✅</span> | |
| <span class="text-light" style="color: #ffffff !important;"><strong style="color: #ffffff !important;">Nível de confiança</strong> baseado em múltiplos indicadores</span> | |
| </div> | |
| <div class="d-flex align-items-center mb-2"> | |
| <span class="badge bg-success me-2">✅</span> | |
| <span class="text-light" style="color: #ffffff !important;"><strong style="color: #ffffff !important;">Stop Loss e Take Profit</strong> calculados automaticamente</span> | |
| </div> | |
| </div> | |
| <div class="col-12 col-md-6"> | |
| <div class="d-flex align-items-center mb-2"> | |
| <span class="badge bg-success me-2">✅</span> | |
| <span class="text-light" style="color: #ffffff !important;"><strong style="color: #ffffff !important;">Análise de sentimento FinBERT</strong> + Sistema Robusto de fallback</span> | |
| </div> | |
| <div class="d-flex align-items-center mb-2"> | |
| <span class="badge bg-success me-2">✅</span> | |
| <span class="text-light" style="color: #ffffff !important;"><strong style="color: #ffffff !important;">Recomendações específicas</strong> para scalping M1/M5</span> | |
| </div> | |
| </div> | |
| </div> | |
| <hr class="my-3" style="border-color: rgba(0, 212, 255, 0.3);"> | |
| <div class="text-center"> | |
| <p class="mb-0 text-light" style="color: #ffffff !important;"> | |
| <strong style="color: #ffffff !important;">📊 Indicadores analisados:</strong> | |
| <span class="badge bg-primary me-1">RSI</span> | |
| <span class="badge bg-primary me-1">EMA</span> | |
| <span class="badge bg-primary me-1">Bollinger Bands</span> | |
| <span class="badge bg-primary me-1">Volume</span> | |
| <span class="badge bg-primary me-1">Momentum</span> | |
| <span class="badge bg-success">🤖 FinBERT AI</span> | |
| <span class="badge bg-warning">🔧 Sistema Robusto</span> | |
| </p> | |
| </div> | |
| </div> | |
| """) | |
| output_text = gr.Markdown( | |
| value="""<div style="color: #ffffff !important;"><strong style="color: #ffffff !important;">🤖 SERVIÇO DE ANÁLISE BERT - AGUARDANDO INDICADORES</strong></div> | |
| <div style="color: #ffffff !important;">⏳ Aguardando indicadores técnicos para análise...</div> | |
| <div style="color: #ffffff !important;">🎯 <strong style="color: #ffffff !important;">Sistema BERT pronto para análise de indicadores!</strong></div>""", | |
| elem_classes=["output-area", "p-3", "rounded-3"] | |
| ) | |
| # JavaScript para conectar botões Bootstrap aos botões Gradio ocultos | |
| gr.HTML(""" | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Conectar botões de exemplo Bootstrap aos botões Gradio ocultos | |
| const exampleBuy = document.getElementById('example-buy'); | |
| const exampleSell = document.getElementById('example-sell'); | |
| const exampleNeutral = document.getElementById('example-neutral'); | |
| if (exampleBuy) { | |
| exampleBuy.addEventListener('click', function() { | |
| // Encontrar o botão de exemplo COMPRA oculto | |
| const gradioButtons = document.querySelectorAll('button'); | |
| for (let btn of gradioButtons) { | |
| if (btn.textContent.includes('📈 Exemplo COMPRA') && btn.style.display === 'none') { | |
| btn.click(); | |
| break; | |
| } | |
| } | |
| }); | |
| } | |
| if (exampleSell) { | |
| exampleSell.addEventListener('click', function() { | |
| // Encontrar o botão de exemplo VENDA oculto | |
| const gradioButtons = document.querySelectorAll('button'); | |
| for (let btn of gradioButtons) { | |
| if (btn.textContent.includes('📉 Exemplo VENDA') && btn.style.display === 'none') { | |
| btn.click(); | |
| break; | |
| } | |
| } | |
| }); | |
| } | |
| if (exampleNeutral) { | |
| exampleNeutral.addEventListener('click', function() { | |
| // Encontrar o botão de exemplo NEUTRO oculto | |
| const gradioButtons = document.querySelectorAll('button'); | |
| for (let btn of gradioButtons) { | |
| if (btn.textContent.includes('⏸️ Exemplo NEUTRO') && btn.style.display === 'none') { | |
| btn.click(); | |
| break; | |
| } | |
| } | |
| }); | |
| } | |
| // Adicionar classes Bootstrap aos elementos Gradio | |
| const textareas = document.querySelectorAll('textarea'); | |
| textareas.forEach(textarea => { | |
| textarea.classList.add('form-control'); | |
| }); | |
| const buttons = document.querySelectorAll('button'); | |
| buttons.forEach(button => { | |
| if (!button.classList.contains('btn')) { | |
| button.classList.add('btn'); | |
| } | |
| }); | |
| // Responsividade adicional | |
| function handleResize() { | |
| const container = document.querySelector('.gradio-container'); | |
| if (window.innerWidth < 768) { | |
| container?.classList.add('mobile-view'); | |
| } else { | |
| container?.classList.remove('mobile-view'); | |
| } | |
| } | |
| window.addEventListener('resize', handleResize); | |
| handleResize(); | |
| }); | |
| </script> | |
| """) | |
| # Event handlers | |
| analyze_btn.click( | |
| fn=process_trading_analysis, | |
| inputs=input_text, | |
| outputs=output_text | |
| ) | |
| get_sample_data_btn.click( | |
| fn=get_sample_data_for_ui, | |
| outputs=input_text | |
| ) | |
| clear_btn.click( | |
| lambda: ("", """**🤖 SERVIÇO DE ANÁLISE BERT - BotCS** | |
| ✅ **Análise técnica completa** com IA FinBERT | |
| ✅ **Indicadores técnicos** analisados | |
| ✅ **Sinais de trading** gerados | |
| ✅ **Recomendações específicas** para scalping | |
| ✅ **Análise de sentimento** com IA | |
| ✅ **Serviço online** no Hugging Face Spaces | |
| **Indicadores analisados:** RSI, EMA, Bollinger Bands, Volume, Momentum"""), | |
| outputs=[input_text, output_text] | |
| ) | |
| # Exemplos (botões ocultos conectados via JavaScript) | |
| example1_btn.click( | |
| lambda: "Análise BTCUSD M1 | P:115510.61(+0.05%) | EMA:ALTA(115520.00/115500.00) | RSI:28 | BB:ABAIXO | Vol:1.2", | |
| outputs=input_text | |
| ) | |
| example2_btn.click( | |
| lambda: "Análise BTCUSD M5 | P:115580.00(-0.03%) | EMA:BAIXA(115520.00/115560.00) | RSI:78 | BB:ACIMA | Vol:1.5", | |
| outputs=input_text | |
| ) | |
| example3_btn.click( | |
| lambda: "Análise BTCUSD M1 | P:115550.00(+0.01%) | EMA:ALTA(115540.00/115530.00) | RSI:52 | BB:DENTRO | Vol:0.6", | |
| outputs=input_text | |
| ) | |
| # Status do sistema | |
| gr.HTML(""" | |
| <div class="row g-3 mb-3"> | |
| <div class="col-12 col-md-6"> | |
| <div class="card card-custom rounded-3"> | |
| <div class="card-body text-center"> | |
| <h5 class="card-title text-white">🤖 IA FinBERT</h5> | |
| <p class="card-text text-white">""" + ("✅ Ativa" if TRANSFORMERS_AVAILABLE and current_model_info else "❌ Indisponível") + """</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-12 col-md-6"> | |
| <div class="card card-custom rounded-3"> | |
| <div class="card-body text-center"> | |
| <h5 class="card-title text-white">📊 Análise Técnica</h5> | |
| <p class="card-text text-white">✅ Disponível</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| """) | |
| # Mostrar modelo de IA ativo | |
| if TRANSFORMERS_AVAILABLE and current_model_info: | |
| gr.HTML(f""" | |
| <div class="alert alert-success border-0 shadow-lg mb-3" style="background: linear-gradient(135deg, rgba(0, 255, 136, 0.15), rgba(78, 205, 196, 0.15)); border: 2px solid rgba(0, 255, 136, 0.3); backdrop-filter: blur(10px);"> | |
| <div class="text-center"> | |
| <h4 class="fw-bold mb-2" style="color: #ffffff !important;">🤖 IA ATIVA: {current_model_info['description']}</h4> | |
| <p class="mb-0" style="color: #ffffff !important;">Análise de sentimento financeiro com modelo especializado</p> | |
| </div> | |
| </div> | |
| """) | |
| else: | |
| gr.HTML(""" | |
| <div class="alert alert-warning border-0 shadow-lg mb-3" style="background: linear-gradient(135deg, rgba(255, 165, 2, 0.15), rgba(255, 107, 107, 0.15)); border: 2px solid rgba(255, 165, 2, 0.3); backdrop-filter: blur(10px);"> | |
| <div class="text-center"> | |
| <h4 class="fw-bold mb-2" style="color: #ffffff !important;">⚠️ IA INDISPONÍVEL</h4> | |
| <p class="mb-0" style="color: #ffffff !important;">Executando apenas análise técnica tradicional</p> | |
| </div> | |
| </div> | |
| """) | |
| # Footer com estratégias | |
| footer_ai_info = "" | |
| if TRANSFORMERS_AVAILABLE and current_model_info: | |
| footer_ai_info = f"🤖 {current_model_info['description']}" | |
| else: | |
| footer_ai_info = "🤖 IA Indisponível" | |
| gr.HTML(f""" | |
| <div style="margin-top: 30px; padding: 35px; background: rgba(30, 30, 40, 0.98); color: #f8f9fa; border-radius: 25px; box-shadow: 0 30px 60px rgba(0, 0, 0, 0.6), 0 0 30px rgba(0, 212, 255, 0.1); border: 2px solid rgba(0, 212, 255, 0.3); backdrop-filter: blur(20px);"> | |
| <h3 style="text-align: center; color: #f0f0f0; font-size: 2.2rem; margin-bottom: 30px; font-family: 'Poppins', sans-serif; font-weight: 700; text-shadow: 0 2px 6px rgba(0, 212, 255, 0.3); letter-spacing: 1px;"> | |
| 🎯 ESTRATÉGIA DE SCALPING AVANÇADA | |
| </h3> | |
| <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 25px;"> | |
| <div style="background: rgba(0, 0, 0, 0.6); padding: 30px; border-radius: 20px; border: 2px solid rgba(0, 212, 255, 0.2); box-shadow: 0 0 20px rgba(0, 212, 255, 0.1); backdrop-filter: blur(10px);"> | |
| <h4 style="color: #f0f0f0; margin-bottom: 20px; font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 1.3rem; text-shadow: 0 1px 4px rgba(0, 255, 136, 0.25);">📈 SINAIS DE COMPRA:</h4> | |
| <ul style="list-style: none; padding: 0;"> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ RSI ≤ 30 (Sobrevenda)</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ Preço abaixo da Banda Inferior</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ EMA em tendência de alta</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ Volume acima da média</li> | |
| </ul> | |
| </div> | |
| <div style="background: rgba(0, 0, 0, 0.6); padding: 30px; border-radius: 20px; border: 2px solid rgba(0, 212, 255, 0.2); box-shadow: 0 0 20px rgba(0, 212, 255, 0.1); backdrop-filter: blur(10px);"> | |
| <h4 style="color: #f0f0f0; margin-bottom: 20px; font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 1.3rem; text-shadow: 0 1px 4px rgba(255, 71, 87, 0.25);">📉 SINAIS DE VENDA:</h4> | |
| <ul style="list-style: none; padding: 0;"> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ RSI ≥ 70 (Sobrecompra)</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ Preço acima da Banda Superior</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ EMA em tendência de baixa</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ Volume confirmando movimento</li> | |
| </ul> | |
| </div> | |
| <div style="background: rgba(0, 0, 0, 0.6); padding: 30px; border-radius: 20px; border: 2px solid rgba(0, 212, 255, 0.2); box-shadow: 0 0 20px rgba(0, 212, 255, 0.1); backdrop-filter: blur(10px);"> | |
| <h4 style="color: #f0f0f0; margin-bottom: 20px; font-family: 'Poppins', sans-serif; font-weight: 600; font-size: 1.3rem; text-shadow: 0 1px 4px rgba(255, 165, 2, 0.25);">⚙️ CONFIGURAÇÕES:</h4> | |
| <ul style="list-style: none; padding: 0;"> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ Timeframes: M1 e M5</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ Stop Loss: 0.07% do preço (BTCUSD)</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ Take Profit: 0.15% do preço (BTCUSD)</li> | |
| <li style="padding: 10px 0; color: #c8c8c8; font-weight: 500; letter-spacing: 0.3px;">▶ Risk/Reward: 1:2</li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div style="text-align: center; margin-top: 40px; padding-top: 25px; border-top: 2px solid rgba(0, 212, 255, 0.3); box-shadow: 0 -5px 15px rgba(0, 212, 255, 0.1);"> | |
| <p style="color: #ffffff; font-size: 1.1rem; font-weight: 500; letter-spacing: 0.3px;">🤖 <strong style="color: #ffffff !important;">Serviço de Análise BERT BotCS</strong> - IA FinBERT + Análise Técnica + Hugging Face Spaces</p> | |
| <p style="color: #ffffff; font-size: 1rem; margin-top: 10px; font-weight: 500; letter-spacing: 0.3px;">🧠 <strong style="color: #ffffff !important;">Modelo Ativo:</strong> {footer_ai_info}</p> | |
| <p style="color: #ffffff; font-size: 1rem; margin-top: 15px; font-weight: 500; text-shadow: 0 1px 3px rgba(0, 212, 255, 0.2);">⚠️ <em style="color: #ffffff !important;">Trading envolve riscos. Use sempre gerenciamento de risco adequado.</em></p> | |
| </div> | |
| </div> | |
| """) | |
| if __name__ == "__main__": | |
| # App rodado no Hugging Face Spaces - sem dashboard local | |
| print("🚀 Iniciando Serviço de Análise BERT no Hugging Face Spaces") | |
| demo.launch() |