torxyton commited on
Commit
7f335a2
·
1 Parent(s): 51220c3

Initial commit: Complete Fibonacci analysis application with Gradio interface

Browse files
Files changed (43) hide show
  1. __init__.py +1 -0
  2. __pycache__/market_analysis.cpython-313.pyc +0 -0
  3. advanced_market_processing.py +466 -0
  4. app.py +566 -16
  5. config/__init__.py +25 -0
  6. config/__pycache__/__init__.cpython-313.pyc +0 -0
  7. config/__pycache__/config.cpython-313.pyc +0 -0
  8. config/config.py +209 -0
  9. docs/README.md +86 -0
  10. docs/api-reference.md +569 -0
  11. docs/architecture.md +350 -0
  12. docs/configuration.md +606 -0
  13. docs/developer-guide.md +963 -0
  14. docs/installation.md +216 -0
  15. docs/troubleshooting.md +679 -0
  16. fibonacci_analysis.py +528 -0
  17. log_parser.py +335 -0
  18. real_time_integration.py +358 -0
  19. src/__init__.py +0 -0
  20. src/__pycache__/__init__.cpython-313.pyc +0 -0
  21. src/analysis/__init__.py +0 -0
  22. src/analysis/__pycache__/__init__.cpython-313.pyc +0 -0
  23. src/analysis/__pycache__/market_analysis.cpython-313.pyc +0 -0
  24. src/analysis/fibonacci_analysis.py +528 -0
  25. market_analysis.py → src/analysis/market_analysis.py +144 -3
  26. src/analysis/sentiment_analysis.py +331 -0
  27. src/core/__init__.py +0 -0
  28. src/core/log_parser.py +335 -0
  29. src/core/performance_monitor.py +366 -0
  30. src/integrations/__init__.py +0 -0
  31. src/integrations/real_time_integration.py +358 -0
  32. src/ui/__init__.py +0 -0
  33. src/ui/__pycache__/gradio_interface.cpython-313.pyc +0 -0
  34. src/ui/gradio_interface.py +828 -0
  35. src/utils/__init__.py +0 -0
  36. src/utils/__pycache__/__init__.cpython-313.pyc +0 -0
  37. src/utils/__pycache__/utils.cpython-313.pyc +0 -0
  38. src/utils/utils.py +330 -0
  39. tests/__init__.py +0 -0
  40. tests/integration/__init__.py +0 -0
  41. tests/unit/__init__.py +0 -0
  42. text +76 -0
  43. ui.py +359 -17
__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Arquivo __init__.py para tornar o diretório raiz um pacote Python
__pycache__/market_analysis.cpython-313.pyc CHANGED
Binary files a/__pycache__/market_analysis.cpython-313.pyc and b/__pycache__/market_analysis.cpython-313.pyc differ
 
advanced_market_processing.py ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+ from typing import Dict, List, Optional, Tuple, Any
4
+ from dataclasses import dataclass
5
+ import logging
6
+ from datetime import datetime
7
+
8
+ # Configurar logging
9
+ logging.basicConfig(level=logging.INFO)
10
+ logger = logging.getLogger(__name__)
11
+
12
+ @dataclass
13
+ class SwingPoint:
14
+ """Representa um ponto de swing no mercado"""
15
+ price: float
16
+ timestamp: datetime
17
+ type: str # 'high' ou 'low'
18
+ strength: float # 0-1, força do swing
19
+ volume: Optional[float] = None
20
+
21
+ @dataclass
22
+ class ConfluenceZone:
23
+ """Representa uma zona de confluência"""
24
+ price_level: float
25
+ strength: float # 0-1
26
+ factors: List[str] # Fatores que contribuem para a confluência
27
+ type: str # 'support' ou 'resistance'
28
+ reliability: float # 0-1
29
+
30
+ @dataclass
31
+ class HarmonicPattern:
32
+ """Representa um padrão harmônico"""
33
+ name: str # 'Gartley', 'Butterfly', 'Bat', 'Crab'
34
+ points: Dict[str, SwingPoint] # X, A, B, C, D
35
+ completion_level: float
36
+ target_levels: List[float]
37
+ stop_level: float
38
+ reliability: float # 0-1
39
+
40
+ class SwingPointDetector:
41
+ """Detector de pontos de swing"""
42
+
43
+ def __init__(self, lookback_period: int = 5, min_strength: float = 0.3):
44
+ self.lookback_period = lookback_period
45
+ self.min_strength = min_strength
46
+
47
+ def detect_swing_points(self, prices: np.ndarray, volumes: Optional[np.ndarray] = None) -> List[SwingPoint]:
48
+ """Detecta pontos de swing em uma série de preços"""
49
+ try:
50
+ swing_points = []
51
+
52
+ for i in range(self.lookback_period, len(prices) - self.lookback_period):
53
+ # Verificar swing high
54
+ if self._is_swing_high(prices, i):
55
+ strength = self._calculate_swing_strength(prices, i, 'high')
56
+ if strength >= self.min_strength:
57
+ swing_points.append(SwingPoint(
58
+ price=prices[i],
59
+ timestamp=datetime.now(),
60
+ type='high',
61
+ strength=strength,
62
+ volume=volumes[i] if volumes is not None else None
63
+ ))
64
+
65
+ # Verificar swing low
66
+ elif self._is_swing_low(prices, i):
67
+ strength = self._calculate_swing_strength(prices, i, 'low')
68
+ if strength >= self.min_strength:
69
+ swing_points.append(SwingPoint(
70
+ price=prices[i],
71
+ timestamp=datetime.now(),
72
+ type='low',
73
+ strength=strength,
74
+ volume=volumes[i] if volumes is not None else None
75
+ ))
76
+
77
+ return swing_points
78
+
79
+ except Exception as e:
80
+ logger.error(f"Erro ao detectar swing points: {e}")
81
+ return []
82
+
83
+ def _is_swing_high(self, prices: np.ndarray, index: int) -> bool:
84
+ """Verifica se um ponto é um swing high"""
85
+ current_price = prices[index]
86
+ left_prices = prices[index - self.lookback_period:index]
87
+ right_prices = prices[index + 1:index + self.lookback_period + 1]
88
+
89
+ return (current_price > np.max(left_prices) and
90
+ current_price > np.max(right_prices))
91
+
92
+ def _is_swing_low(self, prices: np.ndarray, index: int) -> bool:
93
+ """Verifica se um ponto é um swing low"""
94
+ current_price = prices[index]
95
+ left_prices = prices[index - self.lookback_period:index]
96
+ right_prices = prices[index + 1:index + self.lookback_period + 1]
97
+
98
+ return (current_price < np.min(left_prices) and
99
+ current_price < np.min(right_prices))
100
+
101
+ def _calculate_swing_strength(self, prices: np.ndarray, index: int, swing_type: str) -> float:
102
+ """Calcula a força de um swing point"""
103
+ try:
104
+ current_price = prices[index]
105
+ surrounding_prices = np.concatenate([
106
+ prices[max(0, index - self.lookback_period * 2):index],
107
+ prices[index + 1:min(len(prices), index + self.lookback_period * 2 + 1)]
108
+ ])
109
+
110
+ if swing_type == 'high':
111
+ price_diff = current_price - np.mean(surrounding_prices)
112
+ max_diff = np.max(surrounding_prices) - np.min(surrounding_prices)
113
+ else:
114
+ price_diff = np.mean(surrounding_prices) - current_price
115
+ max_diff = np.max(surrounding_prices) - np.min(surrounding_prices)
116
+
117
+ return min(1.0, max(0.0, price_diff / max_diff)) if max_diff > 0 else 0.0
118
+
119
+ except Exception:
120
+ return 0.0
121
+
122
+ class ConfluenceZoneAnalyzer:
123
+ """Analisador de zonas de confluência"""
124
+
125
+ def __init__(self, tolerance: float = 0.001):
126
+ self.tolerance = tolerance # Tolerância para agrupar níveis próximos
127
+
128
+ def analyze_confluence_zones(self,
129
+ swing_points: List[SwingPoint],
130
+ fibonacci_levels: Dict[str, float],
131
+ support_resistance_levels: List[float]) -> List[ConfluenceZone]:
132
+ """Analisa zonas de confluência baseado em múltiplos fatores"""
133
+ try:
134
+ confluence_zones = []
135
+ all_levels = []
136
+
137
+ # Coletar todos os níveis relevantes
138
+ for swing in swing_points:
139
+ all_levels.append(('swing', swing.price, swing.strength))
140
+
141
+ for fib_name, fib_level in fibonacci_levels.items():
142
+ all_levels.append(('fibonacci', fib_level, 0.7))
143
+
144
+ for sr_level in support_resistance_levels:
145
+ all_levels.append(('support_resistance', sr_level, 0.8))
146
+
147
+ # Agrupar níveis próximos
148
+ grouped_levels = self._group_nearby_levels(all_levels)
149
+
150
+ # Criar zonas de confluência
151
+ for group in grouped_levels:
152
+ if len(group) >= 2: # Pelo menos 2 fatores para confluência
153
+ avg_price = np.mean([level[1] for level in group])
154
+ factors = [level[0] for level in group]
155
+ strength = np.mean([level[2] for level in group])
156
+
157
+ # Determinar tipo (support/resistance)
158
+ zone_type = self._determine_zone_type(group, swing_points)
159
+
160
+ confluence_zones.append(ConfluenceZone(
161
+ price_level=avg_price,
162
+ strength=strength,
163
+ factors=factors,
164
+ type=zone_type,
165
+ reliability=min(1.0, len(group) * 0.3)
166
+ ))
167
+
168
+ return sorted(confluence_zones, key=lambda x: x.strength, reverse=True)
169
+
170
+ except Exception as e:
171
+ logger.error(f"Erro ao analisar zonas de confluência: {e}")
172
+ return []
173
+
174
+ def _group_nearby_levels(self, levels: List[Tuple]) -> List[List[Tuple]]:
175
+ """Agrupa níveis próximos baseado na tolerância"""
176
+ if not levels:
177
+ return []
178
+
179
+ sorted_levels = sorted(levels, key=lambda x: x[1])
180
+ groups = []
181
+ current_group = [sorted_levels[0]]
182
+
183
+ for level in sorted_levels[1:]:
184
+ if abs(level[1] - current_group[-1][1]) / current_group[-1][1] <= self.tolerance:
185
+ current_group.append(level)
186
+ else:
187
+ groups.append(current_group)
188
+ current_group = [level]
189
+
190
+ groups.append(current_group)
191
+ return groups
192
+
193
+ def _determine_zone_type(self, group: List[Tuple], swing_points: List[SwingPoint]) -> str:
194
+ """Determina se a zona é de suporte ou resistência"""
195
+ # Lógica simplificada - pode ser melhorada
196
+ swing_highs = [s for s in swing_points if s.type == 'high']
197
+ swing_lows = [s for s in swing_points if s.type == 'low']
198
+
199
+ avg_price = np.mean([level[1] for level in group])
200
+
201
+ if swing_lows:
202
+ avg_low = np.mean([s.price for s in swing_lows])
203
+ if abs(avg_price - avg_low) < abs(avg_price - np.mean([s.price for s in swing_highs]) if swing_highs else avg_price):
204
+ return 'support'
205
+
206
+ return 'resistance'
207
+
208
+ class HarmonicPatternDetector:
209
+ """Detector de padrões harmônicos"""
210
+
211
+ def __init__(self):
212
+ self.pattern_ratios = {
213
+ 'Gartley': {
214
+ 'XA_AB': (0.618, 0.618),
215
+ 'AB_BC': (0.382, 0.886),
216
+ 'BC_CD': (1.13, 1.618),
217
+ 'XA_AD': (0.786, 0.786)
218
+ },
219
+ 'Butterfly': {
220
+ 'XA_AB': (0.786, 0.786),
221
+ 'AB_BC': (0.382, 0.886),
222
+ 'BC_CD': (1.618, 2.618),
223
+ 'XA_AD': (1.27, 1.618)
224
+ },
225
+ 'Bat': {
226
+ 'XA_AB': (0.382, 0.5),
227
+ 'AB_BC': (0.382, 0.886),
228
+ 'BC_CD': (1.618, 2.618),
229
+ 'XA_AD': (0.886, 0.886)
230
+ },
231
+ 'Crab': {
232
+ 'XA_AB': (0.382, 0.618),
233
+ 'AB_BC': (0.382, 0.886),
234
+ 'BC_CD': (2.24, 3.618),
235
+ 'XA_AD': (1.618, 1.618)
236
+ }
237
+ }
238
+
239
+ def detect_harmonic_patterns(self, swing_points: List[SwingPoint]) -> List[HarmonicPattern]:
240
+ """Detecta padrões harmônicos nos swing points"""
241
+ try:
242
+ patterns = []
243
+
244
+ if len(swing_points) < 5:
245
+ return patterns
246
+
247
+ # Procurar por sequências de 5 pontos (X, A, B, C, D)
248
+ for i in range(len(swing_points) - 4):
249
+ points = swing_points[i:i+5]
250
+
251
+ # Verificar se a sequência alterna entre high/low
252
+ if self._is_valid_sequence(points):
253
+ for pattern_name, ratios in self.pattern_ratios.items():
254
+ pattern = self._check_pattern(points, pattern_name, ratios)
255
+ if pattern:
256
+ patterns.append(pattern)
257
+
258
+ return patterns
259
+
260
+ except Exception as e:
261
+ logger.error(f"Erro ao detectar padrões harmônicos: {e}")
262
+ return []
263
+
264
+ def _is_valid_sequence(self, points: List[SwingPoint]) -> bool:
265
+ """Verifica se a sequência de pontos é válida para padrões harmônicos"""
266
+ types = [p.type for p in points]
267
+
268
+ # Deve alternar entre high e low
269
+ for i in range(1, len(types)):
270
+ if types[i] == types[i-1]:
271
+ return False
272
+
273
+ return True
274
+
275
+ def _check_pattern(self, points: List[SwingPoint], pattern_name: str, ratios: Dict) -> Optional[HarmonicPattern]:
276
+ """Verifica se os pontos formam um padrão harmônico específico"""
277
+ try:
278
+ X, A, B, C, D = points
279
+
280
+ # Calcular distâncias
281
+ XA = abs(A.price - X.price)
282
+ AB = abs(B.price - A.price)
283
+ BC = abs(C.price - B.price)
284
+ CD = abs(D.price - C.price)
285
+ XD = abs(D.price - X.price)
286
+
287
+ # Verificar ratios
288
+ tolerance = 0.05 # 5% de tolerância
289
+
290
+ ratios_to_check = [
291
+ ('XA_AB', AB / XA if XA != 0 else 0),
292
+ ('AB_BC', BC / AB if AB != 0 else 0),
293
+ ('BC_CD', CD / BC if BC != 0 else 0),
294
+ ('XA_AD', XD / XA if XA != 0 else 0)
295
+ ]
296
+
297
+ valid_ratios = 0
298
+ for ratio_name, calculated_ratio in ratios_to_check:
299
+ expected_min, expected_max = ratios[ratio_name]
300
+ if expected_min * (1 - tolerance) <= calculated_ratio <= expected_max * (1 + tolerance):
301
+ valid_ratios += 1
302
+
303
+ # Padrão válido se pelo menos 3 dos 4 ratios estiverem corretos
304
+ if valid_ratios >= 3:
305
+ # Calcular níveis de target e stop
306
+ target_levels = self._calculate_targets(X, A, B, C, D)
307
+ stop_level = self._calculate_stop_level(X, A, B, C, D)
308
+
309
+ return HarmonicPattern(
310
+ name=pattern_name,
311
+ points={'X': X, 'A': A, 'B': B, 'C': C, 'D': D},
312
+ completion_level=D.price,
313
+ target_levels=target_levels,
314
+ stop_level=stop_level,
315
+ reliability=valid_ratios / 4.0
316
+ )
317
+
318
+ return None
319
+
320
+ except Exception as e:
321
+ logger.error(f"Erro ao verificar padrão {pattern_name}: {e}")
322
+ return None
323
+
324
+ def _calculate_targets(self, X, A, B, C, D) -> List[float]:
325
+ """Calcula níveis de target para o padrão"""
326
+ try:
327
+ XA = abs(A.price - X.price)
328
+
329
+ # Targets baseados em retracements de Fibonacci
330
+ if D.type == 'low': # Padrão bullish
331
+ target1 = D.price + (XA * 0.382)
332
+ target2 = D.price + (XA * 0.618)
333
+ target3 = D.price + XA
334
+ else: # Padrão bearish
335
+ target1 = D.price - (XA * 0.382)
336
+ target2 = D.price - (XA * 0.618)
337
+ target3 = D.price - XA
338
+
339
+ return [target1, target2, target3]
340
+
341
+ except Exception:
342
+ return [D.price]
343
+
344
+ def _calculate_stop_level(self, X, A, B, C, D) -> float:
345
+ """Calcula nível de stop loss para o padrão"""
346
+ try:
347
+ # Stop além do ponto D
348
+ if D.type == 'low': # Padrão bullish
349
+ return D.price * 0.99 # 1% abaixo
350
+ else: # Padrão bearish
351
+ return D.price * 1.01 # 1% acima
352
+ except Exception:
353
+ return D.price
354
+
355
+ class AdvancedMarketProcessor:
356
+ """Processador avançado de dados de mercado"""
357
+
358
+ def __init__(self):
359
+ self.swing_detector = SwingPointDetector()
360
+ self.confluence_analyzer = ConfluenceZoneAnalyzer()
361
+ self.harmonic_detector = HarmonicPatternDetector()
362
+ logger.info("AdvancedMarketProcessor inicializado")
363
+
364
+ def process_market_data(self,
365
+ prices: np.ndarray,
366
+ volumes: Optional[np.ndarray] = None,
367
+ fibonacci_levels: Optional[Dict[str, float]] = None,
368
+ support_resistance_levels: Optional[List[float]] = None) -> Dict[str, Any]:
369
+ """Processa dados de mercado com análise avançada"""
370
+ try:
371
+ # Detectar swing points
372
+ swing_points = self.swing_detector.detect_swing_points(prices, volumes)
373
+
374
+ # Analisar zonas de confluência
375
+ confluence_zones = []
376
+ if fibonacci_levels or support_resistance_levels:
377
+ confluence_zones = self.confluence_analyzer.analyze_confluence_zones(
378
+ swing_points,
379
+ fibonacci_levels or {},
380
+ support_resistance_levels or []
381
+ )
382
+
383
+ # Detectar padrões harmônicos
384
+ harmonic_patterns = self.harmonic_detector.detect_harmonic_patterns(swing_points)
385
+
386
+ # Compilar resultado
387
+ result = {
388
+ 'swing_points': {
389
+ 'count': len(swing_points),
390
+ 'highs': [sp for sp in swing_points if sp.type == 'high'],
391
+ 'lows': [sp for sp in swing_points if sp.type == 'low'],
392
+ 'avg_strength': np.mean([sp.strength for sp in swing_points]) if swing_points else 0
393
+ },
394
+ 'confluence_zones': {
395
+ 'count': len(confluence_zones),
396
+ 'zones': confluence_zones,
397
+ 'strongest_zone': max(confluence_zones, key=lambda x: x.strength) if confluence_zones else None
398
+ },
399
+ 'harmonic_patterns': {
400
+ 'count': len(harmonic_patterns),
401
+ 'patterns': harmonic_patterns,
402
+ 'most_reliable': max(harmonic_patterns, key=lambda x: x.reliability) if harmonic_patterns else None
403
+ },
404
+ 'market_structure': self._analyze_market_structure(swing_points),
405
+ 'key_levels': self._identify_key_levels(swing_points, confluence_zones)
406
+ }
407
+
408
+ return result
409
+
410
+ except Exception as e:
411
+ logger.error(f"Erro no processamento avançado de mercado: {e}")
412
+ return {
413
+ 'swing_points': {'count': 0, 'highs': [], 'lows': [], 'avg_strength': 0},
414
+ 'confluence_zones': {'count': 0, 'zones': [], 'strongest_zone': None},
415
+ 'harmonic_patterns': {'count': 0, 'patterns': [], 'most_reliable': None},
416
+ 'market_structure': 'UNKNOWN',
417
+ 'key_levels': []
418
+ }
419
+
420
+ def _analyze_market_structure(self, swing_points: List[SwingPoint]) -> str:
421
+ """Analisa a estrutura do mercado baseado nos swing points"""
422
+ try:
423
+ if len(swing_points) < 4:
424
+ return 'INSUFFICIENT_DATA'
425
+
426
+ recent_points = swing_points[-4:]
427
+ highs = [sp for sp in recent_points if sp.type == 'high']
428
+ lows = [sp for sp in recent_points if sp.type == 'low']
429
+
430
+ if len(highs) >= 2 and len(lows) >= 2:
431
+ # Verificar tendência dos highs e lows
432
+ high_trend = 'UP' if highs[-1].price > highs[0].price else 'DOWN'
433
+ low_trend = 'UP' if lows[-1].price > lows[0].price else 'DOWN'
434
+
435
+ if high_trend == 'UP' and low_trend == 'UP':
436
+ return 'UPTREND'
437
+ elif high_trend == 'DOWN' and low_trend == 'DOWN':
438
+ return 'DOWNTREND'
439
+ else:
440
+ return 'SIDEWAYS'
441
+
442
+ return 'CONSOLIDATION'
443
+
444
+ except Exception:
445
+ return 'UNKNOWN'
446
+
447
+ def _identify_key_levels(self, swing_points: List[SwingPoint], confluence_zones: List[ConfluenceZone]) -> List[float]:
448
+ """Identifica níveis-chave baseado em swing points e confluências"""
449
+ try:
450
+ key_levels = []
451
+
452
+ # Adicionar swing points mais fortes
453
+ strong_swings = [sp for sp in swing_points if sp.strength > 0.7]
454
+ key_levels.extend([sp.price for sp in strong_swings])
455
+
456
+ # Adicionar zonas de confluência mais fortes
457
+ strong_zones = [cz for cz in confluence_zones if cz.strength > 0.6]
458
+ key_levels.extend([cz.price_level for cz in strong_zones])
459
+
460
+ # Remover duplicatas e ordenar
461
+ key_levels = sorted(list(set(key_levels)))
462
+
463
+ return key_levels[:10] # Retornar apenas os 10 mais importantes
464
+
465
+ except Exception:
466
+ return []
app.py CHANGED
@@ -6,11 +6,15 @@ from datetime import datetime
6
 
7
  # Importar módulos refatorados
8
  try:
9
- from config import AppConfig
10
- from market_analysis import TechnicalAnalysisEngine
11
- from sentiment_analysis import SentimentAnalysisEngine
12
- from ui import GradioInterface
13
- from utils import LogUtils, ValidationUtils
 
 
 
 
14
  except ImportError:
15
  # Fallback para modo standalone se módulos não existirem
16
  print("⚠️ Módulos refatorados não encontrados. Executando em modo standalone.")
@@ -20,12 +24,27 @@ except ImportError:
20
  GradioInterface = None
21
  LogUtils = None
22
  ValidationUtils = None
 
 
 
 
 
 
 
23
 
24
  # Engines de análise
25
  technical_engine = None
26
  sentiment_engine = None
 
27
  model_info = {'available': False, 'description': 'IA Indisponível'}
28
 
 
 
 
 
 
 
 
29
  # Inicializar engines
30
  def initialize_engines():
31
  """Inicializa engines de análise técnica e de sentimento."""
@@ -483,6 +502,15 @@ def process_trading_analysis(text):
483
  return "⚠️ **Erro:** Nenhum dado de mercado fornecido para análise."
484
 
485
  try:
 
 
 
 
 
 
 
 
 
486
  # Parse dos dados de mercado
487
  market_data = parse_market_data(text)
488
 
@@ -506,6 +534,50 @@ def process_trading_analysis(text):
506
 
507
  return f"❌ **Erro:** {error_msg}"
508
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
  # Função principal de análise para a interface
510
  def main_analysis_function(text: str) -> str:
511
  """Função principal de análise que será usada pela interface."""
@@ -552,26 +624,504 @@ Notícias: Mercado otimista com dados do PIB"""
552
  </div>
553
  """)
554
 
555
- with gr.Row():
556
- with gr.Column(scale=2):
557
- market_input = gr.Textbox(
558
- label="Dados do Mercado",
559
- placeholder=example_data,
560
- lines=8
561
- )
562
- analyze_btn = gr.Button("🔍 Analisar", variant="primary")
563
-
564
- with gr.Column(scale=3):
565
- result_output = gr.HTML()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
566
 
567
  analyze_btn.click(
568
  fn=main_analysis_function,
569
  inputs=[market_input],
570
  outputs=[result_output]
571
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572
 
573
  return interface
574
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
  # Inicializar engines e criar interface
576
  initialize_engines()
577
  demo = create_interface()
 
6
 
7
  # Importar módulos refatorados
8
  try:
9
+ from config.config import AppConfig
10
+ from src.analysis.market_analysis import TechnicalAnalysisEngine
11
+ from src.analysis.sentiment_analysis import SentimentAnalysisEngine
12
+ from src.ui.gradio_interface import GradioInterface
13
+ from src.utils.utils import LogUtils, ValidationUtils
14
+ from src.core.log_parser import VampireBotLogParser
15
+ from src.analysis.fibonacci_analysis import AdvancedFibonacciEngine
16
+ from src.integrations.real_time_integration import RealTimeIntegration, BotEvent
17
+ from src.core.performance_monitor import PerformanceMonitor, measure_analysis_time
18
  except ImportError:
19
  # Fallback para modo standalone se módulos não existirem
20
  print("⚠️ Módulos refatorados não encontrados. Executando em modo standalone.")
 
24
  GradioInterface = None
25
  LogUtils = None
26
  ValidationUtils = None
27
+ VampireBotLogParser = None
28
+ AdvancedFibonacciEngine = None
29
+ AdvancedMarketProcessor = None
30
+ RealTimeIntegration = None
31
+ BotEvent = None
32
+ PerformanceMonitor = None
33
+ measure_analysis_time = None
34
 
35
  # Engines de análise
36
  technical_engine = None
37
  sentiment_engine = None
38
+ real_time_integration = None
39
  model_info = {'available': False, 'description': 'IA Indisponível'}
40
 
41
+ # Estado global para eventos em tempo real
42
+ recent_events = []
43
+ max_events_display = 50
44
+
45
+ # Monitor de performance global
46
+ performance_monitor = PerformanceMonitor() if PerformanceMonitor else None
47
+
48
  # Inicializar engines
49
  def initialize_engines():
50
  """Inicializa engines de análise técnica e de sentimento."""
 
502
  return "⚠️ **Erro:** Nenhum dado de mercado fornecido para análise."
503
 
504
  try:
505
+ # Verificar se é um log do bot
506
+ if 'VAMPIRE TRADING BOT' in text or 'FIBONACCI AVANÇADO' in text:
507
+ if VampireBotLogParser:
508
+ log_parser = VampireBotLogParser()
509
+ return log_parser.process_bot_log(text)
510
+ else:
511
+ # Fallback para processamento de log
512
+ return process_bot_log_fallback(text)
513
+
514
  # Parse dos dados de mercado
515
  market_data = parse_market_data(text)
516
 
 
534
 
535
  return f"❌ **Erro:** {error_msg}"
536
 
537
+ def process_bot_log_fallback(text):
538
+ """Processamento fallback para logs do bot quando VampireBotLogParser não está disponível."""
539
+ try:
540
+ # Extrair informações básicas do log
541
+ import re
542
+
543
+ # Buscar por padrões específicos do bot
544
+ fibonacci_match = re.search(r'FIBONACCI AVANÇADO.*?Nível: ([\d.]+)', text, re.DOTALL)
545
+ action_match = re.search(r'(COMPRAR|VENDER|AGUARDAR)', text)
546
+ confidence_match = re.search(r'Confiança: (\d+)%', text)
547
+
548
+ if fibonacci_match or action_match:
549
+ response = "🤖 **ANÁLISE DE LOG DO BOT DETECTADA**\n\n"
550
+
551
+ if action_match:
552
+ action = action_match.group(1)
553
+ response += f"**Ação Recomendada:** {action}\n"
554
+
555
+ if confidence_match:
556
+ confidence = confidence_match.group(1)
557
+ response += f"**Confiança:** {confidence}%\n"
558
+
559
+ if fibonacci_match:
560
+ fib_level = fibonacci_match.group(1)
561
+ response += f"**Nível Fibonacci:** {fib_level}\n"
562
+
563
+ response += "\n⚠️ **Nota:** Processamento básico de log. Para análise completa, instale os módulos avançados."
564
+ return response
565
+
566
+ # Se não conseguir extrair dados do log, processar como entrada normal
567
+ return process_trading_analysis_basic(text)
568
+
569
+ except Exception as e:
570
+ return f"❌ **Erro no processamento do log:** {str(e)}"
571
+
572
+ def process_trading_analysis_basic(text):
573
+ """Processamento básico quando não há log do bot."""
574
+ market_data = parse_market_data(text)
575
+ if not market_data:
576
+ return "⚠️ **Erro:** Não foi possível extrair dados válidos do texto fornecido."
577
+
578
+ analysis = analyze_scalping_signals(market_data, text)
579
+ return generate_trading_response(analysis)
580
+
581
  # Função principal de análise para a interface
582
  def main_analysis_function(text: str) -> str:
583
  """Função principal de análise que será usada pela interface."""
 
624
  </div>
625
  """)
626
 
627
+ with gr.Tab("📊 Análise de Mercado"):
628
+ with gr.Row():
629
+ with gr.Column(scale=2):
630
+ market_input = gr.Textbox(
631
+ label="Dados do Mercado",
632
+ placeholder=example_data,
633
+ lines=8
634
+ )
635
+ analyze_btn = gr.Button("🔍 Analisar", variant="primary")
636
+
637
+ with gr.Column(scale=3):
638
+ result_output = gr.HTML()
639
+
640
+ with gr.Tab("🤖 Monitor do Bot"):
641
+ with gr.Row():
642
+ with gr.Column(scale=1):
643
+ gr.Markdown("### 🔄 Status do Sistema")
644
+
645
+ with gr.Row():
646
+ start_monitor_btn = gr.Button("▶️ Iniciar Monitor", variant="primary")
647
+ stop_monitor_btn = gr.Button("⏹️ Parar Monitor", variant="secondary")
648
+
649
+ monitor_status = gr.HTML(
650
+ value="<div style='color: #666;'>Monitor parado</div>"
651
+ )
652
+
653
+ gr.Markdown("### ⚡ Eventos Recentes")
654
+ recent_events_display = gr.HTML(
655
+ value="<div style='color: #666;'>Nenhum evento recente</div>"
656
+ )
657
+
658
+ with gr.Column(scale=2):
659
+ gr.Markdown("### 📊 Análise em Tempo Real")
660
+ real_time_analysis = gr.HTML(
661
+ value="<div style='text-align: center; color: #666; padding: 40px;'>Aguardando dados do bot...</div>"
662
+ )
663
+
664
+ log_file_path = gr.Textbox(
665
+ value="d:/hugging_face_spaces/text",
666
+ label="📁 Caminho do Arquivo de Log"
667
+ )
668
+
669
+ check_interval = gr.Slider(
670
+ minimum=0.5,
671
+ maximum=10.0,
672
+ value=1.0,
673
+ step=0.5,
674
+ label="⏱️ Intervalo de Verificação (segundos)"
675
+ )
676
+
677
+ with gr.Tab("📈 Performance"):
678
+ with gr.Row():
679
+ with gr.Column(scale=1):
680
+ gr.Markdown("### 🔧 Controles de Performance")
681
+
682
+ with gr.Row():
683
+ start_perf_btn = gr.Button("▶️ Iniciar Monitoramento", variant="primary")
684
+ stop_perf_btn = gr.Button("⏹️ Parar Monitoramento", variant="secondary")
685
+
686
+ perf_status = gr.HTML(
687
+ value="<div style='color: #666;'>Monitoramento parado</div>"
688
+ )
689
+
690
+ with gr.Row():
691
+ reset_stats_btn = gr.Button("🔄 Reset Estatísticas", variant="secondary")
692
+ export_metrics_btn = gr.Button("💾 Exportar Métricas", variant="secondary")
693
+
694
+ gr.Markdown("### 🚨 Alertas de Performance")
695
+ performance_alerts = gr.HTML(
696
+ value="<div style='color: #666;'>Nenhum alerta ativo</div>"
697
+ )
698
+
699
+ with gr.Column(scale=2):
700
+ gr.Markdown("### 📊 Métricas do Sistema")
701
+ system_metrics = gr.HTML(
702
+ value="<div style='text-align: center; color: #666; padding: 40px;'>Aguardando métricas...</div>"
703
+ )
704
+
705
+ gr.Markdown("### 🤖 Estatísticas do Bot")
706
+ bot_statistics = gr.HTML(
707
+ value="<div style='text-align: center; color: #666; padding: 40px;'>Aguardando estatísticas...</div>"
708
+ )
709
+
710
+ gr.Markdown("### 💡 Sugestões de Otimização")
711
+ optimization_suggestions = gr.HTML(
712
+ value="<div style='color: #666;'>Execute análises para obter sugestões</div>"
713
+ )
714
 
715
  analyze_btn.click(
716
  fn=main_analysis_function,
717
  inputs=[market_input],
718
  outputs=[result_output]
719
  )
720
+
721
+ start_monitor_btn.click(
722
+ fn=start_real_time_monitor,
723
+ inputs=[log_file_path, check_interval],
724
+ outputs=[monitor_status]
725
+ )
726
+
727
+ stop_monitor_btn.click(
728
+ fn=stop_real_time_monitor,
729
+ outputs=[monitor_status]
730
+ )
731
+
732
+ # Event handlers para performance
733
+ start_perf_btn.click(
734
+ fn=start_performance_monitoring,
735
+ outputs=[perf_status]
736
+ )
737
+
738
+ stop_perf_btn.click(
739
+ fn=stop_performance_monitoring,
740
+ outputs=[perf_status]
741
+ )
742
+
743
+ reset_stats_btn.click(
744
+ fn=reset_performance_stats,
745
+ outputs=[bot_statistics]
746
+ )
747
+
748
+ export_metrics_btn.click(
749
+ fn=export_performance_metrics,
750
+ outputs=[perf_status]
751
+ )
752
+
753
+ # Auto-refresh para eventos em tempo real
754
+ interface.load(
755
+ fn=get_recent_events_display,
756
+ outputs=[recent_events_display]
757
+ )
758
+
759
+ interface.load(
760
+ fn=get_real_time_analysis_display,
761
+ outputs=[real_time_analysis]
762
+ )
763
+
764
+ # Auto-refresh para métricas de performance
765
+ interface.load(
766
+ fn=get_system_metrics_display,
767
+ outputs=[system_metrics]
768
+ )
769
+
770
+ interface.load(
771
+ fn=get_bot_statistics_display,
772
+ outputs=[bot_statistics]
773
+ )
774
+
775
+ interface.load(
776
+ fn=get_performance_alerts_display,
777
+ outputs=[performance_alerts]
778
+ )
779
+
780
+ interface.load(
781
+ fn=get_optimization_suggestions_display,
782
+ outputs=[optimization_suggestions]
783
+ )
784
 
785
  return interface
786
 
787
+ # Funções para integração em tempo real
788
+ def start_real_time_monitor(log_path: str, interval: float):
789
+ """Inicia o monitor em tempo real."""
790
+ global real_time_integration, recent_events
791
+
792
+ try:
793
+ if RealTimeIntegration:
794
+ real_time_integration = RealTimeIntegration(log_path)
795
+ real_time_integration.config.check_interval = interval
796
+
797
+ # Callback para capturar eventos
798
+ def event_handler(event):
799
+ global recent_events
800
+ event_dict = {
801
+ 'timestamp': event.timestamp.strftime('%H:%M:%S'),
802
+ 'type': event.event_type,
803
+ 'data': event.data,
804
+ 'priority': event.priority
805
+ }
806
+ recent_events.append(event_dict)
807
+
808
+ # Manter apenas os últimos eventos
809
+ if len(recent_events) > max_events_display:
810
+ recent_events = recent_events[-max_events_display:]
811
+
812
+ real_time_integration.processor.subscribe(event_handler)
813
+ real_time_integration.start()
814
+ return "<div style='color: green;'>✅ Monitor iniciado com sucesso</div>"
815
+ else:
816
+ return "<div style='color: orange;'>⚠️ Integração em tempo real não disponível</div>"
817
+ except Exception as e:
818
+ return f"<div style='color: red;'>❌ Erro ao iniciar monitor: {str(e)}</div>"
819
+
820
+ def stop_real_time_monitor():
821
+ """Para o monitor em tempo real."""
822
+ global real_time_integration
823
+
824
+ try:
825
+ if real_time_integration:
826
+ real_time_integration.stop()
827
+ real_time_integration = None
828
+ return "<div style='color: orange;'>⏹️ Monitor parado</div>"
829
+ else:
830
+ return "<div style='color: #666;'>Monitor já estava parado</div>"
831
+ except Exception as e:
832
+ return f"<div style='color: red;'>❌ Erro ao parar monitor: {str(e)}</div>"
833
+
834
+ def get_recent_events_display():
835
+ """Obtém display dos eventos recentes."""
836
+ global recent_events
837
+
838
+ if not recent_events:
839
+ return "<div style='color: #666;'>Nenhum evento recente</div>"
840
+
841
+ html = "<div style='max-height: 300px; overflow-y: auto;'>"
842
+ for event in recent_events[-10:]: # Últimos 10 eventos
843
+ timestamp = event.get('timestamp', 'N/A')
844
+ event_type = event.get('type', 'UNKNOWN')
845
+ data = event.get('data', {})
846
+
847
+ color = {
848
+ 'COMPRAR': 'green',
849
+ 'VENDER': 'red',
850
+ 'AGUARDAR': 'orange'
851
+ }.get(event_type, '#666')
852
+
853
+ html += f"<div style='border-left: 3px solid {color}; padding: 5px; margin: 5px 0; background: #f9f9f9;'>"
854
+ html += f"<strong>{timestamp}</strong> - {event_type}<br>"
855
+ if 'action' in data:
856
+ html += f"Ação: {data['action']}<br>"
857
+ if 'confidence' in data:
858
+ html += f"Confiança: {data['confidence']}%"
859
+ html += "</div>"
860
+
861
+ html += "</div>"
862
+ return html
863
+
864
+ def get_real_time_analysis_display():
865
+ """Obtém display da análise em tempo real."""
866
+ global real_time_integration, recent_events
867
+
868
+ if not real_time_integration or not recent_events:
869
+ return "<div style='text-align: center; color: #666; padding: 40px;'>Aguardando dados do bot...</div>"
870
+
871
+ # Pegar o evento mais recente
872
+ latest_event = recent_events[-1] if recent_events else None
873
+
874
+ if not latest_event:
875
+ return "<div style='text-align: center; color: #666; padding: 40px;'>Nenhum evento disponível</div>"
876
+
877
+ # Processar o evento mais recente
878
+ try:
879
+ event_data = latest_event.get('data', {})
880
+ if 'raw_text' in event_data:
881
+ analysis_result = main_analysis_function(event_data['raw_text'])
882
+ return f"<div style='border: 2px solid #4CAF50; padding: 15px; border-radius: 10px;'>{analysis_result}</div>"
883
+ else:
884
+ return "<div style='color: #666;'>Dados insuficientes para análise</div>"
885
+ except Exception as e:
886
+ return f"<div style='color: red;'>Erro na análise: {str(e)}</div>"
887
+
888
+ def get_system_stats():
889
+ """Obtém estatísticas do sistema."""
890
+ global recent_events, real_time_integration
891
+
892
+ total_events = len(recent_events)
893
+ monitor_status = "Ativo" if real_time_integration else "Inativo"
894
+
895
+ # Contar tipos de eventos
896
+ event_counts = {}
897
+ for event in recent_events:
898
+ event_type = event.get('type', 'UNKNOWN')
899
+ event_counts[event_type] = event_counts.get(event_type, 0) + 1
900
+
901
+ html = f"""
902
+ <div style='padding: 20px;'>
903
+ <h3>📊 Estatísticas do Sistema</h3>
904
+ <p><strong>Status do Monitor:</strong> {monitor_status}</p>
905
+ <p><strong>Total de Eventos:</strong> {total_events}</p>
906
+ <p><strong>Modelo IA:</strong> {model_info.get('description', 'N/A')}</p>
907
+
908
+ <h4>📈 Distribuição de Eventos:</h4>
909
+ <ul>
910
+ """
911
+
912
+ for event_type, count in event_counts.items():
913
+ html += f"<li>{event_type}: {count}</li>"
914
+
915
+ html += "</ul></div>"
916
+ return html
917
+
918
+ # Funções de controle de performance
919
+ def start_performance_monitoring():
920
+ """Inicia o monitoramento de performance."""
921
+ global performance_monitor
922
+
923
+ if not performance_monitor:
924
+ return "<div style='color: red;'>❌ Monitor de performance não disponível no modo standalone</div>"
925
+
926
+ try:
927
+ if not performance_monitor.monitoring:
928
+ performance_monitor.start_monitoring(interval=5.0)
929
+ return "<div style='color: green;'>✅ Monitoramento de performance iniciado</div>"
930
+ else:
931
+ return "<div style='color: orange;'>⚠️ Monitoramento já está ativo</div>"
932
+ except Exception as e:
933
+ return f"<div style='color: red;'>❌ Erro ao iniciar monitoramento: {str(e)}</div>"
934
+
935
+ def stop_performance_monitoring():
936
+ """Para o monitoramento de performance."""
937
+ global performance_monitor
938
+
939
+ if not performance_monitor:
940
+ return "<div style='color: red;'>❌ Monitor de performance não disponível no modo standalone</div>"
941
+
942
+ try:
943
+ if performance_monitor.monitoring:
944
+ performance_monitor.stop_monitoring()
945
+ return "<div style='color: orange;'>⏹️ Monitoramento de performance parado</div>"
946
+ else:
947
+ return "<div style='color: #666;'>Monitoramento já estava parado</div>"
948
+ except Exception as e:
949
+ return f"<div style='color: red;'>❌ Erro ao parar monitoramento: {str(e)}</div>"
950
+
951
+ def reset_performance_stats():
952
+ """Reseta as estatísticas de performance."""
953
+ global performance_monitor
954
+
955
+ if not performance_monitor:
956
+ return "<div style='color: red;'>❌ Monitor de performance não disponível no modo standalone</div>"
957
+
958
+ try:
959
+ performance_monitor.reset_stats()
960
+ return "<div style='color: green;'>✅ Estatísticas resetadas com sucesso</div>"
961
+ except Exception as e:
962
+ return f"<div style='color: red;'>❌ Erro ao resetar estatísticas: {str(e)}</div>"
963
+
964
+ def export_performance_metrics():
965
+ """Exporta métricas de performance."""
966
+ global performance_monitor
967
+
968
+ if not performance_monitor:
969
+ return "<div style='color: red;'>❌ Monitor de performance não disponível no modo standalone</div>"
970
+
971
+ try:
972
+ from datetime import datetime
973
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
974
+ filepath = f"d:/hugging_face_spaces/performance_metrics_{timestamp}.json"
975
+
976
+ performance_monitor.export_metrics(filepath, hours=24)
977
+ return f"<div style='color: green;'>✅ Métricas exportadas para: {filepath}</div>"
978
+ except Exception as e:
979
+ return f"<div style='color: red;'>❌ Erro ao exportar métricas: {str(e)}</div>"
980
+
981
+ def get_system_metrics_display():
982
+ """Obtém display das métricas do sistema."""
983
+ global performance_monitor
984
+
985
+ if not performance_monitor:
986
+ return "<div style='color: #666;'>Monitor de performance não disponível no modo standalone</div>"
987
+
988
+ try:
989
+ current_metrics = performance_monitor.get_current_metrics()
990
+
991
+ if not current_metrics:
992
+ return "<div style='color: #666;'>Nenhuma métrica disponível</div>"
993
+
994
+ html = f"""
995
+ <div style='padding: 15px; border: 1px solid #ddd; border-radius: 8px;'>
996
+ <h4>🖥️ Métricas Atuais</h4>
997
+ <div style='display: grid; grid-template-columns: 1fr 1fr; gap: 10px;'>
998
+ <div>
999
+ <strong>CPU:</strong> {current_metrics.cpu_usage:.1f}%<br>
1000
+ <div style='background: #f0f0f0; height: 10px; border-radius: 5px; margin: 5px 0;'>
1001
+ <div style='background: {'red' if current_metrics.cpu_usage > 80 else 'orange' if current_metrics.cpu_usage > 60 else 'green'};
1002
+ height: 100%; width: {current_metrics.cpu_usage}%; border-radius: 5px;'></div>
1003
+ </div>
1004
+ </div>
1005
+ <div>
1006
+ <strong>Memória:</strong> {current_metrics.memory_usage:.1f}%<br>
1007
+ <div style='background: #f0f0f0; height: 10px; border-radius: 5px; margin: 5px 0;'>
1008
+ <div style='background: {'red' if current_metrics.memory_usage > 85 else 'orange' if current_metrics.memory_usage > 70 else 'green'};
1009
+ height: 100%; width: {current_metrics.memory_usage}%; border-radius: 5px;'></div>
1010
+ </div>
1011
+ </div>
1012
+ </div>
1013
+ <p><strong>Memória Disponível:</strong> {current_metrics.memory_available:.2f} GB</p>
1014
+ <p><strong>Uso do Disco:</strong> {current_metrics.disk_usage:.1f}%</p>
1015
+ <p><small>Última atualização: {current_metrics.timestamp.strftime('%H:%M:%S')}</small></p>
1016
+ </div>
1017
+ """
1018
+
1019
+ return html
1020
+
1021
+ except Exception as e:
1022
+ return f"<div style='color: red;'>Erro ao obter métricas: {str(e)}</div>"
1023
+
1024
+ def get_bot_statistics_display():
1025
+ """Obtém display das estatísticas do bot."""
1026
+ global performance_monitor
1027
+
1028
+ if not performance_monitor:
1029
+ return "<div style='color: #666;'>Monitor de performance não disponível no modo standalone</div>"
1030
+
1031
+ try:
1032
+ bot_stats = performance_monitor.get_bot_stats()
1033
+
1034
+ success_rate = 0
1035
+ if bot_stats.total_analyses > 0:
1036
+ success_rate = (bot_stats.successful_analyses / bot_stats.total_analyses) * 100
1037
+
1038
+ html = f"""
1039
+ <div style='padding: 15px; border: 1px solid #ddd; border-radius: 8px;'>
1040
+ <h4>🤖 Estatísticas do Bot</h4>
1041
+ <div style='display: grid; grid-template-columns: 1fr 1fr; gap: 15px;'>
1042
+ <div>
1043
+ <p><strong>Total de Análises:</strong> {bot_stats.total_analyses}</p>
1044
+ <p><strong>Sucessos:</strong> {bot_stats.successful_analyses}</p>
1045
+ <p><strong>Falhas:</strong> {bot_stats.failed_analyses}</p>
1046
+ <p><strong>Taxa de Sucesso:</strong> {success_rate:.1f}%</p>
1047
+ </div>
1048
+ <div>
1049
+ <p><strong>Tempo Médio:</strong> {bot_stats.average_analysis_time:.2f}s</p>
1050
+ <p><strong>Alertas Fibonacci:</strong> {bot_stats.fibonacci_alerts_count}</p>
1051
+ <p><strong>Última Atualização:</strong><br>
1052
+ <small>{bot_stats.last_update.strftime('%H:%M:%S') if bot_stats.last_update else 'N/A'}</small></p>
1053
+ </div>
1054
+ </div>
1055
+
1056
+ <h5>📊 Sinais Gerados:</h5>
1057
+ <div style='display: flex; gap: 10px;'>
1058
+ """
1059
+
1060
+ for signal, count in bot_stats.signals_generated.items():
1061
+ color = {'COMPRAR': 'green', 'VENDER': 'red', 'AGUARDAR': 'orange'}.get(signal, '#666')
1062
+ html += f"<span style='background: {color}; color: white; padding: 5px 10px; border-radius: 15px; font-size: 12px;'>{signal}: {count}</span>"
1063
+
1064
+ html += "</div></div>"
1065
+
1066
+ return html
1067
+
1068
+ except Exception as e:
1069
+ return f"<div style='color: red;'>Erro ao obter estatísticas: {str(e)}</div>"
1070
+
1071
+ def get_performance_alerts_display():
1072
+ """Obtém display dos alertas de performance."""
1073
+ global performance_monitor
1074
+
1075
+ if not performance_monitor:
1076
+ return "<div style='color: #666;'>Monitor de performance não disponível no modo standalone</div>"
1077
+
1078
+ try:
1079
+ summary = performance_monitor.get_performance_summary()
1080
+ active_alerts = summary.get('active_alerts', [])
1081
+
1082
+ if not active_alerts:
1083
+ return "<div style='color: green;'>✅ Nenhum alerta ativo - Sistema operando normalmente</div>"
1084
+
1085
+ html = "<div style='padding: 10px;'>"
1086
+ for alert in active_alerts:
1087
+ alert_text = {
1088
+ 'high_cpu': '🔥 CPU Alto',
1089
+ 'high_memory': '💾 Memória Alta',
1090
+ 'slow_analysis': '🐌 Análise Lenta',
1091
+ 'high_error_rate': '❌ Taxa de Erro Alta'
1092
+ }.get(alert, alert)
1093
+
1094
+ html += f"<div style='background: #ffebee; border-left: 4px solid #f44336; padding: 10px; margin: 5px 0;'>⚠️ {alert_text}</div>"
1095
+
1096
+ html += "</div>"
1097
+ return html
1098
+
1099
+ except Exception as e:
1100
+ return f"<div style='color: red;'>Erro ao obter alertas: {str(e)}</div>"
1101
+
1102
+ def get_optimization_suggestions_display():
1103
+ """Obtém display das sugestões de otimização."""
1104
+ global performance_monitor
1105
+
1106
+ if not performance_monitor:
1107
+ return "<div style='color: #666;'>Monitor de performance não disponível no modo standalone</div>"
1108
+
1109
+ try:
1110
+ suggestions = performance_monitor.optimize_performance()
1111
+
1112
+ html = "<div style='padding: 10px;'>"
1113
+ for i, suggestion in enumerate(suggestions, 1):
1114
+ icon = "💡" if "normal" in suggestion.lower() else "⚠️"
1115
+ color = "#e8f5e8" if "normal" in suggestion.lower() else "#fff3cd"
1116
+
1117
+ html += f"<div style='background: {color}; padding: 10px; margin: 5px 0; border-radius: 5px;'>{icon} {suggestion}</div>"
1118
+
1119
+ html += "</div>"
1120
+ return html
1121
+
1122
+ except Exception as e:
1123
+ return f"<div style='color: red;'>Erro ao obter sugestões: {str(e)}</div>"
1124
+
1125
  # Inicializar engines e criar interface
1126
  initialize_engines()
1127
  demo = create_interface()
config/__init__.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Pacote de configurações do Vampire Trading Bot."""
2
+
3
+ from .config import (
4
+ AppConfig,
5
+ TechnicalAnalysisConfig,
6
+ ScoringConfig,
7
+ TradingConfig,
8
+ UIConfig,
9
+ RegexPatterns,
10
+ AIConfig,
11
+ ExampleData,
12
+ FINANCIAL_MODELS
13
+ )
14
+
15
+ __all__ = [
16
+ 'AppConfig',
17
+ 'TechnicalAnalysisConfig',
18
+ 'ScoringConfig',
19
+ 'TradingConfig',
20
+ 'UIConfig',
21
+ 'RegexPatterns',
22
+ 'AIConfig',
23
+ 'ExampleData',
24
+ 'FINANCIAL_MODELS'
25
+ ]
config/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (480 Bytes). View file
 
config/__pycache__/config.cpython-313.pyc ADDED
Binary file (6.21 kB). View file
 
config/config.py ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configurações e constantes do sistema de análise de trading."""
2
+
3
+ from typing import Dict, List, Any
4
+
5
+ # Configurações de modelos de IA
6
+ FINANCIAL_MODELS = [
7
+ {
8
+ "name": "ProsusAI/finbert",
9
+ "description": "FinBERT - Modelo especializado em sentimento financeiro",
10
+ "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"}
11
+ },
12
+ {
13
+ "name": "mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis",
14
+ "description": "DistilRoBERTa - Modelo leve para notícias financeiras",
15
+ "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"}
16
+ },
17
+ {
18
+ "name": "soleimanian/financial-roberta-large-sentiment",
19
+ "description": "Financial RoBERTa - Modelo robusto para textos financeiros",
20
+ "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"}
21
+ },
22
+ {
23
+ "name": "cardiffnlp/twitter-roberta-base-sentiment-latest",
24
+ "description": "RoBERTa - Modelo geral de sentimento (fallback)",
25
+ "labels": {"LABEL_0": "NEGATIVO", "LABEL_1": "NEUTRO", "LABEL_2": "POSITIVO"}
26
+ }
27
+ ]
28
+
29
+ # Configurações de análise técnica
30
+ class TechnicalAnalysisConfig:
31
+ """Configurações para análise técnica."""
32
+
33
+ # RSI thresholds
34
+ RSI_OVERSOLD = 30
35
+ RSI_OVERBOUGHT = 70
36
+ RSI_EXTREME_OVERSOLD = 25
37
+ RSI_EXTREME_OVERBOUGHT = 75
38
+ RSI_NEUTRAL_MIN = 45
39
+ RSI_NEUTRAL_MAX = 55
40
+
41
+ # Bollinger Bands positions
42
+ BB_POSITIONS = {
43
+ 'ABAIXO': 'below',
44
+ 'ACIMA': 'above',
45
+ 'SOBRE': 'above',
46
+ 'DENTRO': 'inside'
47
+ }
48
+
49
+ # EMA trends
50
+ EMA_TRENDS = {
51
+ 'ALTA': 'up',
52
+ 'BAIXA': 'down',
53
+ 'NEUTRO': 'neutral'
54
+ }
55
+
56
+ # Volume thresholds
57
+ VOLUME_HIGH_THRESHOLD = 1.0
58
+ VOLUME_LOW_THRESHOLD = 0.5
59
+
60
+ # Momentum thresholds
61
+ SIGNIFICANT_MOVEMENT_THRESHOLD = 0.05 # 5%
62
+
63
+ # Configurações de scoring
64
+ class ScoringConfig:
65
+ """Configurações para sistema de pontuação."""
66
+
67
+ # Pontuações base
68
+ RSI_SCORE = 25
69
+ EMA_SCORE = 15
70
+ BB_SCORE = 20
71
+ MOMENTUM_SCORE = 10
72
+ VOLUME_SCORE = 10
73
+ SENTIMENT_MAX_SCORE = 20
74
+
75
+ # Bonificações especiais
76
+ PERFECT_SETUP_BONUS = 35
77
+ STRONG_REVERSAL_BONUS = 30
78
+
79
+ # Penalidades
80
+ CONFLICT_PENALTY = 10
81
+ LOW_VOLUME_PENALTY = 5
82
+
83
+ # Limites de confiança
84
+ MAX_CONFIDENCE = 95
85
+ MIN_CONFIDENCE = 10
86
+
87
+ # Configurações de trading
88
+ class TradingConfig:
89
+ """Configurações para recomendações de trading."""
90
+
91
+ # Risk management
92
+ STOP_LOSS_PERCENTAGE = 0.0007 # 0.07%
93
+ TAKE_PROFIT_PERCENTAGE = 0.0015 # 0.15%
94
+ RISK_REWARD_RATIO = 2 # 1:2
95
+
96
+ # Timeframes
97
+ SCALPING_TIMEFRAMES = ['M1', 'M5']
98
+
99
+ # Confidence levels
100
+ CONFIDENCE_LEVELS = {
101
+ 'MUITO_ALTA': 80,
102
+ 'ALTA': 65,
103
+ 'MODERADA': 50,
104
+ 'BAIXA': 0
105
+ }
106
+
107
+ # Configurações de interface
108
+ class UIConfig:
109
+ """Configurações para interface do usuário."""
110
+
111
+ # Emojis para ações
112
+ ACTION_EMOJIS = {
113
+ 'COMPRAR': {'main': '🟢', 'action': '📈'},
114
+ 'VENDER': {'main': '🔴', 'action': '📉'},
115
+ 'AGUARDAR': {'main': '🟡', 'action': '⏸️'}
116
+ }
117
+
118
+ # Emojis para sentimento
119
+ SENTIMENT_EMOJIS = {
120
+ 'POSITIVO': '😊💚',
121
+ 'NEGATIVO': '😟💔',
122
+ 'NEUTRO': '😐💛'
123
+ }
124
+
125
+ # Cores para ações
126
+ ACTION_COLORS = {
127
+ 'COMPRAR': 'verde',
128
+ 'VENDER': 'vermelho',
129
+ 'AGUARDAR': 'amarelo'
130
+ }
131
+
132
+ # Direções de trading
133
+ TRADING_DIRECTIONS = {
134
+ 'COMPRAR': 'LONG',
135
+ 'VENDER': 'SHORT',
136
+ 'AGUARDAR': 'NEUTRO'
137
+ }
138
+
139
+ # Configurações de regex para parsing
140
+ class RegexPatterns:
141
+ """Padrões regex para extração de dados."""
142
+
143
+ PRICE_PATTERN = r'P:([0-9,]+\.?\d*)'
144
+ VARIATION_PATTERN = r'\(([\+\-]\d+\.?\d*%?)\)'
145
+ RSI_PATTERN = r'RSI:(\d+)'
146
+ EMA_PATTERN = r'EMA:(ALTA|BAIXA)'
147
+ BB_PATTERN = r'BB:(DENTRO|SOBRE|ABAIXO|ACIMA)'
148
+ VOLUME_PATTERN = r'Vol:([0-9\.]+)'
149
+
150
+ # Configurações de IA
151
+ class AIConfig:
152
+ """Configurações para análise de IA."""
153
+
154
+ # Tamanho máximo de texto para análise
155
+ MAX_TEXT_LENGTH = 512
156
+
157
+ # Configurações do pipeline
158
+ PIPELINE_CONFIG = {
159
+ 'task': 'sentiment-analysis',
160
+ 'return_all_scores': True
161
+ }
162
+
163
+ # Mapeamento genérico de labels
164
+ GENERIC_LABEL_MAPPING = {
165
+ 'negative': 'NEGATIVO',
166
+ 'positive': 'POSITIVO',
167
+ 'neutral': 'NEUTRO'
168
+ }
169
+
170
+ # Configurações gerais da aplicação
171
+ class AppConfig:
172
+ """Configurações gerais da aplicação."""
173
+
174
+ # Informações da aplicação
175
+ APP_TITLE = "🧛‍♂️ VAMPIRE SCALPING BOT"
176
+ APP_SUBTITLE = "Análise Técnica + IA Financeira para WIN M1/M5"
177
+ APP_DESCRIPTION = "Sistema avançado de análise para scalping com FinBERT e indicadores técnicos"
178
+
179
+ # Configurações do servidor
180
+ DEFAULT_HOST = "127.0.0.1"
181
+ DEFAULT_PORT = 7860
182
+
183
+ # Configurações de logging
184
+ LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
185
+
186
+ # Mensagens de status
187
+ STATUS_MESSAGES = {
188
+ 'AI_UNAVAILABLE': '⚠️ Transformers não disponível. Executando sem IA.',
189
+ 'AI_LOADING': '🔄 Tentando carregar: {}',
190
+ 'AI_SUCCESS': '✅ {} carregado com sucesso!',
191
+ 'AI_FAILED': '❌ Falha ao carregar {}: {}',
192
+ 'NO_MODEL_LOADED': '❌ Nenhum modelo de sentimento pôde ser carregado.'
193
+ }
194
+
195
+ # Configurações de exemplo de dados
196
+ class ExampleData:
197
+ """Dados de exemplo para testes e demonstração."""
198
+
199
+ SAMPLE_MARKET_DATA = {
200
+ 'bullish': 'P:134,500(+0.85%) | EMA:ALTA | RSI:35 | BB:ABAIXO | Vol:1.2',
201
+ 'bearish': 'P:133,200(-1.20%) | EMA:BAIXA | RSI:75 | BB:ACIMA | Vol:1.5',
202
+ 'neutral': 'P:133,850(+0.15%) | EMA:ALTA | RSI:52 | BB:DENTRO | Vol:0.8'
203
+ }
204
+
205
+ SAMPLE_NEWS_TEXT = {
206
+ 'positive': 'Mercado em alta com boas perspectivas econômicas',
207
+ 'negative': 'Preocupações com inflação afetam mercado',
208
+ 'neutral': 'Mercado aguarda dados econômicos'
209
+ }
docs/README.md ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 📈 Vampire Trading Bot - Documentação
2
+
3
+ ## Visão Geral
4
+
5
+ O Vampire Trading Bot é um sistema avançado de análise de mercado financeiro que combina análise técnica tradicional com inteligência artificial para fornecer sinais de trading precisos e análises de Fibonacci sofisticadas.
6
+
7
+ ## 🏗️ Arquitetura do Sistema
8
+
9
+ O sistema é construído com uma arquitetura modular que permite flexibilidade e escalabilidade:
10
+
11
+ ### Componentes Principais
12
+
13
+ - **Core Engine**: Motor principal de análise técnica e de sentimento
14
+ - **Fibonacci Engine**: Sistema avançado de análise de Fibonacci com padrões harmônicos
15
+ - **Real-time Integration**: Integração em tempo real com logs de trading
16
+ - **Performance Monitor**: Monitoramento de performance e métricas do sistema
17
+ - **UI Interface**: Interface web moderna construída com Gradio
18
+
19
+ ### Fluxo de Dados
20
+
21
+ ```
22
+ Dados de Mercado → Análise Técnica → Análise de Sentimento → Fibonacci → Interface
23
+
24
+ Performance Monitor ← Real-time Integration ←────┘
25
+ ```
26
+
27
+ ## 📚 Documentação
28
+
29
+ - [Guia de Instalação](installation.md)
30
+ - [Arquitetura do Sistema](architecture.md)
31
+ - [APIs e Interfaces](api-reference.md)
32
+ - [Guia do Desenvolvedor](developer-guide.md)
33
+ - [Configuração](configuration.md)
34
+ - [Troubleshooting](troubleshooting.md)
35
+
36
+ ## 🚀 Início Rápido
37
+
38
+ 1. Clone o repositório
39
+ 2. Instale as dependências: `pip install -r requirements.txt`
40
+ 3. Execute o aplicativo: `python app.py`
41
+ 4. Acesse a interface em `http://localhost:7860`
42
+
43
+ ## 🔧 Tecnologias Utilizadas
44
+
45
+ - **Python 3.13+**
46
+ - **Gradio**: Interface web interativa
47
+ - **Transformers**: Modelos de IA para análise de sentimento
48
+ - **PyTorch**: Framework de deep learning
49
+ - **NumPy/Pandas**: Processamento de dados
50
+ - **Psutil**: Monitoramento de sistema
51
+
52
+ ## 📊 Funcionalidades
53
+
54
+ ### Análise Técnica
55
+ - RSI (Relative Strength Index)
56
+ - Médias Móveis Exponenciais (EMA)
57
+ - Bandas de Bollinger
58
+ - Análise de Volume e Momentum
59
+ - Detecção de Setups de Scalping
60
+
61
+ ### Análise de Fibonacci
62
+ - Níveis de Retração
63
+ - Níveis de Extensão
64
+ - Projeções Temporais
65
+ - Zonas de Confluência
66
+ - Padrões Harmônicos
67
+
68
+ ### Análise de Sentimento
69
+ - Processamento de texto com IA
70
+ - Modelos financeiros especializados
71
+ - Análise de palavras-chave
72
+ - Pontuação de sentimento
73
+
74
+ ### Monitoramento
75
+ - Métricas de performance em tempo real
76
+ - Histórico de análises
77
+ - Alertas de sistema
78
+ - Estatísticas de precisão
79
+
80
+ ## 📝 Licença
81
+
82
+ Este projeto é proprietário e confidencial.
83
+
84
+ ## 🤝 Contribuição
85
+
86
+ Veja o [Guia do Desenvolvedor](developer-guide.md) para informações sobre como contribuir.
docs/api-reference.md ADDED
@@ -0,0 +1,569 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 📚 Referência de APIs e Interfaces
2
+
3
+ ## Visão Geral
4
+
5
+ Este documento descreve todas as APIs, interfaces e contratos entre os módulos do Vampire Trading Bot. Cada seção inclui exemplos de uso, parâmetros esperados e formatos de resposta.
6
+
7
+ ## 🔧 Core Engines
8
+
9
+ ### TechnicalAnalysisEngine
10
+
11
+ #### Classe Principal
12
+ ```python
13
+ class TechnicalAnalysisEngine:
14
+ def __init__(self):
15
+ """Inicializa o engine de análise técnica."""
16
+
17
+ def analyze_market_data(self, market_text: str) -> Dict[str, Any]:
18
+ """Analisa dados de mercado a partir de texto.
19
+
20
+ Args:
21
+ market_text (str): Texto contendo dados de mercado
22
+
23
+ Returns:
24
+ Dict[str, Any]: Resultado da análise técnica
25
+ {
26
+ 'market_data': MarketData,
27
+ 'technical_signals': List[TechnicalSignal],
28
+ 'scalping_setups': List[ScalpingSetup],
29
+ 'risk_analysis': RiskAnalysis,
30
+ 'overall_signal': str,
31
+ 'confidence': float
32
+ }
33
+ """
34
+ ```
35
+
36
+ #### Estruturas de Dados
37
+
38
+ ```python
39
+ @dataclass
40
+ class MarketData:
41
+ """Dados básicos de mercado."""
42
+ symbol: str # Símbolo do ativo
43
+ current_price: float # Preço atual
44
+ variation: float # Variação absoluta
45
+ variation_percent: float # Variação percentual
46
+ high: float # Máxima do período
47
+ low: float # Mínima do período
48
+ volume: float # Volume negociado
49
+ timestamp: str # Timestamp da cotação
50
+
51
+ @dataclass
52
+ class TechnicalSignal:
53
+ """Sinal de indicador técnico."""
54
+ indicator: str # Nome do indicador (RSI, EMA, etc.)
55
+ value: float # Valor atual do indicador
56
+ signal: str # Sinal gerado (COMPRAR, VENDER, NEUTRO)
57
+ confidence: float # Confiança do sinal (0-100)
58
+ description: str # Descrição detalhada
59
+ timestamp: str # Timestamp do cálculo
60
+
61
+ @dataclass
62
+ class ScalpingSetup:
63
+ """Setup de scalping detectado."""
64
+ name: str # Nome do setup
65
+ entry_price: float # Preço de entrada
66
+ stop_loss: float # Stop loss
67
+ take_profit: float # Take profit
68
+ risk_reward: float # Relação risco/recompensa
69
+ confidence: float # Confiança do setup
70
+ timeframe: str # Timeframe recomendado
71
+ ```
72
+
73
+ #### Exemplo de Uso
74
+
75
+ ```python
76
+ engine = TechnicalAnalysisEngine()
77
+
78
+ market_text = """
79
+ 📊 DADOS DE MERCADO - WINV25
80
+ Preço Atual: 140135.00000 ↗
81
+ Variação: +5.00000 (+0.00%)
82
+ Máxima: 140155.00000
83
+ Mínima: 140075.00000
84
+ Volume: 5023
85
+ """
86
+
87
+ result = engine.analyze_market_data(market_text)
88
+ print(f"Sinal geral: {result['overall_signal']}")
89
+ print(f"Confiança: {result['confidence']}%")
90
+ ```
91
+
92
+ ### SentimentAnalysisEngine
93
+
94
+ #### Classe Principal
95
+ ```python
96
+ class SentimentAnalysisEngine:
97
+ def __init__(self, model_name: str = None):
98
+ """Inicializa o engine de análise de sentimento.
99
+
100
+ Args:
101
+ model_name (str, optional): Nome do modelo a usar
102
+ """
103
+
104
+ def analyze_sentiment(self, text: str) -> SentimentResult:
105
+ """Analisa sentimento de um texto.
106
+
107
+ Args:
108
+ text (str): Texto para análise (max 512 tokens)
109
+
110
+ Returns:
111
+ SentimentResult: Resultado da análise
112
+ """
113
+
114
+ def batch_analyze(self, texts: List[str]) -> List[SentimentResult]:
115
+ """Analisa múltiplos textos em lote.
116
+
117
+ Args:
118
+ texts (List[str]): Lista de textos
119
+
120
+ Returns:
121
+ List[SentimentResult]: Lista de resultados
122
+ """
123
+ ```
124
+
125
+ #### Estruturas de Dados
126
+
127
+ ```python
128
+ @dataclass
129
+ class SentimentResult:
130
+ """Resultado de análise de sentimento."""
131
+ text: str # Texto original
132
+ sentiment: str # POSITIVO, NEGATIVO, NEUTRO
133
+ confidence: float # Confiança (0-100)
134
+ scores: Dict[str, float] # Scores detalhados por classe
135
+ keywords: List[str] # Palavras-chave extraídas
136
+ financial_indicators: List[str] # Indicadores financeiros detectados
137
+ timestamp: str # Timestamp da análise
138
+ model_used: str # Modelo utilizado
139
+ ```
140
+
141
+ #### Exemplo de Uso
142
+
143
+ ```python
144
+ engine = SentimentAnalysisEngine()
145
+
146
+ text = "O mercado está muito otimista hoje, com forte alta nos índices."
147
+ result = engine.analyze_sentiment(text)
148
+
149
+ print(f"Sentimento: {result.sentiment}")
150
+ print(f"Confiança: {result.confidence}%")
151
+ print(f"Palavras-chave: {result.keywords}")
152
+ ```
153
+
154
+ ### AdvancedFibonacciEngine
155
+
156
+ #### Classe Principal
157
+ ```python
158
+ class AdvancedFibonacciEngine:
159
+ def __init__(self):
160
+ """Inicializa o engine de análise de Fibonacci."""
161
+
162
+ def perform_advanced_analysis(
163
+ self,
164
+ swing_high: float,
165
+ swing_low: float,
166
+ current_price: float,
167
+ historical_data: Optional[pd.DataFrame] = None
168
+ ) -> AdvancedFibonacciAnalysis:
169
+ """Realiza análise avançada de Fibonacci.
170
+
171
+ Args:
172
+ swing_high (float): Preço do swing high
173
+ swing_low (float): Preço do swing low
174
+ current_price (float): Preço atual
175
+ historical_data (pd.DataFrame, optional): Dados históricos
176
+
177
+ Returns:
178
+ AdvancedFibonacciAnalysis: Análise completa
179
+ """
180
+ ```
181
+
182
+ #### Estruturas de Dados
183
+
184
+ ```python
185
+ @dataclass
186
+ class FibonacciLevel:
187
+ """Nível de Fibonacci."""
188
+ level: float # Nível (0.236, 0.382, etc.)
189
+ price: float # Preço do nível
190
+ type: str # 'retracement', 'extension', 'projection'
191
+ ratio: float # Ratio de Fibonacci
192
+ distance_from_current: float # Distância do preço atual
193
+ strength: float # Força do nível (0-100)
194
+
195
+ @dataclass
196
+ class ConfluenceZone:
197
+ """Zona de confluência."""
198
+ price_range: Tuple[float, float] # Faixa de preços
199
+ levels_count: int # Número de níveis na zona
200
+ strength: float # Força da zona
201
+ types: List[str] # Tipos de níveis presentes
202
+
203
+ @dataclass
204
+ class AdvancedFibonacciAnalysis:
205
+ """Análise completa de Fibonacci."""
206
+ swing_high: float
207
+ swing_low: float
208
+ current_price: float
209
+ swing_range: float
210
+ retracement_levels: List[FibonacciLevel]
211
+ extension_levels: List[FibonacciLevel]
212
+ projection_levels: List[FibonacciLevel]
213
+ confluence_zones: List[ConfluenceZone]
214
+ harmonic_patterns: List[HarmonicPattern]
215
+ key_support: float
216
+ key_resistance: float
217
+ trend_direction: str
218
+ fibonacci_zone: str
219
+ overall_strength: float
220
+ trading_signal: str
221
+ alerts_count: int
222
+ ```
223
+
224
+ ## 🔄 Real-time Integration
225
+
226
+ ### RealTimeIntegration
227
+
228
+ #### Classe Principal
229
+ ```python
230
+ class RealTimeIntegration:
231
+ def __init__(self, log_file_path: str):
232
+ """Inicializa integração em tempo real.
233
+
234
+ Args:
235
+ log_file_path (str): Caminho para arquivo de log
236
+ """
237
+
238
+ def start(self):
239
+ """Inicia monitoramento em tempo real."""
240
+
241
+ def stop(self):
242
+ """Para monitoramento."""
243
+
244
+ def subscribe(self, callback: Callable[[BotEvent], None]):
245
+ """Inscreve callback para eventos.
246
+
247
+ Args:
248
+ callback: Função a ser chamada para cada evento
249
+ """
250
+ ```
251
+
252
+ #### Estruturas de Dados
253
+
254
+ ```python
255
+ @dataclass
256
+ class BotEvent:
257
+ """Evento do bot em tempo real."""
258
+ timestamp: datetime
259
+ event_type: str # 'new_analysis', 'fibonacci_alert', etc.
260
+ data: Dict[str, Any] # Dados do evento
261
+ priority: str # 'low', 'normal', 'high', 'critical'
262
+
263
+ @dataclass
264
+ class RealTimeConfig:
265
+ """Configuração de tempo real."""
266
+ log_file_path: str
267
+ check_interval: float # Intervalo de verificação (segundos)
268
+ max_queue_size: int # Tamanho máximo da fila
269
+ enable_notifications: bool # Habilitar notificações
270
+ auto_analysis: bool # Análise automática
271
+ backup_logs: bool # Backup de logs
272
+ ```
273
+
274
+ ## 📊 Performance Monitor
275
+
276
+ ### PerformanceMonitor
277
+
278
+ #### Classe Principal
279
+ ```python
280
+ class PerformanceMonitor:
281
+ def __init__(self, max_metrics_history: int = 1000):
282
+ """Inicializa monitor de performance."""
283
+
284
+ def start_monitoring(self, interval: float = 5.0):
285
+ """Inicia monitoramento.
286
+
287
+ Args:
288
+ interval (float): Intervalo entre coletas (segundos)
289
+ """
290
+
291
+ def record_analysis_time(self, analysis_time: float):
292
+ """Registra tempo de análise.
293
+
294
+ Args:
295
+ analysis_time (float): Tempo em segundos
296
+ """
297
+
298
+ def get_performance_summary(self) -> Dict[str, Any]:
299
+ """Retorna resumo de performance.
300
+
301
+ Returns:
302
+ Dict com métricas de performance
303
+ """
304
+ ```
305
+
306
+ #### Estruturas de Dados
307
+
308
+ ```python
309
+ @dataclass
310
+ class PerformanceMetrics:
311
+ """Métricas de performance."""
312
+ timestamp: datetime
313
+ cpu_usage: float # Uso de CPU (%)
314
+ memory_usage: float # Uso de memória (%)
315
+ memory_available: float # Memória disponível (MB)
316
+ disk_usage: float # Uso de disco (%)
317
+ analysis_time: float # Tempo de análise (s)
318
+ events_processed: int # Eventos processados
319
+ errors_count: int # Contagem de erros
320
+ bot_signals_count: int # Sinais do bot
321
+ fibonacci_alerts_count: int # Alertas de Fibonacci
322
+ ```
323
+
324
+ ## 🔍 Log Parser
325
+
326
+ ### VampireBotLogParser
327
+
328
+ #### Classe Principal
329
+ ```python
330
+ class VampireBotLogParser:
331
+ def __init__(self):
332
+ """Inicializa parser de logs."""
333
+
334
+ def parse_log_content(self, log_content: str) -> Optional[BotAnalysis]:
335
+ """Faz parse de conteúdo de log.
336
+
337
+ Args:
338
+ log_content (str): Conteúdo do log
339
+
340
+ Returns:
341
+ BotAnalysis ou None se parsing falhar
342
+ """
343
+
344
+ def parse_log_file(self, file_path: str) -> Optional[BotAnalysis]:
345
+ """Faz parse de arquivo de log.
346
+
347
+ Args:
348
+ file_path (str): Caminho do arquivo
349
+
350
+ Returns:
351
+ BotAnalysis ou None se parsing falhar
352
+ """
353
+ ```
354
+
355
+ #### Estruturas de Dados
356
+
357
+ ```python
358
+ @dataclass
359
+ class BotAnalysis:
360
+ """Análise completa do bot."""
361
+ analysis_number: int
362
+ timestamp: str
363
+ market_data: MarketData
364
+ technical_indicators: TechnicalIndicators
365
+ fibonacci_analysis: FibonacciAnalysis
366
+ performance_time: Optional[float] = None
367
+
368
+ @dataclass
369
+ class TechnicalIndicators:
370
+ """Indicadores técnicos do log."""
371
+ rsi: float
372
+ rsi_status: str
373
+ ema_fast: float
374
+ ema_slow: float
375
+ ema_trend: str
376
+ bollinger_status: str
377
+ bollinger_upper: float
378
+ bollinger_lower: float
379
+ atr: float
380
+ volatility: str
381
+ volatility_multiplier: float
382
+ ```
383
+
384
+ ## 🎨 UI Interface
385
+
386
+ ### GradioInterface
387
+
388
+ #### Classe Principal
389
+ ```python
390
+ class GradioInterface:
391
+ def __init__(self):
392
+ """Inicializa interface Gradio."""
393
+
394
+ def create_interface(self) -> gr.Blocks:
395
+ """Cria interface completa.
396
+
397
+ Returns:
398
+ gr.Blocks: Interface Gradio configurada
399
+ """
400
+
401
+ def launch(self, **kwargs):
402
+ """Lança a interface.
403
+
404
+ Args:
405
+ **kwargs: Argumentos para gr.launch()
406
+ """
407
+ ```
408
+
409
+ #### Componentes da Interface
410
+
411
+ ```python
412
+ class UIComponents:
413
+ """Componentes reutilizáveis da UI."""
414
+
415
+ @staticmethod
416
+ def create_market_input() -> gr.Textbox:
417
+ """Cria campo de entrada de dados de mercado."""
418
+
419
+ @staticmethod
420
+ def create_sentiment_input() -> gr.Textbox:
421
+ """Cria campo de entrada para análise de sentimento."""
422
+
423
+ @staticmethod
424
+ def create_fibonacci_inputs() -> Tuple[gr.Number, gr.Number, gr.Number]:
425
+ """Cria campos para análise de Fibonacci."""
426
+ ```
427
+
428
+ ## 🛠️ Utilities
429
+
430
+ ### Utilitários de Validação
431
+
432
+ ```python
433
+ class ValidationUtils:
434
+ @staticmethod
435
+ def validate_market_data(data: Dict[str, Any]) -> bool:
436
+ """Valida dados de mercado.
437
+
438
+ Args:
439
+ data: Dicionário com dados de mercado
440
+
441
+ Returns:
442
+ bool: True se válido
443
+ """
444
+
445
+ @staticmethod
446
+ def validate_text_input(text: str) -> bool:
447
+ """Valida entrada de texto.
448
+
449
+ Args:
450
+ text: Texto a validar
451
+
452
+ Returns:
453
+ bool: True se válido
454
+ """
455
+ ```
456
+
457
+ ### Utilitários de Formatação
458
+
459
+ ```python
460
+ class FormatUtils:
461
+ @staticmethod
462
+ def format_price(price: float) -> str:
463
+ """Formata preço com separadores."""
464
+
465
+ @staticmethod
466
+ def format_percentage(value: float) -> str:
467
+ """Formata porcentagem com sinal."""
468
+
469
+ @staticmethod
470
+ def format_analysis_result(result: Dict[str, Any]) -> str:
471
+ """Formata resultado de análise para exibição."""
472
+ ```
473
+
474
+ ## 📋 Códigos de Erro
475
+
476
+ ### Códigos de Sistema
477
+ - `SYS_001`: Erro de inicialização
478
+ - `SYS_002`: Erro de configuração
479
+ - `SYS_003`: Erro de memória insuficiente
480
+
481
+ ### Códigos de Análise
482
+ - `ANA_001`: Dados de mercado inválidos
483
+ - `ANA_002`: Erro no modelo de IA
484
+ - `ANA_003`: Timeout de análise
485
+ - `ANA_004`: Erro de parsing de texto
486
+
487
+ ### Códigos de Interface
488
+ - `UI_001`: Erro de renderização
489
+ - `UI_002`: Entrada inválida
490
+ - `UI_003`: Erro de comunicação
491
+
492
+ ## 🔧 Configuração de APIs
493
+
494
+ ### Variáveis de Ambiente
495
+
496
+ ```bash
497
+ # Configurações de modelo
498
+ FINBERT_MODEL_PATH=/path/to/model
499
+ MAX_TEXT_LENGTH=512
500
+
501
+ # Configurações de performance
502
+ MAX_WORKERS=4
503
+ CACHE_SIZE=1000
504
+
505
+ # Configurações de logging
506
+ LOG_LEVEL=INFO
507
+ LOG_FILE_PATH=/path/to/logs
508
+ ```
509
+
510
+ ### Configuração via Arquivo
511
+
512
+ ```python
513
+ # config.py
514
+ class APIConfig:
515
+ MAX_TEXT_LENGTH = 512
516
+ TIMEOUT_SECONDS = 30
517
+ RETRY_ATTEMPTS = 3
518
+ CACHE_TTL = 3600
519
+ ```
520
+
521
+ ## 📝 Exemplos de Integração
522
+
523
+ ### Exemplo Completo
524
+
525
+ ```python
526
+ from market_analysis import TechnicalAnalysisEngine
527
+ from sentiment_analysis import SentimentAnalysisEngine
528
+ from fibonacci_analysis import AdvancedFibonacciEngine
529
+
530
+ # Inicializar engines
531
+ tech_engine = TechnicalAnalysisEngine()
532
+ sentiment_engine = SentimentAnalysisEngine()
533
+ fib_engine = AdvancedFibonacciEngine()
534
+
535
+ # Dados de entrada
536
+ market_text = "Preço: 140135, Variação: +5"
537
+ sentiment_text = "Mercado muito otimista hoje"
538
+
539
+ # Análises
540
+ tech_result = tech_engine.analyze_market_data(market_text)
541
+ sentiment_result = sentiment_engine.analyze_sentiment(sentiment_text)
542
+ fib_result = fib_engine.perform_advanced_analysis(140570, 139540, 140135)
543
+
544
+ # Consolidar resultados
545
+ final_result = {
546
+ 'technical': tech_result,
547
+ 'sentiment': sentiment_result,
548
+ 'fibonacci': fib_result,
549
+ 'timestamp': datetime.now().isoformat()
550
+ }
551
+
552
+ print(json.dumps(final_result, indent=2, default=str))
553
+ ```
554
+
555
+ ## 🚀 Próximas Versões da API
556
+
557
+ ### v2.0 (Planejado)
558
+ - REST API completa
559
+ - WebSocket para tempo real
560
+ - Autenticação e autorização
561
+ - Rate limiting
562
+ - Documentação OpenAPI/Swagger
563
+
564
+ ### v3.0 (Futuro)
565
+ - GraphQL API
566
+ - Microserviços
567
+ - API Gateway
568
+ - Métricas avançadas
569
+ - Multi-tenancy
docs/architecture.md ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🏗️ Arquitetura do Sistema
2
+
3
+ ## Visão Geral
4
+
5
+ O Vampire Trading Bot é construído com uma arquitetura modular e escalável que separa responsabilidades e permite fácil manutenção e extensão. O sistema segue princípios de design limpo e padrões de arquitetura bem estabelecidos.
6
+
7
+ ## Diagrama de Arquitetura
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────────┐
11
+ │ VAMPIRE TRADING BOT │
12
+ ├─────────────────────────────────────────────────────────────────┤
13
+ │ 📱 PRESENTATION LAYER │
14
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
15
+ │ │ Gradio UI │ │ REST API │ │ WebSocket │ │
16
+ │ │ (ui.py) │ │ (future) │ │ (future) │ │
17
+ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
18
+ ├─────────────────────────────────────────────────────────────────┤
19
+ │ 🧠 BUSINESS LOGIC LAYER │
20
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
21
+ │ │ Technical │ │ Sentiment │ │ Fibonacci │ │
22
+ │ │ Analysis Engine │ │ Analysis Engine │ │ Analysis Engine │ │
23
+ │ │ (market_*.py) │ │ (sentiment_*.py)│ │ (fibonacci_*.py)│ │
24
+ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
25
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
26
+ │ │ Real-time │ │ Performance │ │ Log Parser │ │
27
+ │ │ Integration │ │ Monitor │ │ (log_parser.py) │ │
28
+ │ │ (real_time_*.py)│ │ (performance_*) │ │ │ │
29
+ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
30
+ ├─────────────────────────────────────────────────────────────────┤
31
+ │ 🔧 INFRASTRUCTURE LAYER │
32
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
33
+ │ │ Configuration │ │ Utilities │ │ Logging │ │
34
+ │ │ (config.py) │ │ (utils.py) │ │ (built-in) │ │
35
+ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
36
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
37
+ │ │ AI Models │ │ File System │ │ Threading │ │
38
+ │ │ (transformers) │ │ (pathlib) │ │ (asyncio) │ │
39
+ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
40
+ └─────────────────────────────────────────────────────────────────┘
41
+ ```
42
+
43
+ ## Componentes Principais
44
+
45
+ ### 1. 📱 Camada de Apresentação
46
+
47
+ #### Gradio Interface (`ui.py`)
48
+ - **Responsabilidade**: Interface web interativa
49
+ - **Tecnologia**: Gradio 4.44.0
50
+ - **Funcionalidades**:
51
+ - Dashboard principal com métricas em tempo real
52
+ - Formulários de entrada para análise de texto
53
+ - Visualização de resultados de análise
54
+ - Gráficos e indicadores visuais
55
+ - Configurações de usuário
56
+
57
+ ```python
58
+ class GradioInterface:
59
+ def __init__(self):
60
+ self.technical_engine = TechnicalAnalysisEngine()
61
+ self.sentiment_engine = SentimentAnalysisEngine()
62
+ self.fibonacci_engine = AdvancedFibonacciEngine()
63
+
64
+ def create_interface(self) -> gr.Blocks:
65
+ # Criação da interface completa
66
+ ```
67
+
68
+ ### 2. 🧠 Camada de Lógica de Negócio
69
+
70
+ #### Technical Analysis Engine (`market_analysis.py`)
71
+ - **Responsabilidade**: Análise técnica de mercado
72
+ - **Componentes**:
73
+ - `MarketDataParser`: Parsing de dados de mercado
74
+ - `RSIAnalyzer`: Análise de RSI
75
+ - `EMAAnalyzer`: Análise de médias móveis
76
+ - `BollingerAnalyzer`: Análise de Bandas de Bollinger
77
+ - `ScalpingSetupDetector`: Detecção de setups
78
+ - `RiskCalculator`: Cálculo de risco/recompensa
79
+
80
+ ```python
81
+ class TechnicalAnalysisEngine:
82
+ def __init__(self):
83
+ self.rsi_analyzer = RSIAnalyzer()
84
+ self.ema_analyzer = EMAAnalyzer()
85
+ self.bollinger_analyzer = BollingerAnalyzer()
86
+ # ...
87
+ ```
88
+
89
+ #### Sentiment Analysis Engine (`sentiment_analysis.py`)
90
+ - **Responsabilidade**: Análise de sentimento com IA
91
+ - **Componentes**:
92
+ - `ModelManager`: Gerenciamento de modelos de IA
93
+ - `TextPreprocessor`: Pré-processamento de texto
94
+ - `SentimentAnalyzer`: Análise de sentimento
95
+ - `SentimentScorer`: Pontuação de sentimento
96
+
97
+ ```python
98
+ class SentimentAnalysisEngine:
99
+ def __init__(self):
100
+ self.model_manager = ModelManager()
101
+ self.preprocessor = TextPreprocessor()
102
+ self.analyzer = SentimentAnalyzer()
103
+ ```
104
+
105
+ #### Advanced Fibonacci Engine (`fibonacci_analysis.py`)
106
+ - **Responsabilidade**: Análise avançada de Fibonacci
107
+ - **Funcionalidades**:
108
+ - Níveis de retração e extensão
109
+ - Zonas de confluência
110
+ - Padrões harmônicos
111
+ - Projeções temporais
112
+ - Análise de força dos níveis
113
+
114
+ ```python
115
+ class AdvancedFibonacciEngine:
116
+ def perform_advanced_analysis(
117
+ self, swing_high: float, swing_low: float, current_price: float
118
+ ) -> AdvancedFibonacciAnalysis:
119
+ # Análise completa de Fibonacci
120
+ ```
121
+
122
+ #### Real-time Integration (`real_time_integration.py`)
123
+ - **Responsabilidade**: Integração em tempo real
124
+ - **Componentes**:
125
+ - `FileWatcher`: Monitoramento de arquivos
126
+ - `RealTimeProcessor`: Processamento de eventos
127
+ - `BotEvent`: Estrutura de eventos
128
+
129
+ #### Performance Monitor (`performance_monitor.py`)
130
+ - **Responsabilidade**: Monitoramento de performance
131
+ - **Métricas**:
132
+ - CPU e memória
133
+ - Tempo de análise
134
+ - Contadores de eventos
135
+ - Estatísticas de precisão
136
+
137
+ #### Log Parser (`log_parser.py`)
138
+ - **Responsabilidade**: Parsing de logs do bot
139
+ - **Funcionalidades**:
140
+ - Extração de dados de mercado
141
+ - Parsing de indicadores técnicos
142
+ - Análise de Fibonacci dos logs
143
+
144
+ ### 3. 🔧 Camada de Infraestrutura
145
+
146
+ #### Configuration (`config.py`)
147
+ - **Responsabilidade**: Configurações centralizadas
148
+ - **Seções**:
149
+ - Modelos de IA
150
+ - Parâmetros de análise técnica
151
+ - Configurações de UI
152
+ - Configurações de trading
153
+
154
+ #### Utilities (`utils.py`)
155
+ - **Responsabilidade**: Funções auxiliares
156
+ - **Utilitários**:
157
+ - `DateTimeUtils`: Manipulação de datas
158
+ - `NumberUtils`: Formatação de números
159
+ - `ValidationUtils`: Validação de dados
160
+ - `LogUtils`: Utilitários de logging
161
+
162
+ ## Fluxo de Dados
163
+
164
+ ### 1. Fluxo de Análise Principal
165
+
166
+ ```
167
+ 1. Entrada de Dados
168
+ ├── Texto do usuário (UI)
169
+ ├── Dados de mercado (logs)
170
+ └── Parâmetros de configuração
171
+
172
+ 2. Processamento
173
+ ├── Análise Técnica
174
+ │ ├── Parsing de dados
175
+ │ ├── Cálculo de indicadores
176
+ │ └── Detecção de setups
177
+ ├── Análise de Sentimento
178
+ │ ├── Pré-processamento
179
+ │ ├── Inferência do modelo
180
+ │ └── Pontuação
181
+ └── Análise de Fibonacci
182
+ ├── Cálculo de níveis
183
+ ├── Zonas de confluência
184
+ └── Padrões harmônicos
185
+
186
+ 3. Consolidação
187
+ ├── Combinação de resultados
188
+ ├── Cálculo de confiança
189
+ └── Geração de sinais
190
+
191
+ 4. Apresentação
192
+ ├── Formatação de resultados
193
+ ├── Geração de gráficos
194
+ └── Exibição na UI
195
+ ```
196
+
197
+ ### 2. Fluxo de Monitoramento
198
+
199
+ ```
200
+ Sistema → Performance Monitor → Métricas → Dashboard
201
+
202
+ Logs → Log Parser → Eventos → Real-time Integration → UI
203
+ ```
204
+
205
+ ## Padrões de Design Utilizados
206
+
207
+ ### 1. **Strategy Pattern**
208
+ - Diferentes analisadores técnicos
209
+ - Múltiplos modelos de IA
210
+ - Estratégias de formatação
211
+
212
+ ### 2. **Observer Pattern**
213
+ - Sistema de eventos em tempo real
214
+ - Notificações de performance
215
+ - Atualizações de UI
216
+
217
+ ### 3. **Factory Pattern**
218
+ - Criação de analisadores
219
+ - Instanciação de modelos
220
+ - Geração de interfaces
221
+
222
+ ### 4. **Singleton Pattern**
223
+ - Monitor de performance
224
+ - Configurações globais
225
+ - Cache de modelos
226
+
227
+ ### 5. **Facade Pattern**
228
+ - Engines principais
229
+ - Interface unificada
230
+ - Simplificação de APIs
231
+
232
+ ## Estruturas de Dados
233
+
234
+ ### Core Data Classes
235
+
236
+ ```python
237
+ @dataclass
238
+ class MarketData:
239
+ symbol: str
240
+ current_price: float
241
+ variation: float
242
+ high: float
243
+ low: float
244
+ volume: int
245
+ timestamp: str
246
+
247
+ @dataclass
248
+ class TechnicalSignal:
249
+ indicator: str
250
+ value: float
251
+ signal: str
252
+ confidence: float
253
+ timestamp: str
254
+
255
+ @dataclass
256
+ class SentimentResult:
257
+ text: str
258
+ sentiment: str
259
+ confidence: float
260
+ scores: Dict[str, float]
261
+ keywords: List[str]
262
+ ```
263
+
264
+ ## Extensibilidade
265
+
266
+ ### Adicionando Novos Indicadores
267
+
268
+ 1. Criar classe herdando de `BaseAnalyzer`
269
+ 2. Implementar método `analyze()`
270
+ 3. Registrar no `TechnicalAnalysisEngine`
271
+
272
+ ### Adicionando Novos Modelos de IA
273
+
274
+ 1. Adicionar modelo em `config.py`
275
+ 2. Implementar carregamento no `ModelManager`
276
+ 3. Testar compatibilidade
277
+
278
+ ### Adicionando Novas Interfaces
279
+
280
+ 1. Implementar interface seguindo padrão
281
+ 2. Integrar com engines existentes
282
+ 3. Configurar roteamento
283
+
284
+ ## Performance e Otimização
285
+
286
+ ### Estratégias de Cache
287
+ - Cache de modelos de IA
288
+ - Cache de cálculos técnicos
289
+ - Cache de resultados de análise
290
+
291
+ ### Processamento Assíncrono
292
+ - Análises paralelas
293
+ - Carregamento assíncrono de modelos
294
+ - Processamento de eventos em background
295
+
296
+ ### Otimização de Memória
297
+ - Lazy loading de modelos
298
+ - Limpeza automática de cache
299
+ - Monitoramento de uso de memória
300
+
301
+ ## Segurança
302
+
303
+ ### Validação de Entrada
304
+ - Sanitização de texto
305
+ - Validação de parâmetros
306
+ - Limites de tamanho
307
+
308
+ ### Tratamento de Erros
309
+ - Try-catch abrangente
310
+ - Fallbacks para modo standalone
311
+ - Logging detalhado de erros
312
+
313
+ ### Isolamento de Recursos
314
+ - Ambientes virtuais
315
+ - Limitação de recursos
316
+ - Timeouts de operação
317
+
318
+ ## Monitoramento e Observabilidade
319
+
320
+ ### Métricas Coletadas
321
+ - Performance do sistema
322
+ - Tempo de resposta
323
+ - Taxa de sucesso/erro
324
+ - Uso de recursos
325
+
326
+ ### Logging
327
+ - Logs estruturados
328
+ - Níveis de log configuráveis
329
+ - Rotação automática
330
+
331
+ ### Alertas
332
+ - Alertas de performance
333
+ - Notificações de erro
334
+ - Métricas de negócio
335
+
336
+ ## Próximos Passos da Arquitetura
337
+
338
+ ### Melhorias Planejadas
339
+ 1. **Microserviços**: Separação em serviços independentes
340
+ 2. **API REST**: Interface programática
341
+ 3. **WebSocket**: Comunicação em tempo real
342
+ 4. **Database**: Persistência de dados
343
+ 5. **Docker**: Containerização
344
+ 6. **CI/CD**: Pipeline de deployment
345
+
346
+ ### Escalabilidade
347
+ 1. **Load Balancing**: Distribuição de carga
348
+ 2. **Caching Distribuído**: Redis/Memcached
349
+ 3. **Message Queue**: RabbitMQ/Kafka
350
+ 4. **Horizontal Scaling**: Múltiplas instâncias
docs/configuration.md ADDED
@@ -0,0 +1,606 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ⚙️ Guia de Configuração
2
+
3
+ ## Visão Geral
4
+
5
+ Este documento descreve todas as opções de configuração disponíveis no Vampire Trading Bot, incluindo configurações de modelos de IA, análise técnica, interface do usuário e performance.
6
+
7
+ ## 📁 Arquivo Principal de Configuração
8
+
9
+ Todas as configurações estão centralizadas no arquivo `config.py`. Este arquivo contém classes de configuração organizadas por funcionalidade.
10
+
11
+ ### Estrutura do Arquivo
12
+
13
+ ```python
14
+ # config.py
15
+ class FinancialModels: # Modelos de IA
16
+ class TechnicalAnalysis: # Análise técnica
17
+ class ScoringConfig: # Pontuação e confiança
18
+ class TradingConfig: # Configurações de trading
19
+ class UIConfig: # Interface do usuário
20
+ class RegexPatterns: # Padrões de extração
21
+ class AIConfig: # Configurações de IA
22
+ class AppConfig: # Configurações gerais
23
+ ```
24
+
25
+ ## 🤖 Configuração de Modelos de IA
26
+
27
+ ### FinancialModels
28
+
29
+ ```python
30
+ class FinancialModels:
31
+ """Modelos de IA para análise financeira."""
32
+
33
+ # Lista de modelos disponíveis (ordenados por performance/tamanho)
34
+ FINANCIAL_MODELS = [
35
+ "nlptown/bert-base-multilingual-uncased-sentiment", # Leve, multilíngue
36
+ "cardiffnlp/twitter-roberta-base-sentiment-latest", # Médio, redes sociais
37
+ "ProsusAI/finbert", # Pesado, financeiro
38
+ "mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis"
39
+ ]
40
+
41
+ # Modelo padrão (usado se não especificado)
42
+ DEFAULT_MODEL = FINANCIAL_MODELS[0]
43
+
44
+ # Modelos alternativos para fallback
45
+ FALLBACK_MODELS = [
46
+ "cardiffnlp/twitter-roberta-base-sentiment-latest",
47
+ "nlptown/bert-base-multilingual-uncased-sentiment"
48
+ ]
49
+ ```
50
+
51
+ #### Como Configurar
52
+
53
+ 1. **Escolher Modelo por Performance**:
54
+ ```python
55
+ # Para melhor performance (mais leve)
56
+ DEFAULT_MODEL = "nlptown/bert-base-multilingual-uncased-sentiment"
57
+
58
+ # Para melhor precisão (mais pesado)
59
+ DEFAULT_MODEL = "ProsusAI/finbert"
60
+ ```
61
+
62
+ 2. **Adicionar Novos Modelos**:
63
+ ```python
64
+ FINANCIAL_MODELS.append("seu-modelo/nome-do-modelo")
65
+ ```
66
+
67
+ ### AIConfig
68
+
69
+ ```python
70
+ class AIConfig:
71
+ """Configurações gerais de IA."""
72
+
73
+ # Tamanho máximo de texto para análise
74
+ MAX_TEXT_LENGTH = 512
75
+
76
+ # Pipeline de análise de sentimento
77
+ SENTIMENT_PIPELINE = "sentiment-analysis"
78
+
79
+ # Configurações de cache
80
+ ENABLE_MODEL_CACHE = True
81
+ CACHE_SIZE = 100
82
+
83
+ # Timeout para carregamento de modelos (segundos)
84
+ MODEL_LOAD_TIMEOUT = 60
85
+
86
+ # Usar GPU se disponível
87
+ USE_GPU = True
88
+
89
+ # Batch size para processamento
90
+ BATCH_SIZE = 8
91
+ ```
92
+
93
+ #### Configurações Avançadas de IA
94
+
95
+ ```python
96
+ # Configuração de memória
97
+ AIConfig.MAX_TEXT_LENGTH = 256 # Reduzir para economizar memória
98
+ AIConfig.BATCH_SIZE = 4 # Reduzir batch size
99
+
100
+ # Configuração de performance
101
+ AIConfig.USE_GPU = False # Forçar uso de CPU
102
+ AIConfig.ENABLE_MODEL_CACHE = False # Desabilitar cache
103
+
104
+ # Configuração de timeout
105
+ AIConfig.MODEL_LOAD_TIMEOUT = 120 # Aumentar timeout
106
+ ```
107
+
108
+ ## 📊 Configuração de Análise Técnica
109
+
110
+ ### TechnicalAnalysis
111
+
112
+ ```python
113
+ class TechnicalAnalysis:
114
+ """Configurações para análise técnica."""
115
+
116
+ # Configurações do RSI
117
+ RSI_PERIOD = 14
118
+ RSI_OVERSOLD = 30
119
+ RSI_OVERBOUGHT = 70
120
+
121
+ # Configurações das Bandas de Bollinger
122
+ BOLLINGER_PERIOD = 20
123
+ BOLLINGER_STD = 2
124
+
125
+ # Configurações das EMAs
126
+ EMA_FAST_PERIOD = 9
127
+ EMA_SLOW_PERIOD = 21
128
+
129
+ # Configurações de Volume
130
+ VOLUME_MA_PERIOD = 20
131
+ HIGH_VOLUME_MULTIPLIER = 1.5
132
+
133
+ # Configurações de Momentum
134
+ MOMENTUM_PERIOD = 10
135
+ MOMENTUM_THRESHOLD = 0.02
136
+ ```
137
+
138
+ #### Personalização de Indicadores
139
+
140
+ ```python
141
+ # RSI mais sensível
142
+ TechnicalAnalysis.RSI_PERIOD = 10
143
+ TechnicalAnalysis.RSI_OVERSOLD = 25
144
+ TechnicalAnalysis.RSI_OVERBOUGHT = 75
145
+
146
+ # Bandas de Bollinger mais apertadas
147
+ TechnicalAnalysis.BOLLINGER_STD = 1.5
148
+
149
+ # EMAs mais rápidas
150
+ TechnicalAnalysis.EMA_FAST_PERIOD = 5
151
+ TechnicalAnalysis.EMA_SLOW_PERIOD = 13
152
+ ```
153
+
154
+ ## 🎯 Configuração de Trading
155
+
156
+ ### TradingConfig
157
+
158
+ ```python
159
+ class TradingConfig:
160
+ """Configurações de trading e gestão de risco."""
161
+
162
+ # Stop Loss padrão (percentual)
163
+ DEFAULT_STOP_LOSS = 0.5 # 0.5%
164
+
165
+ # Take Profit padrão (percentual)
166
+ DEFAULT_TAKE_PROFIT = 1.0 # 1.0%
167
+
168
+ # Relação risco/recompensa mínima
169
+ MIN_RISK_REWARD = 1.5
170
+
171
+ # Tamanho de posição padrão
172
+ DEFAULT_POSITION_SIZE = 1.0
173
+
174
+ # Configurações de scalping
175
+ SCALPING_TIMEFRAMES = ["1m", "5m", "15m"]
176
+ SCALPING_MIN_VOLUME = 1000
177
+
178
+ # Configurações de volatilidade
179
+ LOW_VOLATILITY_THRESHOLD = 0.5
180
+ HIGH_VOLATILITY_THRESHOLD = 2.0
181
+ ```
182
+
183
+ #### Estratégias de Risco
184
+
185
+ ```python
186
+ # Estratégia conservadora
187
+ TradingConfig.DEFAULT_STOP_LOSS = 0.3
188
+ TradingConfig.DEFAULT_TAKE_PROFIT = 0.6
189
+ TradingConfig.MIN_RISK_REWARD = 2.0
190
+
191
+ # Estratégia agressiva
192
+ TradingConfig.DEFAULT_STOP_LOSS = 0.8
193
+ TradingConfig.DEFAULT_TAKE_PROFIT = 1.5
194
+ TradingConfig.MIN_RISK_REWARD = 1.2
195
+ ```
196
+
197
+ ## 🎨 Configuração da Interface
198
+
199
+ ### UIConfig
200
+
201
+ ```python
202
+ class UIConfig:
203
+ """Configurações da interface do usuário."""
204
+
205
+ # Informações do aplicativo
206
+ TITLE = "📈 Vampire Trading Bot"
207
+ SUBTITLE = "Análise Avançada de Mercado com IA"
208
+ DESCRIPTION = "Sistema completo de análise técnica e sentimento"
209
+
210
+ # Emojis para diferentes ações
211
+ ACTION_EMOJIS = {
212
+ "COMPRAR": "🟢",
213
+ "VENDER": "🔴",
214
+ "AGUARDAR": "🟡",
215
+ "NEUTRO": "⚪"
216
+ }
217
+
218
+ # Cores para diferentes elementos
219
+ COLORS = {
220
+ "success": "#28a745",
221
+ "danger": "#dc3545",
222
+ "warning": "#ffc107",
223
+ "info": "#17a2b8",
224
+ "primary": "#007bff"
225
+ }
226
+
227
+ # Mensagens de status
228
+ STATUS_MESSAGES = {
229
+ "loading": "🔄 Processando análise...",
230
+ "success": "✅ Análise concluída com sucesso!",
231
+ "error": "❌ Erro durante a análise",
232
+ "no_data": "⚠️ Nenhum dado fornecido"
233
+ }
234
+ ```
235
+
236
+ #### Personalização da Interface
237
+
238
+ ```python
239
+ # Tema escuro
240
+ UIConfig.COLORS = {
241
+ "success": "#00ff88",
242
+ "danger": "#ff4444",
243
+ "warning": "#ffaa00",
244
+ "info": "#00aaff",
245
+ "primary": "#8800ff"
246
+ }
247
+
248
+ # Personalizar título
249
+ UIConfig.TITLE = "🧛 Meu Bot de Trading"
250
+ UIConfig.SUBTITLE = "Análise Personalizada"
251
+ ```
252
+
253
+ ## 🔍 Configuração de Padrões Regex
254
+
255
+ ### RegexPatterns
256
+
257
+ ```python
258
+ class RegexPatterns:
259
+ """Padrões regex para extração de dados."""
260
+
261
+ # Extração de preços
262
+ PRICE_PATTERN = r"Preço.*?([\d,]+\.\d+)"
263
+
264
+ # Extração de variação
265
+ VARIATION_PATTERN = r"Variação.*?([+-]?[\d,]+\.\d+)"
266
+
267
+ # Extração de porcentagem
268
+ PERCENTAGE_PATTERN = r"\(([+-]?\d+\.\d+)%\)"
269
+
270
+ # Extração de volume
271
+ VOLUME_PATTERN = r"Volume.*?(\d+)"
272
+
273
+ # Extração de RSI
274
+ RSI_PATTERN = r"RSI.*?(\d+\.\d+)"
275
+
276
+ # Extração de EMAs
277
+ EMA_PATTERN = r"EMA.*?(\d+\.\d+)"
278
+ ```
279
+
280
+ #### Personalização de Padrões
281
+
282
+ ```python
283
+ # Padrões para formato brasileiro
284
+ RegexPatterns.PRICE_PATTERN = r"R\$\s*([\d.]+,\d+)"
285
+ RegexPatterns.PERCENTAGE_PATTERN = r"\(([+-]?\d+,\d+)%\)"
286
+
287
+ # Padrões para outros idiomas
288
+ RegexPatterns.PRICE_PATTERN = r"Price.*?([\d,]+\.\d+)"
289
+ ```
290
+
291
+ ## 📈 Configuração de Pontuação
292
+
293
+ ### ScoringConfig
294
+
295
+ ```python
296
+ class ScoringConfig:
297
+ """Configurações de pontuação e confiança."""
298
+
299
+ # Pesos para diferentes análises
300
+ TECHNICAL_WEIGHT = 0.4
301
+ SENTIMENT_WEIGHT = 0.3
302
+ FIBONACCI_WEIGHT = 0.3
303
+
304
+ # Thresholds de confiança
305
+ HIGH_CONFIDENCE_THRESHOLD = 80
306
+ MEDIUM_CONFIDENCE_THRESHOLD = 60
307
+ LOW_CONFIDENCE_THRESHOLD = 40
308
+
309
+ # Multiplicadores de pontuação
310
+ STRONG_SIGNAL_MULTIPLIER = 1.5
311
+ WEAK_SIGNAL_MULTIPLIER = 0.7
312
+
313
+ # Penalizações
314
+ CONFLICTING_SIGNALS_PENALTY = 0.2
315
+ LOW_VOLUME_PENALTY = 0.1
316
+ ```
317
+
318
+ #### Ajuste de Pesos
319
+
320
+ ```python
321
+ # Priorizar análise técnica
322
+ ScoringConfig.TECHNICAL_WEIGHT = 0.6
323
+ ScoringConfig.SENTIMENT_WEIGHT = 0.2
324
+ ScoringConfig.FIBONACCI_WEIGHT = 0.2
325
+
326
+ # Priorizar sentimento
327
+ ScoringConfig.TECHNICAL_WEIGHT = 0.2
328
+ ScoringConfig.SENTIMENT_WEIGHT = 0.6
329
+ ScoringConfig.FIBONACCI_WEIGHT = 0.2
330
+ ```
331
+
332
+ ## 🚀 Configuração de Performance
333
+
334
+ ### Configurações de Sistema
335
+
336
+ ```python
337
+ # Em performance_monitor.py
338
+ class PerformanceConfig:
339
+ # Intervalo de coleta de métricas (segundos)
340
+ METRICS_INTERVAL = 5.0
341
+
342
+ # Histórico máximo de métricas
343
+ MAX_METRICS_HISTORY = 1000
344
+
345
+ # Thresholds de alerta
346
+ CPU_ALERT_THRESHOLD = 80.0
347
+ MEMORY_ALERT_THRESHOLD = 85.0
348
+
349
+ # Configurações de otimização
350
+ ENABLE_AUTO_OPTIMIZATION = True
351
+ OPTIMIZATION_INTERVAL = 300 # 5 minutos
352
+ ```
353
+
354
+ ### Configurações de Cache
355
+
356
+ ```python
357
+ # Cache de modelos
358
+ MODEL_CACHE_SIZE = 3
359
+ MODEL_CACHE_TTL = 3600 # 1 hora
360
+
361
+ # Cache de análises
362
+ ANALYSIS_CACHE_SIZE = 100
363
+ ANALYSIS_CACHE_TTL = 300 # 5 minutos
364
+ ```
365
+
366
+ ## 🔧 Configuração via Variáveis de Ambiente
367
+
368
+ ### Variáveis Suportadas
369
+
370
+ ```bash
371
+ # Modelo de IA
372
+ export FINBERT_MODEL="ProsusAI/finbert"
373
+ export MAX_TEXT_LENGTH="512"
374
+
375
+ # Performance
376
+ export MAX_WORKERS="4"
377
+ export ENABLE_GPU="true"
378
+ export CACHE_SIZE="1000"
379
+
380
+ # Logging
381
+ export LOG_LEVEL="INFO"
382
+ export LOG_FILE="vampire_bot.log"
383
+
384
+ # Interface
385
+ export GRADIO_SERVER_NAME="0.0.0.0"
386
+ export GRADIO_SERVER_PORT="7860"
387
+ export GRADIO_SHARE="false"
388
+
389
+ # Real-time
390
+ export LOG_FILE_PATH="/path/to/trading.log"
391
+ export CHECK_INTERVAL="1.0"
392
+ ```
393
+
394
+ ### Carregamento de Variáveis
395
+
396
+ ```python
397
+ import os
398
+ from config import AIConfig, UIConfig
399
+
400
+ # Carregar configurações do ambiente
401
+ AIConfig.MAX_TEXT_LENGTH = int(os.getenv('MAX_TEXT_LENGTH', '512'))
402
+ AIConfig.USE_GPU = os.getenv('ENABLE_GPU', 'true').lower() == 'true'
403
+
404
+ UIConfig.TITLE = os.getenv('APP_TITLE', UIConfig.TITLE)
405
+ ```
406
+
407
+ ## 📋 Configuração por Perfil
408
+
409
+ ### Perfis Pré-definidos
410
+
411
+ ```python
412
+ # profiles.py
413
+ class DevelopmentProfile:
414
+ """Perfil para desenvolvimento."""
415
+ DEBUG = True
416
+ LOG_LEVEL = "DEBUG"
417
+ ENABLE_MODEL_CACHE = False
418
+ USE_LIGHTWEIGHT_MODELS = True
419
+
420
+ class ProductionProfile:
421
+ """Perfil para produção."""
422
+ DEBUG = False
423
+ LOG_LEVEL = "INFO"
424
+ ENABLE_MODEL_CACHE = True
425
+ USE_LIGHTWEIGHT_MODELS = False
426
+ ENABLE_MONITORING = True
427
+
428
+ class TestingProfile:
429
+ """Perfil para testes."""
430
+ DEBUG = True
431
+ LOG_LEVEL = "WARNING"
432
+ USE_MOCK_MODELS = True
433
+ DISABLE_REAL_TIME = True
434
+ ```
435
+
436
+ ### Aplicação de Perfis
437
+
438
+ ```python
439
+ # app.py
440
+ import os
441
+ from profiles import DevelopmentProfile, ProductionProfile
442
+
443
+ profile = os.getenv('APP_PROFILE', 'development')
444
+
445
+ if profile == 'production':
446
+ config = ProductionProfile()
447
+ else:
448
+ config = DevelopmentProfile()
449
+
450
+ # Aplicar configurações
451
+ for attr in dir(config):
452
+ if not attr.startswith('_'):
453
+ setattr(globals()[attr.split('_')[0] + 'Config'], attr, getattr(config, attr))
454
+ ```
455
+
456
+ ## 🔄 Configuração Dinâmica
457
+
458
+ ### Recarregamento de Configuração
459
+
460
+ ```python
461
+ class ConfigManager:
462
+ """Gerenciador de configuração dinâmica."""
463
+
464
+ @staticmethod
465
+ def reload_config():
466
+ """Recarrega configurações do arquivo."""
467
+ importlib.reload(config)
468
+
469
+ @staticmethod
470
+ def update_config(section: str, key: str, value: Any):
471
+ """Atualiza configuração específica."""
472
+ config_class = getattr(config, section)
473
+ setattr(config_class, key, value)
474
+
475
+ @staticmethod
476
+ def get_config(section: str, key: str) -> Any:
477
+ """Obtém valor de configuração."""
478
+ config_class = getattr(config, section)
479
+ return getattr(config_class, key)
480
+ ```
481
+
482
+ ### Interface de Configuração
483
+
484
+ ```python
485
+ # Adicionar à interface Gradio
486
+ def create_config_interface():
487
+ with gr.Tab("⚙️ Configurações"):
488
+ with gr.Row():
489
+ model_dropdown = gr.Dropdown(
490
+ choices=FinancialModels.FINANCIAL_MODELS,
491
+ value=FinancialModels.DEFAULT_MODEL,
492
+ label="Modelo de IA"
493
+ )
494
+
495
+ with gr.Row():
496
+ rsi_period = gr.Number(
497
+ value=TechnicalAnalysis.RSI_PERIOD,
498
+ label="Período RSI"
499
+ )
500
+
501
+ update_btn = gr.Button("Atualizar Configurações")
502
+
503
+ update_btn.click(
504
+ fn=update_configurations,
505
+ inputs=[model_dropdown, rsi_period],
506
+ outputs=[]
507
+ )
508
+ ```
509
+
510
+ ## 📝 Exemplos de Configuração
511
+
512
+ ### Configuração Básica
513
+
514
+ ```python
515
+ # config_basic.py
516
+ from config import *
517
+
518
+ # Usar modelo leve
519
+ FinancialModels.DEFAULT_MODEL = "nlptown/bert-base-multilingual-uncased-sentiment"
520
+
521
+ # Configurações conservadoras
522
+ TradingConfig.DEFAULT_STOP_LOSS = 0.3
523
+ TradingConfig.MIN_RISK_REWARD = 2.0
524
+
525
+ # Interface simples
526
+ UIConfig.TITLE = "Bot de Trading Simples"
527
+ ```
528
+
529
+ ### Configuração Avançada
530
+
531
+ ```python
532
+ # config_advanced.py
533
+ from config import *
534
+
535
+ # Usar modelo mais preciso
536
+ FinancialModels.DEFAULT_MODEL = "ProsusAI/finbert"
537
+
538
+ # Análise técnica mais sensível
539
+ TechnicalAnalysis.RSI_PERIOD = 10
540
+ TechnicalAnalysis.EMA_FAST_PERIOD = 5
541
+
542
+ # Trading mais agressivo
543
+ TradingConfig.DEFAULT_STOP_LOSS = 0.8
544
+ TradingConfig.MIN_RISK_REWARD = 1.2
545
+
546
+ # Performance otimizada
547
+ AIConfig.BATCH_SIZE = 16
548
+ AIConfig.ENABLE_MODEL_CACHE = True
549
+ ```
550
+
551
+ ## 🔍 Troubleshooting de Configuração
552
+
553
+ ### Problemas Comuns
554
+
555
+ 1. **Modelo não carrega**:
556
+ ```python
557
+ # Verificar se modelo existe
558
+ try:
559
+ from transformers import pipeline
560
+ pipeline("sentiment-analysis", model=FinancialModels.DEFAULT_MODEL)
561
+ except Exception as e:
562
+ print(f"Erro ao carregar modelo: {e}")
563
+ ```
564
+
565
+ 2. **Configuração não aplicada**:
566
+ ```python
567
+ # Verificar se configuração foi carregada
568
+ print(f"Modelo atual: {FinancialModels.DEFAULT_MODEL}")
569
+ print(f"RSI período: {TechnicalAnalysis.RSI_PERIOD}")
570
+ ```
571
+
572
+ 3. **Performance baixa**:
573
+ ```python
574
+ # Configurações para melhor performance
575
+ AIConfig.MAX_TEXT_LENGTH = 256
576
+ AIConfig.BATCH_SIZE = 4
577
+ AIConfig.USE_GPU = False
578
+ ```
579
+
580
+ ### Validação de Configuração
581
+
582
+ ```python
583
+ def validate_config():
584
+ """Valida configurações atuais."""
585
+ errors = []
586
+
587
+ # Validar modelo
588
+ if FinancialModels.DEFAULT_MODEL not in FinancialModels.FINANCIAL_MODELS:
589
+ errors.append("Modelo padrão não está na lista de modelos")
590
+
591
+ # Validar períodos
592
+ if TechnicalAnalysis.RSI_PERIOD < 2:
593
+ errors.append("Período RSI muito baixo")
594
+
595
+ # Validar trading
596
+ if TradingConfig.DEFAULT_STOP_LOSS <= 0:
597
+ errors.append("Stop loss deve ser positivo")
598
+
599
+ return errors
600
+ ```
601
+
602
+ ## 📚 Próximos Passos
603
+
604
+ - Leia o [Guia do Desenvolvedor](developer-guide.md)
605
+ - Consulte a [Referência da API](api-reference.md)
606
+ - Veja exemplos em [Troubleshooting](troubleshooting.md)
docs/developer-guide.md ADDED
@@ -0,0 +1,963 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 👨‍💻 Guia do Desenvolvedor
2
+
3
+ ## Visão Geral
4
+
5
+ Este guia fornece informações essenciais para desenvolvedores que desejam contribuir ou estender o Vampire Trading Bot. Inclui padrões de código, arquitetura, fluxos de desenvolvimento e melhores práticas.
6
+
7
+ ## 🏗️ Arquitetura do Sistema
8
+
9
+ ### Estrutura Modular
10
+
11
+ ```
12
+ vampire-trading-bot/
13
+ ├── app.py # Ponto de entrada principal
14
+ ├── config.py # Configurações centralizadas
15
+ ├── ui.py # Interface Gradio
16
+ ├── market_analysis.py # Análise técnica
17
+ ├── sentiment_analysis.py # Análise de sentimento
18
+ ├── fibonacci_analysis.py # Análise de Fibonacci
19
+ ├── log_parser.py # Parser de logs
20
+ ├── real_time_integration.py # Integração tempo real
21
+ ├── performance_monitor.py # Monitoramento
22
+ ├── utils.py # Utilitários
23
+ ├── docs/ # Documentação
24
+ └── tests/ # Testes automatizados
25
+ ```
26
+
27
+ ### Princípios de Design
28
+
29
+ 1. **Separação de Responsabilidades**: Cada módulo tem uma função específica
30
+ 2. **Baixo Acoplamento**: Módulos independentes com interfaces bem definidas
31
+ 3. **Alta Coesão**: Funcionalidades relacionadas agrupadas
32
+ 4. **Extensibilidade**: Fácil adição de novos recursos
33
+ 5. **Testabilidade**: Código facilmente testável
34
+
35
+ ## 🔧 Configuração do Ambiente de Desenvolvimento
36
+
37
+ ### Pré-requisitos
38
+
39
+ ```bash
40
+ # Python 3.8+
41
+ python --version
42
+
43
+ # Git
44
+ git --version
45
+
46
+ # Editor recomendado: VS Code com extensões Python
47
+ ```
48
+
49
+ ### Setup Inicial
50
+
51
+ ```bash
52
+ # 1. Clonar repositório
53
+ git clone <repository-url>
54
+ cd vampire-trading-bot
55
+
56
+ # 2. Criar ambiente virtual
57
+ python -m venv venv
58
+
59
+ # 3. Ativar ambiente
60
+ # Windows
61
+ venv\Scripts\activate
62
+ # Linux/macOS
63
+ source venv/bin/activate
64
+
65
+ # 4. Instalar dependências de desenvolvimento
66
+ pip install -r requirements-dev.txt
67
+
68
+ # 5. Instalar hooks de pre-commit
69
+ pre-commit install
70
+ ```
71
+
72
+ ### Dependências de Desenvolvimento
73
+
74
+ ```txt
75
+ # requirements-dev.txt
76
+ pytest>=7.0.0
77
+ pytest-cov>=4.0.0
78
+ black>=22.0.0
79
+ flake8>=5.0.0
80
+ mypy>=1.0.0
81
+ pre-commit>=2.20.0
82
+ bandit>=1.7.0
83
+ isort>=5.10.0
84
+ memory-profiler>=0.60.0
85
+ line-profiler>=4.0.0
86
+ ```
87
+
88
+ ## 📝 Padrões de Código
89
+
90
+ ### Estilo de Código
91
+
92
+ **Formatação com Black**:
93
+ ```bash
94
+ # Formatar código
95
+ black .
96
+
97
+ # Verificar formatação
98
+ black --check .
99
+ ```
100
+
101
+ **Linting com Flake8**:
102
+ ```bash
103
+ # Verificar código
104
+ flake8 .
105
+
106
+ # Configuração em .flake8
107
+ [flake8]
108
+ max-line-length = 88
109
+ ignore = E203, W503
110
+ exclude = venv, __pycache__
111
+ ```
112
+
113
+ **Ordenação de Imports com isort**:
114
+ ```bash
115
+ # Ordenar imports
116
+ isort .
117
+
118
+ # Configuração em pyproject.toml
119
+ [tool.isort]
120
+ profile = "black"
121
+ line_length = 88
122
+ ```
123
+
124
+ ### Convenções de Nomenclatura
125
+
126
+ ```python
127
+ # Classes: PascalCase
128
+ class TechnicalAnalysisEngine:
129
+ pass
130
+
131
+ # Funções e variáveis: snake_case
132
+ def calculate_rsi_value(prices: List[float]) -> float:
133
+ pass
134
+
135
+ # Constantes: UPPER_SNAKE_CASE
136
+ DEFAULT_RSI_PERIOD = 14
137
+ MAX_RETRY_ATTEMPTS = 3
138
+
139
+ # Arquivos: snake_case
140
+ # market_analysis.py
141
+ # sentiment_analysis.py
142
+ ```
143
+
144
+ ### Documentação de Código
145
+
146
+ ```python
147
+ def analyze_market_data(
148
+ self,
149
+ text: str,
150
+ include_fibonacci: bool = True
151
+ ) -> Dict[str, Any]:
152
+ """
153
+ Analisa dados de mercado extraindo indicadores técnicos.
154
+
155
+ Args:
156
+ text: Texto contendo dados de mercado
157
+ include_fibonacci: Se deve incluir análise de Fibonacci
158
+
159
+ Returns:
160
+ Dict contendo:
161
+ - technical_signals: Lista de sinais técnicos
162
+ - market_data: Dados extraídos do mercado
163
+ - fibonacci_analysis: Análise de Fibonacci (se habilitada)
164
+
165
+ Raises:
166
+ ValueError: Se o texto não contém dados válidos
167
+ RuntimeError: Se falha na análise técnica
168
+
169
+ Example:
170
+ >>> engine = TechnicalAnalysisEngine()
171
+ >>> result = engine.analyze_market_data("WINV25: 140135")
172
+ >>> print(result['technical_signals'])
173
+ """
174
+ pass
175
+ ```
176
+
177
+ ### Type Hints
178
+
179
+ ```python
180
+ from typing import List, Dict, Optional, Union, Tuple, Any
181
+ from dataclasses import dataclass
182
+ from enum import Enum
183
+
184
+ # Usar type hints em todas as funções
185
+ def calculate_ema(
186
+ prices: List[float],
187
+ period: int
188
+ ) -> List[float]:
189
+ pass
190
+
191
+ # Dataclasses para estruturas de dados
192
+ @dataclass
193
+ class MarketData:
194
+ symbol: str
195
+ price: float
196
+ volume: int
197
+ timestamp: Optional[str] = None
198
+
199
+ # Enums para constantes
200
+ class SignalType(Enum):
201
+ BUY = "buy"
202
+ SELL = "sell"
203
+ HOLD = "hold"
204
+ ```
205
+
206
+ ## 🧪 Testes
207
+
208
+ ### Estrutura de Testes
209
+
210
+ ```
211
+ tests/
212
+ ├── __init__.py
213
+ ├── conftest.py # Fixtures compartilhadas
214
+ ├── test_market_analysis.py # Testes análise técnica
215
+ ├── test_sentiment_analysis.py # Testes análise sentimento
216
+ ├── test_fibonacci_analysis.py # Testes Fibonacci
217
+ ├── test_integration.py # Testes integração
218
+ ├── test_performance.py # Testes performance
219
+ └── fixtures/ # Dados de teste
220
+ ├── sample_logs.txt
221
+ └── market_data.json
222
+ ```
223
+
224
+ ### Escrevendo Testes
225
+
226
+ ```python
227
+ # test_market_analysis.py
228
+ import pytest
229
+ from unittest.mock import Mock, patch
230
+ from market_analysis import TechnicalAnalysisEngine, MarketData
231
+
232
+ class TestTechnicalAnalysisEngine:
233
+
234
+ @pytest.fixture
235
+ def engine(self):
236
+ """Fixture para engine de análise."""
237
+ return TechnicalAnalysisEngine()
238
+
239
+ @pytest.fixture
240
+ def sample_market_data(self):
241
+ """Fixture para dados de mercado."""
242
+ return MarketData(
243
+ symbol="WINV25",
244
+ price=140135.0,
245
+ volume=5023
246
+ )
247
+
248
+ def test_analyze_market_data_success(self, engine, sample_market_data):
249
+ """Testa análise bem-sucedida de dados de mercado."""
250
+ text = "WINV25: 140135, Volume: 5023"
251
+
252
+ result = engine.analyze_market_data(text)
253
+
254
+ assert "technical_signals" in result
255
+ assert "market_data" in result
256
+ assert len(result["technical_signals"]) > 0
257
+
258
+ def test_analyze_market_data_invalid_input(self, engine):
259
+ """Testa comportamento com entrada inválida."""
260
+ with pytest.raises(ValueError, match="Dados inválidos"):
261
+ engine.analyze_market_data("")
262
+
263
+ @patch('market_analysis.calculate_rsi')
264
+ def test_rsi_calculation_called(self, mock_rsi, engine):
265
+ """Testa se cálculo RSI é chamado."""
266
+ mock_rsi.return_value = 65.5
267
+ text = "WINV25: 140135"
268
+
269
+ engine.analyze_market_data(text)
270
+
271
+ mock_rsi.assert_called_once()
272
+
273
+ @pytest.mark.parametrize("price,expected_signal", [
274
+ (140000, "buy"),
275
+ (145000, "sell"),
276
+ (142500, "hold")
277
+ ])
278
+ def test_signal_generation(self, engine, price, expected_signal):
279
+ """Testa geração de sinais para diferentes preços."""
280
+ text = f"WINV25: {price}"
281
+
282
+ result = engine.analyze_market_data(text)
283
+ signal = result["technical_signals"][0]
284
+
285
+ assert signal["action"] == expected_signal
286
+ ```
287
+
288
+ ### Executando Testes
289
+
290
+ ```bash
291
+ # Executar todos os testes
292
+ pytest
293
+
294
+ # Executar com cobertura
295
+ pytest --cov=. --cov-report=html
296
+
297
+ # Executar testes específicos
298
+ pytest tests/test_market_analysis.py::TestTechnicalAnalysisEngine::test_analyze_market_data_success
299
+
300
+ # Executar testes em paralelo
301
+ pytest -n auto
302
+
303
+ # Executar apenas testes rápidos
304
+ pytest -m "not slow"
305
+ ```
306
+
307
+ ### Fixtures Compartilhadas
308
+
309
+ ```python
310
+ # conftest.py
311
+ import pytest
312
+ from pathlib import Path
313
+
314
+ @pytest.fixture
315
+ def sample_log_content():
316
+ """Conteúdo de log de exemplo."""
317
+ return """
318
+ ⏰ Análise #1 - 09:46:58
319
+ 📊 DADOS DE MERCADO - WINV25
320
+ Preço Atual: 140135.00000 ↗
321
+ Variação: +5 (+0.00%)
322
+ Volume: 5023
323
+ """
324
+
325
+ @pytest.fixture
326
+ def temp_log_file(tmp_path, sample_log_content):
327
+ """Arquivo de log temporário."""
328
+ log_file = tmp_path / "test_log.txt"
329
+ log_file.write_text(sample_log_content)
330
+ return log_file
331
+
332
+ @pytest.fixture
333
+ def mock_ai_model():
334
+ """Mock do modelo de IA."""
335
+ from unittest.mock import Mock
336
+
337
+ model = Mock()
338
+ model.predict.return_value = [
339
+ {"label": "POSITIVE", "score": 0.85}
340
+ ]
341
+ return model
342
+ ```
343
+
344
+ ## 🔄 Fluxo de Desenvolvimento
345
+
346
+ ### Git Workflow
347
+
348
+ ```bash
349
+ # 1. Criar branch para feature
350
+ git checkout -b feature/nova-funcionalidade
351
+
352
+ # 2. Fazer commits pequenos e frequentes
353
+ git add .
354
+ git commit -m "feat: adiciona cálculo de MACD"
355
+
356
+ # 3. Push da branch
357
+ git push origin feature/nova-funcionalidade
358
+
359
+ # 4. Criar Pull Request
360
+ # 5. Code Review
361
+ # 6. Merge após aprovação
362
+ ```
363
+
364
+ ### Convenções de Commit
365
+
366
+ ```bash
367
+ # Formato: tipo(escopo): descrição
368
+
369
+ # Tipos:
370
+ feat: nova funcionalidade
371
+ fix: correção de bug
372
+ docs: documentação
373
+ style: formatação
374
+ refactor: refatoração
375
+ test: testes
376
+ chore: tarefas de manutenção
377
+
378
+ # Exemplos:
379
+ feat(analysis): adiciona indicador MACD
380
+ fix(ui): corrige erro na interface
381
+ docs(api): atualiza documentação da API
382
+ test(fibonacci): adiciona testes para análise
383
+ ```
384
+
385
+ ### Pre-commit Hooks
386
+
387
+ ```yaml
388
+ # .pre-commit-config.yaml
389
+ repos:
390
+ - repo: https://github.com/psf/black
391
+ rev: 22.10.0
392
+ hooks:
393
+ - id: black
394
+ language_version: python3
395
+
396
+ - repo: https://github.com/pycqa/flake8
397
+ rev: 5.0.4
398
+ hooks:
399
+ - id: flake8
400
+
401
+ - repo: https://github.com/pycqa/isort
402
+ rev: 5.10.1
403
+ hooks:
404
+ - id: isort
405
+
406
+ - repo: https://github.com/pre-commit/mirrors-mypy
407
+ rev: v0.991
408
+ hooks:
409
+ - id: mypy
410
+ additional_dependencies: [types-all]
411
+
412
+ - repo: https://github.com/PyCQA/bandit
413
+ rev: 1.7.4
414
+ hooks:
415
+ - id: bandit
416
+ args: ['-r', '.', '-f', 'json', '-o', 'bandit-report.json']
417
+ ```
418
+
419
+ ## 🏗️ Adicionando Novas Funcionalidades
420
+
421
+ ### 1. Novo Indicador Técnico
422
+
423
+ ```python
424
+ # Em market_analysis.py
425
+
426
+ class MACDAnalyzer(BaseAnalyzer):
427
+ """Analisador MACD (Moving Average Convergence Divergence)."""
428
+
429
+ def __init__(self, fast_period: int = 12, slow_period: int = 26, signal_period: int = 9):
430
+ self.fast_period = fast_period
431
+ self.slow_period = slow_period
432
+ self.signal_period = signal_period
433
+
434
+ def analyze(self, prices: List[float]) -> List[TechnicalSignal]:
435
+ """Calcula MACD e gera sinais."""
436
+ if len(prices) < self.slow_period:
437
+ return []
438
+
439
+ # Calcular EMAs
440
+ ema_fast = self._calculate_ema(prices, self.fast_period)
441
+ ema_slow = self._calculate_ema(prices, self.slow_period)
442
+
443
+ # Calcular MACD
444
+ macd_line = [fast - slow for fast, slow in zip(ema_fast, ema_slow)]
445
+ signal_line = self._calculate_ema(macd_line, self.signal_period)
446
+
447
+ # Gerar sinais
448
+ signals = []
449
+ for i in range(1, len(macd_line)):
450
+ if macd_line[i] > signal_line[i] and macd_line[i-1] <= signal_line[i-1]:
451
+ signals.append(TechnicalSignal(
452
+ indicator="MACD",
453
+ signal_type="buy",
454
+ strength=0.7,
455
+ value=macd_line[i],
456
+ timestamp=datetime.now()
457
+ ))
458
+
459
+ return signals
460
+
461
+ # Registrar no engine
462
+ class TechnicalAnalysisEngine:
463
+ def __init__(self):
464
+ # ... outros analisadores
465
+ self.macd_analyzer = MACDAnalyzer()
466
+
467
+ def analyze_market_data(self, text: str) -> Dict[str, Any]:
468
+ # ... análise existente
469
+ macd_signals = self.macd_analyzer.analyze(prices)
470
+ all_signals.extend(macd_signals)
471
+ ```
472
+
473
+ ### 2. Novo Modelo de IA
474
+
475
+ ```python
476
+ # Em sentiment_analysis.py
477
+
478
+ class CustomFinancialModel:
479
+ """Modelo personalizado para análise financeira."""
480
+
481
+ def __init__(self, model_path: str):
482
+ self.model_path = model_path
483
+ self.model = None
484
+ self.tokenizer = None
485
+
486
+ def load(self):
487
+ """Carrega modelo personalizado."""
488
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
489
+
490
+ self.tokenizer = AutoTokenizer.from_pretrained(self.model_path)
491
+ self.model = AutoModelForSequenceClassification.from_pretrained(self.model_path)
492
+
493
+ def predict(self, text: str) -> Dict[str, float]:
494
+ """Faz predição de sentimento."""
495
+ inputs = self.tokenizer(text, return_tensors="pt", truncation=True, padding=True)
496
+
497
+ with torch.no_grad():
498
+ outputs = self.model(**inputs)
499
+ probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
500
+
501
+ return {
502
+ "bullish": probabilities[0][0].item(),
503
+ "bearish": probabilities[0][1].item(),
504
+ "neutral": probabilities[0][2].item()
505
+ }
506
+
507
+ # Registrar no ModelManager
508
+ class ModelManager:
509
+ def __init__(self):
510
+ # ... modelos existentes
511
+ self.custom_models = {
512
+ "financial-bert": CustomFinancialModel,
513
+ "trading-roberta": CustomFinancialModel
514
+ }
515
+ ```
516
+
517
+ ### 3. Nova Interface de Usuário
518
+
519
+ ```python
520
+ # Em ui.py
521
+
522
+ def create_advanced_analysis_tab():
523
+ """Cria aba de análise avançada."""
524
+ with gr.Tab("🔬 Análise Avançada"):
525
+ with gr.Row():
526
+ with gr.Column(scale=1):
527
+ # Controles
528
+ timeframe_dropdown = gr.Dropdown(
529
+ choices=["1m", "5m", "15m", "1h", "4h", "1d"],
530
+ value="5m",
531
+ label="📊 Timeframe"
532
+ )
533
+
534
+ indicators_checklist = gr.CheckboxGroup(
535
+ choices=["RSI", "MACD", "Bollinger", "EMA", "Fibonacci"],
536
+ value=["RSI", "MACD"],
537
+ label="📈 Indicadores"
538
+ )
539
+
540
+ analyze_btn = gr.Button("🚀 Analisar", variant="primary")
541
+
542
+ with gr.Column(scale=2):
543
+ # Resultados
544
+ analysis_output = gr.JSON(label="📊 Resultado da Análise")
545
+ chart_output = gr.Plot(label="📈 Gráfico")
546
+
547
+ # Conectar eventos
548
+ analyze_btn.click(
549
+ fn=advanced_analysis,
550
+ inputs=[timeframe_dropdown, indicators_checklist],
551
+ outputs=[analysis_output, chart_output]
552
+ )
553
+
554
+ return timeframe_dropdown, indicators_checklist, analyze_btn
555
+
556
+ def advanced_analysis(timeframe: str, indicators: List[str]) -> Tuple[Dict, Any]:
557
+ """Executa análise avançada."""
558
+ # Implementar lógica de análise
559
+ result = {
560
+ "timeframe": timeframe,
561
+ "indicators": indicators,
562
+ "signals": [],
563
+ "confidence": 0.0
564
+ }
565
+
566
+ # Gerar gráfico
567
+ import plotly.graph_objects as go
568
+ fig = go.Figure()
569
+ # ... adicionar dados ao gráfico
570
+
571
+ return result, fig
572
+ ```
573
+
574
+ ## 🔍 Debugging e Profiling
575
+
576
+ ### Logging para Debug
577
+
578
+ ```python
579
+ import logging
580
+ from utils import LogUtils
581
+
582
+ # Configurar logging detalhado
583
+ logging.basicConfig(
584
+ level=logging.DEBUG,
585
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
586
+ handlers=[
587
+ logging.FileHandler('debug.log'),
588
+ logging.StreamHandler()
589
+ ]
590
+ )
591
+
592
+ logger = logging.getLogger(__name__)
593
+
594
+ def analyze_market_data(self, text: str) -> Dict[str, Any]:
595
+ logger.debug(f"Iniciando análise para texto: {text[:100]}...")
596
+
597
+ try:
598
+ # Análise
599
+ result = self._perform_analysis(text)
600
+ logger.debug(f"Análise concluída: {len(result.get('signals', []))} sinais")
601
+ return result
602
+
603
+ except Exception as e:
604
+ logger.error(f"Erro na análise: {e}", exc_info=True)
605
+ raise
606
+ ```
607
+
608
+ ### Profiling de Performance
609
+
610
+ ```python
611
+ # performance_profiler.py
612
+ import cProfile
613
+ import pstats
614
+ from functools import wraps
615
+ from memory_profiler import profile
616
+ from line_profiler import LineProfiler
617
+
618
+ def profile_time(func):
619
+ """Decorator para profiling de tempo."""
620
+ @wraps(func)
621
+ def wrapper(*args, **kwargs):
622
+ profiler = cProfile.Profile()
623
+ profiler.enable()
624
+
625
+ result = func(*args, **kwargs)
626
+
627
+ profiler.disable()
628
+ stats = pstats.Stats(profiler)
629
+ stats.sort_stats('cumulative')
630
+ stats.print_stats(10) # Top 10 funções
631
+
632
+ return result
633
+ return wrapper
634
+
635
+ @profile_time
636
+ @profile # memory_profiler
637
+ def analyze_large_dataset(data):
638
+ """Análise de dataset grande."""
639
+ # Implementação
640
+ pass
641
+
642
+ # Usar line_profiler
643
+ def profile_line_by_line():
644
+ profiler = LineProfiler()
645
+ profiler.add_function(analyze_market_data)
646
+ profiler.enable_by_count()
647
+
648
+ # Executar função
649
+ analyze_market_data(sample_text)
650
+
651
+ profiler.print_stats()
652
+ ```
653
+
654
+ ### Debugging com pdb
655
+
656
+ ```python
657
+ import pdb
658
+
659
+ def problematic_function(data):
660
+ # Ponto de breakpoint
661
+ pdb.set_trace()
662
+
663
+ # Código para debug
664
+ processed_data = process_data(data)
665
+
666
+ # Breakpoint condicional
667
+ if len(processed_data) == 0:
668
+ pdb.set_trace()
669
+
670
+ return processed_data
671
+
672
+ # Comandos úteis no pdb:
673
+ # l - listar código
674
+ # n - próxima linha
675
+ # s - step into
676
+ # c - continuar
677
+ # p variable - imprimir variável
678
+ # pp variable - pretty print
679
+ # h - ajuda
680
+ ```
681
+
682
+ ## 📊 Monitoramento e Métricas
683
+
684
+ ### Métricas Customizadas
685
+
686
+ ```python
687
+ # custom_metrics.py
688
+ from dataclasses import dataclass
689
+ from typing import Dict, List
690
+ import time
691
+ from collections import defaultdict
692
+
693
+ @dataclass
694
+ class AnalysisMetrics:
695
+ """Métricas de análise."""
696
+ total_analyses: int = 0
697
+ successful_analyses: int = 0
698
+ failed_analyses: int = 0
699
+ average_processing_time: float = 0.0
700
+ error_types: Dict[str, int] = None
701
+
702
+ def __post_init__(self):
703
+ if self.error_types is None:
704
+ self.error_types = defaultdict(int)
705
+
706
+ class MetricsCollector:
707
+ """Coletor de métricas personalizado."""
708
+
709
+ def __init__(self):
710
+ self.metrics = AnalysisMetrics()
711
+ self.processing_times = []
712
+
713
+ def record_analysis_start(self) -> float:
714
+ """Registra início de análise."""
715
+ return time.time()
716
+
717
+ def record_analysis_success(self, start_time: float):
718
+ """Registra análise bem-sucedida."""
719
+ processing_time = time.time() - start_time
720
+
721
+ self.metrics.total_analyses += 1
722
+ self.metrics.successful_analyses += 1
723
+ self.processing_times.append(processing_time)
724
+
725
+ # Calcular média móvel
726
+ if len(self.processing_times) > 100:
727
+ self.processing_times = self.processing_times[-100:]
728
+
729
+ self.metrics.average_processing_time = sum(self.processing_times) / len(self.processing_times)
730
+
731
+ def record_analysis_failure(self, start_time: float, error_type: str):
732
+ """Registra falha na análise."""
733
+ self.metrics.total_analyses += 1
734
+ self.metrics.failed_analyses += 1
735
+ self.metrics.error_types[error_type] += 1
736
+
737
+ def get_success_rate(self) -> float:
738
+ """Calcula taxa de sucesso."""
739
+ if self.metrics.total_analyses == 0:
740
+ return 0.0
741
+ return self.metrics.successful_analyses / self.metrics.total_analyses
742
+
743
+ def export_metrics(self) -> Dict:
744
+ """Exporta métricas para análise."""
745
+ return {
746
+ "total_analyses": self.metrics.total_analyses,
747
+ "success_rate": self.get_success_rate(),
748
+ "average_processing_time": self.metrics.average_processing_time,
749
+ "error_distribution": dict(self.metrics.error_types)
750
+ }
751
+ ```
752
+
753
+ ## 🚀 Deploy e Produção
754
+
755
+ ### Configuração para Produção
756
+
757
+ ```python
758
+ # production_config.py
759
+ import os
760
+ from dataclasses import dataclass
761
+
762
+ @dataclass
763
+ class ProductionConfig:
764
+ """Configurações para produção."""
765
+
766
+ # Servidor
767
+ HOST: str = os.getenv("HOST", "0.0.0.0")
768
+ PORT: int = int(os.getenv("PORT", "7860"))
769
+ WORKERS: int = int(os.getenv("WORKERS", "4"))
770
+
771
+ # Logging
772
+ LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO")
773
+ LOG_FILE: str = os.getenv("LOG_FILE", "app.log")
774
+
775
+ # Performance
776
+ MAX_CONCURRENT_ANALYSES: int = int(os.getenv("MAX_CONCURRENT_ANALYSES", "10"))
777
+ ANALYSIS_TIMEOUT: int = int(os.getenv("ANALYSIS_TIMEOUT", "30"))
778
+
779
+ # Segurança
780
+ ENABLE_AUTH: bool = os.getenv("ENABLE_AUTH", "false").lower() == "true"
781
+ SECRET_KEY: str = os.getenv("SECRET_KEY", "")
782
+
783
+ # Cache
784
+ ENABLE_REDIS: bool = os.getenv("ENABLE_REDIS", "false").lower() == "true"
785
+ REDIS_URL: str = os.getenv("REDIS_URL", "redis://localhost:6379")
786
+ ```
787
+
788
+ ### Docker
789
+
790
+ ```dockerfile
791
+ # Dockerfile
792
+ FROM python:3.9-slim
793
+
794
+ # Instalar dependências do sistema
795
+ RUN apt-get update && apt-get install -y \
796
+ gcc \
797
+ g++ \
798
+ && rm -rf /var/lib/apt/lists/*
799
+
800
+ # Criar usuário não-root
801
+ RUN useradd --create-home --shell /bin/bash app
802
+ USER app
803
+ WORKDIR /home/app
804
+
805
+ # Copiar requirements
806
+ COPY --chown=app:app requirements.txt .
807
+
808
+ # Instalar dependências Python
809
+ RUN pip install --user --no-cache-dir -r requirements.txt
810
+
811
+ # Copiar código
812
+ COPY --chown=app:app . .
813
+
814
+ # Expor porta
815
+ EXPOSE 7860
816
+
817
+ # Comando de inicialização
818
+ CMD ["python", "app.py", "--host", "0.0.0.0", "--port", "7860"]
819
+ ```
820
+
821
+ ```yaml
822
+ # docker-compose.yml
823
+ version: '3.8'
824
+
825
+ services:
826
+ vampire-bot:
827
+ build: .
828
+ ports:
829
+ - "7860:7860"
830
+ environment:
831
+ - LOG_LEVEL=INFO
832
+ - MAX_CONCURRENT_ANALYSES=5
833
+ volumes:
834
+ - ./logs:/home/app/logs
835
+ - ./models:/home/app/models
836
+ restart: unless-stopped
837
+
838
+ redis:
839
+ image: redis:7-alpine
840
+ ports:
841
+ - "6379:6379"
842
+ volumes:
843
+ - redis_data:/data
844
+ restart: unless-stopped
845
+
846
+ volumes:
847
+ redis_data:
848
+ ```
849
+
850
+ ## 📚 Recursos Adicionais
851
+
852
+ ### Ferramentas Recomendadas
853
+
854
+ - **IDE**: VS Code com extensões Python
855
+ - **Debugging**: pdb, ipdb, VS Code debugger
856
+ - **Profiling**: cProfile, memory_profiler, line_profiler
857
+ - **Testing**: pytest, coverage.py
858
+ - **Linting**: flake8, pylint, mypy
859
+ - **Formatting**: black, isort
860
+ - **Documentation**: Sphinx, mkdocs
861
+
862
+ ### Bibliotecas Úteis
863
+
864
+ ```python
865
+ # Análise de dados
866
+ import pandas as pd
867
+ import numpy as np
868
+ from scipy import stats
869
+
870
+ # Visualização
871
+ import matplotlib.pyplot as plt
872
+ import plotly.graph_objects as go
873
+ import seaborn as sns
874
+
875
+ # Machine Learning
876
+ from sklearn.metrics import accuracy_score, classification_report
877
+ from sklearn.model_selection import train_test_split
878
+
879
+ # Async/Concorrência
880
+ import asyncio
881
+ from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
882
+
883
+ # Monitoramento
884
+ import psutil
885
+ from prometheus_client import Counter, Histogram, Gauge
886
+ ```
887
+
888
+ ### Padrões de Design Úteis
889
+
890
+ ```python
891
+ # Strategy Pattern para diferentes análises
892
+ from abc import ABC, abstractmethod
893
+
894
+ class AnalysisStrategy(ABC):
895
+ @abstractmethod
896
+ def analyze(self, data) -> Dict:
897
+ pass
898
+
899
+ class RSIStrategy(AnalysisStrategy):
900
+ def analyze(self, data) -> Dict:
901
+ # Implementar RSI
902
+ pass
903
+
904
+ class MACDStrategy(AnalysisStrategy):
905
+ def analyze(self, data) -> Dict:
906
+ # Implementar MACD
907
+ pass
908
+
909
+ # Factory Pattern para criação de analisadores
910
+ class AnalyzerFactory:
911
+ _strategies = {
912
+ "rsi": RSIStrategy,
913
+ "macd": MACDStrategy
914
+ }
915
+
916
+ @classmethod
917
+ def create_analyzer(cls, analyzer_type: str) -> AnalysisStrategy:
918
+ if analyzer_type not in cls._strategies:
919
+ raise ValueError(f"Analisador {analyzer_type} não suportado")
920
+ return cls._strategies[analyzer_type]()
921
+
922
+ # Observer Pattern para notificações
923
+ class Observable:
924
+ def __init__(self):
925
+ self._observers = []
926
+
927
+ def attach(self, observer):
928
+ self._observers.append(observer)
929
+
930
+ def notify(self, event):
931
+ for observer in self._observers:
932
+ observer.update(event)
933
+ ```
934
+
935
+ ## 🤝 Contribuindo
936
+
937
+ ### Processo de Contribuição
938
+
939
+ 1. **Fork** do repositório
940
+ 2. **Clone** do seu fork
941
+ 3. **Criar branch** para feature/bugfix
942
+ 4. **Implementar** mudanças com testes
943
+ 5. **Executar** testes e linting
944
+ 6. **Commit** seguindo convenções
945
+ 7. **Push** da branch
946
+ 8. **Criar Pull Request**
947
+ 9. **Code Review**
948
+ 10. **Merge** após aprovação
949
+
950
+ ### Checklist para Pull Requests
951
+
952
+ - [ ] Código segue padrões de estilo
953
+ - [ ] Testes adicionados/atualizados
954
+ - [ ] Documentação atualizada
955
+ - [ ] Todos os testes passam
956
+ - [ ] Sem warnings de linting
957
+ - [ ] Performance não degradada
958
+ - [ ] Compatibilidade mantida
959
+ - [ ] Changelog atualizado
960
+
961
+ ---
962
+
963
+ **🎯 Objetivo**: Manter código limpo, testável e bem documentado para facilitar manutenção e evolução do projeto!
docs/installation.md ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚀 Guia de Instalação
2
+
3
+ ## Pré-requisitos
4
+
5
+ ### Sistema Operacional
6
+ - Windows 10/11 (recomendado)
7
+ - Linux (Ubuntu 20.04+)
8
+ - macOS (10.15+)
9
+
10
+ ### Software Necessário
11
+ - **Python 3.13+** (obrigatório)
12
+ - **Git** (para clonagem do repositório)
13
+ - **Visual Studio Build Tools** (Windows - para compilação de dependências)
14
+
15
+ ## Instalação Passo a Passo
16
+
17
+ ### 1. Preparação do Ambiente
18
+
19
+ #### Windows
20
+ ```powershell
21
+ # Verificar versão do Python
22
+ python --version
23
+
24
+ # Instalar Visual Studio Build Tools (se necessário)
25
+ # Baixar de: https://visualstudio.microsoft.com/visual-cpp-build-tools/
26
+ ```
27
+
28
+ #### Linux/macOS
29
+ ```bash
30
+ # Verificar versão do Python
31
+ python3 --version
32
+
33
+ # Instalar dependências do sistema (Ubuntu)
34
+ sudo apt update
35
+ sudo apt install python3-pip python3-venv build-essential
36
+ ```
37
+
38
+ ### 2. Clonagem do Repositório
39
+
40
+ ```bash
41
+ git clone <repository-url>
42
+ cd vampire-trading-bot
43
+ ```
44
+
45
+ ### 3. Criação do Ambiente Virtual
46
+
47
+ #### Windows
48
+ ```powershell
49
+ # Criar ambiente virtual
50
+ python -m venv venv
51
+
52
+ # Ativar ambiente virtual
53
+ .\venv\Scripts\Activate.ps1
54
+ ```
55
+
56
+ #### Linux/macOS
57
+ ```bash
58
+ # Criar ambiente virtual
59
+ python3 -m venv venv
60
+
61
+ # Ativar ambiente virtual
62
+ source venv/bin/activate
63
+ ```
64
+
65
+ ### 4. Instalação das Dependências
66
+
67
+ ```bash
68
+ # Atualizar pip
69
+ pip install --upgrade pip
70
+
71
+ # Instalar dependências principais
72
+ pip install -r requirements.txt
73
+ ```
74
+
75
+ #### Dependências Principais
76
+ - `gradio==4.44.0` - Interface web
77
+ - `transformers` - Modelos de IA
78
+ - `torch` - Framework de deep learning
79
+ - `numpy` - Computação numérica
80
+ - `pandas` - Manipulação de dados
81
+ - `scipy` - Computação científica
82
+ - `psutil` - Monitoramento de sistema
83
+
84
+ ### 5. Verificação da Instalação
85
+
86
+ ```bash
87
+ # Testar importações principais
88
+ python -c "import gradio, transformers, torch, numpy, pandas; print('✅ Todas as dependências instaladas com sucesso!')"
89
+
90
+ # Executar aplicação em modo de teste
91
+ python app.py
92
+ ```
93
+
94
+ ## Resolução de Problemas Comuns
95
+
96
+ ### Erro de Compilação do Rust (tokenizers)
97
+
98
+ **Problema**: Erro ao instalar `tokenizers` devido à falta do Rust
99
+
100
+ **Solução**:
101
+ ```bash
102
+ # Instalar versão mais recente do transformers
103
+ pip install --upgrade transformers
104
+
105
+ # Ou instalar Rust (alternativa)
106
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
107
+ ```
108
+
109
+ ### Erro do pyaudioop (Python 3.13)
110
+
111
+ **Problema**: `ModuleNotFoundError: No module named 'pyaudioop'`
112
+
113
+ **Solução**:
114
+ ```bash
115
+ # Atualizar Gradio para versão mais recente
116
+ pip install --upgrade gradio
117
+
118
+ # O audioop-lts será instalado automaticamente
119
+ ```
120
+
121
+ ### Problemas de Memória
122
+
123
+ **Problema**: Erro de memória ao carregar modelos de IA
124
+
125
+ **Solução**:
126
+ - Usar modelos menores (configurar em `config.py`)
127
+ - Aumentar memória virtual do sistema
128
+ - Executar em modo standalone (sem IA)
129
+
130
+ ### Problemas de Permissão (Windows)
131
+
132
+ **Problema**: Erro de permissão ao executar scripts
133
+
134
+ **Solução**:
135
+ ```powershell
136
+ # Alterar política de execução
137
+ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
138
+ ```
139
+
140
+ ## Configuração Inicial
141
+
142
+ ### 1. Configurar Modelos de IA
143
+
144
+ Edite o arquivo `config.py`:
145
+
146
+ ```python
147
+ # Modelos disponíveis (do menor para o maior)
148
+ FINANCIAL_MODELS = [
149
+ "nlptown/bert-base-multilingual-uncased-sentiment", # Mais leve
150
+ "cardiffnlp/twitter-roberta-base-sentiment-latest", # Médio
151
+ "ProsusAI/finbert" # Mais pesado, melhor precisão
152
+ ]
153
+ ```
154
+
155
+ ### 2. Configurar Caminhos de Log
156
+
157
+ Para integração em tempo real, configure o caminho dos logs:
158
+
159
+ ```python
160
+ # Em real_time_integration.py
161
+ LOG_FILE_PATH = "caminho/para/seus/logs/trading.log"
162
+ ```
163
+
164
+ ### 3. Configurar Interface
165
+
166
+ Personalize a interface em `config.py`:
167
+
168
+ ```python
169
+ class UIConfig:
170
+ TITLE = "Seu Título Personalizado"
171
+ SUBTITLE = "Sua Descrição"
172
+ # ... outras configurações
173
+ ```
174
+
175
+ ## Execução
176
+
177
+ ### Modo Desenvolvimento
178
+ ```bash
179
+ # Executar com reload automático
180
+ python app.py
181
+ ```
182
+
183
+ ### Modo Produção
184
+ ```bash
185
+ # Executar com configurações otimizadas
186
+ python app.py --share=False --server_name=0.0.0.0 --server_port=7860
187
+ ```
188
+
189
+ ### Modo Standalone (Sem IA)
190
+ ```bash
191
+ # Executar sem dependências de IA
192
+ python app.py --no-ai
193
+ ```
194
+
195
+ ## Verificação Final
196
+
197
+ Após a instalação, verifique se:
198
+
199
+ 1. ✅ O aplicativo inicia sem erros
200
+ 2. ✅ A interface web carrega em `http://localhost:7860`
201
+ 3. ✅ As análises técnicas funcionam
202
+ 4. ✅ Os modelos de IA carregam (se disponíveis)
203
+ 5. ✅ O monitoramento de performance está ativo
204
+
205
+ ## Próximos Passos
206
+
207
+ - Leia a [Documentação da Arquitetura](architecture.md)
208
+ - Configure suas preferências em [Configuração](configuration.md)
209
+ - Explore a [Referência da API](api-reference.md)
210
+
211
+ ## Suporte
212
+
213
+ Para problemas não cobertos neste guia, consulte:
214
+ - [Troubleshooting](troubleshooting.md)
215
+ - [Issues do GitHub](link-para-issues)
216
+ - Documentação oficial das dependências
docs/troubleshooting.md ADDED
@@ -0,0 +1,679 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🔧 Guia de Troubleshooting
2
+
3
+ ## Visão Geral
4
+
5
+ Este guia ajuda a resolver problemas comuns encontrados ao usar o Vampire Trading Bot. Os problemas estão organizados por categoria com soluções passo a passo.
6
+
7
+ ## 🚨 Problemas de Instalação
8
+
9
+ ### Erro: "Microsoft Visual C++ 14.0 is required"
10
+
11
+ **Sintomas**:
12
+ ```
13
+ error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools"
14
+ ```
15
+
16
+ **Causa**: Falta de ferramentas de compilação no Windows.
17
+
18
+ **Solução**:
19
+ 1. Baixe e instale o [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
20
+ 2. Durante a instalação, selecione "C++ build tools"
21
+ 3. Reinicie o terminal e tente novamente:
22
+ ```bash
23
+ pip install -r requirements.txt
24
+ ```
25
+
26
+ ### Erro: "No module named 'pyaudioop'"
27
+
28
+ **Sintomas**:
29
+ ```
30
+ ModuleNotFoundError: No module named 'pyaudioop'
31
+ ```
32
+
33
+ **Causa**: Incompatibilidade com Python 3.13.
34
+
35
+ **Solução**:
36
+ ```bash
37
+ # Atualizar Gradio para versão mais recente
38
+ pip install --upgrade gradio
39
+
40
+ # Verificar se audioop-lts foi instalado
41
+ pip list | grep audioop
42
+ ```
43
+
44
+ ### Erro: "Failed building wheel for tokenizers"
45
+
46
+ **Sintomas**:
47
+ ```
48
+ Failed building wheel for tokenizers
49
+ ERROR: Could not build wheels for tokenizers
50
+ ```
51
+
52
+ **Causa**: Falta do compilador Rust.
53
+
54
+ **Soluções**:
55
+
56
+ **Opção 1 - Usar versão pré-compilada**:
57
+ ```bash
58
+ pip install --upgrade transformers
59
+ ```
60
+
61
+ **Opção 2 - Instalar Rust**:
62
+ ```bash
63
+ # Windows (PowerShell)
64
+ Invoke-WebRequest -Uri https://win.rustup.rs/ -OutFile rustup-init.exe
65
+ .\rustup-init.exe
66
+
67
+ # Linux/macOS
68
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
69
+ source ~/.cargo/env
70
+ ```
71
+
72
+ ### Erro: "Permission denied" (Windows)
73
+
74
+ **Sintomas**:
75
+ ```
76
+ PermissionError: [WinError 5] Access is denied
77
+ ```
78
+
79
+ **Solução**:
80
+ ```powershell
81
+ # Alterar política de execução
82
+ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
83
+
84
+ # Executar como administrador se necessário
85
+ ```
86
+
87
+ ## 🤖 Problemas com Modelos de IA
88
+
89
+ ### Erro: "OutOfMemoryError" ao carregar modelo
90
+
91
+ **Sintomas**:
92
+ ```
93
+ torch.cuda.OutOfMemoryError: CUDA out of memory
94
+ # ou
95
+ RuntimeError: [enforce fail at alloc_cpu.cpp:75]
96
+ ```
97
+
98
+ **Soluções**:
99
+
100
+ **1. Usar modelo mais leve**:
101
+ ```python
102
+ # Em config.py
103
+ FinancialModels.DEFAULT_MODEL = "nlptown/bert-base-multilingual-uncased-sentiment"
104
+ ```
105
+
106
+ **2. Reduzir tamanho do texto**:
107
+ ```python
108
+ # Em config.py
109
+ AIConfig.MAX_TEXT_LENGTH = 256 # Reduzir de 512
110
+ AIConfig.BATCH_SIZE = 4 # Reduzir de 8
111
+ ```
112
+
113
+ **3. Forçar uso de CPU**:
114
+ ```python
115
+ # Em config.py
116
+ AIConfig.USE_GPU = False
117
+ ```
118
+
119
+ **4. Executar em modo standalone**:
120
+ ```bash
121
+ python app.py --no-ai
122
+ ```
123
+
124
+ ### Erro: "Model not found" ou "Repository not found"
125
+
126
+ **Sintomas**:
127
+ ```
128
+ OSError: Repository not found
129
+ HTTPError: 404 Client Error
130
+ ```
131
+
132
+ **Soluções**:
133
+
134
+ **1. Verificar conectividade**:
135
+ ```python
136
+ import requests
137
+ response = requests.get("https://huggingface.co")
138
+ print(f"Status: {response.status_code}")
139
+ ```
140
+
141
+ **2. Usar modelo alternativo**:
142
+ ```python
143
+ # Em config.py
144
+ FinancialModels.DEFAULT_MODEL = "cardiffnlp/twitter-roberta-base-sentiment-latest"
145
+ ```
146
+
147
+ **3. Cache offline**:
148
+ ```bash
149
+ # Baixar modelo manualmente
150
+ from transformers import pipeline
151
+ pipeline("sentiment-analysis", model="nlptown/bert-base-multilingual-uncased-sentiment")
152
+ ```
153
+
154
+ ### Modelo carrega muito lentamente
155
+
156
+ **Sintomas**: Demora excessiva no primeiro carregamento.
157
+
158
+ **Soluções**:
159
+
160
+ **1. Habilitar cache**:
161
+ ```python
162
+ # Em config.py
163
+ AIConfig.ENABLE_MODEL_CACHE = True
164
+ AIConfig.CACHE_SIZE = 100
165
+ ```
166
+
167
+ **2. Pré-carregar modelos**:
168
+ ```python
169
+ # Adicionar ao início do app.py
170
+ from sentiment_analysis import SentimentAnalysisEngine
171
+ engine = SentimentAnalysisEngine()
172
+ engine.model_manager.load_model() # Pré-carrega
173
+ ```
174
+
175
+ **3. Usar modelo local**:
176
+ ```bash
177
+ # Baixar modelo para pasta local
178
+ mkdir models
179
+ # Configurar caminho local em config.py
180
+ ```
181
+
182
+ ## 🖥️ Problemas de Interface
183
+
184
+ ### Interface não carrega (erro 500)
185
+
186
+ **Sintomas**: Página em branco ou erro 500 no navegador.
187
+
188
+ **Diagnóstico**:
189
+ ```bash
190
+ # Verificar logs no terminal
191
+ python -u app.py
192
+
193
+ # Verificar porta
194
+ netstat -an | findstr 7860
195
+ ```
196
+
197
+ **Soluções**:
198
+
199
+ **1. Verificar dependências**:
200
+ ```python
201
+ try:
202
+ import gradio as gr
203
+ print(f"Gradio versão: {gr.__version__}")
204
+ except ImportError as e:
205
+ print(f"Erro ao importar Gradio: {e}")
206
+ ```
207
+
208
+ **2. Usar porta diferente**:
209
+ ```bash
210
+ python app.py --server_port=8080
211
+ ```
212
+
213
+ **3. Modo debug**:
214
+ ```python
215
+ # Em app.py
216
+ demo.launch(debug=True, show_error=True)
217
+ ```
218
+
219
+ ### Interface trava durante análise
220
+
221
+ **Sintomas**: Interface não responde após submeter análise.
222
+
223
+ **Soluções**:
224
+
225
+ **1. Verificar timeout**:
226
+ ```python
227
+ # Em config.py
228
+ AIConfig.MODEL_LOAD_TIMEOUT = 120 # Aumentar timeout
229
+ ```
230
+
231
+ **2. Adicionar indicador de progresso**:
232
+ ```python
233
+ # Em ui.py
234
+ def analyze_with_progress(text):
235
+ yield "🔄 Iniciando análise..."
236
+ # ... análise
237
+ yield "✅ Análise concluída!"
238
+ ```
239
+
240
+ **3. Processamento assíncrono**:
241
+ ```python
242
+ import asyncio
243
+
244
+ async def async_analysis(text):
245
+ # Análise em background
246
+ pass
247
+ ```
248
+
249
+ ### Erro: "Connection refused" ou "Address already in use"
250
+
251
+ **Sintomas**:
252
+ ```
253
+ OSError: [Errno 98] Address already in use
254
+ ConnectionRefusedError: [Errno 111] Connection refused
255
+ ```
256
+
257
+ **Soluções**:
258
+
259
+ **1. Verificar processos na porta**:
260
+ ```bash
261
+ # Windows
262
+ netstat -ano | findstr :7860
263
+ taskkill /PID <PID> /F
264
+
265
+ # Linux/macOS
266
+ lsof -ti:7860 | xargs kill -9
267
+ ```
268
+
269
+ **2. Usar porta diferente**:
270
+ ```bash
271
+ python app.py --server_port=8080
272
+ ```
273
+
274
+ ## 📊 Problemas de Performance
275
+
276
+ ### Alto uso de CPU/Memória
277
+
278
+ **Sintomas**: Sistema lento, ventilador alto.
279
+
280
+ **Diagnóstico**:
281
+ ```python
282
+ # Verificar uso de recursos
283
+ from performance_monitor import PerformanceMonitor
284
+ monitor = PerformanceMonitor()
285
+ monitor.start_monitoring()
286
+ print(monitor.get_current_metrics())
287
+ ```
288
+
289
+ **Soluções**:
290
+
291
+ **1. Otimizar configurações**:
292
+ ```python
293
+ # Em config.py
294
+ AIConfig.MAX_TEXT_LENGTH = 256
295
+ AIConfig.BATCH_SIZE = 2
296
+ AIConfig.USE_GPU = False
297
+ ```
298
+
299
+ **2. Limitar histórico**:
300
+ ```python
301
+ # Em performance_monitor.py
302
+ PerformanceMonitor(max_metrics_history=100)
303
+ ```
304
+
305
+ **3. Desabilitar recursos**:
306
+ ```python
307
+ # Desabilitar monitoramento em tempo real
308
+ real_time_integration = None
309
+ ```
310
+
311
+ ### Análises muito lentas
312
+
313
+ **Sintomas**: Demora excessiva para gerar resultados.
314
+
315
+ **Soluções**:
316
+
317
+ **1. Profile de performance**:
318
+ ```python
319
+ import cProfile
320
+
321
+ def profile_analysis():
322
+ cProfile.run('engine.analyze_market_data(text)')
323
+ ```
324
+
325
+ **2. Cache de resultados**:
326
+ ```python
327
+ from functools import lru_cache
328
+
329
+ @lru_cache(maxsize=100)
330
+ def cached_analysis(text_hash):
331
+ return engine.analyze_market_data(text)
332
+ ```
333
+
334
+ **3. Processamento paralelo**:
335
+ ```python
336
+ from concurrent.futures import ThreadPoolExecutor
337
+
338
+ with ThreadPoolExecutor(max_workers=2) as executor:
339
+ future = executor.submit(analyze_function, text)
340
+ result = future.result(timeout=30)
341
+ ```
342
+
343
+ ## 📁 Problemas de Arquivos e Logs
344
+
345
+ ### Erro: "File not found" para logs
346
+
347
+ **Sintomas**:
348
+ ```
349
+ FileNotFoundError: [Errno 2] No such file or directory: 'trading.log'
350
+ ```
351
+
352
+ **Soluções**:
353
+
354
+ **1. Verificar caminho**:
355
+ ```python
356
+ from pathlib import Path
357
+ log_path = Path("d:/hugging_face_spaces/text")
358
+ print(f"Existe: {log_path.exists()}")
359
+ print(f"É arquivo: {log_path.is_file()}")
360
+ ```
361
+
362
+ **2. Criar arquivo de exemplo**:
363
+ ```python
364
+ # Criar log de exemplo para testes
365
+ with open("sample_log.txt", "w") as f:
366
+ f.write("""⏰ Análise #1 - 09:46:58
367
+ 📊 DADOS DE MERCADO - WINV25
368
+ Preço Atual: 140135.00000 ↗
369
+ """)
370
+ ```
371
+
372
+ **3. Configurar caminho correto**:
373
+ ```python
374
+ # Em real_time_integration.py
375
+ LOG_FILE_PATH = "caminho/correto/para/logs.txt"
376
+ ```
377
+
378
+ ### Erro de permissão em arquivos
379
+
380
+ **Sintomas**:
381
+ ```
382
+ PermissionError: [Errno 13] Permission denied
383
+ ```
384
+
385
+ **Soluções**:
386
+
387
+ **1. Verificar permissões**:
388
+ ```bash
389
+ # Linux/macOS
390
+ ls -la arquivo.log
391
+ chmod 644 arquivo.log
392
+
393
+ # Windows
394
+ icacls arquivo.log
395
+ ```
396
+
397
+ **2. Executar como administrador**:
398
+ ```bash
399
+ # Windows (PowerShell como Admin)
400
+ python app.py
401
+ ```
402
+
403
+ ## 🔄 Problemas de Integração em Tempo Real
404
+
405
+ ### FileWatcher não detecta mudanças
406
+
407
+ **Sintomas**: Logs atualizados mas sistema não processa.
408
+
409
+ **Diagnóstico**:
410
+ ```python
411
+ from real_time_integration import FileWatcher
412
+
413
+ def test_callback(content):
414
+ print(f"Arquivo mudou: {len(content)} caracteres")
415
+
416
+ watcher = FileWatcher("test.txt", test_callback)
417
+ watcher.start()
418
+ ```
419
+
420
+ **Soluções**:
421
+
422
+ **1. Verificar intervalo**:
423
+ ```python
424
+ # Em real_time_integration.py
425
+ config = RealTimeConfig(
426
+ log_file_path="logs.txt",
427
+ check_interval=0.5 # Reduzir intervalo
428
+ )
429
+ ```
430
+
431
+ **2. Forçar flush do arquivo**:
432
+ ```python
433
+ # No sistema que gera logs
434
+ with open("logs.txt", "a") as f:
435
+ f.write("nova linha\n")
436
+ f.flush() # Forçar escrita
437
+ ```
438
+
439
+ ### Eventos duplicados
440
+
441
+ **Sintomas**: Mesmo evento processado múltiplas vezes.
442
+
443
+ **Solução**:
444
+ ```python
445
+ # Adicionar deduplicação
446
+ class EventDeduplicator:
447
+ def __init__(self):
448
+ self.processed_events = set()
449
+
450
+ def is_duplicate(self, event_hash):
451
+ if event_hash in self.processed_events:
452
+ return True
453
+ self.processed_events.add(event_hash)
454
+ return False
455
+ ```
456
+
457
+ ## 🧪 Problemas de Desenvolvimento
458
+
459
+ ### Erro ao importar módulos
460
+
461
+ **Sintomas**:
462
+ ```
463
+ ModuleNotFoundError: No module named 'market_analysis'
464
+ ```
465
+
466
+ **Soluções**:
467
+
468
+ **1. Verificar PYTHONPATH**:
469
+ ```bash
470
+ # Windows
471
+ set PYTHONPATH=%PYTHONPATH%;D:\hugging_face_spaces
472
+
473
+ # Linux/macOS
474
+ export PYTHONPATH=$PYTHONPATH:/path/to/project
475
+ ```
476
+
477
+ **2. Usar imports relativos**:
478
+ ```python
479
+ # Em vez de
480
+ from market_analysis import TechnicalAnalysisEngine
481
+
482
+ # Use
483
+ from .market_analysis import TechnicalAnalysisEngine
484
+ ```
485
+
486
+ **3. Adicionar ao sys.path**:
487
+ ```python
488
+ import sys
489
+ import os
490
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
491
+ ```
492
+
493
+ ### Erro de encoding
494
+
495
+ **Sintomas**:
496
+ ```
497
+ UnicodeDecodeError: 'utf-8' codec can't decode
498
+ ```
499
+
500
+ **Soluções**:
501
+
502
+ **1. Especificar encoding**:
503
+ ```python
504
+ with open("arquivo.txt", "r", encoding="utf-8") as f:
505
+ content = f.read()
506
+ ```
507
+
508
+ **2. Detectar encoding automaticamente**:
509
+ ```python
510
+ import chardet
511
+
512
+ with open("arquivo.txt", "rb") as f:
513
+ raw_data = f.read()
514
+ encoding = chardet.detect(raw_data)['encoding']
515
+ content = raw_data.decode(encoding)
516
+ ```
517
+
518
+ ## 🔍 Ferramentas de Diagnóstico
519
+
520
+ ### Script de Diagnóstico Completo
521
+
522
+ ```python
523
+ #!/usr/bin/env python3
524
+ # diagnostic.py
525
+
526
+ import sys
527
+ import os
528
+ import importlib
529
+ import platform
530
+ import psutil
531
+ from pathlib import Path
532
+
533
+ def run_diagnostics():
534
+ print("🔍 DIAGNÓSTICO DO VAMPIRE TRADING BOT")
535
+ print("=" * 50)
536
+
537
+ # Sistema
538
+ print(f"🖥️ Sistema: {platform.system()} {platform.release()}")
539
+ print(f"🐍 Python: {sys.version}")
540
+ print(f"📁 Diretório: {os.getcwd()}")
541
+
542
+ # Recursos
543
+ print(f"💾 RAM: {psutil.virtual_memory().total // (1024**3)} GB")
544
+ print(f"🔥 CPU: {psutil.cpu_count()} cores")
545
+
546
+ # Dependências
547
+ print("\n📦 DEPENDÊNCIAS:")
548
+ dependencies = [
549
+ 'gradio', 'transformers', 'torch',
550
+ 'numpy', 'pandas', 'scipy', 'psutil'
551
+ ]
552
+
553
+ for dep in dependencies:
554
+ try:
555
+ module = importlib.import_module(dep)
556
+ version = getattr(module, '__version__', 'N/A')
557
+ print(f"✅ {dep}: {version}")
558
+ except ImportError:
559
+ print(f"❌ {dep}: NÃO INSTALADO")
560
+
561
+ # Arquivos
562
+ print("\n📁 ARQUIVOS:")
563
+ files = [
564
+ 'app.py', 'config.py', 'market_analysis.py',
565
+ 'sentiment_analysis.py', 'ui.py', 'requirements.txt'
566
+ ]
567
+
568
+ for file in files:
569
+ path = Path(file)
570
+ if path.exists():
571
+ size = path.stat().st_size
572
+ print(f"✅ {file}: {size} bytes")
573
+ else:
574
+ print(f"❌ {file}: NÃO ENCONTRADO")
575
+
576
+ # Teste de importação
577
+ print("\n🧪 TESTE DE IMPORTAÇÃO:")
578
+ modules = [
579
+ 'market_analysis', 'sentiment_analysis',
580
+ 'fibonacci_analysis', 'ui'
581
+ ]
582
+
583
+ for module in modules:
584
+ try:
585
+ importlib.import_module(module)
586
+ print(f"✅ {module}: OK")
587
+ except Exception as e:
588
+ print(f"❌ {module}: {str(e)[:50]}...")
589
+
590
+ print("\n🏁 Diagnóstico concluído!")
591
+
592
+ if __name__ == "__main__":
593
+ run_diagnostics()
594
+ ```
595
+
596
+ ### Script de Teste de Performance
597
+
598
+ ```python
599
+ #!/usr/bin/env python3
600
+ # performance_test.py
601
+
602
+ import time
603
+ import psutil
604
+ from memory_profiler import profile
605
+
606
+ @profile
607
+ def test_analysis_performance():
608
+ """Testa performance das análises."""
609
+
610
+ # Simular análise técnica
611
+ start_time = time.time()
612
+
613
+ # Teste de análise
614
+ sample_text = "Preço: 140135, Variação: +5, Volume: 5023"
615
+
616
+ try:
617
+ from market_analysis import TechnicalAnalysisEngine
618
+ engine = TechnicalAnalysisEngine()
619
+ result = engine.analyze_market_data(sample_text)
620
+
621
+ end_time = time.time()
622
+ analysis_time = end_time - start_time
623
+
624
+ print(f"⏱️ Tempo de análise: {analysis_time:.2f}s")
625
+ print(f"💾 Uso de memória: {psutil.Process().memory_info().rss / 1024 / 1024:.1f} MB")
626
+ print(f"🔥 Uso de CPU: {psutil.cpu_percent()}%")
627
+
628
+ return True
629
+
630
+ except Exception as e:
631
+ print(f"❌ Erro na análise: {e}")
632
+ return False
633
+
634
+ if __name__ == "__main__":
635
+ test_analysis_performance()
636
+ ```
637
+
638
+ ## 📞 Obtendo Ajuda
639
+
640
+ ### Informações para Suporte
641
+
642
+ Ao reportar problemas, inclua:
643
+
644
+ 1. **Informações do sistema**:
645
+ ```bash
646
+ python diagnostic.py > diagnostic_report.txt
647
+ ```
648
+
649
+ 2. **Logs de erro completos**:
650
+ ```bash
651
+ python app.py > app_log.txt 2>&1
652
+ ```
653
+
654
+ 3. **Configurações utilizadas**:
655
+ ```python
656
+ # Exportar configurações
657
+ from config import *
658
+ print(f"Modelo: {FinancialModels.DEFAULT_MODEL}")
659
+ print(f"RSI: {TechnicalAnalysis.RSI_PERIOD}")
660
+ ```
661
+
662
+ ### Recursos Adicionais
663
+
664
+ - 📚 [Documentação da Arquitetura](architecture.md)
665
+ - ⚙️ [Guia de Configuração](configuration.md)
666
+ - 🚀 [Guia de Instalação](installation.md)
667
+ - 📖 [Referência da API](api-reference.md)
668
+ - 👨‍💻 [Guia do Desenvolvedor](developer-guide.md)
669
+
670
+ ### Comunidade e Suporte
671
+
672
+ - 🐛 **Issues**: Para reportar bugs
673
+ - 💬 **Discussões**: Para dúvidas gerais
674
+ - 📧 **Email**: Para suporte direto
675
+ - 📖 **Wiki**: Para documentação adicional
676
+
677
+ ---
678
+
679
+ **💡 Dica**: Mantenha sempre uma cópia de backup das suas configurações antes de fazer alterações significativas!
fibonacci_analysis.py ADDED
@@ -0,0 +1,528 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+ from typing import Dict, List, Tuple, Optional, Any
4
+ from dataclasses import dataclass, asdict
5
+ import logging
6
+ from log_parser import FibonacciAnalysis, BotAnalysis
7
+
8
+ # Configurar logging
9
+ logging.basicConfig(level=logging.INFO)
10
+ logger = logging.getLogger(__name__)
11
+
12
+ @dataclass
13
+ class FibonacciLevel:
14
+ """Estrutura para um nível de Fibonacci"""
15
+ level: float
16
+ price: float
17
+ type: str # 'retracement', 'extension', 'projection'
18
+ ratio: float
19
+ distance_from_current: float
20
+ strength: float
21
+
22
+ @dataclass
23
+ class SwingPoint:
24
+ """Estrutura para pontos de swing"""
25
+ price: float
26
+ timestamp: str
27
+ type: str # 'high' ou 'low'
28
+ strength: float
29
+
30
+ @dataclass
31
+ class ConfluenceZone:
32
+ """Estrutura para zonas de confluência"""
33
+ price_range: Tuple[float, float]
34
+ levels_count: int
35
+ strength: float
36
+ types: List[str]
37
+
38
+ @dataclass
39
+ class HarmonicPattern:
40
+ """Estrutura para padrões harmônicos"""
41
+ name: str
42
+ completion_point: float
43
+ confidence: float
44
+ target_levels: List[float]
45
+ stop_loss: float
46
+
47
+ @dataclass
48
+ class AdvancedFibonacciAnalysis:
49
+ """Análise avançada de Fibonacci completa"""
50
+ swing_high: float
51
+ swing_low: float
52
+ current_price: float
53
+ swing_range: float
54
+ retracement_levels: List[FibonacciLevel]
55
+ extension_levels: List[FibonacciLevel]
56
+ projection_levels: List[FibonacciLevel]
57
+ confluence_zones: List[ConfluenceZone]
58
+ harmonic_patterns: List[HarmonicPattern]
59
+ key_support: float
60
+ key_resistance: float
61
+ trend_direction: str
62
+ fibonacci_zone: str
63
+ overall_strength: float
64
+ trading_signal: str
65
+ alerts_count: int
66
+
67
+ class AdvancedFibonacciEngine:
68
+ """Engine para análise avançada de Fibonacci"""
69
+
70
+ def __init__(self):
71
+ # Ratios de Fibonacci padrão
72
+ self.retracement_ratios = [0.236, 0.382, 0.5, 0.618, 0.786]
73
+ self.extension_ratios = [1.272, 1.414, 1.618, 2.0, 2.618]
74
+ self.projection_ratios = [0.618, 1.0, 1.272, 1.618]
75
+
76
+ # Configurações de confluência
77
+ self.confluence_threshold = 0.001 # 0.1% de tolerância
78
+ self.min_confluence_levels = 2
79
+
80
+ # Padrões harmônicos
81
+ self.harmonic_patterns = {
82
+ 'Gartley': {'XA': 0.618, 'AB': 0.618, 'BC': 0.786, 'CD': 1.272},
83
+ 'Butterfly': {'XA': 0.786, 'AB': 0.618, 'BC': 0.886, 'CD': 1.618},
84
+ 'Bat': {'XA': 0.382, 'AB': 0.618, 'BC': 0.886, 'CD': 2.618},
85
+ 'Crab': {'XA': 0.618, 'AB': 0.618, 'BC': 0.886, 'CD': 3.618}
86
+ }
87
+
88
+ def analyze_from_bot_data(self, bot_analysis: BotAnalysis) -> AdvancedFibonacciAnalysis:
89
+ """Analisa dados do bot externo"""
90
+ fib_data = bot_analysis.fibonacci_analysis
91
+ market_data = bot_analysis.market_data
92
+
93
+ return self.perform_advanced_analysis(
94
+ swing_high=fib_data.swing_high,
95
+ swing_low=fib_data.swing_low,
96
+ current_price=fib_data.current_price,
97
+ historical_data=None, # Pode ser expandido futuramente
98
+ bot_fibonacci_data=fib_data
99
+ )
100
+
101
+ def perform_advanced_analysis(
102
+ self,
103
+ swing_high: float,
104
+ swing_low: float,
105
+ current_price: float,
106
+ historical_data: Optional[pd.DataFrame] = None,
107
+ bot_fibonacci_data: Optional[FibonacciAnalysis] = None
108
+ ) -> AdvancedFibonacciAnalysis:
109
+ """Realiza análise avançada de Fibonacci"""
110
+
111
+ try:
112
+ swing_range = swing_high - swing_low
113
+
114
+ # Calcular níveis de retracement
115
+ retracement_levels = self._calculate_retracement_levels(
116
+ swing_high, swing_low, current_price
117
+ )
118
+
119
+ # Calcular níveis de extensão
120
+ extension_levels = self._calculate_extension_levels(
121
+ swing_high, swing_low, current_price
122
+ )
123
+
124
+ # Calcular níveis de projeção
125
+ projection_levels = self._calculate_projection_levels(
126
+ swing_high, swing_low, current_price
127
+ )
128
+
129
+ # Identificar zonas de confluência
130
+ all_levels = retracement_levels + extension_levels + projection_levels
131
+ confluence_zones = self._identify_confluence_zones(all_levels)
132
+
133
+ # Detectar padrões harmônicos
134
+ harmonic_patterns = self._detect_harmonic_patterns(
135
+ swing_high, swing_low, current_price, historical_data
136
+ )
137
+
138
+ # Determinar suporte e resistência chave
139
+ key_support, key_resistance = self._determine_key_levels(
140
+ all_levels, current_price
141
+ )
142
+
143
+ # Determinar direção da tendência
144
+ trend_direction = self._determine_trend_direction(
145
+ swing_high, swing_low, current_price
146
+ )
147
+
148
+ # Determinar zona de Fibonacci
149
+ fibonacci_zone = self._determine_fibonacci_zone(
150
+ swing_high, swing_low, current_price
151
+ )
152
+
153
+ # Calcular força geral da análise
154
+ overall_strength = self._calculate_overall_strength(
155
+ retracement_levels, extension_levels, confluence_zones, harmonic_patterns
156
+ )
157
+
158
+ # Gerar sinal de trading
159
+ trading_signal = self._generate_trading_signal(
160
+ current_price, key_support, key_resistance, trend_direction, overall_strength
161
+ )
162
+
163
+ # Contar alertas (baseado nos dados do bot se disponível)
164
+ alerts_count = bot_fibonacci_data.alerts if bot_fibonacci_data else len(confluence_zones)
165
+
166
+ return AdvancedFibonacciAnalysis(
167
+ swing_high=swing_high,
168
+ swing_low=swing_low,
169
+ current_price=current_price,
170
+ swing_range=swing_range,
171
+ retracement_levels=retracement_levels,
172
+ extension_levels=extension_levels,
173
+ projection_levels=projection_levels,
174
+ confluence_zones=confluence_zones,
175
+ harmonic_patterns=harmonic_patterns,
176
+ key_support=key_support,
177
+ key_resistance=key_resistance,
178
+ trend_direction=trend_direction,
179
+ fibonacci_zone=fibonacci_zone,
180
+ overall_strength=overall_strength,
181
+ trading_signal=trading_signal,
182
+ alerts_count=alerts_count
183
+ )
184
+
185
+ except Exception as e:
186
+ logger.error(f"Erro na análise avançada de Fibonacci: {e}")
187
+ raise
188
+
189
+ def _calculate_retracement_levels(
190
+ self, swing_high: float, swing_low: float, current_price: float
191
+ ) -> List[FibonacciLevel]:
192
+ """Calcula níveis de retracement de Fibonacci"""
193
+ levels = []
194
+ swing_range = swing_high - swing_low
195
+
196
+ for ratio in self.retracement_ratios:
197
+ price = swing_high - (swing_range * ratio)
198
+ distance = abs(current_price - price)
199
+ strength = self._calculate_level_strength(price, current_price, 'retracement')
200
+
201
+ levels.append(FibonacciLevel(
202
+ level=ratio,
203
+ price=price,
204
+ type='retracement',
205
+ ratio=ratio,
206
+ distance_from_current=distance,
207
+ strength=strength
208
+ ))
209
+
210
+ return sorted(levels, key=lambda x: x.distance_from_current)
211
+
212
+ def _calculate_extension_levels(
213
+ self, swing_high: float, swing_low: float, current_price: float
214
+ ) -> List[FibonacciLevel]:
215
+ """Calcula níveis de extensão de Fibonacci"""
216
+ levels = []
217
+ swing_range = swing_high - swing_low
218
+
219
+ for ratio in self.extension_ratios:
220
+ # Extensão para cima
221
+ price_up = swing_high + (swing_range * (ratio - 1))
222
+ distance_up = abs(current_price - price_up)
223
+ strength_up = self._calculate_level_strength(price_up, current_price, 'extension')
224
+
225
+ levels.append(FibonacciLevel(
226
+ level=ratio,
227
+ price=price_up,
228
+ type='extension_up',
229
+ ratio=ratio,
230
+ distance_from_current=distance_up,
231
+ strength=strength_up
232
+ ))
233
+
234
+ # Extensão para baixo
235
+ price_down = swing_low - (swing_range * (ratio - 1))
236
+ distance_down = abs(current_price - price_down)
237
+ strength_down = self._calculate_level_strength(price_down, current_price, 'extension')
238
+
239
+ levels.append(FibonacciLevel(
240
+ level=ratio,
241
+ price=price_down,
242
+ type='extension_down',
243
+ ratio=ratio,
244
+ distance_from_current=distance_down,
245
+ strength=strength_down
246
+ ))
247
+
248
+ return sorted(levels, key=lambda x: x.distance_from_current)
249
+
250
+ def _calculate_projection_levels(
251
+ self, swing_high: float, swing_low: float, current_price: float
252
+ ) -> List[FibonacciLevel]:
253
+ """Calcula níveis de projeção de Fibonacci"""
254
+ levels = []
255
+ swing_range = swing_high - swing_low
256
+
257
+ for ratio in self.projection_ratios:
258
+ # Projeção baseada no movimento atual
259
+ if current_price > (swing_high + swing_low) / 2: # Tendência de alta
260
+ price = current_price + (swing_range * ratio)
261
+ direction = 'projection_up'
262
+ else: # Tendência de baixa
263
+ price = current_price - (swing_range * ratio)
264
+ direction = 'projection_down'
265
+
266
+ distance = abs(current_price - price)
267
+ strength = self._calculate_level_strength(price, current_price, 'projection')
268
+
269
+ levels.append(FibonacciLevel(
270
+ level=ratio,
271
+ price=price,
272
+ type=direction,
273
+ ratio=ratio,
274
+ distance_from_current=distance,
275
+ strength=strength
276
+ ))
277
+
278
+ return sorted(levels, key=lambda x: x.distance_from_current)
279
+
280
+ def _calculate_level_strength(
281
+ self, level_price: float, current_price: float, level_type: str
282
+ ) -> float:
283
+ """Calcula a força de um nível de Fibonacci"""
284
+ distance_factor = 1 / (1 + abs(level_price - current_price) / current_price)
285
+
286
+ type_weights = {
287
+ 'retracement': 1.0,
288
+ 'extension': 0.8,
289
+ 'projection': 0.6
290
+ }
291
+
292
+ base_strength = type_weights.get(level_type, 0.5)
293
+ return base_strength * distance_factor
294
+
295
+ def _identify_confluence_zones(
296
+ self, all_levels: List[FibonacciLevel]
297
+ ) -> List[ConfluenceZone]:
298
+ """Identifica zonas de confluência entre níveis"""
299
+ confluence_zones = []
300
+
301
+ # Agrupar níveis próximos
302
+ sorted_levels = sorted(all_levels, key=lambda x: x.price)
303
+
304
+ i = 0
305
+ while i < len(sorted_levels):
306
+ current_level = sorted_levels[i]
307
+ zone_levels = [current_level]
308
+ zone_types = [current_level.type]
309
+
310
+ # Procurar níveis próximos
311
+ j = i + 1
312
+ while j < len(sorted_levels):
313
+ next_level = sorted_levels[j]
314
+ price_diff = abs(next_level.price - current_level.price) / current_level.price
315
+
316
+ if price_diff <= self.confluence_threshold:
317
+ zone_levels.append(next_level)
318
+ zone_types.append(next_level.type)
319
+ j += 1
320
+ else:
321
+ break
322
+
323
+ # Criar zona de confluência se houver níveis suficientes
324
+ if len(zone_levels) >= self.min_confluence_levels:
325
+ min_price = min(level.price for level in zone_levels)
326
+ max_price = max(level.price for level in zone_levels)
327
+ avg_strength = sum(level.strength for level in zone_levels) / len(zone_levels)
328
+
329
+ confluence_zones.append(ConfluenceZone(
330
+ price_range=(min_price, max_price),
331
+ levels_count=len(zone_levels),
332
+ strength=avg_strength * len(zone_levels), # Força multiplicada pelo número de níveis
333
+ types=list(set(zone_types))
334
+ ))
335
+
336
+ i = j if j > i + 1 else i + 1
337
+
338
+ return sorted(confluence_zones, key=lambda x: x.strength, reverse=True)
339
+
340
+ def _detect_harmonic_patterns(
341
+ self, swing_high: float, swing_low: float, current_price: float,
342
+ historical_data: Optional[pd.DataFrame] = None
343
+ ) -> List[HarmonicPattern]:
344
+ """Detecta padrões harmônicos (implementação básica)"""
345
+ patterns = []
346
+
347
+ # Implementação simplificada - pode ser expandida com dados históricos
348
+ swing_range = swing_high - swing_low
349
+
350
+ for pattern_name, ratios in self.harmonic_patterns.items():
351
+ # Verificar se o preço atual está em uma posição válida para o padrão
352
+ completion_point = swing_low + (swing_range * ratios['CD'])
353
+
354
+ if abs(current_price - completion_point) / current_price < 0.02: # 2% de tolerância
355
+ confidence = 0.7 # Confiança básica
356
+
357
+ # Calcular alvos baseados no padrão
358
+ target_levels = [
359
+ completion_point + (swing_range * 0.382),
360
+ completion_point + (swing_range * 0.618),
361
+ completion_point + (swing_range * 1.0)
362
+ ]
363
+
364
+ stop_loss = completion_point - (swing_range * 0.236)
365
+
366
+ patterns.append(HarmonicPattern(
367
+ name=pattern_name,
368
+ completion_point=completion_point,
369
+ confidence=confidence,
370
+ target_levels=target_levels,
371
+ stop_loss=stop_loss
372
+ ))
373
+
374
+ return sorted(patterns, key=lambda x: x.confidence, reverse=True)
375
+
376
+ def _determine_key_levels(
377
+ self, all_levels: List[FibonacciLevel], current_price: float
378
+ ) -> Tuple[float, float]:
379
+ """Determina níveis chave de suporte e resistência"""
380
+ support_levels = [level for level in all_levels if level.price < current_price]
381
+ resistance_levels = [level for level in all_levels if level.price > current_price]
382
+
383
+ # Suporte mais próximo e forte
384
+ key_support = current_price
385
+ if support_levels:
386
+ key_support = max(support_levels, key=lambda x: x.strength).price
387
+
388
+ # Resistência mais próxima e forte
389
+ key_resistance = current_price
390
+ if resistance_levels:
391
+ key_resistance = min(resistance_levels, key=lambda x: x.strength).price
392
+
393
+ return key_support, key_resistance
394
+
395
+ def _determine_trend_direction(
396
+ self, swing_high: float, swing_low: float, current_price: float
397
+ ) -> str:
398
+ """Determina direção da tendência"""
399
+ mid_point = (swing_high + swing_low) / 2
400
+
401
+ if current_price > mid_point + (swing_high - swing_low) * 0.1:
402
+ return 'ALTA'
403
+ elif current_price < mid_point - (swing_high - swing_low) * 0.1:
404
+ return 'BAIXA'
405
+ else:
406
+ return 'LATERAL'
407
+
408
+ def _determine_fibonacci_zone(
409
+ self, swing_high: float, swing_low: float, current_price: float
410
+ ) -> str:
411
+ """Determina zona de Fibonacci atual"""
412
+ swing_range = swing_high - swing_low
413
+ position = (current_price - swing_low) / swing_range
414
+
415
+ if position >= 0.786:
416
+ return 'ZONA_ALTA'
417
+ elif position >= 0.618:
418
+ return 'ZONA_MEDIA_ALTA'
419
+ elif position >= 0.382:
420
+ return 'ZONA_MEDIA'
421
+ elif position >= 0.236:
422
+ return 'ZONA_MEDIA_BAIXA'
423
+ else:
424
+ return 'ZONA_BAIXA'
425
+
426
+ def _calculate_overall_strength(
427
+ self, retracement_levels: List[FibonacciLevel],
428
+ extension_levels: List[FibonacciLevel],
429
+ confluence_zones: List[ConfluenceZone],
430
+ harmonic_patterns: List[HarmonicPattern]
431
+ ) -> float:
432
+ """Calcula força geral da análise"""
433
+ # Força baseada em níveis próximos
434
+ level_strength = sum(level.strength for level in retracement_levels[:3]) # Top 3
435
+ level_strength += sum(level.strength for level in extension_levels[:3]) # Top 3
436
+
437
+ # Força das zonas de confluência
438
+ confluence_strength = sum(zone.strength for zone in confluence_zones)
439
+
440
+ # Força dos padrões harmônicos
441
+ harmonic_strength = sum(pattern.confidence for pattern in harmonic_patterns)
442
+
443
+ # Normalizar para 0-1
444
+ total_strength = (level_strength + confluence_strength + harmonic_strength) / 10
445
+ return min(total_strength, 1.0)
446
+
447
+ def _generate_trading_signal(
448
+ self, current_price: float, key_support: float, key_resistance: float,
449
+ trend_direction: str, overall_strength: float
450
+ ) -> str:
451
+ """Gera sinal de trading baseado na análise"""
452
+ support_distance = abs(current_price - key_support) / current_price
453
+ resistance_distance = abs(current_price - key_resistance) / current_price
454
+
455
+ if overall_strength < 0.3:
456
+ return 'HOLD'
457
+
458
+ if trend_direction == 'ALTA' and support_distance < 0.02:
459
+ return 'BUY'
460
+ elif trend_direction == 'BAIXA' and resistance_distance < 0.02:
461
+ return 'SELL'
462
+ elif support_distance < resistance_distance and overall_strength > 0.6:
463
+ return 'BUY'
464
+ elif resistance_distance < support_distance and overall_strength > 0.6:
465
+ return 'SELL'
466
+ else:
467
+ return 'HOLD'
468
+
469
+ def format_analysis_report(self, analysis: AdvancedFibonacciAnalysis) -> str:
470
+ """Formata relatório da análise"""
471
+ report = f"""
472
+ 🔮 ANÁLISE AVANÇADA DE FIBONACCI
473
+ {'='*50}
474
+
475
+ 📊 DADOS BÁSICOS:
476
+ Swing Alto: {analysis.swing_high:,.2f}
477
+ Swing Baixo: {analysis.swing_low:,.2f}
478
+ Preço Atual: {analysis.current_price:,.2f}
479
+ Range: {analysis.swing_range:,.2f}
480
+
481
+ 📈 NÍVEIS DE RETRACEMENT ({len(analysis.retracement_levels)}):
482
+ """
483
+
484
+ for level in analysis.retracement_levels[:5]: # Top 5
485
+ report += f" {level.ratio:.1%}: {level.price:,.2f} (Força: {level.strength:.2f})\n"
486
+
487
+ report += f"\n📊 NÍVEIS DE EXTENSÃO ({len(analysis.extension_levels)}):\n"
488
+ for level in analysis.extension_levels[:5]: # Top 5
489
+ report += f" {level.ratio:.1%}: {level.price:,.2f} ({level.type})\n"
490
+
491
+ if analysis.confluence_zones:
492
+ report += f"\n🎯 ZONAS DE CONFLUÊNCIA ({len(analysis.confluence_zones)}):\n"
493
+ for zone in analysis.confluence_zones[:3]: # Top 3
494
+ report += f" {zone.price_range[0]:,.2f} - {zone.price_range[1]:,.2f} ({zone.levels_count} níveis)\n"
495
+
496
+ if analysis.harmonic_patterns:
497
+ report += f"\n🎼 PADRÕES HARMÔNICOS ({len(analysis.harmonic_patterns)}):\n"
498
+ for pattern in analysis.harmonic_patterns:
499
+ report += f" {pattern.name}: {pattern.confidence:.1%} confiança\n"
500
+
501
+ report += f"""
502
+
503
+ 🎯 NÍVEIS CHAVE:
504
+ Suporte: {analysis.key_support:,.2f}
505
+ Resistência: {analysis.key_resistance:,.2f}
506
+
507
+ 📊 ANÁLISE GERAL:
508
+ Tendência: {analysis.trend_direction}
509
+ Zona Fibonacci: {analysis.fibonacci_zone}
510
+ Força da Análise: {analysis.overall_strength:.1%}
511
+ Sinal: {analysis.trading_signal}
512
+ Alertas: {analysis.alerts_count}
513
+ """
514
+
515
+ return report
516
+
517
+ # Exemplo de uso
518
+ if __name__ == "__main__":
519
+ engine = AdvancedFibonacciEngine()
520
+
521
+ # Exemplo com dados do bot
522
+ analysis = engine.perform_advanced_analysis(
523
+ swing_high=140570.0,
524
+ swing_low=139540.0,
525
+ current_price=140135.0
526
+ )
527
+
528
+ print(engine.format_analysis_report(analysis))
log_parser.py ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import json
3
+ from datetime import datetime
4
+ from typing import Dict, List, Optional, Any
5
+ from dataclasses import dataclass, asdict
6
+ import logging
7
+
8
+ # Configurar logging
9
+ logging.basicConfig(level=logging.INFO)
10
+ logger = logging.getLogger(__name__)
11
+
12
+ @dataclass
13
+ class MarketData:
14
+ """Estrutura para dados de mercado"""
15
+ symbol: str
16
+ current_price: float
17
+ variation: float
18
+ variation_percent: float
19
+ high: float
20
+ low: float
21
+ volume: int
22
+ timestamp: str
23
+
24
+ @dataclass
25
+ class TechnicalIndicators:
26
+ """Estrutura para indicadores técnicos"""
27
+ rsi: float
28
+ rsi_status: str
29
+ ema_fast: float
30
+ ema_slow: float
31
+ ema_trend: str
32
+ bollinger_status: str
33
+ bollinger_upper: float
34
+ bollinger_lower: float
35
+ atr: float
36
+ volatility: str
37
+ volatility_multiplier: float
38
+
39
+ @dataclass
40
+ class FibonacciAnalysis:
41
+ """Estrutura para análise de Fibonacci"""
42
+ swing_high: float
43
+ swing_low: float
44
+ current_price: float
45
+ swing_difference: float
46
+ retracement_levels: int
47
+ extension_levels: int
48
+ projection_levels: int
49
+ total_levels: int
50
+ confluence_zones: int
51
+ harmonic_patterns: int
52
+ temporal_projections: int
53
+ analysis_strength: float
54
+ zone: str
55
+ support: float
56
+ resistance: float
57
+ alerts: int
58
+ signal: str
59
+
60
+ @dataclass
61
+ class BotAnalysis:
62
+ """Estrutura completa da análise do bot"""
63
+ analysis_number: int
64
+ timestamp: str
65
+ market_data: MarketData
66
+ technical_indicators: TechnicalIndicators
67
+ fibonacci_analysis: FibonacciAnalysis
68
+ performance_time: Optional[float] = None
69
+
70
+ class VampireBotLogParser:
71
+ """Parser para logs do Vampire Trading Bot"""
72
+
73
+ def __init__(self):
74
+ self.patterns = self._compile_patterns()
75
+
76
+ def _compile_patterns(self) -> Dict[str, re.Pattern]:
77
+ """Compila padrões regex para extração de dados"""
78
+ return {
79
+ 'analysis_header': re.compile(r'⏰ Análise #(\d+) - ([\d:]+)'),
80
+ 'market_symbol': re.compile(r'📊 DADOS DE MERCADO - (\w+)'),
81
+ 'current_price': re.compile(r'Preço Atual: ([\d.]+) ↗'),
82
+ 'variation': re.compile(r'Variação: ([+-][\d.]+) \(([+-][\d.]+)%\)'),
83
+ 'high_low': re.compile(r'Máxima: ([\d.]+)\nMínima: ([\d.]+)'),
84
+ 'volume': re.compile(r'Volume: (\d+)'),
85
+ 'rsi': re.compile(r'RSI \(14\): ([\d.]+) \((\w+)\)'),
86
+ 'ema': re.compile(r'EMA Rápida: ([\d.]+)\nEMA Lenta: ([\d.]+)'),
87
+ 'ema_trend': re.compile(r'Tendência EMA: (\w+)'),
88
+ 'bollinger': re.compile(r'Bollinger: ([\w\s]+)\n\s+Superior: ([\d.]+)\n\s+Inferior: ([\d.]+)'),
89
+ 'atr': re.compile(r'ATR: ([\d.]+)'),
90
+ 'volatility': re.compile(r'Volatilidade: (\w+) \(([\d.]+)x\)'),
91
+ 'swing_points': re.compile(r'📊 Swing Points - Alta: ([\d,]+\.\d+), Baixa: ([\d,]+\.\d+), Atual: ([\d,]+\.\d+)'),
92
+ 'swing_difference': re.compile(r'📏 Diferença Swing: ([\d,]+\.\d+) pontos'),
93
+ 'retracement_levels': re.compile(r'📈 Níveis de Retracement calculados: (\d+) níveis'),
94
+ 'extension_levels': re.compile(r'📊 Níveis de Extensão calculados: (\d+) níveis'),
95
+ 'projection_levels': re.compile(r'🎯 Níveis de Projeção calculados: (\d+) níveis'),
96
+ 'total_levels': re.compile(r'🔢 Total de níveis Fibonacci: (\d+)'),
97
+ 'confluence_zones': re.compile(r'🎯 Zonas de Confluência detectadas: (\d+)'),
98
+ 'harmonic_patterns': re.compile(r'🎼 Padrões Harmônicos detectados: (\d+)'),
99
+ 'temporal_projections': re.compile(r'⏰ Projeções Temporais calculadas: (\d+)'),
100
+ 'analysis_strength': re.compile(r'💪 Força Geral da Análise: ([\d.]+)'),
101
+ 'fibonacci_conclusion': re.compile(r'🔮 ANÁLISE CONCLUÍDA - Zona: (\w+), Suporte: ([\d.]+), Resistência: ([\d.]+)'),
102
+ 'performance_time': re.compile(r'Análise de mercado lenta: ([\d.]+)s'),
103
+ 'fibonacci_signal': re.compile(r'🔮 Fibonacci Avançado:\s+Alertas:(\d+) FibSinal:(\w+)')
104
+ }
105
+
106
+ def parse_log_content(self, log_content: str) -> Optional[BotAnalysis]:
107
+ """Parseia o conteúdo completo do log"""
108
+ try:
109
+ # Extrair cabeçalho da análise
110
+ analysis_match = self.patterns['analysis_header'].search(log_content)
111
+ if not analysis_match:
112
+ logger.warning("Cabeçalho da análise não encontrado")
113
+ return None
114
+
115
+ analysis_number = int(analysis_match.group(1))
116
+ timestamp = analysis_match.group(2)
117
+
118
+ # Extrair dados de mercado
119
+ market_data = self._extract_market_data(log_content)
120
+ if not market_data:
121
+ logger.warning("Dados de mercado não encontrados")
122
+ return None
123
+
124
+ # Extrair indicadores técnicos
125
+ technical_indicators = self._extract_technical_indicators(log_content)
126
+ if not technical_indicators:
127
+ logger.warning("Indicadores técnicos não encontrados")
128
+ return None
129
+
130
+ # Extrair análise de Fibonacci
131
+ fibonacci_analysis = self._extract_fibonacci_analysis(log_content)
132
+ if not fibonacci_analysis:
133
+ logger.warning("Análise de Fibonacci não encontrada")
134
+ return None
135
+
136
+ # Extrair tempo de performance (opcional)
137
+ performance_match = self.patterns['performance_time'].search(log_content)
138
+ performance_time = float(performance_match.group(1)) if performance_match else None
139
+
140
+ return BotAnalysis(
141
+ analysis_number=analysis_number,
142
+ timestamp=timestamp,
143
+ market_data=market_data,
144
+ technical_indicators=technical_indicators,
145
+ fibonacci_analysis=fibonacci_analysis,
146
+ performance_time=performance_time
147
+ )
148
+
149
+ except Exception as e:
150
+ logger.error(f"Erro ao parsear log: {e}")
151
+ return None
152
+
153
+ def _extract_market_data(self, content: str) -> Optional[MarketData]:
154
+ """Extrai dados de mercado do log"""
155
+ try:
156
+ symbol_match = self.patterns['market_symbol'].search(content)
157
+ price_match = self.patterns['current_price'].search(content)
158
+ variation_match = self.patterns['variation'].search(content)
159
+ high_low_match = self.patterns['high_low'].search(content)
160
+ volume_match = self.patterns['volume'].search(content)
161
+
162
+ if not all([symbol_match, price_match, variation_match, high_low_match, volume_match]):
163
+ return None
164
+
165
+ return MarketData(
166
+ symbol=symbol_match.group(1),
167
+ current_price=float(price_match.group(1)),
168
+ variation=float(variation_match.group(1)),
169
+ variation_percent=float(variation_match.group(2)),
170
+ high=float(high_low_match.group(1)),
171
+ low=float(high_low_match.group(2)),
172
+ volume=int(volume_match.group(1)),
173
+ timestamp=datetime.now().isoformat()
174
+ )
175
+
176
+ except Exception as e:
177
+ logger.error(f"Erro ao extrair dados de mercado: {e}")
178
+ return None
179
+
180
+ def _extract_technical_indicators(self, content: str) -> Optional[TechnicalIndicators]:
181
+ """Extrai indicadores técnicos do log"""
182
+ try:
183
+ rsi_match = self.patterns['rsi'].search(content)
184
+ ema_match = self.patterns['ema'].search(content)
185
+ ema_trend_match = self.patterns['ema_trend'].search(content)
186
+ bollinger_match = self.patterns['bollinger'].search(content)
187
+ atr_match = self.patterns['atr'].search(content)
188
+ volatility_match = self.patterns['volatility'].search(content)
189
+
190
+ if not all([rsi_match, ema_match, ema_trend_match, bollinger_match, atr_match, volatility_match]):
191
+ return None
192
+
193
+ return TechnicalIndicators(
194
+ rsi=float(rsi_match.group(1)),
195
+ rsi_status=rsi_match.group(2),
196
+ ema_fast=float(ema_match.group(1)),
197
+ ema_slow=float(ema_match.group(2)),
198
+ ema_trend=ema_trend_match.group(1),
199
+ bollinger_status=bollinger_match.group(1).strip(),
200
+ bollinger_upper=float(bollinger_match.group(2)),
201
+ bollinger_lower=float(bollinger_match.group(3)),
202
+ atr=float(atr_match.group(1)),
203
+ volatility=volatility_match.group(1),
204
+ volatility_multiplier=float(volatility_match.group(2))
205
+ )
206
+
207
+ except Exception as e:
208
+ logger.error(f"Erro ao extrair indicadores técnicos: {e}")
209
+ return None
210
+
211
+ def _extract_fibonacci_analysis(self, content: str) -> Optional[FibonacciAnalysis]:
212
+ """Extrai análise de Fibonacci do log"""
213
+ try:
214
+ # Buscar pelos últimos valores (análise final)
215
+ swing_matches = list(self.patterns['swing_points'].finditer(content))
216
+ swing_diff_matches = list(self.patterns['swing_difference'].finditer(content))
217
+ retracement_matches = list(self.patterns['retracement_levels'].finditer(content))
218
+ extension_matches = list(self.patterns['extension_levels'].finditer(content))
219
+ projection_matches = list(self.patterns['projection_levels'].finditer(content))
220
+ total_matches = list(self.patterns['total_levels'].finditer(content))
221
+ confluence_matches = list(self.patterns['confluence_zones'].finditer(content))
222
+ harmonic_matches = list(self.patterns['harmonic_patterns'].finditer(content))
223
+ temporal_matches = list(self.patterns['temporal_projections'].finditer(content))
224
+ strength_matches = list(self.patterns['analysis_strength'].finditer(content))
225
+ conclusion_matches = list(self.patterns['fibonacci_conclusion'].finditer(content))
226
+ signal_match = self.patterns['fibonacci_signal'].search(content)
227
+
228
+ if not (swing_matches and conclusion_matches and signal_match):
229
+ return None
230
+
231
+ # Usar os últimos valores encontrados
232
+ swing_match = swing_matches[-1]
233
+ conclusion_match = conclusion_matches[-1]
234
+
235
+ swing_high = float(swing_match.group(1).replace(',', ''))
236
+ swing_low = float(swing_match.group(2).replace(',', ''))
237
+ current_price = float(swing_match.group(3).replace(',', ''))
238
+
239
+ return FibonacciAnalysis(
240
+ swing_high=swing_high,
241
+ swing_low=swing_low,
242
+ current_price=current_price,
243
+ swing_difference=float(swing_diff_matches[-1].group(1).replace(',', '')) if swing_diff_matches else 0,
244
+ retracement_levels=int(retracement_matches[-1].group(1)) if retracement_matches else 0,
245
+ extension_levels=int(extension_matches[-1].group(1)) if extension_matches else 0,
246
+ projection_levels=int(projection_matches[-1].group(1)) if projection_matches else 0,
247
+ total_levels=int(total_matches[-1].group(1)) if total_matches else 0,
248
+ confluence_zones=int(confluence_matches[-1].group(1)) if confluence_matches else 0,
249
+ harmonic_patterns=int(harmonic_matches[-1].group(1)) if harmonic_matches else 0,
250
+ temporal_projections=int(temporal_matches[-1].group(1)) if temporal_matches else 0,
251
+ analysis_strength=float(strength_matches[-1].group(1)) if strength_matches else 0.0,
252
+ zone=conclusion_match.group(1),
253
+ support=float(conclusion_match.group(2)),
254
+ resistance=float(conclusion_match.group(3)),
255
+ alerts=int(signal_match.group(1)),
256
+ signal=signal_match.group(2)
257
+ )
258
+
259
+ except Exception as e:
260
+ logger.error(f"Erro ao extrair análise de Fibonacci: {e}")
261
+ return None
262
+
263
+ def parse_log_file(self, file_path: str) -> Optional[BotAnalysis]:
264
+ """Parseia arquivo de log"""
265
+ try:
266
+ with open(file_path, 'r', encoding='utf-8') as file:
267
+ content = file.read()
268
+ return self.parse_log_content(content)
269
+ except Exception as e:
270
+ logger.error(f"Erro ao ler arquivo de log: {e}")
271
+ return None
272
+
273
+ def to_dict(self, analysis: BotAnalysis) -> Dict[str, Any]:
274
+ """Converte análise para dicionário"""
275
+ return asdict(analysis)
276
+
277
+ def to_json(self, analysis: BotAnalysis) -> str:
278
+ """Converte análise para JSON"""
279
+ return json.dumps(self.to_dict(analysis), indent=2, ensure_ascii=False)
280
+
281
+ # Exemplo de uso
282
+ if __name__ == "__main__":
283
+ parser = VampireBotLogParser()
284
+
285
+ # Exemplo com o log fornecido
286
+ sample_log = """
287
+ ⏰ Análise #8 - 09:46:58
288
+
289
+ ================================================================================
290
+ 🧛 VAMPIRE TRADING BOT - ANÁLISE DETALHADA
291
+ ================================================================================
292
+
293
+ 📊 DADOS DE MERCADO - WINV25
294
+ ──────────────────────────────────────────────────
295
+ Preço Atual: 140135.00000 ↗
296
+ Variação: +5.00000 (+0.00%)
297
+ Máxima: 140155.00000
298
+ Mínima: 140075.00000
299
+ Volume: 5023
300
+
301
+ 📈 INDICADORES TÉCNICOS
302
+ ──────────────────────────────────────────────────
303
+ RSI (14): 46.39 (NEUTRO)
304
+ EMA Rápida: 140192.30752
305
+ EMA Lenta: 140221.86717
306
+ Tendência EMA: BAIXA
307
+ Bollinger: DENTRO DAS BANDAS
308
+ Superior: 140672.37317
309
+ Inferior: 139913.62683
310
+ ATR: 170.73782
311
+ Volatilidade: MÉDIA (1.23x)
312
+ 🔮 Fibonacci Avançado: Alertas:15 FibSinal:HOLD
313
+ """
314
+
315
+ # Simular dados de Fibonacci (já que não estão completos no exemplo)
316
+ full_sample = sample_log + """
317
+ 2025-08-27 09:46:58,333 - src.core.analysis.advanced_fibonacci - INFO - 🔮 ANÁLISE CONCLUÍDA - Zona: ZONA_MEDIA_ALTA, Suporte: 140133.28, Resistência: 140176.54
318
+ 2025-08-27 09:46:58,218 - src.core.analysis.advanced_fibonacci - INFO - 📊 Swing Points - Alta: 140,570.00, Baixa: 139,540.00, Atual: 140,135.00
319
+ 2025-08-27 09:46:58,219 - src.core.analysis.advanced_fibonacci - INFO - 📏 Diferença Swing: 1,030.00 pontos
320
+ 2025-08-27 09:46:58,244 - src.core.analysis.advanced_fibonacci - INFO - 📈 Níveis de Retracement calculados: 13 níveis
321
+ 2025-08-27 09:46:58,297 - src.core.analysis.advanced_fibonacci - INFO - 📊 Níveis de Extensão calculados: 11 níveis
322
+ 2025-08-27 09:46:58,323 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Níveis de Projeção calculados: 8 níveis
323
+ 2025-08-27 09:46:58,325 - src.core.analysis.advanced_fibonacci - INFO - 🔢 Total de níveis Fibonacci: 32
324
+ 2025-08-27 09:46:58,327 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Zonas de Confluência detectadas: 0
325
+ 2025-08-27 09:46:58,329 - src.core.analysis.advanced_fibonacci - INFO - 🎼 Padrões Harmônicos detectados: 0
326
+ 2025-08-27 09:46:58,332 - src.core.analysis.advanced_fibonacci - INFO - ⏰ Projeções Temporais calculadas: 0
327
+ 2025-08-27 09:46:58,332 - src.core.analysis.advanced_fibonacci - INFO - 💪 Força Geral da Análise: 0.00
328
+ """
329
+
330
+ result = parser.parse_log_content(full_sample)
331
+ if result:
332
+ print("✅ Log parseado com sucesso!")
333
+ print(parser.to_json(result))
334
+ else:
335
+ print("❌ Erro ao parsear log")
real_time_integration.py ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import os
3
+ import time
4
+ from datetime import datetime
5
+ from typing import Dict, Any, Optional, Callable
6
+ from pathlib import Path
7
+ import json
8
+ import logging
9
+ from dataclasses import dataclass, asdict
10
+ from threading import Thread, Event
11
+ import queue
12
+
13
+ from log_parser import VampireBotLogParser, BotAnalysis
14
+ from market_analysis import TechnicalAnalysisEngine
15
+
16
+ @dataclass
17
+ class RealTimeConfig:
18
+ """Configuração para integração em tempo real"""
19
+ log_file_path: str
20
+ check_interval: float = 1.0 # segundos
21
+ max_queue_size: int = 100
22
+ enable_notifications: bool = True
23
+ auto_analysis: bool = True
24
+ backup_logs: bool = True
25
+
26
+ @dataclass
27
+ class BotEvent:
28
+ """Evento do bot em tempo real"""
29
+ timestamp: datetime
30
+ event_type: str # 'new_analysis', 'fibonacci_alert', 'signal_change'
31
+ data: Dict[str, Any]
32
+ priority: str = 'normal' # 'low', 'normal', 'high', 'critical'
33
+
34
+ class FileWatcher:
35
+ """Monitor de arquivos para detectar mudanças em tempo real"""
36
+
37
+ def __init__(self, file_path: str, callback: Callable[[str], None]):
38
+ self.file_path = Path(file_path)
39
+ self.callback = callback
40
+ self.last_modified = 0
41
+ self.last_size = 0
42
+ self.running = False
43
+ self._stop_event = Event()
44
+
45
+ def start(self):
46
+ """Inicia o monitoramento do arquivo"""
47
+ self.running = True
48
+ self._stop_event.clear()
49
+
50
+ if self.file_path.exists():
51
+ stat = self.file_path.stat()
52
+ self.last_modified = stat.st_mtime
53
+ self.last_size = stat.st_size
54
+
55
+ def stop(self):
56
+ """Para o monitoramento"""
57
+ self.running = False
58
+ self._stop_event.set()
59
+
60
+ def check_changes(self) -> bool:
61
+ """Verifica se o arquivo foi modificado"""
62
+ if not self.file_path.exists():
63
+ return False
64
+
65
+ try:
66
+ stat = self.file_path.stat()
67
+ current_modified = stat.st_mtime
68
+ current_size = stat.st_size
69
+
70
+ # Verifica se houve mudança
71
+ if (current_modified > self.last_modified or
72
+ current_size != self.last_size):
73
+
74
+ self.last_modified = current_modified
75
+ self.last_size = current_size
76
+
77
+ # Lê o conteúdo novo
78
+ try:
79
+ with open(self.file_path, 'r', encoding='utf-8') as f:
80
+ content = f.read()
81
+ self.callback(content)
82
+ return True
83
+ except Exception as e:
84
+ logging.error(f"Erro ao ler arquivo: {e}")
85
+
86
+ except Exception as e:
87
+ logging.error(f"Erro ao verificar arquivo: {e}")
88
+
89
+ return False
90
+
91
+ class RealTimeProcessor:
92
+ """Processador de dados em tempo real do bot"""
93
+
94
+ def __init__(self, config: RealTimeConfig):
95
+ self.config = config
96
+ self.log_parser = VampireBotLogParser()
97
+ self.technical_engine = TechnicalAnalysisEngine()
98
+ self.event_queue = queue.Queue(maxsize=config.max_queue_size)
99
+ self.subscribers = []
100
+ self.running = False
101
+ self.last_analysis: Optional[BotAnalysis] = None
102
+
103
+ # Setup logging
104
+ self.logger = logging.getLogger(__name__)
105
+
106
+ def subscribe(self, callback: Callable[[BotEvent], None]):
107
+ """Inscreve um callback para receber eventos"""
108
+ self.subscribers.append(callback)
109
+
110
+ def unsubscribe(self, callback: Callable[[BotEvent], None]):
111
+ """Remove um callback da lista de inscritos"""
112
+ if callback in self.subscribers:
113
+ self.subscribers.remove(callback)
114
+
115
+ def _notify_subscribers(self, event: BotEvent):
116
+ """Notifica todos os inscritos sobre um evento"""
117
+ for callback in self.subscribers:
118
+ try:
119
+ callback(event)
120
+ except Exception as e:
121
+ self.logger.error(f"Erro ao notificar subscriber: {e}")
122
+
123
+ def _process_new_log_data(self, log_content: str):
124
+ """Processa novos dados de log"""
125
+ try:
126
+ # Parse do log
127
+ bot_analysis = self.log_parser.parse_log(log_content)
128
+
129
+ if bot_analysis:
130
+ # Verifica se é uma nova análise
131
+ is_new_analysis = (
132
+ self.last_analysis is None or
133
+ bot_analysis.timestamp != self.last_analysis.timestamp
134
+ )
135
+
136
+ if is_new_analysis:
137
+ # Cria evento de nova análise
138
+ event = BotEvent(
139
+ timestamp=datetime.now(),
140
+ event_type='new_analysis',
141
+ data=asdict(bot_analysis),
142
+ priority='normal'
143
+ )
144
+
145
+ # Adiciona à fila de eventos
146
+ try:
147
+ self.event_queue.put_nowait(event)
148
+ except queue.Full:
149
+ self.logger.warning("Fila de eventos cheia, removendo evento mais antigo")
150
+ try:
151
+ self.event_queue.get_nowait()
152
+ self.event_queue.put_nowait(event)
153
+ except queue.Empty:
154
+ pass
155
+
156
+ # Verifica alertas de Fibonacci
157
+ if bot_analysis.fibonacci_analysis and bot_analysis.fibonacci_analysis.alerts:
158
+ fib_event = BotEvent(
159
+ timestamp=datetime.now(),
160
+ event_type='fibonacci_alert',
161
+ data={
162
+ 'alerts': bot_analysis.fibonacci_analysis.alerts,
163
+ 'signal': bot_analysis.fibonacci_analysis.signal,
164
+ 'confidence': bot_analysis.fibonacci_analysis.confidence
165
+ },
166
+ priority='high'
167
+ )
168
+
169
+ try:
170
+ self.event_queue.put_nowait(fib_event)
171
+ except queue.Full:
172
+ pass
173
+
174
+ # Verifica mudança de sinal
175
+ if (self.last_analysis and
176
+ bot_analysis.fibonacci_analysis and
177
+ self.last_analysis.fibonacci_analysis and
178
+ bot_analysis.fibonacci_analysis.signal != self.last_analysis.fibonacci_analysis.signal):
179
+
180
+ signal_event = BotEvent(
181
+ timestamp=datetime.now(),
182
+ event_type='signal_change',
183
+ data={
184
+ 'old_signal': self.last_analysis.fibonacci_analysis.signal,
185
+ 'new_signal': bot_analysis.fibonacci_analysis.signal,
186
+ 'confidence': bot_analysis.fibonacci_analysis.confidence
187
+ },
188
+ priority='critical'
189
+ )
190
+
191
+ try:
192
+ self.event_queue.put_nowait(signal_event)
193
+ except queue.Full:
194
+ pass
195
+
196
+ self.last_analysis = bot_analysis
197
+
198
+ except Exception as e:
199
+ self.logger.error(f"Erro ao processar log: {e}")
200
+
201
+ def _event_processor_loop(self):
202
+ """Loop principal de processamento de eventos"""
203
+ while self.running:
204
+ try:
205
+ # Processa eventos da fila
206
+ try:
207
+ event = self.event_queue.get(timeout=0.1)
208
+ self._notify_subscribers(event)
209
+ self.event_queue.task_done()
210
+ except queue.Empty:
211
+ continue
212
+
213
+ except Exception as e:
214
+ self.logger.error(f"Erro no loop de eventos: {e}")
215
+ time.sleep(0.1)
216
+
217
+ def start(self):
218
+ """Inicia o processamento em tempo real"""
219
+ if self.running:
220
+ return
221
+
222
+ self.running = True
223
+ self.logger.info("Iniciando processamento em tempo real")
224
+
225
+ # Inicia thread de processamento de eventos
226
+ self.event_thread = Thread(target=self._event_processor_loop, daemon=True)
227
+ self.event_thread.start()
228
+
229
+ # Configura watcher de arquivo
230
+ self.file_watcher = FileWatcher(
231
+ self.config.log_file_path,
232
+ self._process_new_log_data
233
+ )
234
+ self.file_watcher.start()
235
+
236
+ # Inicia thread de monitoramento
237
+ self.monitor_thread = Thread(target=self._monitor_loop, daemon=True)
238
+ self.monitor_thread.start()
239
+
240
+ def stop(self):
241
+ """Para o processamento em tempo real"""
242
+ if not self.running:
243
+ return
244
+
245
+ self.logger.info("Parando processamento em tempo real")
246
+ self.running = False
247
+
248
+ if hasattr(self, 'file_watcher'):
249
+ self.file_watcher.stop()
250
+
251
+ def _monitor_loop(self):
252
+ """Loop de monitoramento de arquivo"""
253
+ while self.running:
254
+ try:
255
+ self.file_watcher.check_changes()
256
+ time.sleep(self.config.check_interval)
257
+ except Exception as e:
258
+ self.logger.error(f"Erro no monitoramento: {e}")
259
+ time.sleep(1)
260
+
261
+ def get_status(self) -> Dict[str, Any]:
262
+ """Retorna status do processador"""
263
+ return {
264
+ 'running': self.running,
265
+ 'queue_size': self.event_queue.qsize(),
266
+ 'subscribers_count': len(self.subscribers),
267
+ 'last_analysis_time': self.last_analysis.timestamp if self.last_analysis else None,
268
+ 'config': asdict(self.config)
269
+ }
270
+
271
+ class RealTimeIntegration:
272
+ """Sistema principal de integração em tempo real"""
273
+
274
+ def __init__(self, log_file_path: str):
275
+ self.config = RealTimeConfig(log_file_path=log_file_path)
276
+ self.processor = RealTimeProcessor(self.config)
277
+ self.event_history = []
278
+ self.max_history = 1000
279
+
280
+ # Setup logging
281
+ self.logger = logging.getLogger(__name__)
282
+
283
+ # Inscreve callback padrão
284
+ self.processor.subscribe(self._default_event_handler)
285
+
286
+ def _default_event_handler(self, event: BotEvent):
287
+ """Handler padrão para eventos"""
288
+ # Adiciona ao histórico
289
+ self.event_history.append(event)
290
+
291
+ # Mantém tamanho do histórico
292
+ if len(self.event_history) > self.max_history:
293
+ self.event_history = self.event_history[-self.max_history:]
294
+
295
+ # Log do evento
296
+ self.logger.info(f"Evento {event.event_type} - Prioridade: {event.priority}")
297
+
298
+ # Processamento específico por tipo
299
+ if event.event_type == 'signal_change':
300
+ self.logger.warning(
301
+ f"MUDANÇA DE SINAL: {event.data['old_signal']} -> {event.data['new_signal']} "
302
+ f"(Confiança: {event.data['confidence']}%)"
303
+ )
304
+ elif event.event_type == 'fibonacci_alert':
305
+ self.logger.info(f"Alerta Fibonacci: {len(event.data['alerts'])} alertas")
306
+
307
+ def start(self):
308
+ """Inicia a integração em tempo real"""
309
+ self.processor.start()
310
+ self.logger.info(f"Integração em tempo real iniciada para: {self.config.log_file_path}")
311
+
312
+ def stop(self):
313
+ """Para a integração em tempo real"""
314
+ self.processor.stop()
315
+ self.logger.info("Integração em tempo real parada")
316
+
317
+ def get_recent_events(self, limit: int = 10) -> list[BotEvent]:
318
+ """Retorna eventos recentes"""
319
+ return self.event_history[-limit:] if self.event_history else []
320
+
321
+ def get_status(self) -> Dict[str, Any]:
322
+ """Retorna status completo do sistema"""
323
+ processor_status = self.processor.get_status()
324
+ return {
325
+ **processor_status,
326
+ 'event_history_size': len(self.event_history),
327
+ 'recent_events': len([e for e in self.event_history if
328
+ (datetime.now() - e.timestamp).seconds < 300]) # últimos 5 min
329
+ }
330
+
331
+ # Exemplo de uso
332
+ if __name__ == "__main__":
333
+ # Configurar logging
334
+ logging.basicConfig(level=logging.INFO)
335
+
336
+ # Criar integração
337
+ integration = RealTimeIntegration("d:/hugging_face_spaces/text")
338
+
339
+ # Callback personalizado
340
+ def custom_handler(event: BotEvent):
341
+ print(f"[{event.timestamp}] {event.event_type}: {event.priority}")
342
+
343
+ integration.processor.subscribe(custom_handler)
344
+
345
+ try:
346
+ # Iniciar
347
+ integration.start()
348
+
349
+ # Manter rodando
350
+ while True:
351
+ time.sleep(1)
352
+ status = integration.get_status()
353
+ if status['recent_events'] > 0:
354
+ print(f"Eventos recentes: {status['recent_events']}")
355
+
356
+ except KeyboardInterrupt:
357
+ print("Parando integração...")
358
+ integration.stop()
src/__init__.py ADDED
File without changes
src/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (135 Bytes). View file
 
src/analysis/__init__.py ADDED
File without changes
src/analysis/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (144 Bytes). View file
 
src/analysis/__pycache__/market_analysis.cpython-313.pyc ADDED
Binary file (23.9 kB). View file
 
src/analysis/fibonacci_analysis.py ADDED
@@ -0,0 +1,528 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+ from typing import Dict, List, Tuple, Optional, Any
4
+ from dataclasses import dataclass, asdict
5
+ import logging
6
+ from src.core.log_parser import FibonacciAnalysis, BotAnalysis
7
+
8
+ # Configurar logging
9
+ logging.basicConfig(level=logging.INFO)
10
+ logger = logging.getLogger(__name__)
11
+
12
+ @dataclass
13
+ class FibonacciLevel:
14
+ """Estrutura para um nível de Fibonacci"""
15
+ level: float
16
+ price: float
17
+ type: str # 'retracement', 'extension', 'projection'
18
+ ratio: float
19
+ distance_from_current: float
20
+ strength: float
21
+
22
+ @dataclass
23
+ class SwingPoint:
24
+ """Estrutura para pontos de swing"""
25
+ price: float
26
+ timestamp: str
27
+ type: str # 'high' ou 'low'
28
+ strength: float
29
+
30
+ @dataclass
31
+ class ConfluenceZone:
32
+ """Estrutura para zonas de confluência"""
33
+ price_range: Tuple[float, float]
34
+ levels_count: int
35
+ strength: float
36
+ types: List[str]
37
+
38
+ @dataclass
39
+ class HarmonicPattern:
40
+ """Estrutura para padrões harmônicos"""
41
+ name: str
42
+ completion_point: float
43
+ confidence: float
44
+ target_levels: List[float]
45
+ stop_loss: float
46
+
47
+ @dataclass
48
+ class AdvancedFibonacciAnalysis:
49
+ """Análise avançada de Fibonacci completa"""
50
+ swing_high: float
51
+ swing_low: float
52
+ current_price: float
53
+ swing_range: float
54
+ retracement_levels: List[FibonacciLevel]
55
+ extension_levels: List[FibonacciLevel]
56
+ projection_levels: List[FibonacciLevel]
57
+ confluence_zones: List[ConfluenceZone]
58
+ harmonic_patterns: List[HarmonicPattern]
59
+ key_support: float
60
+ key_resistance: float
61
+ trend_direction: str
62
+ fibonacci_zone: str
63
+ overall_strength: float
64
+ trading_signal: str
65
+ alerts_count: int
66
+
67
+ class AdvancedFibonacciEngine:
68
+ """Engine para análise avançada de Fibonacci"""
69
+
70
+ def __init__(self):
71
+ # Ratios de Fibonacci padrão
72
+ self.retracement_ratios = [0.236, 0.382, 0.5, 0.618, 0.786]
73
+ self.extension_ratios = [1.272, 1.414, 1.618, 2.0, 2.618]
74
+ self.projection_ratios = [0.618, 1.0, 1.272, 1.618]
75
+
76
+ # Configurações de confluência
77
+ self.confluence_threshold = 0.001 # 0.1% de tolerância
78
+ self.min_confluence_levels = 2
79
+
80
+ # Padrões harmônicos
81
+ self.harmonic_patterns = {
82
+ 'Gartley': {'XA': 0.618, 'AB': 0.618, 'BC': 0.786, 'CD': 1.272},
83
+ 'Butterfly': {'XA': 0.786, 'AB': 0.618, 'BC': 0.886, 'CD': 1.618},
84
+ 'Bat': {'XA': 0.382, 'AB': 0.618, 'BC': 0.886, 'CD': 2.618},
85
+ 'Crab': {'XA': 0.618, 'AB': 0.618, 'BC': 0.886, 'CD': 3.618}
86
+ }
87
+
88
+ def analyze_from_bot_data(self, bot_analysis: BotAnalysis) -> AdvancedFibonacciAnalysis:
89
+ """Analisa dados do bot externo"""
90
+ fib_data = bot_analysis.fibonacci_analysis
91
+ market_data = bot_analysis.market_data
92
+
93
+ return self.perform_advanced_analysis(
94
+ swing_high=fib_data.swing_high,
95
+ swing_low=fib_data.swing_low,
96
+ current_price=fib_data.current_price,
97
+ historical_data=None, # Pode ser expandido futuramente
98
+ bot_fibonacci_data=fib_data
99
+ )
100
+
101
+ def perform_advanced_analysis(
102
+ self,
103
+ swing_high: float,
104
+ swing_low: float,
105
+ current_price: float,
106
+ historical_data: Optional[pd.DataFrame] = None,
107
+ bot_fibonacci_data: Optional[FibonacciAnalysis] = None
108
+ ) -> AdvancedFibonacciAnalysis:
109
+ """Realiza análise avançada de Fibonacci"""
110
+
111
+ try:
112
+ swing_range = swing_high - swing_low
113
+
114
+ # Calcular níveis de retracement
115
+ retracement_levels = self._calculate_retracement_levels(
116
+ swing_high, swing_low, current_price
117
+ )
118
+
119
+ # Calcular níveis de extensão
120
+ extension_levels = self._calculate_extension_levels(
121
+ swing_high, swing_low, current_price
122
+ )
123
+
124
+ # Calcular níveis de projeção
125
+ projection_levels = self._calculate_projection_levels(
126
+ swing_high, swing_low, current_price
127
+ )
128
+
129
+ # Identificar zonas de confluência
130
+ all_levels = retracement_levels + extension_levels + projection_levels
131
+ confluence_zones = self._identify_confluence_zones(all_levels)
132
+
133
+ # Detectar padrões harmônicos
134
+ harmonic_patterns = self._detect_harmonic_patterns(
135
+ swing_high, swing_low, current_price, historical_data
136
+ )
137
+
138
+ # Determinar suporte e resistência chave
139
+ key_support, key_resistance = self._determine_key_levels(
140
+ all_levels, current_price
141
+ )
142
+
143
+ # Determinar direção da tendência
144
+ trend_direction = self._determine_trend_direction(
145
+ swing_high, swing_low, current_price
146
+ )
147
+
148
+ # Determinar zona de Fibonacci
149
+ fibonacci_zone = self._determine_fibonacci_zone(
150
+ swing_high, swing_low, current_price
151
+ )
152
+
153
+ # Calcular força geral da análise
154
+ overall_strength = self._calculate_overall_strength(
155
+ retracement_levels, extension_levels, confluence_zones, harmonic_patterns
156
+ )
157
+
158
+ # Gerar sinal de trading
159
+ trading_signal = self._generate_trading_signal(
160
+ current_price, key_support, key_resistance, trend_direction, overall_strength
161
+ )
162
+
163
+ # Contar alertas (baseado nos dados do bot se disponível)
164
+ alerts_count = bot_fibonacci_data.alerts if bot_fibonacci_data else len(confluence_zones)
165
+
166
+ return AdvancedFibonacciAnalysis(
167
+ swing_high=swing_high,
168
+ swing_low=swing_low,
169
+ current_price=current_price,
170
+ swing_range=swing_range,
171
+ retracement_levels=retracement_levels,
172
+ extension_levels=extension_levels,
173
+ projection_levels=projection_levels,
174
+ confluence_zones=confluence_zones,
175
+ harmonic_patterns=harmonic_patterns,
176
+ key_support=key_support,
177
+ key_resistance=key_resistance,
178
+ trend_direction=trend_direction,
179
+ fibonacci_zone=fibonacci_zone,
180
+ overall_strength=overall_strength,
181
+ trading_signal=trading_signal,
182
+ alerts_count=alerts_count
183
+ )
184
+
185
+ except Exception as e:
186
+ logger.error(f"Erro na análise avançada de Fibonacci: {e}")
187
+ raise
188
+
189
+ def _calculate_retracement_levels(
190
+ self, swing_high: float, swing_low: float, current_price: float
191
+ ) -> List[FibonacciLevel]:
192
+ """Calcula níveis de retracement de Fibonacci"""
193
+ levels = []
194
+ swing_range = swing_high - swing_low
195
+
196
+ for ratio in self.retracement_ratios:
197
+ price = swing_high - (swing_range * ratio)
198
+ distance = abs(current_price - price)
199
+ strength = self._calculate_level_strength(price, current_price, 'retracement')
200
+
201
+ levels.append(FibonacciLevel(
202
+ level=ratio,
203
+ price=price,
204
+ type='retracement',
205
+ ratio=ratio,
206
+ distance_from_current=distance,
207
+ strength=strength
208
+ ))
209
+
210
+ return sorted(levels, key=lambda x: x.distance_from_current)
211
+
212
+ def _calculate_extension_levels(
213
+ self, swing_high: float, swing_low: float, current_price: float
214
+ ) -> List[FibonacciLevel]:
215
+ """Calcula níveis de extensão de Fibonacci"""
216
+ levels = []
217
+ swing_range = swing_high - swing_low
218
+
219
+ for ratio in self.extension_ratios:
220
+ # Extensão para cima
221
+ price_up = swing_high + (swing_range * (ratio - 1))
222
+ distance_up = abs(current_price - price_up)
223
+ strength_up = self._calculate_level_strength(price_up, current_price, 'extension')
224
+
225
+ levels.append(FibonacciLevel(
226
+ level=ratio,
227
+ price=price_up,
228
+ type='extension_up',
229
+ ratio=ratio,
230
+ distance_from_current=distance_up,
231
+ strength=strength_up
232
+ ))
233
+
234
+ # Extensão para baixo
235
+ price_down = swing_low - (swing_range * (ratio - 1))
236
+ distance_down = abs(current_price - price_down)
237
+ strength_down = self._calculate_level_strength(price_down, current_price, 'extension')
238
+
239
+ levels.append(FibonacciLevel(
240
+ level=ratio,
241
+ price=price_down,
242
+ type='extension_down',
243
+ ratio=ratio,
244
+ distance_from_current=distance_down,
245
+ strength=strength_down
246
+ ))
247
+
248
+ return sorted(levels, key=lambda x: x.distance_from_current)
249
+
250
+ def _calculate_projection_levels(
251
+ self, swing_high: float, swing_low: float, current_price: float
252
+ ) -> List[FibonacciLevel]:
253
+ """Calcula níveis de projeção de Fibonacci"""
254
+ levels = []
255
+ swing_range = swing_high - swing_low
256
+
257
+ for ratio in self.projection_ratios:
258
+ # Projeção baseada no movimento atual
259
+ if current_price > (swing_high + swing_low) / 2: # Tendência de alta
260
+ price = current_price + (swing_range * ratio)
261
+ direction = 'projection_up'
262
+ else: # Tendência de baixa
263
+ price = current_price - (swing_range * ratio)
264
+ direction = 'projection_down'
265
+
266
+ distance = abs(current_price - price)
267
+ strength = self._calculate_level_strength(price, current_price, 'projection')
268
+
269
+ levels.append(FibonacciLevel(
270
+ level=ratio,
271
+ price=price,
272
+ type=direction,
273
+ ratio=ratio,
274
+ distance_from_current=distance,
275
+ strength=strength
276
+ ))
277
+
278
+ return sorted(levels, key=lambda x: x.distance_from_current)
279
+
280
+ def _calculate_level_strength(
281
+ self, level_price: float, current_price: float, level_type: str
282
+ ) -> float:
283
+ """Calcula a força de um nível de Fibonacci"""
284
+ distance_factor = 1 / (1 + abs(level_price - current_price) / current_price)
285
+
286
+ type_weights = {
287
+ 'retracement': 1.0,
288
+ 'extension': 0.8,
289
+ 'projection': 0.6
290
+ }
291
+
292
+ base_strength = type_weights.get(level_type, 0.5)
293
+ return base_strength * distance_factor
294
+
295
+ def _identify_confluence_zones(
296
+ self, all_levels: List[FibonacciLevel]
297
+ ) -> List[ConfluenceZone]:
298
+ """Identifica zonas de confluência entre níveis"""
299
+ confluence_zones = []
300
+
301
+ # Agrupar níveis próximos
302
+ sorted_levels = sorted(all_levels, key=lambda x: x.price)
303
+
304
+ i = 0
305
+ while i < len(sorted_levels):
306
+ current_level = sorted_levels[i]
307
+ zone_levels = [current_level]
308
+ zone_types = [current_level.type]
309
+
310
+ # Procurar níveis próximos
311
+ j = i + 1
312
+ while j < len(sorted_levels):
313
+ next_level = sorted_levels[j]
314
+ price_diff = abs(next_level.price - current_level.price) / current_level.price
315
+
316
+ if price_diff <= self.confluence_threshold:
317
+ zone_levels.append(next_level)
318
+ zone_types.append(next_level.type)
319
+ j += 1
320
+ else:
321
+ break
322
+
323
+ # Criar zona de confluência se houver níveis suficientes
324
+ if len(zone_levels) >= self.min_confluence_levels:
325
+ min_price = min(level.price for level in zone_levels)
326
+ max_price = max(level.price for level in zone_levels)
327
+ avg_strength = sum(level.strength for level in zone_levels) / len(zone_levels)
328
+
329
+ confluence_zones.append(ConfluenceZone(
330
+ price_range=(min_price, max_price),
331
+ levels_count=len(zone_levels),
332
+ strength=avg_strength * len(zone_levels), # Força multiplicada pelo número de níveis
333
+ types=list(set(zone_types))
334
+ ))
335
+
336
+ i = j if j > i + 1 else i + 1
337
+
338
+ return sorted(confluence_zones, key=lambda x: x.strength, reverse=True)
339
+
340
+ def _detect_harmonic_patterns(
341
+ self, swing_high: float, swing_low: float, current_price: float,
342
+ historical_data: Optional[pd.DataFrame] = None
343
+ ) -> List[HarmonicPattern]:
344
+ """Detecta padrões harmônicos (implementação básica)"""
345
+ patterns = []
346
+
347
+ # Implementação simplificada - pode ser expandida com dados históricos
348
+ swing_range = swing_high - swing_low
349
+
350
+ for pattern_name, ratios in self.harmonic_patterns.items():
351
+ # Verificar se o preço atual está em uma posição válida para o padrão
352
+ completion_point = swing_low + (swing_range * ratios['CD'])
353
+
354
+ if abs(current_price - completion_point) / current_price < 0.02: # 2% de tolerância
355
+ confidence = 0.7 # Confiança básica
356
+
357
+ # Calcular alvos baseados no padrão
358
+ target_levels = [
359
+ completion_point + (swing_range * 0.382),
360
+ completion_point + (swing_range * 0.618),
361
+ completion_point + (swing_range * 1.0)
362
+ ]
363
+
364
+ stop_loss = completion_point - (swing_range * 0.236)
365
+
366
+ patterns.append(HarmonicPattern(
367
+ name=pattern_name,
368
+ completion_point=completion_point,
369
+ confidence=confidence,
370
+ target_levels=target_levels,
371
+ stop_loss=stop_loss
372
+ ))
373
+
374
+ return sorted(patterns, key=lambda x: x.confidence, reverse=True)
375
+
376
+ def _determine_key_levels(
377
+ self, all_levels: List[FibonacciLevel], current_price: float
378
+ ) -> Tuple[float, float]:
379
+ """Determina níveis chave de suporte e resistência"""
380
+ support_levels = [level for level in all_levels if level.price < current_price]
381
+ resistance_levels = [level for level in all_levels if level.price > current_price]
382
+
383
+ # Suporte mais próximo e forte
384
+ key_support = current_price
385
+ if support_levels:
386
+ key_support = max(support_levels, key=lambda x: x.strength).price
387
+
388
+ # Resistência mais próxima e forte
389
+ key_resistance = current_price
390
+ if resistance_levels:
391
+ key_resistance = min(resistance_levels, key=lambda x: x.strength).price
392
+
393
+ return key_support, key_resistance
394
+
395
+ def _determine_trend_direction(
396
+ self, swing_high: float, swing_low: float, current_price: float
397
+ ) -> str:
398
+ """Determina direção da tendência"""
399
+ mid_point = (swing_high + swing_low) / 2
400
+
401
+ if current_price > mid_point + (swing_high - swing_low) * 0.1:
402
+ return 'ALTA'
403
+ elif current_price < mid_point - (swing_high - swing_low) * 0.1:
404
+ return 'BAIXA'
405
+ else:
406
+ return 'LATERAL'
407
+
408
+ def _determine_fibonacci_zone(
409
+ self, swing_high: float, swing_low: float, current_price: float
410
+ ) -> str:
411
+ """Determina zona de Fibonacci atual"""
412
+ swing_range = swing_high - swing_low
413
+ position = (current_price - swing_low) / swing_range
414
+
415
+ if position >= 0.786:
416
+ return 'ZONA_ALTA'
417
+ elif position >= 0.618:
418
+ return 'ZONA_MEDIA_ALTA'
419
+ elif position >= 0.382:
420
+ return 'ZONA_MEDIA'
421
+ elif position >= 0.236:
422
+ return 'ZONA_MEDIA_BAIXA'
423
+ else:
424
+ return 'ZONA_BAIXA'
425
+
426
+ def _calculate_overall_strength(
427
+ self, retracement_levels: List[FibonacciLevel],
428
+ extension_levels: List[FibonacciLevel],
429
+ confluence_zones: List[ConfluenceZone],
430
+ harmonic_patterns: List[HarmonicPattern]
431
+ ) -> float:
432
+ """Calcula força geral da análise"""
433
+ # Força baseada em níveis próximos
434
+ level_strength = sum(level.strength for level in retracement_levels[:3]) # Top 3
435
+ level_strength += sum(level.strength for level in extension_levels[:3]) # Top 3
436
+
437
+ # Força das zonas de confluência
438
+ confluence_strength = sum(zone.strength for zone in confluence_zones)
439
+
440
+ # Força dos padrões harmônicos
441
+ harmonic_strength = sum(pattern.confidence for pattern in harmonic_patterns)
442
+
443
+ # Normalizar para 0-1
444
+ total_strength = (level_strength + confluence_strength + harmonic_strength) / 10
445
+ return min(total_strength, 1.0)
446
+
447
+ def _generate_trading_signal(
448
+ self, current_price: float, key_support: float, key_resistance: float,
449
+ trend_direction: str, overall_strength: float
450
+ ) -> str:
451
+ """Gera sinal de trading baseado na análise"""
452
+ support_distance = abs(current_price - key_support) / current_price
453
+ resistance_distance = abs(current_price - key_resistance) / current_price
454
+
455
+ if overall_strength < 0.3:
456
+ return 'HOLD'
457
+
458
+ if trend_direction == 'ALTA' and support_distance < 0.02:
459
+ return 'BUY'
460
+ elif trend_direction == 'BAIXA' and resistance_distance < 0.02:
461
+ return 'SELL'
462
+ elif support_distance < resistance_distance and overall_strength > 0.6:
463
+ return 'BUY'
464
+ elif resistance_distance < support_distance and overall_strength > 0.6:
465
+ return 'SELL'
466
+ else:
467
+ return 'HOLD'
468
+
469
+ def format_analysis_report(self, analysis: AdvancedFibonacciAnalysis) -> str:
470
+ """Formata relatório da análise"""
471
+ report = f"""
472
+ 🔮 ANÁLISE AVANÇADA DE FIBONACCI
473
+ {'='*50}
474
+
475
+ 📊 DADOS BÁSICOS:
476
+ Swing Alto: {analysis.swing_high:,.2f}
477
+ Swing Baixo: {analysis.swing_low:,.2f}
478
+ Preço Atual: {analysis.current_price:,.2f}
479
+ Range: {analysis.swing_range:,.2f}
480
+
481
+ 📈 NÍVEIS DE RETRACEMENT ({len(analysis.retracement_levels)}):
482
+ """
483
+
484
+ for level in analysis.retracement_levels[:5]: # Top 5
485
+ report += f" {level.ratio:.1%}: {level.price:,.2f} (Força: {level.strength:.2f})\n"
486
+
487
+ report += f"\n📊 NÍVEIS DE EXTENSÃO ({len(analysis.extension_levels)}):\n"
488
+ for level in analysis.extension_levels[:5]: # Top 5
489
+ report += f" {level.ratio:.1%}: {level.price:,.2f} ({level.type})\n"
490
+
491
+ if analysis.confluence_zones:
492
+ report += f"\n🎯 ZONAS DE CONFLUÊNCIA ({len(analysis.confluence_zones)}):\n"
493
+ for zone in analysis.confluence_zones[:3]: # Top 3
494
+ report += f" {zone.price_range[0]:,.2f} - {zone.price_range[1]:,.2f} ({zone.levels_count} níveis)\n"
495
+
496
+ if analysis.harmonic_patterns:
497
+ report += f"\n🎼 PADRÕES HARMÔNICOS ({len(analysis.harmonic_patterns)}):\n"
498
+ for pattern in analysis.harmonic_patterns:
499
+ report += f" {pattern.name}: {pattern.confidence:.1%} confiança\n"
500
+
501
+ report += f"""
502
+
503
+ 🎯 NÍVEIS CHAVE:
504
+ Suporte: {analysis.key_support:,.2f}
505
+ Resistência: {analysis.key_resistance:,.2f}
506
+
507
+ 📊 ANÁLISE GERAL:
508
+ Tendência: {analysis.trend_direction}
509
+ Zona Fibonacci: {analysis.fibonacci_zone}
510
+ Força da Análise: {analysis.overall_strength:.1%}
511
+ Sinal: {analysis.trading_signal}
512
+ Alertas: {analysis.alerts_count}
513
+ """
514
+
515
+ return report
516
+
517
+ # Exemplo de uso
518
+ if __name__ == "__main__":
519
+ engine = AdvancedFibonacciEngine()
520
+
521
+ # Exemplo com dados do bot
522
+ analysis = engine.perform_advanced_analysis(
523
+ swing_high=140570.0,
524
+ swing_low=139540.0,
525
+ current_price=140135.0
526
+ )
527
+
528
+ print(engine.format_analysis_report(analysis))
market_analysis.py → src/analysis/market_analysis.py RENAMED
@@ -4,13 +4,23 @@ import re
4
  from typing import Dict, List, Optional, Any
5
  from dataclasses import dataclass
6
  from datetime import datetime
 
 
 
7
 
8
- from config import (
9
  TechnicalAnalysisConfig,
10
  ScoringConfig,
11
  TradingConfig,
12
  RegexPatterns
13
  )
 
 
 
 
 
 
 
14
 
15
 
16
  @dataclass
@@ -332,6 +342,11 @@ class TechnicalAnalysisEngine:
332
  self.momentum_analyzer = MomentumAnalyzer()
333
  self.volume_analyzer = VolumeAnalyzer()
334
  self.setup_detector = ScalpingSetupDetector()
 
 
 
 
 
335
 
336
  def analyze(self, market_data: MarketData) -> Dict[str, Any]:
337
  """Executa análise técnica completa."""
@@ -348,14 +363,22 @@ class TechnicalAnalysisEngine:
348
  special_signals = self.setup_detector.detect_perfect_setups(market_data, signals)
349
  all_signals = signals + special_signals
350
 
 
 
 
 
 
 
351
  # Calcular ação e confiança
352
  action, confidence = self._calculate_action_and_confidence(all_signals)
353
 
354
  return {
355
  'action': action,
356
  'confidence': confidence,
357
- 'signals': all_signals,
358
- 'market_data': market_data
 
 
359
  }
360
 
361
  def _calculate_action_and_confidence(self, signals: List[TechnicalSignal]) -> tuple[str, int]:
@@ -390,6 +413,124 @@ class TechnicalAnalysisEngine:
390
  min(ScoringConfig.MAX_CONFIDENCE, confidence_score))
391
 
392
  return action, confidence_score
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
 
394
 
395
  class RiskCalculator:
 
4
  from typing import Dict, List, Optional, Any
5
  from dataclasses import dataclass
6
  from datetime import datetime
7
+ import numpy as np
8
+ import pandas as pd
9
+ import logging
10
 
11
+ from config.config import (
12
  TechnicalAnalysisConfig,
13
  ScoringConfig,
14
  TradingConfig,
15
  RegexPatterns
16
  )
17
+ from ..utils.utils import calculate_rsi, calculate_bollinger_bands, calculate_ema, format_number
18
+ from .fibonacci_analysis import AdvancedFibonacciEngine, AdvancedFibonacciAnalysis
19
+ from ..core.log_parser import VampireBotLogParser, BotAnalysis
20
+
21
+ # Configurar logging
22
+ logging.basicConfig(level=logging.INFO)
23
+ logger = logging.getLogger(__name__)
24
 
25
 
26
  @dataclass
 
342
  self.momentum_analyzer = MomentumAnalyzer()
343
  self.volume_analyzer = VolumeAnalyzer()
344
  self.setup_detector = ScalpingSetupDetector()
345
+ self.fibonacci_engine = AdvancedFibonacciEngine()
346
+ self.log_parser = VampireBotLogParser()
347
+ self.advanced_processor = AdvancedMarketProcessor()
348
+ self.config = TECHNICAL_CONFIG
349
+ logger.info("TechnicalAnalysisEngine inicializado com processamento avançado")
350
 
351
  def analyze(self, market_data: MarketData) -> Dict[str, Any]:
352
  """Executa análise técnica completa."""
 
363
  special_signals = self.setup_detector.detect_perfect_setups(market_data, signals)
364
  all_signals = signals + special_signals
365
 
366
+ # Análise avançada de Fibonacci
367
+ fibonacci_analysis = self._perform_fibonacci_analysis(market_data)
368
+
369
+ # Processamento avançado de mercado
370
+ advanced_analysis = self._perform_advanced_market_analysis(market_data)
371
+
372
  # Calcular ação e confiança
373
  action, confidence = self._calculate_action_and_confidence(all_signals)
374
 
375
  return {
376
  'action': action,
377
  'confidence': confidence,
378
+ 'signals': all_signals,
379
+ 'fibonacci': fibonacci_analysis,
380
+ 'advanced_analysis': advanced_analysis,
381
+ 'market_data': market_data
382
  }
383
 
384
  def _calculate_action_and_confidence(self, signals: List[TechnicalSignal]) -> tuple[str, int]:
 
413
  min(ScoringConfig.MAX_CONFIDENCE, confidence_score))
414
 
415
  return action, confidence_score
416
+
417
+ def _perform_fibonacci_analysis(self, market_data: MarketData) -> Dict[str, Any]:
418
+ """Executa análise avançada de Fibonacci."""
419
+ try:
420
+ # Simular dados de preço para análise Fibonacci
421
+ prices = np.array([market_data.price * (1 + np.random.normal(0, 0.01)) for _ in range(100)])
422
+
423
+ # Executar análise Fibonacci
424
+ fib_analysis = self.fibonacci_engine.analyze_fibonacci_levels(
425
+ prices=prices,
426
+ current_price=market_data.price
427
+ )
428
+
429
+ return {
430
+ 'levels': fib_analysis.levels if fib_analysis else {},
431
+ 'signals': fib_analysis.signals if fib_analysis else [],
432
+ 'confluence_zones': fib_analysis.confluence_zones if fib_analysis else [],
433
+ 'strength': fib_analysis.overall_strength if fib_analysis else 0
434
+ }
435
+ except Exception as e:
436
+ logger.error(f"Erro na análise Fibonacci: {e}")
437
+ return {
438
+ 'levels': {},
439
+ 'signals': [],
440
+ 'confluence_zones': [],
441
+ 'strength': 0
442
+ }
443
+
444
+ def process_bot_log_data(self, log_content: str) -> Dict[str, Any]:
445
+ """Processa dados de log do bot externo."""
446
+ try:
447
+ # Parse do log
448
+ bot_analysis = self.log_parser.parse_log(log_content)
449
+
450
+ if not bot_analysis:
451
+ return {'error': 'Falha ao processar log do bot'}
452
+
453
+ # Converter para MarketData
454
+ market_data = MarketData(
455
+ price=bot_analysis.market_info.price,
456
+ variation=0, # Será calculado se necessário
457
+ rsi=bot_analysis.technical_indicators.rsi if bot_analysis.technical_indicators else 50,
458
+ ema_trend=bot_analysis.technical_indicators.ema if bot_analysis.technical_indicators else 'NEUTRO',
459
+ bb_position=bot_analysis.technical_indicators.bollinger if bot_analysis.technical_indicators else 'DENTRO',
460
+ volume=bot_analysis.market_info.volume
461
+ )
462
+
463
+ # Executar análise completa
464
+ analysis_result = self.analyze(market_data)
465
+
466
+ # Adicionar dados específicos do bot
467
+ analysis_result['bot_data'] = {
468
+ 'fibonacci_alerts': bot_analysis.fibonacci_analysis.alerts if bot_analysis.fibonacci_analysis else 0,
469
+ 'fibonacci_signal': bot_analysis.fibonacci_analysis.signal if bot_analysis.fibonacci_analysis else 'UNKNOWN',
470
+ 'technical_indicators': {
471
+ 'rsi': bot_analysis.technical_indicators.rsi if bot_analysis.technical_indicators else None,
472
+ 'ema': bot_analysis.technical_indicators.ema if bot_analysis.technical_indicators else None,
473
+ 'bollinger': bot_analysis.technical_indicators.bollinger if bot_analysis.technical_indicators else None,
474
+ 'atr': bot_analysis.technical_indicators.atr if bot_analysis.technical_indicators else None
475
+ },
476
+ 'original_analysis': bot_analysis
477
+ }
478
+
479
+ return analysis_result
480
+
481
+ except Exception as e:
482
+ logger.error(f"Erro ao processar dados do bot: {e}")
483
+ return {'error': f'Erro no processamento: {str(e)}'}
484
+
485
+ def _perform_advanced_market_analysis(self, market_data: MarketData) -> Dict[str, Any]:
486
+ """Executa análise avançada de mercado com swing points e padrões harmônicos."""
487
+ try:
488
+ # Simular dados históricos de preço para análise
489
+ base_price = market_data.price
490
+ prices = np.array([base_price * (1 + np.random.normal(0, 0.02)) for _ in range(100)])
491
+ volumes = np.array([1000 + np.random.randint(-200, 200) for _ in range(100)])
492
+
493
+ # Níveis de Fibonacci simulados
494
+ fibonacci_levels = {
495
+ '23.6%': base_price * 0.764,
496
+ '38.2%': base_price * 0.618,
497
+ '50.0%': base_price * 0.5,
498
+ '61.8%': base_price * 0.382,
499
+ '78.6%': base_price * 0.214
500
+ }
501
+
502
+ # Níveis de suporte/resistência simulados
503
+ support_resistance = [
504
+ base_price * 0.95,
505
+ base_price * 0.98,
506
+ base_price * 1.02,
507
+ base_price * 1.05
508
+ ]
509
+
510
+ # Executar processamento avançado
511
+ advanced_result = self.advanced_processor.process_market_data(
512
+ prices=prices,
513
+ volumes=volumes,
514
+ fibonacci_levels=fibonacci_levels,
515
+ support_resistance_levels=support_resistance
516
+ )
517
+
518
+ return advanced_result
519
+
520
+ except Exception as e:
521
+ logger.error(f"Erro na análise avançada de mercado: {e}")
522
+ return {
523
+ 'swing_points': {'count': 0, 'highs': [], 'lows': [], 'avg_strength': 0},
524
+ 'confluence_zones': {'count': 0, 'zones': [], 'strongest_zone': None},
525
+ 'harmonic_patterns': {'count': 0, 'patterns': [], 'most_reliable': None},
526
+ 'market_structure': 'UNKNOWN',
527
+ 'key_levels': []
528
+ }
529
+
530
+
531
+ class MarketAnalyzer:
532
+ """Analisador principal de mercado."""
533
+ pass
534
 
535
 
536
  class RiskCalculator:
src/analysis/sentiment_analysis.py ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Módulo de análise de sentimento usando IA financeira."""
2
+
3
+ import re
4
+ from typing import Dict, Optional, Any
5
+ from dataclasses import dataclass
6
+
7
+ from config.config import FINANCIAL_MODELS, AIConfig, AppConfig
8
+
9
+ # Importações opcionais para IA
10
+ try:
11
+ from transformers import pipeline
12
+ import torch
13
+ TRANSFORMERS_AVAILABLE = True
14
+ except ImportError:
15
+ TRANSFORMERS_AVAILABLE = False
16
+ print(AppConfig.STATUS_MESSAGES['AI_UNAVAILABLE'])
17
+
18
+
19
+ @dataclass
20
+ class SentimentResult:
21
+ """Classe para representar resultado de análise de sentimento."""
22
+ sentiment: str # 'positive', 'negative', 'neutral'
23
+ confidence: float # 0.0 - 1.0
24
+ label: str # 'POSITIVO', 'NEGATIVO', 'NEUTRO'
25
+ model_used: Optional[str] = None
26
+
27
+
28
+ class ModelManager:
29
+ """Gerenciador de modelos de IA."""
30
+
31
+ def __init__(self):
32
+ self.sentiment_pipeline = None
33
+ self.current_model_info = None
34
+ self.is_available = TRANSFORMERS_AVAILABLE
35
+
36
+ if self.is_available:
37
+ self._load_models()
38
+
39
+ def _load_models(self) -> None:
40
+ """Tenta carregar modelos em ordem de prioridade."""
41
+ for model_config in FINANCIAL_MODELS:
42
+ try:
43
+ print(AppConfig.STATUS_MESSAGES['AI_LOADING'].format(
44
+ model_config['description']
45
+ ))
46
+
47
+ self.sentiment_pipeline = pipeline(
48
+ AIConfig.PIPELINE_CONFIG['task'],
49
+ model=model_config["name"],
50
+ return_all_scores=AIConfig.PIPELINE_CONFIG['return_all_scores']
51
+ )
52
+
53
+ self.current_model_info = model_config
54
+ print(AppConfig.STATUS_MESSAGES['AI_SUCCESS'].format(
55
+ model_config['description']
56
+ ))
57
+ break
58
+
59
+ except Exception as e:
60
+ print(AppConfig.STATUS_MESSAGES['AI_FAILED'].format(
61
+ model_config['name'], str(e)
62
+ ))
63
+ continue
64
+
65
+ if self.sentiment_pipeline is None:
66
+ print(AppConfig.STATUS_MESSAGES['NO_MODEL_LOADED'])
67
+ self.is_available = False
68
+
69
+ def get_model_info(self) -> Optional[Dict[str, Any]]:
70
+ """Retorna informações do modelo atual."""
71
+ return self.current_model_info
72
+
73
+ def is_model_available(self) -> bool:
74
+ """Verifica se há modelo disponível."""
75
+ return self.is_available and self.sentiment_pipeline is not None
76
+
77
+
78
+ class TextPreprocessor:
79
+ """Pré-processador de texto para análise de sentimento."""
80
+
81
+ @staticmethod
82
+ def clean_text(text: str) -> str:
83
+ """Limpa e prepara texto para análise."""
84
+ if not text:
85
+ return ""
86
+
87
+ # Remover caracteres especiais, manter apenas palavras, espaços e alguns símbolos
88
+ clean_text = re.sub(r'[^\w\s\+\-\%\.]', ' ', text)
89
+
90
+ # Limitar tamanho para o modelo
91
+ clean_text = clean_text[:AIConfig.MAX_TEXT_LENGTH]
92
+
93
+ # Remover espaços extras
94
+ clean_text = ' '.join(clean_text.split())
95
+
96
+ return clean_text
97
+
98
+ @staticmethod
99
+ def extract_financial_keywords(text: str) -> Dict[str, int]:
100
+ """Extrai palavras-chave financeiras do texto."""
101
+ financial_keywords = {
102
+ 'positive': ['alta', 'subida', 'ganho', 'lucro', 'crescimento', 'otimista', 'positivo'],
103
+ 'negative': ['baixa', 'queda', 'perda', 'prejuízo', 'declínio', 'pessimista', 'negativo'],
104
+ 'neutral': ['estável', 'neutro', 'lateral', 'consolidação']
105
+ }
106
+
107
+ text_lower = text.lower()
108
+ keyword_counts = {'positive': 0, 'negative': 0, 'neutral': 0}
109
+
110
+ for category, keywords in financial_keywords.items():
111
+ for keyword in keywords:
112
+ keyword_counts[category] += text_lower.count(keyword)
113
+
114
+ return keyword_counts
115
+
116
+
117
+ class SentimentAnalyzer:
118
+ """Analisador de sentimento principal."""
119
+
120
+ def __init__(self, model_manager: ModelManager):
121
+ self.model_manager = model_manager
122
+ self.preprocessor = TextPreprocessor()
123
+
124
+ def analyze(self, text: str) -> SentimentResult:
125
+ """Analisa o sentimento do texto."""
126
+ if not self.model_manager.is_model_available():
127
+ return self._get_fallback_sentiment(text)
128
+
129
+ try:
130
+ # Pré-processar texto
131
+ clean_text = self.preprocessor.clean_text(text)
132
+
133
+ if not clean_text.strip():
134
+ return SentimentResult(
135
+ sentiment='neutral',
136
+ confidence=0.5,
137
+ label='NEUTRO',
138
+ model_used='fallback'
139
+ )
140
+
141
+ # Executar análise de sentimento
142
+ result = self.model_manager.sentiment_pipeline(clean_text)
143
+
144
+ # Processar resultado
145
+ return self._process_model_result(result)
146
+
147
+ except Exception as e:
148
+ print(f"Erro na análise de sentimento: {e}")
149
+ return self._get_fallback_sentiment(text)
150
+
151
+ def _process_model_result(self, result: Any) -> SentimentResult:
152
+ """Processa resultado do modelo de IA."""
153
+ try:
154
+ # Processar resultado baseado no formato
155
+ if isinstance(result, list) and len(result) > 0:
156
+ # Se return_all_scores=True, pegar o resultado com maior score
157
+ if isinstance(result[0], list):
158
+ predictions = result[0]
159
+ best_prediction = max(predictions, key=lambda x: x['score'])
160
+ else:
161
+ best_prediction = result[0]
162
+
163
+ # Mapear label usando o mapeamento do modelo atual
164
+ label = best_prediction['label']
165
+ confidence = best_prediction['score']
166
+
167
+ # Usar mapeamento específico do modelo ou fallback genérico
168
+ model_info = self.model_manager.get_model_info()
169
+ if model_info and label in model_info['labels']:
170
+ sentiment_label = model_info['labels'][label]
171
+ else:
172
+ # Fallback para mapeamento genérico
173
+ sentiment_label = self._map_generic_label(label)
174
+
175
+ return SentimentResult(
176
+ sentiment=label.lower(),
177
+ confidence=confidence,
178
+ label=sentiment_label,
179
+ model_used=model_info['name'] if model_info else 'unknown'
180
+ )
181
+
182
+ # Fallback se resultado não esperado
183
+ return SentimentResult(
184
+ sentiment='neutral',
185
+ confidence=0.5,
186
+ label='NEUTRO',
187
+ model_used='fallback'
188
+ )
189
+
190
+ except Exception as e:
191
+ print(f"Erro ao processar resultado do modelo: {e}")
192
+ return SentimentResult(
193
+ sentiment='neutral',
194
+ confidence=0.5,
195
+ label='NEUTRO',
196
+ model_used='error_fallback'
197
+ )
198
+
199
+ def _map_generic_label(self, label: str) -> str:
200
+ """Mapeia labels genéricos para formato padrão."""
201
+ label_lower = label.lower()
202
+
203
+ if 'neg' in label_lower or 'bad' in label_lower:
204
+ return 'NEGATIVO'
205
+ elif 'pos' in label_lower or 'good' in label_lower:
206
+ return 'POSITIVO'
207
+ else:
208
+ return 'NEUTRO'
209
+
210
+ def _get_fallback_sentiment(self, text: str) -> SentimentResult:
211
+ """Análise de sentimento baseada em palavras-chave (fallback)."""
212
+ if not text:
213
+ return SentimentResult(
214
+ sentiment='neutral',
215
+ confidence=0.5,
216
+ label='NEUTRO',
217
+ model_used='keyword_fallback'
218
+ )
219
+
220
+ # Análise baseada em palavras-chave
221
+ keyword_counts = self.preprocessor.extract_financial_keywords(text)
222
+
223
+ total_keywords = sum(keyword_counts.values())
224
+ if total_keywords == 0:
225
+ return SentimentResult(
226
+ sentiment='neutral',
227
+ confidence=0.5,
228
+ label='NEUTRO',
229
+ model_used='keyword_fallback'
230
+ )
231
+
232
+ # Determinar sentimento dominante
233
+ max_category = max(keyword_counts, key=keyword_counts.get)
234
+ max_count = keyword_counts[max_category]
235
+ confidence = min(0.8, max_count / total_keywords) # Máximo 80% de confiança
236
+
237
+ sentiment_mapping = {
238
+ 'positive': ('positive', 'POSITIVO'),
239
+ 'negative': ('negative', 'NEGATIVO'),
240
+ 'neutral': ('neutral', 'NEUTRO')
241
+ }
242
+
243
+ sentiment, label = sentiment_mapping[max_category]
244
+
245
+ return SentimentResult(
246
+ sentiment=sentiment,
247
+ confidence=confidence,
248
+ label=label,
249
+ model_used='keyword_fallback'
250
+ )
251
+
252
+
253
+ class SentimentScorer:
254
+ """Calculador de pontuação baseada em sentimento."""
255
+
256
+ @staticmethod
257
+ def calculate_sentiment_score(sentiment_result: SentimentResult) -> int:
258
+ """Calcula pontuação de confiança baseada no sentimento."""
259
+ from config import ScoringConfig
260
+
261
+ base_score = int(sentiment_result.confidence * ScoringConfig.SENTIMENT_MAX_SCORE)
262
+
263
+ # Bonificação por modelo de IA vs fallback
264
+ if sentiment_result.model_used and 'fallback' not in sentiment_result.model_used:
265
+ base_score = int(base_score * 1.2) # 20% de bonificação para modelos de IA
266
+
267
+ return min(base_score, ScoringConfig.SENTIMENT_MAX_SCORE)
268
+
269
+ @staticmethod
270
+ def get_sentiment_signal_description(sentiment_result: SentimentResult) -> str:
271
+ """Gera descrição do sinal de sentimento."""
272
+ confidence_pct = sentiment_result.confidence * 100
273
+
274
+ if sentiment_result.label == 'POSITIVO':
275
+ bias = "viés de COMPRA"
276
+ elif sentiment_result.label == 'NEGATIVO':
277
+ bias = "viés de VENDA"
278
+ else:
279
+ bias = "sem viés claro"
280
+
281
+ model_indicator = "🤖 IA" if 'fallback' not in (sentiment_result.model_used or '') else "📝 Palavras-chave"
282
+
283
+ return f"{model_indicator} Sentimento: {sentiment_result.label} ({confidence_pct:.1f}%): {bias}"
284
+
285
+
286
+ class SentimentAnalysisEngine:
287
+ """Engine principal de análise de sentimento."""
288
+
289
+ def __init__(self):
290
+ self.model_manager = ModelManager()
291
+ self.analyzer = SentimentAnalyzer(self.model_manager)
292
+ self.scorer = SentimentScorer()
293
+
294
+ def analyze_text(self, text: str) -> Dict[str, Any]:
295
+ """Executa análise completa de sentimento."""
296
+ # Análise de sentimento
297
+ sentiment_result = self.analyzer.analyze(text)
298
+
299
+ # Calcular pontuação
300
+ score = self.scorer.calculate_sentiment_score(sentiment_result)
301
+
302
+ # Gerar descrição
303
+ description = self.scorer.get_sentiment_signal_description(sentiment_result)
304
+
305
+ return {
306
+ 'result': sentiment_result,
307
+ 'score': score,
308
+ 'description': description
309
+ }
310
+
311
+ def get_model_status(self) -> Dict[str, Any]:
312
+ """Retorna status do modelo atual."""
313
+ if self.model_manager.is_model_available():
314
+ model_info = self.model_manager.get_model_info()
315
+ return {
316
+ 'available': True,
317
+ 'model_name': model_info['name'] if model_info else 'Unknown',
318
+ 'description': model_info['description'] if model_info else 'Unknown Model',
319
+ 'status': 'active'
320
+ }
321
+ else:
322
+ return {
323
+ 'available': False,
324
+ 'model_name': None,
325
+ 'description': 'IA indisponível - usando análise por palavras-chave',
326
+ 'status': 'fallback'
327
+ }
328
+
329
+ def is_available(self) -> bool:
330
+ """Verifica se análise de IA está disponível."""
331
+ return self.model_manager.is_model_available()
src/core/__init__.py ADDED
File without changes
src/core/log_parser.py ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import json
3
+ from datetime import datetime
4
+ from typing import Dict, List, Optional, Any
5
+ from dataclasses import dataclass, asdict
6
+ import logging
7
+
8
+ # Configurar logging
9
+ logging.basicConfig(level=logging.INFO)
10
+ logger = logging.getLogger(__name__)
11
+
12
+ @dataclass
13
+ class MarketData:
14
+ """Estrutura para dados de mercado"""
15
+ symbol: str
16
+ current_price: float
17
+ variation: float
18
+ variation_percent: float
19
+ high: float
20
+ low: float
21
+ volume: int
22
+ timestamp: str
23
+
24
+ @dataclass
25
+ class TechnicalIndicators:
26
+ """Estrutura para indicadores técnicos"""
27
+ rsi: float
28
+ rsi_status: str
29
+ ema_fast: float
30
+ ema_slow: float
31
+ ema_trend: str
32
+ bollinger_status: str
33
+ bollinger_upper: float
34
+ bollinger_lower: float
35
+ atr: float
36
+ volatility: str
37
+ volatility_multiplier: float
38
+
39
+ @dataclass
40
+ class FibonacciAnalysis:
41
+ """Estrutura para análise de Fibonacci"""
42
+ swing_high: float
43
+ swing_low: float
44
+ current_price: float
45
+ swing_difference: float
46
+ retracement_levels: int
47
+ extension_levels: int
48
+ projection_levels: int
49
+ total_levels: int
50
+ confluence_zones: int
51
+ harmonic_patterns: int
52
+ temporal_projections: int
53
+ analysis_strength: float
54
+ zone: str
55
+ support: float
56
+ resistance: float
57
+ alerts: int
58
+ signal: str
59
+
60
+ @dataclass
61
+ class BotAnalysis:
62
+ """Estrutura completa da análise do bot"""
63
+ analysis_number: int
64
+ timestamp: str
65
+ market_data: MarketData
66
+ technical_indicators: TechnicalIndicators
67
+ fibonacci_analysis: FibonacciAnalysis
68
+ performance_time: Optional[float] = None
69
+
70
+ class VampireBotLogParser:
71
+ """Parser para logs do Vampire Trading Bot"""
72
+
73
+ def __init__(self):
74
+ self.patterns = self._compile_patterns()
75
+
76
+ def _compile_patterns(self) -> Dict[str, re.Pattern]:
77
+ """Compila padrões regex para extração de dados"""
78
+ return {
79
+ 'analysis_header': re.compile(r'⏰ Análise #(\d+) - ([\d:]+)'),
80
+ 'market_symbol': re.compile(r'📊 DADOS DE MERCADO - (\w+)'),
81
+ 'current_price': re.compile(r'Preço Atual: ([\d.]+) ↗'),
82
+ 'variation': re.compile(r'Variação: ([+-][\d.]+) \(([+-][\d.]+)%\)'),
83
+ 'high_low': re.compile(r'Máxima: ([\d.]+)\nMínima: ([\d.]+)'),
84
+ 'volume': re.compile(r'Volume: (\d+)'),
85
+ 'rsi': re.compile(r'RSI \(14\): ([\d.]+) \((\w+)\)'),
86
+ 'ema': re.compile(r'EMA Rápida: ([\d.]+)\nEMA Lenta: ([\d.]+)'),
87
+ 'ema_trend': re.compile(r'Tendência EMA: (\w+)'),
88
+ 'bollinger': re.compile(r'Bollinger: ([\w\s]+)\n\s+Superior: ([\d.]+)\n\s+Inferior: ([\d.]+)'),
89
+ 'atr': re.compile(r'ATR: ([\d.]+)'),
90
+ 'volatility': re.compile(r'Volatilidade: (\w+) \(([\d.]+)x\)'),
91
+ 'swing_points': re.compile(r'📊 Swing Points - Alta: ([\d,]+\.\d+), Baixa: ([\d,]+\.\d+), Atual: ([\d,]+\.\d+)'),
92
+ 'swing_difference': re.compile(r'📏 Diferença Swing: ([\d,]+\.\d+) pontos'),
93
+ 'retracement_levels': re.compile(r'📈 Níveis de Retracement calculados: (\d+) níveis'),
94
+ 'extension_levels': re.compile(r'📊 Níveis de Extensão calculados: (\d+) níveis'),
95
+ 'projection_levels': re.compile(r'🎯 Níveis de Projeção calculados: (\d+) níveis'),
96
+ 'total_levels': re.compile(r'🔢 Total de níveis Fibonacci: (\d+)'),
97
+ 'confluence_zones': re.compile(r'🎯 Zonas de Confluência detectadas: (\d+)'),
98
+ 'harmonic_patterns': re.compile(r'🎼 Padrões Harmônicos detectados: (\d+)'),
99
+ 'temporal_projections': re.compile(r'⏰ Projeções Temporais calculadas: (\d+)'),
100
+ 'analysis_strength': re.compile(r'💪 Força Geral da Análise: ([\d.]+)'),
101
+ 'fibonacci_conclusion': re.compile(r'🔮 ANÁLISE CONCLUÍDA - Zona: (\w+), Suporte: ([\d.]+), Resistência: ([\d.]+)'),
102
+ 'performance_time': re.compile(r'Análise de mercado lenta: ([\d.]+)s'),
103
+ 'fibonacci_signal': re.compile(r'🔮 Fibonacci Avançado:\s+Alertas:(\d+) FibSinal:(\w+)')
104
+ }
105
+
106
+ def parse_log_content(self, log_content: str) -> Optional[BotAnalysis]:
107
+ """Parseia o conteúdo completo do log"""
108
+ try:
109
+ # Extrair cabeçalho da análise
110
+ analysis_match = self.patterns['analysis_header'].search(log_content)
111
+ if not analysis_match:
112
+ logger.warning("Cabeçalho da análise não encontrado")
113
+ return None
114
+
115
+ analysis_number = int(analysis_match.group(1))
116
+ timestamp = analysis_match.group(2)
117
+
118
+ # Extrair dados de mercado
119
+ market_data = self._extract_market_data(log_content)
120
+ if not market_data:
121
+ logger.warning("Dados de mercado não encontrados")
122
+ return None
123
+
124
+ # Extrair indicadores técnicos
125
+ technical_indicators = self._extract_technical_indicators(log_content)
126
+ if not technical_indicators:
127
+ logger.warning("Indicadores técnicos não encontrados")
128
+ return None
129
+
130
+ # Extrair análise de Fibonacci
131
+ fibonacci_analysis = self._extract_fibonacci_analysis(log_content)
132
+ if not fibonacci_analysis:
133
+ logger.warning("Análise de Fibonacci não encontrada")
134
+ return None
135
+
136
+ # Extrair tempo de performance (opcional)
137
+ performance_match = self.patterns['performance_time'].search(log_content)
138
+ performance_time = float(performance_match.group(1)) if performance_match else None
139
+
140
+ return BotAnalysis(
141
+ analysis_number=analysis_number,
142
+ timestamp=timestamp,
143
+ market_data=market_data,
144
+ technical_indicators=technical_indicators,
145
+ fibonacci_analysis=fibonacci_analysis,
146
+ performance_time=performance_time
147
+ )
148
+
149
+ except Exception as e:
150
+ logger.error(f"Erro ao parsear log: {e}")
151
+ return None
152
+
153
+ def _extract_market_data(self, content: str) -> Optional[MarketData]:
154
+ """Extrai dados de mercado do log"""
155
+ try:
156
+ symbol_match = self.patterns['market_symbol'].search(content)
157
+ price_match = self.patterns['current_price'].search(content)
158
+ variation_match = self.patterns['variation'].search(content)
159
+ high_low_match = self.patterns['high_low'].search(content)
160
+ volume_match = self.patterns['volume'].search(content)
161
+
162
+ if not all([symbol_match, price_match, variation_match, high_low_match, volume_match]):
163
+ return None
164
+
165
+ return MarketData(
166
+ symbol=symbol_match.group(1),
167
+ current_price=float(price_match.group(1)),
168
+ variation=float(variation_match.group(1)),
169
+ variation_percent=float(variation_match.group(2)),
170
+ high=float(high_low_match.group(1)),
171
+ low=float(high_low_match.group(2)),
172
+ volume=int(volume_match.group(1)),
173
+ timestamp=datetime.now().isoformat()
174
+ )
175
+
176
+ except Exception as e:
177
+ logger.error(f"Erro ao extrair dados de mercado: {e}")
178
+ return None
179
+
180
+ def _extract_technical_indicators(self, content: str) -> Optional[TechnicalIndicators]:
181
+ """Extrai indicadores técnicos do log"""
182
+ try:
183
+ rsi_match = self.patterns['rsi'].search(content)
184
+ ema_match = self.patterns['ema'].search(content)
185
+ ema_trend_match = self.patterns['ema_trend'].search(content)
186
+ bollinger_match = self.patterns['bollinger'].search(content)
187
+ atr_match = self.patterns['atr'].search(content)
188
+ volatility_match = self.patterns['volatility'].search(content)
189
+
190
+ if not all([rsi_match, ema_match, ema_trend_match, bollinger_match, atr_match, volatility_match]):
191
+ return None
192
+
193
+ return TechnicalIndicators(
194
+ rsi=float(rsi_match.group(1)),
195
+ rsi_status=rsi_match.group(2),
196
+ ema_fast=float(ema_match.group(1)),
197
+ ema_slow=float(ema_match.group(2)),
198
+ ema_trend=ema_trend_match.group(1),
199
+ bollinger_status=bollinger_match.group(1).strip(),
200
+ bollinger_upper=float(bollinger_match.group(2)),
201
+ bollinger_lower=float(bollinger_match.group(3)),
202
+ atr=float(atr_match.group(1)),
203
+ volatility=volatility_match.group(1),
204
+ volatility_multiplier=float(volatility_match.group(2))
205
+ )
206
+
207
+ except Exception as e:
208
+ logger.error(f"Erro ao extrair indicadores técnicos: {e}")
209
+ return None
210
+
211
+ def _extract_fibonacci_analysis(self, content: str) -> Optional[FibonacciAnalysis]:
212
+ """Extrai análise de Fibonacci do log"""
213
+ try:
214
+ # Buscar pelos últimos valores (análise final)
215
+ swing_matches = list(self.patterns['swing_points'].finditer(content))
216
+ swing_diff_matches = list(self.patterns['swing_difference'].finditer(content))
217
+ retracement_matches = list(self.patterns['retracement_levels'].finditer(content))
218
+ extension_matches = list(self.patterns['extension_levels'].finditer(content))
219
+ projection_matches = list(self.patterns['projection_levels'].finditer(content))
220
+ total_matches = list(self.patterns['total_levels'].finditer(content))
221
+ confluence_matches = list(self.patterns['confluence_zones'].finditer(content))
222
+ harmonic_matches = list(self.patterns['harmonic_patterns'].finditer(content))
223
+ temporal_matches = list(self.patterns['temporal_projections'].finditer(content))
224
+ strength_matches = list(self.patterns['analysis_strength'].finditer(content))
225
+ conclusion_matches = list(self.patterns['fibonacci_conclusion'].finditer(content))
226
+ signal_match = self.patterns['fibonacci_signal'].search(content)
227
+
228
+ if not (swing_matches and conclusion_matches and signal_match):
229
+ return None
230
+
231
+ # Usar os últimos valores encontrados
232
+ swing_match = swing_matches[-1]
233
+ conclusion_match = conclusion_matches[-1]
234
+
235
+ swing_high = float(swing_match.group(1).replace(',', ''))
236
+ swing_low = float(swing_match.group(2).replace(',', ''))
237
+ current_price = float(swing_match.group(3).replace(',', ''))
238
+
239
+ return FibonacciAnalysis(
240
+ swing_high=swing_high,
241
+ swing_low=swing_low,
242
+ current_price=current_price,
243
+ swing_difference=float(swing_diff_matches[-1].group(1).replace(',', '')) if swing_diff_matches else 0,
244
+ retracement_levels=int(retracement_matches[-1].group(1)) if retracement_matches else 0,
245
+ extension_levels=int(extension_matches[-1].group(1)) if extension_matches else 0,
246
+ projection_levels=int(projection_matches[-1].group(1)) if projection_matches else 0,
247
+ total_levels=int(total_matches[-1].group(1)) if total_matches else 0,
248
+ confluence_zones=int(confluence_matches[-1].group(1)) if confluence_matches else 0,
249
+ harmonic_patterns=int(harmonic_matches[-1].group(1)) if harmonic_matches else 0,
250
+ temporal_projections=int(temporal_matches[-1].group(1)) if temporal_matches else 0,
251
+ analysis_strength=float(strength_matches[-1].group(1)) if strength_matches else 0.0,
252
+ zone=conclusion_match.group(1),
253
+ support=float(conclusion_match.group(2)),
254
+ resistance=float(conclusion_match.group(3)),
255
+ alerts=int(signal_match.group(1)),
256
+ signal=signal_match.group(2)
257
+ )
258
+
259
+ except Exception as e:
260
+ logger.error(f"Erro ao extrair análise de Fibonacci: {e}")
261
+ return None
262
+
263
+ def parse_log_file(self, file_path: str) -> Optional[BotAnalysis]:
264
+ """Parseia arquivo de log"""
265
+ try:
266
+ with open(file_path, 'r', encoding='utf-8') as file:
267
+ content = file.read()
268
+ return self.parse_log_content(content)
269
+ except Exception as e:
270
+ logger.error(f"Erro ao ler arquivo de log: {e}")
271
+ return None
272
+
273
+ def to_dict(self, analysis: BotAnalysis) -> Dict[str, Any]:
274
+ """Converte análise para dicionário"""
275
+ return asdict(analysis)
276
+
277
+ def to_json(self, analysis: BotAnalysis) -> str:
278
+ """Converte análise para JSON"""
279
+ return json.dumps(self.to_dict(analysis), indent=2, ensure_ascii=False)
280
+
281
+ # Exemplo de uso
282
+ if __name__ == "__main__":
283
+ parser = VampireBotLogParser()
284
+
285
+ # Exemplo com o log fornecido
286
+ sample_log = """
287
+ ⏰ Análise #8 - 09:46:58
288
+
289
+ ================================================================================
290
+ 🧛 VAMPIRE TRADING BOT - ANÁLISE DETALHADA
291
+ ================================================================================
292
+
293
+ 📊 DADOS DE MERCADO - WINV25
294
+ ──────────────────────────────────────────────────
295
+ Preço Atual: 140135.00000 ↗
296
+ Variação: +5.00000 (+0.00%)
297
+ Máxima: 140155.00000
298
+ Mínima: 140075.00000
299
+ Volume: 5023
300
+
301
+ 📈 INDICADORES TÉCNICOS
302
+ ──────────────────────────────────────────────────
303
+ RSI (14): 46.39 (NEUTRO)
304
+ EMA Rápida: 140192.30752
305
+ EMA Lenta: 140221.86717
306
+ Tendência EMA: BAIXA
307
+ Bollinger: DENTRO DAS BANDAS
308
+ Superior: 140672.37317
309
+ Inferior: 139913.62683
310
+ ATR: 170.73782
311
+ Volatilidade: MÉDIA (1.23x)
312
+ 🔮 Fibonacci Avançado: Alertas:15 FibSinal:HOLD
313
+ """
314
+
315
+ # Simular dados de Fibonacci (já que não estão completos no exemplo)
316
+ full_sample = sample_log + """
317
+ 2025-08-27 09:46:58,333 - src.core.analysis.advanced_fibonacci - INFO - 🔮 ANÁLISE CONCLUÍDA - Zona: ZONA_MEDIA_ALTA, Suporte: 140133.28, Resistência: 140176.54
318
+ 2025-08-27 09:46:58,218 - src.core.analysis.advanced_fibonacci - INFO - 📊 Swing Points - Alta: 140,570.00, Baixa: 139,540.00, Atual: 140,135.00
319
+ 2025-08-27 09:46:58,219 - src.core.analysis.advanced_fibonacci - INFO - 📏 Diferença Swing: 1,030.00 pontos
320
+ 2025-08-27 09:46:58,244 - src.core.analysis.advanced_fibonacci - INFO - 📈 Níveis de Retracement calculados: 13 níveis
321
+ 2025-08-27 09:46:58,297 - src.core.analysis.advanced_fibonacci - INFO - 📊 Níveis de Extensão calculados: 11 níveis
322
+ 2025-08-27 09:46:58,323 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Níveis de Projeção calculados: 8 níveis
323
+ 2025-08-27 09:46:58,325 - src.core.analysis.advanced_fibonacci - INFO - 🔢 Total de níveis Fibonacci: 32
324
+ 2025-08-27 09:46:58,327 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Zonas de Confluência detectadas: 0
325
+ 2025-08-27 09:46:58,329 - src.core.analysis.advanced_fibonacci - INFO - 🎼 Padrões Harmônicos detectados: 0
326
+ 2025-08-27 09:46:58,332 - src.core.analysis.advanced_fibonacci - INFO - ⏰ Projeções Temporais calculadas: 0
327
+ 2025-08-27 09:46:58,332 - src.core.analysis.advanced_fibonacci - INFO - 💪 Força Geral da Análise: 0.00
328
+ """
329
+
330
+ result = parser.parse_log_content(full_sample)
331
+ if result:
332
+ print("✅ Log parseado com sucesso!")
333
+ print(parser.to_json(result))
334
+ else:
335
+ print("❌ Erro ao parsear log")
src/core/performance_monitor.py ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import psutil
3
+ import threading
4
+ from datetime import datetime, timedelta
5
+ from typing import Dict, List, Any, Optional
6
+ from dataclasses import dataclass, asdict
7
+ from collections import deque, defaultdict
8
+ import json
9
+ import logging
10
+ from pathlib import Path
11
+
12
+ @dataclass
13
+ class PerformanceMetrics:
14
+ """Métricas de performance do sistema"""
15
+ timestamp: datetime
16
+ cpu_usage: float
17
+ memory_usage: float
18
+ memory_available: float
19
+ disk_usage: float
20
+ analysis_time: float = 0.0
21
+ events_processed: int = 0
22
+ errors_count: int = 0
23
+ bot_signals_count: int = 0
24
+ fibonacci_alerts_count: int = 0
25
+
26
+ @dataclass
27
+ class BotPerformanceStats:
28
+ """Estatísticas de performance específicas do bot"""
29
+ total_analyses: int = 0
30
+ successful_analyses: int = 0
31
+ failed_analyses: int = 0
32
+ average_analysis_time: float = 0.0
33
+ signals_generated: Dict[str, int] = None
34
+ fibonacci_accuracy: float = 0.0
35
+ last_update: datetime = None
36
+
37
+ def __post_init__(self):
38
+ if self.signals_generated is None:
39
+ self.signals_generated = {'COMPRAR': 0, 'VENDER': 0, 'AGUARDAR': 0}
40
+ if self.last_update is None:
41
+ self.last_update = datetime.now()
42
+
43
+ class PerformanceMonitor:
44
+ """Monitor de performance do sistema e bot"""
45
+
46
+ def __init__(self, max_metrics_history: int = 1000):
47
+ self.max_metrics_history = max_metrics_history
48
+ self.metrics_history = deque(maxlen=max_metrics_history)
49
+ self.bot_stats = BotPerformanceStats()
50
+ self.analysis_times = deque(maxlen=100) # Últimos 100 tempos de análise
51
+ self.error_log = deque(maxlen=50) # Últimos 50 erros
52
+
53
+ self.monitoring = False
54
+ self.monitor_thread = None
55
+ self.lock = threading.Lock()
56
+
57
+ # Setup logging
58
+ self.logger = logging.getLogger(__name__)
59
+
60
+ # Alertas de performance
61
+ self.performance_alerts = {
62
+ 'high_cpu': {'threshold': 80.0, 'triggered': False},
63
+ 'high_memory': {'threshold': 85.0, 'triggered': False},
64
+ 'slow_analysis': {'threshold': 5.0, 'triggered': False}, # segundos
65
+ 'high_error_rate': {'threshold': 0.1, 'triggered': False} # 10%
66
+ }
67
+
68
+ def start_monitoring(self, interval: float = 5.0):
69
+ """Inicia o monitoramento de performance"""
70
+ if self.monitoring:
71
+ return
72
+
73
+ self.monitoring = True
74
+ self.monitor_thread = threading.Thread(
75
+ target=self._monitoring_loop,
76
+ args=(interval,),
77
+ daemon=True
78
+ )
79
+ self.monitor_thread.start()
80
+ self.logger.info(f"Monitoramento de performance iniciado (intervalo: {interval}s)")
81
+
82
+ def stop_monitoring(self):
83
+ """Para o monitoramento de performance"""
84
+ self.monitoring = False
85
+ if self.monitor_thread:
86
+ self.monitor_thread.join(timeout=1.0)
87
+ self.logger.info("Monitoramento de performance parado")
88
+
89
+ def _monitoring_loop(self, interval: float):
90
+ """Loop principal de monitoramento"""
91
+ while self.monitoring:
92
+ try:
93
+ metrics = self._collect_system_metrics()
94
+
95
+ with self.lock:
96
+ self.metrics_history.append(metrics)
97
+
98
+ # Verificar alertas
99
+ self._check_performance_alerts(metrics)
100
+
101
+ time.sleep(interval)
102
+
103
+ except Exception as e:
104
+ self.logger.error(f"Erro no monitoramento: {e}")
105
+ time.sleep(interval)
106
+
107
+ def _collect_system_metrics(self) -> PerformanceMetrics:
108
+ """Coleta métricas do sistema"""
109
+ # CPU
110
+ cpu_usage = psutil.cpu_percent(interval=0.1)
111
+
112
+ # Memória
113
+ memory = psutil.virtual_memory()
114
+ memory_usage = memory.percent
115
+ memory_available = memory.available / (1024**3) # GB
116
+
117
+ # Disco
118
+ disk = psutil.disk_usage('/')
119
+ disk_usage = disk.percent
120
+
121
+ return PerformanceMetrics(
122
+ timestamp=datetime.now(),
123
+ cpu_usage=cpu_usage,
124
+ memory_usage=memory_usage,
125
+ memory_available=memory_available,
126
+ disk_usage=disk_usage
127
+ )
128
+
129
+ def record_analysis_time(self, analysis_time: float):
130
+ """Registra tempo de análise"""
131
+ with self.lock:
132
+ self.analysis_times.append(analysis_time)
133
+ self.bot_stats.total_analyses += 1
134
+
135
+ # Atualizar tempo médio
136
+ if self.analysis_times:
137
+ self.bot_stats.average_analysis_time = sum(self.analysis_times) / len(self.analysis_times)
138
+
139
+ def record_successful_analysis(self, signal: str = None):
140
+ """Registra análise bem-sucedida"""
141
+ with self.lock:
142
+ self.bot_stats.successful_analyses += 1
143
+
144
+ if signal and signal in self.bot_stats.signals_generated:
145
+ self.bot_stats.signals_generated[signal] += 1
146
+
147
+ self.bot_stats.last_update = datetime.now()
148
+
149
+ def record_failed_analysis(self, error: str):
150
+ """Registra análise falhada"""
151
+ with self.lock:
152
+ self.bot_stats.failed_analyses += 1
153
+ self.error_log.append({
154
+ 'timestamp': datetime.now(),
155
+ 'error': error
156
+ })
157
+ self.bot_stats.last_update = datetime.now()
158
+
159
+ def record_fibonacci_alert(self):
160
+ """Registra alerta de Fibonacci"""
161
+ with self.lock:
162
+ self.bot_stats.fibonacci_alerts_count += 1
163
+
164
+ def _check_performance_alerts(self, metrics: PerformanceMetrics):
165
+ """Verifica alertas de performance"""
166
+ # CPU alto
167
+ if metrics.cpu_usage > self.performance_alerts['high_cpu']['threshold']:
168
+ if not self.performance_alerts['high_cpu']['triggered']:
169
+ self.logger.warning(f"ALERTA: CPU alto ({metrics.cpu_usage:.1f}%)")
170
+ self.performance_alerts['high_cpu']['triggered'] = True
171
+ else:
172
+ self.performance_alerts['high_cpu']['triggered'] = False
173
+
174
+ # Memória alta
175
+ if metrics.memory_usage > self.performance_alerts['high_memory']['threshold']:
176
+ if not self.performance_alerts['high_memory']['triggered']:
177
+ self.logger.warning(f"ALERTA: Memória alta ({metrics.memory_usage:.1f}%)")
178
+ self.performance_alerts['high_memory']['triggered'] = True
179
+ else:
180
+ self.performance_alerts['high_memory']['triggered'] = False
181
+
182
+ # Análise lenta
183
+ if self.analysis_times and self.bot_stats.average_analysis_time > self.performance_alerts['slow_analysis']['threshold']:
184
+ if not self.performance_alerts['slow_analysis']['triggered']:
185
+ self.logger.warning(f"ALERTA: Análise lenta ({self.bot_stats.average_analysis_time:.2f}s)")
186
+ self.performance_alerts['slow_analysis']['triggered'] = True
187
+ else:
188
+ self.performance_alerts['slow_analysis']['triggered'] = False
189
+
190
+ # Taxa de erro alta
191
+ if self.bot_stats.total_analyses > 0:
192
+ error_rate = self.bot_stats.failed_analyses / self.bot_stats.total_analyses
193
+ if error_rate > self.performance_alerts['high_error_rate']['threshold']:
194
+ if not self.performance_alerts['high_error_rate']['triggered']:
195
+ self.logger.warning(f"ALERTA: Taxa de erro alta ({error_rate:.1%})")
196
+ self.performance_alerts['high_error_rate']['triggered'] = True
197
+ else:
198
+ self.performance_alerts['high_error_rate']['triggered'] = False
199
+
200
+ def get_current_metrics(self) -> Optional[PerformanceMetrics]:
201
+ """Retorna métricas atuais"""
202
+ with self.lock:
203
+ return self.metrics_history[-1] if self.metrics_history else None
204
+
205
+ def get_metrics_history(self, minutes: int = 60) -> List[PerformanceMetrics]:
206
+ """Retorna histórico de métricas dos últimos N minutos"""
207
+ cutoff_time = datetime.now() - timedelta(minutes=minutes)
208
+
209
+ with self.lock:
210
+ return [m for m in self.metrics_history if m.timestamp >= cutoff_time]
211
+
212
+ def get_bot_stats(self) -> BotPerformanceStats:
213
+ """Retorna estatísticas do bot"""
214
+ with self.lock:
215
+ return BotPerformanceStats(
216
+ total_analyses=self.bot_stats.total_analyses,
217
+ successful_analyses=self.bot_stats.successful_analyses,
218
+ failed_analyses=self.bot_stats.failed_analyses,
219
+ average_analysis_time=self.bot_stats.average_analysis_time,
220
+ signals_generated=self.bot_stats.signals_generated.copy(),
221
+ fibonacci_accuracy=self.bot_stats.fibonacci_accuracy,
222
+ last_update=self.bot_stats.last_update
223
+ )
224
+
225
+ def get_performance_summary(self) -> Dict[str, Any]:
226
+ """Retorna resumo de performance"""
227
+ current_metrics = self.get_current_metrics()
228
+ bot_stats = self.get_bot_stats()
229
+
230
+ # Calcular estatísticas dos últimos 30 minutos
231
+ recent_metrics = self.get_metrics_history(30)
232
+
233
+ avg_cpu = sum(m.cpu_usage for m in recent_metrics) / len(recent_metrics) if recent_metrics else 0
234
+ avg_memory = sum(m.memory_usage for m in recent_metrics) / len(recent_metrics) if recent_metrics else 0
235
+
236
+ # Taxa de sucesso
237
+ success_rate = 0
238
+ if bot_stats.total_analyses > 0:
239
+ success_rate = bot_stats.successful_analyses / bot_stats.total_analyses
240
+
241
+ # Alertas ativos
242
+ active_alerts = [name for name, alert in self.performance_alerts.items() if alert['triggered']]
243
+
244
+ return {
245
+ 'current_metrics': asdict(current_metrics) if current_metrics else None,
246
+ 'bot_stats': asdict(bot_stats),
247
+ 'averages_30min': {
248
+ 'cpu_usage': avg_cpu,
249
+ 'memory_usage': avg_memory
250
+ },
251
+ 'success_rate': success_rate,
252
+ 'active_alerts': active_alerts,
253
+ 'recent_errors': list(self.error_log)[-5:], # Últimos 5 erros
254
+ 'monitoring_status': self.monitoring
255
+ }
256
+
257
+ def export_metrics(self, filepath: str, hours: int = 24):
258
+ """Exporta métricas para arquivo JSON"""
259
+ metrics_data = self.get_metrics_history(hours * 60)
260
+ bot_stats = self.get_bot_stats()
261
+
262
+ export_data = {
263
+ 'export_timestamp': datetime.now().isoformat(),
264
+ 'metrics_history': [asdict(m) for m in metrics_data],
265
+ 'bot_statistics': asdict(bot_stats),
266
+ 'performance_summary': self.get_performance_summary()
267
+ }
268
+
269
+ # Converter datetime para string
270
+ def datetime_converter(obj):
271
+ if isinstance(obj, datetime):
272
+ return obj.isoformat()
273
+ raise TypeError(f"Object of type {type(obj)} is not JSON serializable")
274
+
275
+ with open(filepath, 'w', encoding='utf-8') as f:
276
+ json.dump(export_data, f, indent=2, default=datetime_converter, ensure_ascii=False)
277
+
278
+ self.logger.info(f"Métricas exportadas para: {filepath}")
279
+
280
+ def reset_stats(self):
281
+ """Reseta estatísticas do bot"""
282
+ with self.lock:
283
+ self.bot_stats = BotPerformanceStats()
284
+ self.analysis_times.clear()
285
+ self.error_log.clear()
286
+
287
+ self.logger.info("Estatísticas resetadas")
288
+
289
+ def optimize_performance(self) -> List[str]:
290
+ """Sugere otimizações baseadas nas métricas"""
291
+ suggestions = []
292
+ current_metrics = self.get_current_metrics()
293
+ bot_stats = self.get_bot_stats()
294
+
295
+ if current_metrics:
296
+ # CPU alto
297
+ if current_metrics.cpu_usage > 70:
298
+ suggestions.append("CPU alto detectado. Considere reduzir a frequência de análise.")
299
+
300
+ # Memória alta
301
+ if current_metrics.memory_usage > 80:
302
+ suggestions.append("Uso de memória alto. Considere limpar cache ou reduzir histórico.")
303
+
304
+ # Análise lenta
305
+ if bot_stats.average_analysis_time > 3.0:
306
+ suggestions.append("Análises lentas detectadas. Verifique a complexidade dos cálculos.")
307
+
308
+ # Taxa de erro alta
309
+ if bot_stats.total_analyses > 10:
310
+ error_rate = bot_stats.failed_analyses / bot_stats.total_analyses
311
+ if error_rate > 0.05: # 5%
312
+ suggestions.append(f"Taxa de erro alta ({error_rate:.1%}). Verifique logs de erro.")
313
+
314
+ if not suggestions:
315
+ suggestions.append("Sistema operando dentro dos parâmetros normais.")
316
+
317
+ return suggestions
318
+
319
+ # Instância global do monitor
320
+ performance_monitor = PerformanceMonitor()
321
+
322
+ # Decorador para medir tempo de análise
323
+ def measure_analysis_time(func):
324
+ """Decorador para medir tempo de análise"""
325
+ def wrapper(*args, **kwargs):
326
+ start_time = time.time()
327
+ try:
328
+ result = func(*args, **kwargs)
329
+ analysis_time = time.time() - start_time
330
+ performance_monitor.record_analysis_time(analysis_time)
331
+ performance_monitor.record_successful_analysis()
332
+ return result
333
+ except Exception as e:
334
+ analysis_time = time.time() - start_time
335
+ performance_monitor.record_analysis_time(analysis_time)
336
+ performance_monitor.record_failed_analysis(str(e))
337
+ raise
338
+ return wrapper
339
+
340
+ # Exemplo de uso
341
+ if __name__ == "__main__":
342
+ # Configurar logging
343
+ logging.basicConfig(level=logging.INFO)
344
+
345
+ # Iniciar monitoramento
346
+ monitor = PerformanceMonitor()
347
+ monitor.start_monitoring(interval=2.0)
348
+
349
+ try:
350
+ # Simular algumas análises
351
+ for i in range(10):
352
+ time.sleep(1)
353
+ monitor.record_analysis_time(0.5 + i * 0.1)
354
+ if i % 3 == 0:
355
+ monitor.record_successful_analysis('COMPRAR')
356
+ else:
357
+ monitor.record_successful_analysis('AGUARDAR')
358
+
359
+ # Mostrar resumo
360
+ summary = monitor.get_performance_summary()
361
+ print(json.dumps(summary, indent=2, default=str))
362
+
363
+ except KeyboardInterrupt:
364
+ print("Parando monitor...")
365
+ finally:
366
+ monitor.stop_monitoring()
src/integrations/__init__.py ADDED
File without changes
src/integrations/real_time_integration.py ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import os
3
+ import time
4
+ from datetime import datetime
5
+ from typing import Dict, Any, Optional, Callable
6
+ from pathlib import Path
7
+ import json
8
+ import logging
9
+ from dataclasses import dataclass, asdict
10
+ from threading import Thread, Event
11
+ import queue
12
+
13
+ from src.core.log_parser import VampireBotLogParser, BotAnalysis
14
+ from src.analysis.market_analysis import TechnicalAnalysisEngine
15
+
16
+ @dataclass
17
+ class RealTimeConfig:
18
+ """Configuração para integração em tempo real"""
19
+ log_file_path: str
20
+ check_interval: float = 1.0 # segundos
21
+ max_queue_size: int = 100
22
+ enable_notifications: bool = True
23
+ auto_analysis: bool = True
24
+ backup_logs: bool = True
25
+
26
+ @dataclass
27
+ class BotEvent:
28
+ """Evento do bot em tempo real"""
29
+ timestamp: datetime
30
+ event_type: str # 'new_analysis', 'fibonacci_alert', 'signal_change'
31
+ data: Dict[str, Any]
32
+ priority: str = 'normal' # 'low', 'normal', 'high', 'critical'
33
+
34
+ class FileWatcher:
35
+ """Monitor de arquivos para detectar mudanças em tempo real"""
36
+
37
+ def __init__(self, file_path: str, callback: Callable[[str], None]):
38
+ self.file_path = Path(file_path)
39
+ self.callback = callback
40
+ self.last_modified = 0
41
+ self.last_size = 0
42
+ self.running = False
43
+ self._stop_event = Event()
44
+
45
+ def start(self):
46
+ """Inicia o monitoramento do arquivo"""
47
+ self.running = True
48
+ self._stop_event.clear()
49
+
50
+ if self.file_path.exists():
51
+ stat = self.file_path.stat()
52
+ self.last_modified = stat.st_mtime
53
+ self.last_size = stat.st_size
54
+
55
+ def stop(self):
56
+ """Para o monitoramento"""
57
+ self.running = False
58
+ self._stop_event.set()
59
+
60
+ def check_changes(self) -> bool:
61
+ """Verifica se o arquivo foi modificado"""
62
+ if not self.file_path.exists():
63
+ return False
64
+
65
+ try:
66
+ stat = self.file_path.stat()
67
+ current_modified = stat.st_mtime
68
+ current_size = stat.st_size
69
+
70
+ # Verifica se houve mudança
71
+ if (current_modified > self.last_modified or
72
+ current_size != self.last_size):
73
+
74
+ self.last_modified = current_modified
75
+ self.last_size = current_size
76
+
77
+ # Lê o conteúdo novo
78
+ try:
79
+ with open(self.file_path, 'r', encoding='utf-8') as f:
80
+ content = f.read()
81
+ self.callback(content)
82
+ return True
83
+ except Exception as e:
84
+ logging.error(f"Erro ao ler arquivo: {e}")
85
+
86
+ except Exception as e:
87
+ logging.error(f"Erro ao verificar arquivo: {e}")
88
+
89
+ return False
90
+
91
+ class RealTimeProcessor:
92
+ """Processador de dados em tempo real do bot"""
93
+
94
+ def __init__(self, config: RealTimeConfig):
95
+ self.config = config
96
+ self.log_parser = VampireBotLogParser()
97
+ self.technical_engine = TechnicalAnalysisEngine()
98
+ self.event_queue = queue.Queue(maxsize=config.max_queue_size)
99
+ self.subscribers = []
100
+ self.running = False
101
+ self.last_analysis: Optional[BotAnalysis] = None
102
+
103
+ # Setup logging
104
+ self.logger = logging.getLogger(__name__)
105
+
106
+ def subscribe(self, callback: Callable[[BotEvent], None]):
107
+ """Inscreve um callback para receber eventos"""
108
+ self.subscribers.append(callback)
109
+
110
+ def unsubscribe(self, callback: Callable[[BotEvent], None]):
111
+ """Remove um callback da lista de inscritos"""
112
+ if callback in self.subscribers:
113
+ self.subscribers.remove(callback)
114
+
115
+ def _notify_subscribers(self, event: BotEvent):
116
+ """Notifica todos os inscritos sobre um evento"""
117
+ for callback in self.subscribers:
118
+ try:
119
+ callback(event)
120
+ except Exception as e:
121
+ self.logger.error(f"Erro ao notificar subscriber: {e}")
122
+
123
+ def _process_new_log_data(self, log_content: str):
124
+ """Processa novos dados de log"""
125
+ try:
126
+ # Parse do log
127
+ bot_analysis = self.log_parser.parse_log(log_content)
128
+
129
+ if bot_analysis:
130
+ # Verifica se é uma nova análise
131
+ is_new_analysis = (
132
+ self.last_analysis is None or
133
+ bot_analysis.timestamp != self.last_analysis.timestamp
134
+ )
135
+
136
+ if is_new_analysis:
137
+ # Cria evento de nova análise
138
+ event = BotEvent(
139
+ timestamp=datetime.now(),
140
+ event_type='new_analysis',
141
+ data=asdict(bot_analysis),
142
+ priority='normal'
143
+ )
144
+
145
+ # Adiciona à fila de eventos
146
+ try:
147
+ self.event_queue.put_nowait(event)
148
+ except queue.Full:
149
+ self.logger.warning("Fila de eventos cheia, removendo evento mais antigo")
150
+ try:
151
+ self.event_queue.get_nowait()
152
+ self.event_queue.put_nowait(event)
153
+ except queue.Empty:
154
+ pass
155
+
156
+ # Verifica alertas de Fibonacci
157
+ if bot_analysis.fibonacci_analysis and bot_analysis.fibonacci_analysis.alerts:
158
+ fib_event = BotEvent(
159
+ timestamp=datetime.now(),
160
+ event_type='fibonacci_alert',
161
+ data={
162
+ 'alerts': bot_analysis.fibonacci_analysis.alerts,
163
+ 'signal': bot_analysis.fibonacci_analysis.signal,
164
+ 'confidence': bot_analysis.fibonacci_analysis.confidence
165
+ },
166
+ priority='high'
167
+ )
168
+
169
+ try:
170
+ self.event_queue.put_nowait(fib_event)
171
+ except queue.Full:
172
+ pass
173
+
174
+ # Verifica mudança de sinal
175
+ if (self.last_analysis and
176
+ bot_analysis.fibonacci_analysis and
177
+ self.last_analysis.fibonacci_analysis and
178
+ bot_analysis.fibonacci_analysis.signal != self.last_analysis.fibonacci_analysis.signal):
179
+
180
+ signal_event = BotEvent(
181
+ timestamp=datetime.now(),
182
+ event_type='signal_change',
183
+ data={
184
+ 'old_signal': self.last_analysis.fibonacci_analysis.signal,
185
+ 'new_signal': bot_analysis.fibonacci_analysis.signal,
186
+ 'confidence': bot_analysis.fibonacci_analysis.confidence
187
+ },
188
+ priority='critical'
189
+ )
190
+
191
+ try:
192
+ self.event_queue.put_nowait(signal_event)
193
+ except queue.Full:
194
+ pass
195
+
196
+ self.last_analysis = bot_analysis
197
+
198
+ except Exception as e:
199
+ self.logger.error(f"Erro ao processar log: {e}")
200
+
201
+ def _event_processor_loop(self):
202
+ """Loop principal de processamento de eventos"""
203
+ while self.running:
204
+ try:
205
+ # Processa eventos da fila
206
+ try:
207
+ event = self.event_queue.get(timeout=0.1)
208
+ self._notify_subscribers(event)
209
+ self.event_queue.task_done()
210
+ except queue.Empty:
211
+ continue
212
+
213
+ except Exception as e:
214
+ self.logger.error(f"Erro no loop de eventos: {e}")
215
+ time.sleep(0.1)
216
+
217
+ def start(self):
218
+ """Inicia o processamento em tempo real"""
219
+ if self.running:
220
+ return
221
+
222
+ self.running = True
223
+ self.logger.info("Iniciando processamento em tempo real")
224
+
225
+ # Inicia thread de processamento de eventos
226
+ self.event_thread = Thread(target=self._event_processor_loop, daemon=True)
227
+ self.event_thread.start()
228
+
229
+ # Configura watcher de arquivo
230
+ self.file_watcher = FileWatcher(
231
+ self.config.log_file_path,
232
+ self._process_new_log_data
233
+ )
234
+ self.file_watcher.start()
235
+
236
+ # Inicia thread de monitoramento
237
+ self.monitor_thread = Thread(target=self._monitor_loop, daemon=True)
238
+ self.monitor_thread.start()
239
+
240
+ def stop(self):
241
+ """Para o processamento em tempo real"""
242
+ if not self.running:
243
+ return
244
+
245
+ self.logger.info("Parando processamento em tempo real")
246
+ self.running = False
247
+
248
+ if hasattr(self, 'file_watcher'):
249
+ self.file_watcher.stop()
250
+
251
+ def _monitor_loop(self):
252
+ """Loop de monitoramento de arquivo"""
253
+ while self.running:
254
+ try:
255
+ self.file_watcher.check_changes()
256
+ time.sleep(self.config.check_interval)
257
+ except Exception as e:
258
+ self.logger.error(f"Erro no monitoramento: {e}")
259
+ time.sleep(1)
260
+
261
+ def get_status(self) -> Dict[str, Any]:
262
+ """Retorna status do processador"""
263
+ return {
264
+ 'running': self.running,
265
+ 'queue_size': self.event_queue.qsize(),
266
+ 'subscribers_count': len(self.subscribers),
267
+ 'last_analysis_time': self.last_analysis.timestamp if self.last_analysis else None,
268
+ 'config': asdict(self.config)
269
+ }
270
+
271
+ class RealTimeIntegration:
272
+ """Sistema principal de integração em tempo real"""
273
+
274
+ def __init__(self, log_file_path: str):
275
+ self.config = RealTimeConfig(log_file_path=log_file_path)
276
+ self.processor = RealTimeProcessor(self.config)
277
+ self.event_history = []
278
+ self.max_history = 1000
279
+
280
+ # Setup logging
281
+ self.logger = logging.getLogger(__name__)
282
+
283
+ # Inscreve callback padrão
284
+ self.processor.subscribe(self._default_event_handler)
285
+
286
+ def _default_event_handler(self, event: BotEvent):
287
+ """Handler padrão para eventos"""
288
+ # Adiciona ao histórico
289
+ self.event_history.append(event)
290
+
291
+ # Mantém tamanho do histórico
292
+ if len(self.event_history) > self.max_history:
293
+ self.event_history = self.event_history[-self.max_history:]
294
+
295
+ # Log do evento
296
+ self.logger.info(f"Evento {event.event_type} - Prioridade: {event.priority}")
297
+
298
+ # Processamento específico por tipo
299
+ if event.event_type == 'signal_change':
300
+ self.logger.warning(
301
+ f"MUDANÇA DE SINAL: {event.data['old_signal']} -> {event.data['new_signal']} "
302
+ f"(Confiança: {event.data['confidence']}%)"
303
+ )
304
+ elif event.event_type == 'fibonacci_alert':
305
+ self.logger.info(f"Alerta Fibonacci: {len(event.data['alerts'])} alertas")
306
+
307
+ def start(self):
308
+ """Inicia a integração em tempo real"""
309
+ self.processor.start()
310
+ self.logger.info(f"Integração em tempo real iniciada para: {self.config.log_file_path}")
311
+
312
+ def stop(self):
313
+ """Para a integração em tempo real"""
314
+ self.processor.stop()
315
+ self.logger.info("Integração em tempo real parada")
316
+
317
+ def get_recent_events(self, limit: int = 10) -> list[BotEvent]:
318
+ """Retorna eventos recentes"""
319
+ return self.event_history[-limit:] if self.event_history else []
320
+
321
+ def get_status(self) -> Dict[str, Any]:
322
+ """Retorna status completo do sistema"""
323
+ processor_status = self.processor.get_status()
324
+ return {
325
+ **processor_status,
326
+ 'event_history_size': len(self.event_history),
327
+ 'recent_events': len([e for e in self.event_history if
328
+ (datetime.now() - e.timestamp).seconds < 300]) # últimos 5 min
329
+ }
330
+
331
+ # Exemplo de uso
332
+ if __name__ == "__main__":
333
+ # Configurar logging
334
+ logging.basicConfig(level=logging.INFO)
335
+
336
+ # Criar integração
337
+ integration = RealTimeIntegration("d:/hugging_face_spaces/text")
338
+
339
+ # Callback personalizado
340
+ def custom_handler(event: BotEvent):
341
+ print(f"[{event.timestamp}] {event.event_type}: {event.priority}")
342
+
343
+ integration.processor.subscribe(custom_handler)
344
+
345
+ try:
346
+ # Iniciar
347
+ integration.start()
348
+
349
+ # Manter rodando
350
+ while True:
351
+ time.sleep(1)
352
+ status = integration.get_status()
353
+ if status['recent_events'] > 0:
354
+ print(f"Eventos recentes: {status['recent_events']}")
355
+
356
+ except KeyboardInterrupt:
357
+ print("Parando integração...")
358
+ integration.stop()
src/ui/__init__.py ADDED
File without changes
src/ui/__pycache__/gradio_interface.cpython-313.pyc ADDED
Binary file (39.2 kB). View file
 
src/ui/gradio_interface.py ADDED
@@ -0,0 +1,828 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Módulo de interface do usuário com Gradio."""
2
+
3
+ import gradio as gr
4
+ from typing import Dict, Any, Optional, Tuple
5
+
6
+ from config.config import UIConfig, AppConfig
7
+ from src.utils.utils import (
8
+ DateTimeUtils,
9
+ NumberUtils,
10
+ ConfidenceUtils,
11
+ ActionUtils,
12
+ SentimentUtils,
13
+ FormatUtils
14
+ )
15
+
16
+
17
+ class UIComponents:
18
+ """Componentes da interface do usuário."""
19
+
20
+ @staticmethod
21
+ def create_header() -> str:
22
+ """Cria o cabeçalho da aplicação."""
23
+ return f"""
24
+ <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; margin-bottom: 20px;">
25
+ <h1 style="color: white; margin: 0; font-size: 2.5em; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">
26
+ 📈 {AppConfig.APP_TITLE}
27
+ </h1>
28
+ <p style="color: #f0f0f0; margin: 10px 0 0 0; font-size: 1.2em;">
29
+ {AppConfig.APP_DESCRIPTION}
30
+ </p>
31
+ </div>
32
+ """
33
+
34
+ @staticmethod
35
+ def format_harmonic_patterns(analysis_result: Dict[str, Any]) -> str:
36
+ """Formata padrões harmônicos detectados."""
37
+ harmonic_patterns = analysis_result.get('harmonic_patterns', [])
38
+
39
+ if not harmonic_patterns:
40
+ return """
41
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
42
+ <h3 style="color: #495057; margin-top: 0;">🎵 Padrões Harmônicos</h3>
43
+ <div style="text-align: center; padding: 30px; color: #6c757d;">
44
+ <div style="font-size: 2em; margin-bottom: 10px;">📊</div>
45
+ <p>Nenhum padrão harmônico detectado</p>
46
+ </div>
47
+ </div>
48
+ """
49
+
50
+ patterns_html = ""
51
+ for pattern in harmonic_patterns:
52
+ pattern_name = pattern.get('name', 'Desconhecido')
53
+ confidence = pattern.get('confidence', 0)
54
+ direction = pattern.get('direction', 'NEUTRO')
55
+
56
+ direction_emoji = "📈" if direction == "ALTA" else "📉" if direction == "BAIXA" else "➡️"
57
+
58
+ patterns_html += f"""
59
+ <div style="background: #f8f9fa; border-radius: 6px; padding: 15px; margin-bottom: 10px; border-left: 4px solid #007bff;">
60
+ <div style="display: flex; justify-content: space-between; align-items: center;">
61
+ <div>
62
+ <strong style="color: #495057;">{direction_emoji} {pattern_name}</strong>
63
+ <div style="color: #6c757d; font-size: 0.9em;">Direção: {direction}</div>
64
+ </div>
65
+ <div style="text-align: right;">
66
+ <div style="font-weight: bold; color: #007bff;">{confidence}%</div>
67
+ <div style="color: #6c757d; font-size: 0.8em;">Confiança</div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ """
72
+
73
+ return f"""
74
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
75
+ <h3 style="color: #495057; margin-top: 0; border-bottom: 2px solid #007bff; padding-bottom: 10px;">
76
+ 🎵 Padrões Harmônicos Detectados
77
+ </h3>
78
+ {patterns_html}
79
+ </div>
80
+ """
81
+
82
+ @staticmethod
83
+ def format_fibonacci_alerts(analysis_result: Dict[str, Any]) -> str:
84
+ """Formata alertas de Fibonacci."""
85
+ fibonacci_data = analysis_result.get('fibonacci_analysis', {})
86
+
87
+ if not fibonacci_data:
88
+ return """
89
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
90
+ <h3 style="color: #495057; margin-top: 0;">📐 Análise de Fibonacci</h3>
91
+ <div style="text-align: center; padding: 30px; color: #6c757d;">
92
+ <div style="font-size: 2em; margin-bottom: 10px;">📊</div>
93
+ <p>Dados de Fibonacci não disponíveis</p>
94
+ </div>
95
+ </div>
96
+ """
97
+
98
+ levels = fibonacci_data.get('levels', [])
99
+ current_level = fibonacci_data.get('current_level', 'N/A')
100
+ support_resistance = fibonacci_data.get('support_resistance', {})
101
+
102
+ levels_html = ""
103
+ for level in levels:
104
+ level_value = level.get('level', 0)
105
+ price = level.get('price', 0)
106
+ status = level.get('status', 'NEUTRO')
107
+
108
+ status_color = {
109
+ 'SUPORTE': '#28a745',
110
+ 'RESISTENCIA': '#dc3545',
111
+ 'NEUTRO': '#6c757d'
112
+ }.get(status, '#6c757d')
113
+
114
+ levels_html += f"""
115
+ <div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee;">
116
+ <span style="color: #495057;">{level_value}%</span>
117
+ <span style="font-weight: bold; color: #495057;">{NumberUtils.format_price(price)}</span>
118
+ <span style="color: {status_color}; font-weight: 600;">{status}</span>
119
+ </div>
120
+ """
121
+
122
+ return f"""
123
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
124
+ <h3 style="color: #495057; margin-top: 0; border-bottom: 2px solid #ffc107; padding-bottom: 10px;">
125
+ 📐 Análise de Fibonacci
126
+ </h3>
127
+
128
+ <div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 15px; margin-bottom: 15px;">
129
+ <strong style="color: #856404;">Nível Atual: {current_level}</strong>
130
+ </div>
131
+
132
+ <h4 style="color: #495057; margin-bottom: 10px;">📊 Níveis de Fibonacci</h4>
133
+ <div style="background: #f8f9fa; border-radius: 6px; padding: 15px;">
134
+ <div style="display: flex; justify-content: space-between; font-weight: bold; color: #495057; border-bottom: 2px solid #dee2e6; padding-bottom: 8px; margin-bottom: 10px;">
135
+ <span>Nível</span>
136
+ <span>Preço</span>
137
+ <span>Status</span>
138
+ </div>
139
+ {levels_html}
140
+ </div>
141
+ </div>
142
+ """
143
+
144
+ @staticmethod
145
+ def format_bot_analysis_result(analysis_result: Dict[str, Any]) -> str:
146
+ """Formata resultado específico da análise do bot externo."""
147
+ try:
148
+ bot_data = analysis_result.get('bot_data', {})
149
+ fibonacci_alerts = bot_data.get('fibonacci_alerts', 0)
150
+ fibonacci_signal = bot_data.get('fibonacci_signal', 'UNKNOWN')
151
+ technical_indicators = bot_data.get('technical_indicators', {})
152
+
153
+ # Formatação do sinal Fibonacci
154
+ signal_color = {
155
+ 'BUY': '#28a745',
156
+ 'SELL': '#dc3545',
157
+ 'HOLD': '#ffc107',
158
+ 'UNKNOWN': '#6c757d'
159
+ }.get(fibonacci_signal, '#6c757d')
160
+
161
+ signal_emoji = {
162
+ 'BUY': '📈',
163
+ 'SELL': '📉',
164
+ 'HOLD': '⏸️',
165
+ 'UNKNOWN': '❓'
166
+ }.get(fibonacci_signal, '❓')
167
+
168
+ # Indicadores técnicos do bot
169
+ indicators_html = ""
170
+ for indicator, value in technical_indicators.items():
171
+ if value is not None:
172
+ indicators_html += f"""
173
+ <div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee;">
174
+ <span style="color: #495057; text-transform: uppercase;">{indicator}</span>
175
+ <span style="font-weight: bold; color: #495057;">{value}</span>
176
+ </div>
177
+ """
178
+
179
+ return f"""
180
+ <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; padding: 25px; color: white; margin-bottom: 20px;">
181
+ <h2 style="margin-top: 0; display: flex; align-items: center; gap: 10px;">
182
+ 🤖 Análise do Bot de Trading
183
+ </h2>
184
+
185
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px;">
186
+ <div style="background: rgba(255,255,255,0.1); border-radius: 8px; padding: 15px;">
187
+ <h4 style="margin-top: 0; color: #f8f9fa;">📐 Fibonacci</h4>
188
+ <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
189
+ <span style="font-size: 1.5em;">{signal_emoji}</span>
190
+ <div>
191
+ <div style="font-weight: bold; font-size: 1.1em; color: {signal_color};">{fibonacci_signal}</div>
192
+ <div style="font-size: 0.9em; opacity: 0.8;">Sinal Atual</div>
193
+ </div>
194
+ </div>
195
+ <div style="font-size: 0.9em; opacity: 0.8;">Alertas: {fibonacci_alerts}</div>
196
+ </div>
197
+
198
+ <div style="background: rgba(255,255,255,0.1); border-radius: 8px; padding: 15px;">
199
+ <h4 style="margin-top: 0; color: #f8f9fa;">📊 Indicadores</h4>
200
+ <div style="font-size: 0.9em;">
201
+ {indicators_html if indicators_html else '<div style="opacity: 0.8;">Dados não disponíveis</div>'}
202
+ </div>
203
+ </div>
204
+ </div>
205
+ </div>
206
+
207
+ {ResultFormatter.format_main_result(analysis_result)}
208
+ """
209
+
210
+ except Exception as e:
211
+ return f"""
212
+ <div style="background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 8px; padding: 15px; color: #721c24;">
213
+ <h4 style="margin-top: 0;">❌ Erro na Formatação</h4>
214
+ <p style="margin: 0;">Erro ao formatar resultado do bot: {str(e)}</p>
215
+ </div>
216
+ """
217
+
218
+ @staticmethod
219
+ def create_header() -> str:
220
+ """Cria cabeçalho da aplicação."""
221
+ return f"""
222
+ <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; margin-bottom: 20px;">
223
+ <h1 style="color: white; margin: 0; font-size: 2.5em; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">
224
+ 📈 {AppConfig.APP_TITLE}
225
+ </h1>
226
+ <p style="color: #f0f0f0; margin: 10px 0 0 0; font-size: 1.2em;">
227
+ {AppConfig.APP_DESCRIPTION}
228
+ </p>
229
+ </div>
230
+ """
231
+
232
+ @staticmethod
233
+ def create_input_section() -> gr.Column:
234
+ """Cria seção de entrada de dados."""
235
+ with gr.Column() as input_section:
236
+ gr.HTML("""
237
+ <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #007bff;">
238
+ <h3 style="margin: 0 0 10px 0; color: #495057;">📊 Dados de Mercado</h3>
239
+ <p style="margin: 0; color: #6c757d; font-size: 0.9em;">
240
+ Cole os dados do ativo ou digite manualmente os valores
241
+ </p>
242
+ </div>
243
+ """)
244
+
245
+ # Abas para diferentes tipos de entrada
246
+ with gr.Tabs():
247
+ with gr.Tab("📊 Análise Manual"):
248
+ symbol_input = gr.Textbox(
249
+ label="Símbolo do Ativo",
250
+ placeholder="Ex: BTCUSDT",
251
+ lines=1
252
+ )
253
+ price_input = gr.Number(
254
+ label="Preço Atual",
255
+ placeholder="Ex: 45000.50"
256
+ )
257
+ volume_input = gr.Number(
258
+ label="Volume (Opcional)",
259
+ placeholder="Ex: 1000000"
260
+ )
261
+ sentiment_input = gr.Textbox(
262
+ label="Texto para Análise de Sentimento (Opcional)",
263
+ placeholder="Ex: Notícias ou comentários sobre o ativo",
264
+ lines=3
265
+ )
266
+ analyze_manual_btn = gr.Button(
267
+ "🔍 Analisar Manualmente",
268
+ variant="primary",
269
+ size="lg"
270
+ )
271
+
272
+ with gr.Tab("🤖 Log do Bot"):
273
+ market_input = gr.Textbox(
274
+ label="Log do Bot de Trading",
275
+ placeholder=AppConfig.EXAMPLE_INPUT,
276
+ lines=8,
277
+ max_lines=15
278
+ )
279
+ analyze_btn = gr.Button(
280
+ "🔍 Analisar Log do Bot",
281
+ variant="primary",
282
+ size="lg"
283
+ )
284
+
285
+ return input_section, market_input, analyze_btn, symbol_input, price_input, volume_input, sentiment_input, analyze_manual_btn
286
+
287
+ @staticmethod
288
+ def create_output_section() -> Tuple[gr.Column, Dict[str, Any]]:
289
+ """Cria seção de saída de resultados."""
290
+ outputs = {}
291
+
292
+ with gr.Column() as output_section:
293
+ # Status do modelo de IA
294
+ outputs['ai_status'] = gr.HTML(
295
+ UIComponents._get_ai_status_html(available=False)
296
+ )
297
+
298
+ # Resultado principal
299
+ outputs['main_result'] = gr.HTML()
300
+
301
+ # Abas de detalhes
302
+ with gr.Tabs():
303
+ # Aba de Análise Técnica
304
+ with gr.Tab("📊 Análise Técnica"):
305
+ outputs['technical_analysis'] = gr.HTML()
306
+
307
+ # Aba de Análise de Sentimento
308
+ with gr.Tab("🧠 Análise de Sentimento"):
309
+ outputs['sentiment_analysis'] = gr.HTML()
310
+
311
+ # Aba de Recomendações
312
+ with gr.Tab("💡 Recomendações"):
313
+ outputs['recommendations'] = gr.HTML()
314
+
315
+ # Aba de Padrões Harmônicos
316
+ with gr.Tab("🎵 Padrões Harmônicos"):
317
+ outputs['harmonic_patterns'] = gr.HTML()
318
+
319
+ # Aba de Alertas Fibonacci
320
+ with gr.Tab("📐 Fibonacci"):
321
+ outputs['fibonacci_alerts'] = gr.HTML()
322
+
323
+ # Aba de Dados Brutos
324
+ with gr.Tab("🔍 Dados Detalhados"):
325
+ outputs['raw_data'] = gr.JSON()
326
+
327
+ # Adicionar novos outputs ao dicionário
328
+ if 'harmonic_patterns' not in outputs:
329
+ outputs['harmonic_patterns'] = gr.HTML()
330
+ if 'fibonacci_alerts' not in outputs:
331
+ outputs['fibonacci_alerts'] = gr.HTML()
332
+
333
+ return output_section, outputs
334
+
335
+ @staticmethod
336
+ def create_footer(model_info: Optional[Dict[str, Any]] = None) -> str:
337
+ """Cria rodapé da aplicação."""
338
+ timestamp = DateTimeUtils.get_current_datetime()
339
+
340
+ if model_info and model_info.get('available', False):
341
+ ai_status = f"🤖 IA: {model_info.get('description', 'Modelo Ativo')}"
342
+ else:
343
+ ai_status = "⚠️ IA: Indisponível (apenas análise técnica)"
344
+
345
+ return f"""
346
+ <div style="text-align: center; padding: 15px; background: #f8f9fa; border-radius: 8px; margin-top: 20px; border-top: 2px solid #dee2e6;">
347
+ <p style="margin: 0; color: #6c757d; font-size: 0.9em;">
348
+ {ai_status} | ⏰ Última atualização: {timestamp}
349
+ </p>
350
+ <p style="margin: 5px 0 0 0; color: #adb5bd; font-size: 0.8em;">
351
+ Desenvolvido para análise de scalping no mercado financeiro
352
+ </p>
353
+ </div>
354
+ """
355
+
356
+ @staticmethod
357
+ def _get_ai_status_html(available: bool, model_description: str = "") -> str:
358
+ """Gera HTML para status da IA."""
359
+ if available:
360
+ return f"""
361
+ <div style="background: #d4edda; border: 1px solid #c3e6cb; border-radius: 8px; padding: 12px; margin-bottom: 15px;">
362
+ <div style="display: flex; align-items: center; gap: 10px;">
363
+ <span style="font-size: 1.2em;">🤖</span>
364
+ <div>
365
+ <strong style="color: #155724;">IA Ativa:</strong>
366
+ <span style="color: #155724;">{model_description}</span>
367
+ </div>
368
+ </div>
369
+ </div>
370
+ """
371
+ else:
372
+ return """
373
+ <div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 8px; padding: 12px; margin-bottom: 15px;">
374
+ <div style="display: flex; align-items: center; gap: 10px;">
375
+ <span style="font-size: 1.2em;">⚠️</span>
376
+ <div>
377
+ <strong style="color: #856404;">IA Indisponível:</strong>
378
+ <span style="color: #856404;">Executando apenas análise técnica</span>
379
+ </div>
380
+ </div>
381
+ </div>
382
+ """
383
+
384
+
385
+ class ResultFormatter:
386
+ """Formatador de resultados para a interface."""
387
+
388
+ @staticmethod
389
+ def format_main_result(analysis_result: Dict[str, Any]) -> str:
390
+ """Formata resultado principal da análise."""
391
+ action = analysis_result.get('action', 'AGUARDAR')
392
+ confidence = analysis_result.get('confidence', 0)
393
+ market_data = analysis_result.get('market_data', {})
394
+
395
+ # Obter informações da ação
396
+ action_emojis = ActionUtils.get_action_emojis(action)
397
+ action_color = ActionUtils.get_action_color(action)
398
+ confidence_level = ConfidenceUtils.get_confidence_level(confidence)
399
+ confidence_bar = ConfidenceUtils.generate_confidence_bar(confidence)
400
+
401
+ # Formatação do preço
402
+ price = market_data.get('price', 0)
403
+ variation = market_data.get('variation', 0)
404
+ formatted_price = NumberUtils.format_price(price)
405
+ formatted_variation = NumberUtils.format_percentage(variation)
406
+
407
+ # Cor da variação
408
+ variation_color = "#28a745" if variation >= 0 else "#dc3545"
409
+
410
+ return f"""
411
+ <div style="background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); border-radius: 12px; padding: 25px; margin: 15px 0; border: 2px solid #dee2e6;">
412
+ <div style="text-align: center; margin-bottom: 20px;">
413
+ <div style="font-size: 3em; margin-bottom: 10px;">{action_emojis['main']}</div>
414
+ <h2 style="margin: 0; color: {action_color}; font-size: 2em; text-transform: uppercase; letter-spacing: 1px;">
415
+ {action_emojis['action']} {action}
416
+ </h2>
417
+ </div>
418
+
419
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
420
+ <div style="text-align: center; padding: 15px; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
421
+ <div style="font-size: 0.9em; color: #6c757d; margin-bottom: 5px;">PREÇO ATUAL</div>
422
+ <div style="font-size: 1.8em; font-weight: bold; color: #495057;">{formatted_price}</div>
423
+ <div style="font-size: 1.1em; color: {variation_color}; font-weight: 600;">{formatted_variation}</div>
424
+ </div>
425
+
426
+ <div style="text-align: center; padding: 15px; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
427
+ <div style="font-size: 0.9em; color: #6c757d; margin-bottom: 5px;">CONFIANÇA</div>
428
+ <div style="font-size: 1.8em; font-weight: bold; color: #495057;">{confidence}%</div>
429
+ <div style="font-size: 0.9em; color: #6c757d;">{confidence_level}</div>
430
+ </div>
431
+ </div>
432
+
433
+ <div style="text-align: center; margin-top: 15px;">
434
+ <div style="font-size: 0.9em; color: #6c757d; margin-bottom: 8px;">NÍVEL DE CONFIANÇA</div>
435
+ <div style="font-family: monospace; font-size: 1.2em; letter-spacing: 2px; color: #495057;">{confidence_bar}</div>
436
+ </div>
437
+ </div>
438
+ """
439
+
440
+ @staticmethod
441
+ def format_technical_analysis(analysis_result: Dict[str, Any]) -> str:
442
+ """Formata análise técnica."""
443
+ market_data = analysis_result.get('market_data', {})
444
+ signals = analysis_result.get('signals', [])
445
+
446
+ # Resumo dos dados de mercado
447
+ market_summary = FormatUtils.format_market_summary(market_data)
448
+
449
+ # Lista de sinais
450
+ signals_list = FormatUtils.format_signal_list(signals)
451
+
452
+ return f"""
453
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
454
+ <h3 style="color: #495057; margin-top: 0; border-bottom: 2px solid #007bff; padding-bottom: 10px;">
455
+ 📊 Indicadores Técnicos
456
+ </h3>
457
+
458
+ <div style="background: #f8f9fa; padding: 15px; border-radius: 6px; margin-bottom: 20px;">
459
+ {market_summary}
460
+ </div>
461
+
462
+ <h4 style="color: #495057; margin-bottom: 15px;">🎯 Sinais Detectados</h4>
463
+ <div style="background: #f8f9fa; padding: 15px; border-radius: 6px; font-family: monospace; white-space: pre-line;">
464
+ {signals_list}
465
+ </div>
466
+ </div>
467
+ """
468
+
469
+ @staticmethod
470
+ def format_sentiment_analysis(analysis_result: Dict[str, Any]) -> str:
471
+ """Formata análise de sentimento."""
472
+ sentiment = analysis_result.get('sentiment', {})
473
+
474
+ if not sentiment:
475
+ return """
476
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
477
+ <h3 style="color: #495057; margin-top: 0;">🧠 Análise de Sentimento</h3>
478
+ <div style="text-align: center; padding: 30px; color: #6c757d;">
479
+ <div style="font-size: 2em; margin-bottom: 10px;">⚠️</div>
480
+ <p>Análise de sentimento não disponível</p>
481
+ <p style="font-size: 0.9em;">Instale as dependências de IA para ativar esta funcionalidade</p>
482
+ </div>
483
+ </div>
484
+ """
485
+
486
+ label = sentiment.get('label', 'NEUTRO')
487
+ confidence = sentiment.get('confidence', 0)
488
+ emoji = SentimentUtils.get_sentiment_emoji(label)
489
+
490
+ # Cor baseada no sentimento
491
+ sentiment_colors = {
492
+ 'POSITIVO': '#28a745',
493
+ 'NEGATIVO': '#dc3545',
494
+ 'NEUTRO': '#ffc107'
495
+ }
496
+ color = sentiment_colors.get(label, '#6c757d')
497
+
498
+ return f"""
499
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
500
+ <h3 style="color: #495057; margin-top: 0; border-bottom: 2px solid #28a745; padding-bottom: 10px;">
501
+ 🧠 Análise de Sentimento
502
+ </h3>
503
+
504
+ <div style="text-align: center; padding: 20px;">
505
+ <div style="font-size: 3em; margin-bottom: 15px;">{emoji}</div>
506
+ <h4 style="color: {color}; margin: 0; font-size: 1.5em; text-transform: uppercase;">{label}</h4>
507
+ <div style="margin-top: 10px; color: #6c757d;">Confiança: {confidence:.1f}%</div>
508
+ </div>
509
+
510
+ <div style="background: #f8f9fa; padding: 15px; border-radius: 6px; margin-top: 15px;">
511
+ <h5 style="margin-top: 0; color: #495057;">📝 Detalhes da Análise</h5>
512
+ <p style="margin: 0; color: #6c757d; font-size: 0.9em;">
513
+ O modelo de IA analisou o contexto do mercado e determinou um sentimento <strong>{label.lower()}</strong>
514
+ com {confidence:.1f}% de confiança.
515
+ </p>
516
+ </div>
517
+ </div>
518
+ """
519
+
520
+ @staticmethod
521
+ def format_recommendations(analysis_result: Dict[str, Any]) -> str:
522
+ """Formata recomendações de trading."""
523
+ action = analysis_result.get('action', 'AGUARDAR')
524
+ market_data = analysis_result.get('market_data', {})
525
+ price = market_data.get('price', 0)
526
+
527
+ # Recomendações de trading
528
+ trading_recs = FormatUtils.format_trading_recommendations(action, price)
529
+
530
+ # Direção de trading
531
+ direction = ActionUtils.get_trading_direction(action)
532
+ direction_emoji = "📈" if direction == "COMPRA" else "📉" if direction == "VENDA" else "⏸️"
533
+
534
+ return f"""
535
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
536
+ <h3 style="color: #495057; margin-top: 0; border-bottom: 2px solid #ffc107; padding-bottom: 10px;">
537
+ 💡 Recomendações de Trading
538
+ </h3>
539
+
540
+ <div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 15px; margin-bottom: 20px;">
541
+ <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
542
+ <span style="font-size: 1.5em;">{direction_emoji}</span>
543
+ <strong style="color: #856404;">Direção: {direction}</strong>
544
+ </div>
545
+ </div>
546
+
547
+ <div style="background: #f8f9fa; padding: 15px; border-radius: 6px; white-space: pre-line;">
548
+ {trading_recs}
549
+ </div>
550
+
551
+ <div style="background: #d1ecf1; border: 1px solid #bee5eb; border-radius: 6px; padding: 15px; margin-top: 15px;">
552
+ <h5 style="margin-top: 0; color: #0c5460;">⚠️ Aviso Importante</h5>
553
+ <p style="margin: 0; color: #0c5460; font-size: 0.9em;">
554
+ Esta análise é apenas para fins educacionais. Sempre faça sua própria pesquisa e
555
+ considere consultar um consultor financeiro antes de tomar decisões de investimento.
556
+ </p>
557
+ </div>
558
+ </div>
559
+ """
560
+
561
+
562
+ class GradioInterface:
563
+ """Interface principal do Gradio."""
564
+
565
+ def __init__(self, analysis_function, model_info: Optional[Dict[str, Any]] = None):
566
+ """Inicializa interface."""
567
+ self.analysis_function = analysis_function
568
+ self.model_info = model_info or {'available': False}
569
+ self.interface = None
570
+
571
+ def analyze_market(self, symbol, price, volume, sentiment_text):
572
+ """Função principal de análise"""
573
+ try:
574
+ # Validar entrada
575
+ if not symbol or not price:
576
+ return "❌ Erro: Símbolo e preço são obrigatórios"
577
+
578
+ price = float(price)
579
+ volume = float(volume) if volume else 0
580
+
581
+ # Criar dados de mercado
582
+ market_data = {
583
+ 'price': price,
584
+ 'variation': 0, # Será calculado se necessário
585
+ 'rsi': 50, # Valor padrão
586
+ 'ema_trend': 'NEUTRO',
587
+ 'bb_position': 'DENTRO',
588
+ 'volume': volume
589
+ }
590
+
591
+ # Executar análise
592
+ result = self.analysis_function(f"{symbol}: {price}")
593
+
594
+ # Formatar resultado
595
+ return self.format_analysis_result(result, sentiment_text, symbol)
596
+
597
+ except Exception as e:
598
+ return f"❌ Erro na análise: {str(e)}"
599
+
600
+ def analyze_bot_log(self, log_content):
601
+ """Função para analisar logs do bot externo"""
602
+ try:
603
+ if not log_content.strip():
604
+ return "❌ Erro: Conteúdo do log é obrigatório"
605
+
606
+ # Executar análise do log
607
+ result = self.analysis_function(log_content)
608
+
609
+ if 'error' in result:
610
+ return f"❌ {result['error']}"
611
+
612
+ # Formatar resultado específico do bot
613
+ return self.format_bot_analysis_result(result)
614
+
615
+ except Exception as e:
616
+ return f"❌ Erro na análise do log: {str(e)}"
617
+
618
+ def format_analysis_result(self, result, sentiment_text, symbol):
619
+ """Formata resultado da análise"""
620
+ return ResultFormatter.format_main_result(result)
621
+
622
+ def format_bot_analysis_result(self, result):
623
+ """Formata resultado específico da análise do bot"""
624
+ return ResultFormatter.format_main_result(result)
625
+
626
+ def create_interface(self) -> gr.Blocks:
627
+ """Cria interface completa do Gradio."""
628
+ with gr.Blocks(
629
+ title=AppConfig.APP_TITLE,
630
+ theme=gr.themes.Soft(),
631
+ css=self._get_custom_css()
632
+ ) as interface:
633
+ # Cabeçalho
634
+ gr.HTML(UIComponents.create_header())
635
+
636
+ # Layout principal
637
+ with gr.Row():
638
+ # Coluna de entrada (40%)
639
+ with gr.Column(scale=2):
640
+ input_section, market_input, analyze_btn, symbol_input, price_input, volume_input, sentiment_input, analyze_manual_btn = UIComponents.create_input_section()
641
+
642
+ # Coluna de saída (60%)
643
+ with gr.Column(scale=3):
644
+ output_section, outputs = UIComponents.create_output_section()
645
+
646
+ # Rodapé
647
+ gr.HTML(UIComponents.create_footer(self.model_info))
648
+
649
+ # Configurar eventos de análise
650
+ analyze_btn.click(
651
+ fn=self._analyze_wrapper,
652
+ inputs=[market_input],
653
+ outputs=[
654
+ outputs['ai_status'],
655
+ outputs['main_result'],
656
+ outputs['technical_analysis'],
657
+ outputs['sentiment_analysis'],
658
+ outputs['recommendations'],
659
+ outputs['harmonic_patterns'],
660
+ outputs['fibonacci_alerts'],
661
+ outputs['raw_data']
662
+ ]
663
+ )
664
+
665
+ analyze_manual_btn.click(
666
+ fn=self._analyze_manual_wrapper,
667
+ inputs=[symbol_input, price_input, volume_input, sentiment_input],
668
+ outputs=[
669
+ outputs['ai_status'],
670
+ outputs['main_result'],
671
+ outputs['technical_analysis'],
672
+ outputs['sentiment_analysis'],
673
+ outputs['recommendations'],
674
+ outputs['harmonic_patterns'],
675
+ outputs['fibonacci_alerts'],
676
+ outputs['raw_data']
677
+ ]
678
+ )
679
+
680
+ # Atualizar status da IA na inicialização
681
+ interface.load(
682
+ fn=lambda: UIComponents._get_ai_status_html(
683
+ self.model_info.get('available', False),
684
+ self.model_info.get('description', '')
685
+ ),
686
+ outputs=[outputs['ai_status']]
687
+ )
688
+
689
+ self.interface = interface
690
+ return interface
691
+
692
+ def _analyze_wrapper(self, market_input: str) -> Tuple[str, str, str, str, str, str, str, Dict[str, Any]]:
693
+ """Wrapper para função de análise com formatação de saída."""
694
+ try:
695
+ # Executar análise
696
+ analysis_result = self.analysis_function(market_input)
697
+
698
+ # Formatear resultados
699
+ ai_status = UIComponents._get_ai_status_html(
700
+ self.model_info.get('available', False),
701
+ self.model_info.get('description', '')
702
+ )
703
+
704
+ main_result = ResultFormatter.format_main_result(analysis_result)
705
+ technical_analysis = ResultFormatter.format_technical_analysis(analysis_result)
706
+ sentiment_analysis = ResultFormatter.format_sentiment_analysis(analysis_result)
707
+ recommendations = ResultFormatter.format_recommendations(analysis_result)
708
+ harmonic_patterns = ResultFormatter.format_harmonic_patterns(analysis_result)
709
+ fibonacci_alerts = ResultFormatter.format_fibonacci_alerts(analysis_result)
710
+
711
+ # Dados brutos para debug
712
+ raw_data = {
713
+ 'timestamp': DateTimeUtils.get_current_datetime(),
714
+ 'analysis_result': analysis_result
715
+ }
716
+
717
+ return (
718
+ ai_status,
719
+ main_result,
720
+ technical_analysis,
721
+ sentiment_analysis,
722
+ recommendations,
723
+ harmonic_patterns,
724
+ fibonacci_alerts,
725
+ raw_data
726
+ )
727
+
728
+ except Exception as e:
729
+ error_msg = f"Erro na análise: {str(e)}"
730
+ error_html = f"""
731
+ <div style="background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 8px; padding: 15px; color: #721c24;">
732
+ <h4 style="margin-top: 0;">❌ Erro na Análise</h4>
733
+ <p style="margin: 0;">{error_msg}</p>
734
+ </div>
735
+ """
736
+
737
+ return (
738
+ UIComponents._get_ai_status_html(False),
739
+ error_html,
740
+ error_html,
741
+ error_html,
742
+ error_html,
743
+ error_html,
744
+ error_html,
745
+ {'error': error_msg}
746
+ )
747
+
748
+ def _analyze_manual_wrapper(self, symbol: str, price: float, volume: float, sentiment_text: str) -> Tuple[str, str, str, str, str, str, str, Dict[str, Any]]:
749
+ """Wrapper para análise manual com formatação de saída."""
750
+ try:
751
+ # Validar entrada
752
+ if not symbol or not price:
753
+ raise ValueError("Símbolo e preço são obrigatórios")
754
+
755
+ # Criar entrada formatada
756
+ market_input = f"{symbol}: Preço={price}, Volume={volume or 0}"
757
+ if sentiment_text:
758
+ market_input += f", Sentimento={sentiment_text}"
759
+
760
+ # Executar análise usando o wrapper padrão
761
+ return self._analyze_wrapper(market_input)
762
+
763
+ except Exception as e:
764
+ error_msg = f"Erro na análise manual: {str(e)}"
765
+ error_html = f"""
766
+ <div style="background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 8px; padding: 15px; color: #721c24;">
767
+ <h4 style="margin-top: 0;">❌ Erro na Análise Manual</h4>
768
+ <p style="margin: 0;">{error_msg}</p>
769
+ </div>
770
+ """
771
+
772
+ return (
773
+ UIComponents._get_ai_status_html(False),
774
+ error_html,
775
+ error_html,
776
+ error_html,
777
+ error_html,
778
+ error_html,
779
+ error_html,
780
+ {'error': error_msg}
781
+ )
782
+
783
+ def _get_custom_css(self) -> str:
784
+ """Retorna CSS customizado para a interface."""
785
+ return """
786
+ .gradio-container {
787
+ max-width: 1200px !important;
788
+ margin: auto !important;
789
+ }
790
+
791
+ .gr-button {
792
+ transition: all 0.3s ease !important;
793
+ }
794
+
795
+ .gr-button:hover {
796
+ transform: translateY(-2px) !important;
797
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;
798
+ }
799
+
800
+ .gr-textbox textarea {
801
+ font-family: 'Courier New', monospace !important;
802
+ }
803
+
804
+ .gr-tab-nav {
805
+ background: #f8f9fa !important;
806
+ }
807
+
808
+ .gr-tab-nav button {
809
+ border-radius: 8px 8px 0 0 !important;
810
+ }
811
+ """
812
+
813
+ def launch(self, **kwargs) -> None:
814
+ """Lança a interface."""
815
+ if not self.interface:
816
+ self.create_interface()
817
+
818
+ default_kwargs = {
819
+ 'server_name': '127.0.0.1',
820
+ 'server_port': 7860,
821
+ 'share': False,
822
+ 'show_error': True
823
+ }
824
+
825
+ # Mesclar argumentos padrão com os fornecidos
826
+ launch_kwargs = {**default_kwargs, **kwargs}
827
+
828
+ self.interface.launch(**launch_kwargs)
src/utils/__init__.py ADDED
File without changes
src/utils/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (141 Bytes). View file
 
src/utils/__pycache__/utils.cpython-313.pyc ADDED
Binary file (18.2 kB). View file
 
src/utils/utils.py ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Módulo de utilitários e funções auxiliares."""
2
+
3
+ import json
4
+ from datetime import datetime
5
+ from typing import Dict, Any, Optional
6
+
7
+ from config.config import (
8
+ TradingConfig,
9
+ UIConfig,
10
+ ScoringConfig
11
+ )
12
+
13
+
14
+ class DateTimeUtils:
15
+ """Utilitários para manipulação de data e hora."""
16
+
17
+ @staticmethod
18
+ def get_current_timestamp() -> str:
19
+ """Retorna timestamp atual formatado."""
20
+ return datetime.now().strftime("%H:%M:%S")
21
+
22
+ @staticmethod
23
+ def get_current_datetime() -> str:
24
+ """Retorna data e hora atual formatada."""
25
+ return datetime.now().strftime("%d/%m/%Y %H:%M:%S")
26
+
27
+ @staticmethod
28
+ def format_timestamp(dt: datetime) -> str:
29
+ """Formata datetime para timestamp."""
30
+ return dt.strftime("%H:%M:%S")
31
+
32
+
33
+ class NumberUtils:
34
+ """Utilitários para manipulação de números."""
35
+
36
+ @staticmethod
37
+ def format_price(price: float) -> str:
38
+ """Formata preço com separadores de milhares."""
39
+ return f"{price:,.0f}"
40
+
41
+ @staticmethod
42
+ def format_percentage(value: float) -> str:
43
+ """Formata porcentagem com sinal."""
44
+ return f"{value:+.2f}%"
45
+
46
+ @staticmethod
47
+ def format_volume(volume: float) -> str:
48
+ """Formata volume com uma casa decimal."""
49
+ return f"{volume:.1f}x"
50
+
51
+ @staticmethod
52
+ def calculate_points_from_percentage(price: float, percentage: float) -> float:
53
+ """Calcula pontos baseado em porcentagem do preço."""
54
+ return price * (percentage / 100)
55
+
56
+
57
+ class ConfidenceUtils:
58
+ """Utilitários para manipulação de níveis de confiança."""
59
+
60
+ @staticmethod
61
+ def get_confidence_level(confidence: int) -> str:
62
+ """Retorna nível de confiança textual."""
63
+ config = TradingConfig.CONFIDENCE_LEVELS
64
+
65
+ if confidence >= config['MUITO_ALTA']:
66
+ return "MUITO ALTA"
67
+ elif confidence >= config['ALTA']:
68
+ return "ALTA"
69
+ elif confidence >= config['MODERADA']:
70
+ return "MODERADA"
71
+ else:
72
+ return "BAIXA"
73
+
74
+ @staticmethod
75
+ def generate_confidence_bar(confidence: int) -> str:
76
+ """Gera barra visual de confiança."""
77
+ filled_bars = int(confidence / 10)
78
+ empty_bars = 10 - filled_bars
79
+ return "█" * filled_bars + "░" * empty_bars
80
+
81
+ @staticmethod
82
+ def is_high_confidence(confidence: int) -> bool:
83
+ """Verifica se confiança é alta."""
84
+ return confidence >= TradingConfig.CONFIDENCE_LEVELS['ALTA']
85
+
86
+
87
+ class ActionUtils:
88
+ """Utilitários para manipulação de ações de trading."""
89
+
90
+ @staticmethod
91
+ def get_action_emojis(action: str) -> Dict[str, str]:
92
+ """Retorna emojis para ação específica."""
93
+ return UIConfig.ACTION_EMOJIS.get(action, {
94
+ 'main': '⚪',
95
+ 'action': '❓'
96
+ })
97
+
98
+ @staticmethod
99
+ def get_action_color(action: str) -> str:
100
+ """Retorna cor para ação específica."""
101
+ return UIConfig.ACTION_COLORS.get(action, 'cinza')
102
+
103
+ @staticmethod
104
+ def get_trading_direction(action: str) -> str:
105
+ """Retorna direção de trading para ação."""
106
+ return UIConfig.TRADING_DIRECTIONS.get(action, 'INDEFINIDO')
107
+
108
+
109
+ class SentimentUtils:
110
+ """Utilitários para manipulação de sentimento."""
111
+
112
+ @staticmethod
113
+ def get_sentiment_emoji(sentiment_label: str) -> str:
114
+ """Retorna emoji para sentimento."""
115
+ return UIConfig.SENTIMENT_EMOJIS.get(sentiment_label, '😐💛')
116
+
117
+ @staticmethod
118
+ def normalize_sentiment_label(label: str) -> str:
119
+ """Normaliza label de sentimento."""
120
+ label_upper = label.upper()
121
+ valid_labels = ['POSITIVO', 'NEGATIVO', 'NEUTRO']
122
+
123
+ if label_upper in valid_labels:
124
+ return label_upper
125
+
126
+ # Mapeamento de labels alternativos
127
+ label_mapping = {
128
+ 'POSITIVE': 'POSITIVO',
129
+ 'NEGATIVE': 'NEGATIVO',
130
+ 'NEUTRAL': 'NEUTRO',
131
+ 'POS': 'POSITIVO',
132
+ 'NEG': 'NEGATIVO',
133
+ 'NEU': 'NEUTRO'
134
+ }
135
+
136
+ return label_mapping.get(label_upper, 'NEUTRO')
137
+
138
+
139
+ class ValidationUtils:
140
+ """Utilitários para validação de dados."""
141
+
142
+ @staticmethod
143
+ def validate_market_data(data: Dict[str, Any]) -> bool:
144
+ """Valida dados de mercado."""
145
+ required_fields = ['price', 'variation', 'rsi', 'ema_trend', 'bb_position', 'volume']
146
+
147
+ # Verificar se todos os campos obrigatórios estão presentes
148
+ for field in required_fields:
149
+ if field not in data:
150
+ return False
151
+
152
+ # Validar tipos e valores
153
+ try:
154
+ price = float(data['price'])
155
+ variation = float(data['variation'])
156
+ rsi = int(data['rsi'])
157
+ volume = float(data['volume'])
158
+
159
+ # Validar ranges
160
+ if price < 0 or not (0 <= rsi <= 100) or volume < 0:
161
+ return False
162
+
163
+ # Validar strings
164
+ valid_ema_trends = ['ALTA', 'BAIXA', 'NEUTRO']
165
+ valid_bb_positions = ['DENTRO', 'SOBRE', 'ABAIXO', 'ACIMA']
166
+
167
+ if (data['ema_trend'] not in valid_ema_trends or
168
+ data['bb_position'] not in valid_bb_positions):
169
+ return False
170
+
171
+ return True
172
+
173
+ except (ValueError, TypeError):
174
+ return False
175
+
176
+ @staticmethod
177
+ def validate_confidence_score(score: int) -> int:
178
+ """Valida e normaliza pontuação de confiança."""
179
+ return max(ScoringConfig.MIN_CONFIDENCE,
180
+ min(ScoringConfig.MAX_CONFIDENCE, score))
181
+
182
+ @staticmethod
183
+ def validate_text_input(text: str) -> bool:
184
+ """Valida entrada de texto."""
185
+ if not text or not isinstance(text, str):
186
+ return False
187
+
188
+ # Verificar se não é apenas espaços em branco
189
+ if not text.strip():
190
+ return False
191
+
192
+ # Verificar tamanho mínimo
193
+ if len(text.strip()) < 3:
194
+ return False
195
+
196
+ return True
197
+
198
+
199
+ class FormatUtils:
200
+ """Utilitários para formatação de texto e dados."""
201
+
202
+ @staticmethod
203
+ def format_signal_list(signals: list) -> str:
204
+ """Formata lista de sinais para exibição."""
205
+ if not signals:
206
+ return "Nenhum sinal detectado"
207
+
208
+ formatted_signals = []
209
+ for i, signal in enumerate(signals[:5], 1): # Máximo 5 sinais
210
+ if hasattr(signal, 'description'):
211
+ formatted_signals.append(f"{i}. {signal.description}")
212
+ else:
213
+ formatted_signals.append(f"{i}. {str(signal)}")
214
+
215
+ return "\n".join(formatted_signals)
216
+
217
+ @staticmethod
218
+ def format_market_summary(market_data: Dict[str, Any]) -> str:
219
+ """Formata resumo dos dados de mercado."""
220
+ price = NumberUtils.format_price(market_data.get('price', 0))
221
+ variation = NumberUtils.format_percentage(market_data.get('variation', 0))
222
+ volume = NumberUtils.format_volume(market_data.get('volume', 0))
223
+
224
+ return f"""• **Preço:** {price}
225
+ • **Variação:** {variation}
226
+ • **RSI:** {market_data.get('rsi', 'N/A')}
227
+ • **EMA:** {market_data.get('ema_trend', 'N/A')}
228
+ • **Bollinger:** {market_data.get('bb_position', 'N/A')}
229
+ • **Volume:** {volume}"""
230
+
231
+ @staticmethod
232
+ def format_trading_recommendations(action: str, price: float) -> str:
233
+ """Formata recomendações de trading."""
234
+ if action == 'COMPRAR':
235
+ stop_loss = price * (1 - TradingConfig.STOP_LOSS_PERCENTAGE)
236
+ take_profit = price * (1 + TradingConfig.TAKE_PROFIT_PERCENTAGE)
237
+
238
+ return f"""• **Stop Loss:** -{NumberUtils.calculate_points_from_percentage(price, TradingConfig.STOP_LOSS_PERCENTAGE * 100):.0f} pts ({TradingConfig.STOP_LOSS_PERCENTAGE * 100:.2f}%)
239
+ • **Take Profit:** +{NumberUtils.calculate_points_from_percentage(price, TradingConfig.TAKE_PROFIT_PERCENTAGE * 100):.0f} pts ({TradingConfig.TAKE_PROFIT_PERCENTAGE * 100:.2f}%)
240
+ • **Timeframe:** {'/'.join(TradingConfig.SCALPING_TIMEFRAMES)}
241
+ • **Risk/Reward:** 1:{TradingConfig.RISK_REWARD_RATIO}"""
242
+
243
+ elif action == 'VENDER':
244
+ stop_loss = price * (1 + TradingConfig.STOP_LOSS_PERCENTAGE)
245
+ take_profit = price * (1 - TradingConfig.TAKE_PROFIT_PERCENTAGE)
246
+
247
+ return f"""• **Stop Loss:** +{NumberUtils.calculate_points_from_percentage(price, TradingConfig.STOP_LOSS_PERCENTAGE * 100):.0f} pts ({TradingConfig.STOP_LOSS_PERCENTAGE * 100:.2f}%)
248
+ • **Take Profit:** -{NumberUtils.calculate_points_from_percentage(price, TradingConfig.TAKE_PROFIT_PERCENTAGE * 100):.0f} pts ({TradingConfig.TAKE_PROFIT_PERCENTAGE * 100:.2f}%)
249
+ • **Timeframe:** {'/'.join(TradingConfig.SCALPING_TIMEFRAMES)}
250
+ • **Risk/Reward:** 1:{TradingConfig.RISK_REWARD_RATIO}"""
251
+
252
+ else:
253
+ return """• **Aguardar:** Setup mais definido
254
+ • **Monitorar:** Rompimentos de suporte/resistência
255
+ • **Observar:** Confluência de sinais técnicos"""
256
+
257
+
258
+ class LogUtils:
259
+ """Utilitários para logging e debug."""
260
+
261
+ @staticmethod
262
+ def log_analysis_result(analysis_result: Dict[str, Any]) -> None:
263
+ """Registra resultado de análise para debug."""
264
+ timestamp = DateTimeUtils.get_current_datetime()
265
+ action = analysis_result.get('action', 'UNKNOWN')
266
+ confidence = analysis_result.get('confidence', 0)
267
+
268
+ print(f"[{timestamp}] Análise: {action} (Confiança: {confidence}%)")
269
+
270
+ @staticmethod
271
+ def log_error(error_message: str, context: str = "") -> None:
272
+ """Registra erro com contexto."""
273
+ timestamp = DateTimeUtils.get_current_datetime()
274
+ context_str = f" [{context}]" if context else ""
275
+ print(f"[{timestamp}] ERRO{context_str}: {error_message}")
276
+
277
+ @staticmethod
278
+ def log_model_status(model_info: Dict[str, Any]) -> None:
279
+ """Registra status do modelo de IA."""
280
+ timestamp = DateTimeUtils.get_current_datetime()
281
+ status = "ATIVO" if model_info.get('available', False) else "INATIVO"
282
+ model_name = model_info.get('description', 'Desconhecido')
283
+
284
+ print(f"[{timestamp}] Modelo IA: {status} - {model_name}")
285
+
286
+
287
+ class DataExportUtils:
288
+ """Utilitários para exportação de dados."""
289
+
290
+ @staticmethod
291
+ def export_analysis_to_json(analysis_result: Dict[str, Any]) -> str:
292
+ """Exporta resultado de análise para JSON."""
293
+ # Preparar dados para serialização
294
+ export_data = {
295
+ 'timestamp': DateTimeUtils.get_current_datetime(),
296
+ 'action': analysis_result.get('action'),
297
+ 'confidence': analysis_result.get('confidence'),
298
+ 'market_data': analysis_result.get('market_data'),
299
+ 'sentiment': analysis_result.get('sentiment')
300
+ }
301
+
302
+ # Converter objetos complexos para dicionários
303
+ if 'signals' in analysis_result:
304
+ export_data['signals'] = [
305
+ {
306
+ 'indicator': getattr(signal, 'indicator', 'unknown'),
307
+ 'signal_type': getattr(signal, 'signal_type', 'unknown'),
308
+ 'strength': getattr(signal, 'strength', 0),
309
+ 'description': getattr(signal, 'description', '')
310
+ }
311
+ for signal in analysis_result['signals']
312
+ ]
313
+
314
+ return json.dumps(export_data, indent=2, ensure_ascii=False)
315
+
316
+ @staticmethod
317
+ def create_analysis_summary(analysis_result: Dict[str, Any]) -> Dict[str, Any]:
318
+ """Cria resumo da análise para relatórios."""
319
+ return {
320
+ 'timestamp': DateTimeUtils.get_current_datetime(),
321
+ 'action': analysis_result.get('action', 'UNKNOWN'),
322
+ 'confidence': analysis_result.get('confidence', 0),
323
+ 'confidence_level': ConfidenceUtils.get_confidence_level(
324
+ analysis_result.get('confidence', 0)
325
+ ),
326
+ 'signals_count': len(analysis_result.get('signals', [])),
327
+ 'sentiment_label': analysis_result.get('sentiment', {}).get('label', 'NEUTRO'),
328
+ 'market_price': analysis_result.get('market_data', {}).get('price', 0),
329
+ 'market_rsi': analysis_result.get('market_data', {}).get('rsi', 50)
330
+ }
tests/__init__.py ADDED
File without changes
tests/integration/__init__.py ADDED
File without changes
tests/unit/__init__.py ADDED
File without changes
text ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ⏰ Análise #8 - 09:46:58
2
+
3
+ ================================================================================
4
+ 🧛 VAMPIRE TRADING BOT - ANÁLISE DETALHADA
5
+ ================================================================================
6
+
7
+ 📊 DADOS DE MERCADO - WINV25
8
+ ──────────────────────────────────────────────────
9
+ Preço Atual: 140135.00000 ↗
10
+ Variação: +5.00000 (+0.00%)
11
+ Máxima: 140155.00000
12
+ Mínima: 140075.00000
13
+ Volume: 5023
14
+
15
+ 📈 INDICADORES TÉCNICOS
16
+ ──────────────────────────────────────────────────
17
+ RSI (14): 46.39 (NEUTRO)
18
+ EMA Rápida: 140192.30752
19
+ EMA Lenta: 140221.86717
20
+ Tendência EMA: BAIXA
21
+ Bollinger: DENTRO DAS BANDAS
22
+ Superior: 140672.37317
23
+ Inferior: 139913.62683
24
+ ATR: 170.73782
25
+ Volatilidade: MÉDIA (1.23x)
26
+ 2025-08-27 09:46:58,218 - src.core.analysis.advanced_fibonacci - INFO - 🔮 INICIANDO ANÁLISE AVANÇADA DE FIBONACCI - Lookback: 40 períodos
27
+ 2025-08-27 09:46:58,218 - src.core.analysis.advanced_fibonacci - INFO - 📊 Swing Points - Alta: 140,570.00, Baixa: 139,540.00, Atual: 140,135.00
28
+ 2025-08-27 09:46:58,219 - src.core.analysis.advanced_fibonacci - INFO - 📏 Diferença Swing: 1,030.00 pontos
29
+ 2025-08-27 09:46:58,244 - src.core.analysis.advanced_fibonacci - INFO - 📈 Níveis de Retracement calculados: 13 níveis
30
+ 2025-08-27 09:46:58,297 - src.core.analysis.advanced_fibonacci - INFO - 📊 Níveis de Extensão calculados: 11 níveis
31
+ 2025-08-27 09:46:58,323 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Níveis de Projeção calculados: 8 níveis
32
+ 2025-08-27 09:46:58,325 - src.core.analysis.advanced_fibonacci - INFO - 🔢 Total de níveis Fibonacci: 32
33
+ 2025-08-27 09:46:58,327 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Zonas de Confluência detectadas: 0
34
+ 2025-08-27 09:46:58,329 - src.core.analysis.advanced_fibonacci - INFO - 🎼 Padrões Harmônicos detectados: 0
35
+ 2025-08-27 09:46:58,332 - src.core.analysis.advanced_fibonacci - INFO - ⏰ Projeções Temporais calculadas: 0
36
+ 2025-08-27 09:46:58,332 - src.core.analysis.advanced_fibonacci - INFO - 💪 Força Geral da Análise: 0.00
37
+ 2025-08-27 09:46:58,333 - src.core.analysis.advanced_fibonacci - INFO - 🔮 ANÁLISE CONCLUÍDA - Zona: ZONA_MEDIA_ALTA, Suporte: 140133.28, Resistência: 140176.54
38
+ 2025-08-27 09:46:58,339 - src.core.analysis.advanced_fibonacci - INFO - 🔮 INICIANDO ANÁLISE AVANÇADA DE FIBONACCI - Lookback: 40 períodos
39
+ 2025-08-27 09:46:58,340 - src.core.analysis.advanced_fibonacci - INFO - 📊 Swing Points - Alta: 140,570.00, Baixa: 139,540.00, Atual: 140,135.00
40
+ 2025-08-27 09:46:58,340 - src.core.analysis.advanced_fibonacci - INFO - 📏 Diferença Swing: 1,030.00 pontos
41
+ 2025-08-27 09:46:58,365 - src.core.analysis.advanced_fibonacci - INFO - 📈 Níveis de Retracement calculados: 13 níveis
42
+ 2025-08-27 09:46:58,396 - src.core.analysis.advanced_fibonacci - INFO - 📊 Níveis de Extensão calculados: 11 níveis
43
+ 2025-08-27 09:46:58,418 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Níveis de Projeção calculados: 8 níveis
44
+ 2025-08-27 09:46:58,419 - src.core.analysis.advanced_fibonacci - INFO - 🔢 Total de níveis Fibonacci: 32
45
+ 2025-08-27 09:46:58,421 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Zonas de Confluência detectadas: 0
46
+ 2025-08-27 09:46:58,423 - src.core.analysis.advanced_fibonacci - INFO - 🎼 Padrões Harmônicos detectados: 0
47
+ 2025-08-27 09:46:58,424 - src.core.analysis.advanced_fibonacci - INFO - ⏰ Projeções Temporais calculadas: 0
48
+ 2025-08-27 09:46:58,425 - src.core.analysis.advanced_fibonacci - INFO - 💪 Força Geral da Análise: 0.00
49
+ 2025-08-27 09:46:58,427 - src.core.analysis.advanced_fibonacci - INFO - 🔮 ANÁLISE CONCLUÍDA - Zona: ZONA_MEDIA_ALTA, Suporte: 140133.28, Resistência: 140176.54
50
+ 2025-08-27 09:46:58,428 - src.core.analysis.advanced_fibonacci - INFO - 🔮 INICIANDO ANÁLISE AVANÇADA DE FIBONACCI - Lookback: 40 períodos
51
+ 2025-08-27 09:46:58,430 - src.core.analysis.advanced_fibonacci - INFO - 📊 Swing Points - Alta: 140,570.00, Baixa: 139,540.00, Atual: 140,135.00
52
+ 2025-08-27 09:46:58,431 - src.core.analysis.advanced_fibonacci - INFO - 📏 Diferença Swing: 1,030.00 pontos
53
+ 2025-08-27 09:46:58,460 - src.core.analysis.advanced_fibonacci - INFO - 📈 Níveis de Retracement calculados: 13 níveis
54
+ 2025-08-27 09:46:58,487 - src.core.analysis.advanced_fibonacci - INFO - 📊 Níveis de Extensão calculados: 11 níveis
55
+ 2025-08-27 09:46:58,504 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Níveis de Projeção calculados: 8 níveis
56
+ 2025-08-27 09:46:58,520 - src.core.analysis.advanced_fibonacci - INFO - 🔢 Total de níveis Fibonacci: 32
57
+ 2025-08-27 09:46:58,543 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Zonas de Confluência detectadas: 0
58
+ 2025-08-27 09:46:58,558 - src.core.analysis.advanced_fibonacci - INFO - 🎼 Padrões Harmônicos detectados: 0
59
+ 2025-08-27 09:46:58,575 - src.core.analysis.advanced_fibonacci - INFO - ⏰ Projeções Temporais calculadas: 0
60
+ 2025-08-27 09:46:58,606 - src.core.analysis.advanced_fibonacci - INFO - 💪 Força Geral da Análise: 0.00
61
+ 2025-08-27 09:46:58,614 - src.core.analysis.advanced_fibonacci - INFO - 🔮 ANÁLISE CONCLUÍDA - Zona: ZONA_MEDIA_ALTA, Suporte: 140133.28, Resistência: 140176.54
62
+ 2025-08-27 09:46:58,618 - src.core.analysis.advanced_fibonacci - INFO - 🔮 INICIANDO ANÁLISE AVANÇADA DE FIBONACCI - Lookback: 40 períodos
63
+ 2025-08-27 09:46:58,622 - src.core.analysis.advanced_fibonacci - INFO - 📊 Swing Points - Alta: 140,570.00, Baixa: 139,540.00, Atual: 140,135.00
64
+ 2025-08-27 09:46:58,624 - src.core.analysis.advanced_fibonacci - INFO - 📏 Diferença Swing: 1,030.00 pontos
65
+ 2025-08-27 09:46:58,696 - src.core.analysis.advanced_fibonacci - INFO - 📈 Níveis de Retracement calculados: 13 níveis
66
+ 2025-08-27 09:46:58,758 - src.core.analysis.advanced_fibonacci - INFO - 📊 Níveis de Extensão calculados: 11 níveis
67
+ 2025-08-27 09:46:58,808 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Níveis de Projeção calculados: 8 níveis
68
+ 2025-08-27 09:46:58,821 - src.core.analysis.advanced_fibonacci - INFO - 🔢 Total de níveis Fibonacci: 32
69
+ 2025-08-27 09:46:58,832 - src.core.analysis.advanced_fibonacci - INFO - 🎯 Zonas de Confluência detectadas: 0
70
+ 2025-08-27 09:46:58,840 - src.core.analysis.advanced_fibonacci - INFO - 🎼 Padrões Harmônicos detectados: 0
71
+ 2025-08-27 09:46:58,841 - src.core.analysis.advanced_fibonacci - INFO - ⏰ Projeções Temporais calculadas: 0
72
+ 2025-08-27 09:46:58,850 - src.core.analysis.advanced_fibonacci - INFO - 💪 Força Geral da Análise: 0.00
73
+ 2025-08-27 09:46:58,855 - src.core.analysis.advanced_fibonacci - INFO - 🔮 ANÁLISE CONCLUÍDA - Zona: ZONA_MEDIA_ALTA, Suporte: 140133.28, Resistência: 140176.54
74
+ 2025-08-27 09:46:58,859 - src.core.managers.performance_optimizer - WARNING - Análise de mercado lenta: 0.526s
75
+ 2025-08-27 09:46:58,869 - __main__ - INFO - 📊 FIBONACCI AVANÇADO ENVIADO: Alertas:15 FibSinal:HOLD
76
+ 🔮 Fibonacci Avançado: Alertas:15 FibSinal:HOLD
ui.py CHANGED
@@ -17,6 +17,194 @@ from utils import (
17
  class UIComponents:
18
  """Componentes da interface do usuário."""
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  @staticmethod
21
  def create_header() -> str:
22
  """Cria cabeçalho da aplicação."""
@@ -44,20 +232,47 @@ class UIComponents:
44
  </div>
45
  """)
46
 
47
- market_input = gr.Textbox(
48
- label="Dados do Mercado",
49
- placeholder=AppConfig.EXAMPLE_INPUT,
50
- lines=8,
51
- max_lines=15
52
- )
53
-
54
- analyze_btn = gr.Button(
55
- "🔍 Analisar Mercado",
56
- variant="primary",
57
- size="lg"
58
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
- return input_section, market_input, analyze_btn
61
 
62
  @staticmethod
63
  def create_output_section() -> Tuple[gr.Column, Dict[str, Any]]:
@@ -87,11 +302,25 @@ class UIComponents:
87
  with gr.Tab("💡 Recomendações"):
88
  outputs['recommendations'] = gr.HTML()
89
 
 
 
 
 
 
 
 
 
90
  # Aba de Dados Brutos
91
  with gr.Tab("🔍 Dados Detalhados"):
92
  outputs['raw_data'] = gr.JSON()
93
 
94
- return output_section, outputs
 
 
 
 
 
 
95
 
96
  @staticmethod
97
  def create_footer(model_info: Optional[Dict[str, Any]] = None) -> str:
@@ -329,6 +558,61 @@ class GradioInterface:
329
  self.model_info = model_info or {'available': False}
330
  self.interface = None
331
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
  def create_interface(self) -> gr.Blocks:
333
  """Cria interface completa do Gradio."""
334
  with gr.Blocks(
@@ -343,7 +627,7 @@ class GradioInterface:
343
  with gr.Row():
344
  # Coluna de entrada (40%)
345
  with gr.Column(scale=2):
346
- input_section, market_input, analyze_btn = UIComponents.create_input_section()
347
 
348
  # Coluna de saída (60%)
349
  with gr.Column(scale=3):
@@ -352,7 +636,7 @@ class GradioInterface:
352
  # Rodapé
353
  gr.HTML(UIComponents.create_footer(self.model_info))
354
 
355
- # Configurar evento de análise
356
  analyze_btn.click(
357
  fn=self._analyze_wrapper,
358
  inputs=[market_input],
@@ -362,6 +646,23 @@ class GradioInterface:
362
  outputs['technical_analysis'],
363
  outputs['sentiment_analysis'],
364
  outputs['recommendations'],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  outputs['raw_data']
366
  ]
367
  )
@@ -378,7 +679,7 @@ class GradioInterface:
378
  self.interface = interface
379
  return interface
380
 
381
- def _analyze_wrapper(self, market_input: str) -> Tuple[str, str, str, str, str, Dict[str, Any]]:
382
  """Wrapper para função de análise com formatação de saída."""
383
  try:
384
  # Executar análise
@@ -394,6 +695,8 @@ class GradioInterface:
394
  technical_analysis = ResultFormatter.format_technical_analysis(analysis_result)
395
  sentiment_analysis = ResultFormatter.format_sentiment_analysis(analysis_result)
396
  recommendations = ResultFormatter.format_recommendations(analysis_result)
 
 
397
 
398
  # Dados brutos para debug
399
  raw_data = {
@@ -407,6 +710,8 @@ class GradioInterface:
407
  technical_analysis,
408
  sentiment_analysis,
409
  recommendations,
 
 
410
  raw_data
411
  )
412
 
@@ -425,6 +730,43 @@ class GradioInterface:
425
  error_html,
426
  error_html,
427
  error_html,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  {'error': error_msg}
429
  )
430
 
 
17
  class UIComponents:
18
  """Componentes da interface do usuário."""
19
 
20
+ @staticmethod
21
+ def create_header() -> str:
22
+ """
23
+
24
+ @staticmethod
25
+ def format_harmonic_patterns(analysis_result: Dict[str, Any]) -> str:
26
+ """Formata padrões harmônicos detectados."""
27
+ harmonic_patterns = analysis_result.get('harmonic_patterns', [])
28
+
29
+ if not harmonic_patterns:
30
+ return """
31
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
32
+ <h3 style="color: #495057; margin-top: 0;">🎵 Padrões Harmônicos</h3>
33
+ <div style="text-align: center; padding: 30px; color: #6c757d;">
34
+ <div style="font-size: 2em; margin-bottom: 10px;">📊</div>
35
+ <p>Nenhum padrão harmônico detectado</p>
36
+ </div>
37
+ </div>
38
+ """
39
+
40
+ patterns_html = ""
41
+ for pattern in harmonic_patterns:
42
+ pattern_name = pattern.get('name', 'Desconhecido')
43
+ confidence = pattern.get('confidence', 0)
44
+ direction = pattern.get('direction', 'NEUTRO')
45
+
46
+ direction_emoji = "📈" if direction == "ALTA" else "📉" if direction == "BAIXA" else "➡️"
47
+
48
+ patterns_html += f"""
49
+ <div style="background: #f8f9fa; border-radius: 6px; padding: 15px; margin-bottom: 10px; border-left: 4px solid #007bff;">
50
+ <div style="display: flex; justify-content: space-between; align-items: center;">
51
+ <div>
52
+ <strong style="color: #495057;">{direction_emoji} {pattern_name}</strong>
53
+ <div style="color: #6c757d; font-size: 0.9em;">Direção: {direction}</div>
54
+ </div>
55
+ <div style="text-align: right;">
56
+ <div style="font-weight: bold; color: #007bff;">{confidence}%</div>
57
+ <div style="color: #6c757d; font-size: 0.8em;">Confiança</div>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ """
62
+
63
+ return f"""
64
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
65
+ <h3 style="color: #495057; margin-top: 0; border-bottom: 2px solid #007bff; padding-bottom: 10px;">
66
+ 🎵 Padrões Harmônicos Detectados
67
+ </h3>
68
+ {patterns_html}
69
+ </div>
70
+ """
71
+
72
+ @staticmethod
73
+ def format_fibonacci_alerts(analysis_result: Dict[str, Any]) -> str:
74
+ """Formata alertas de Fibonacci."""
75
+ fibonacci_data = analysis_result.get('fibonacci_analysis', {})
76
+
77
+ if not fibonacci_data:
78
+ return """
79
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
80
+ <h3 style="color: #495057; margin-top: 0;">📐 Análise de Fibonacci</h3>
81
+ <div style="text-align: center; padding: 30px; color: #6c757d;">
82
+ <div style="font-size: 2em; margin-bottom: 10px;">📊</div>
83
+ <p>Dados de Fibonacci não disponíveis</p>
84
+ </div>
85
+ </div>
86
+ """
87
+
88
+ levels = fibonacci_data.get('levels', [])
89
+ current_level = fibonacci_data.get('current_level', 'N/A')
90
+ support_resistance = fibonacci_data.get('support_resistance', {})
91
+
92
+ levels_html = ""
93
+ for level in levels:
94
+ level_value = level.get('level', 0)
95
+ price = level.get('price', 0)
96
+ status = level.get('status', 'NEUTRO')
97
+
98
+ status_color = {
99
+ 'SUPORTE': '#28a745',
100
+ 'RESISTENCIA': '#dc3545',
101
+ 'NEUTRO': '#6c757d'
102
+ }.get(status, '#6c757d')
103
+
104
+ levels_html += f"""
105
+ <div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee;">
106
+ <span style="color: #495057;">{level_value}%</span>
107
+ <span style="font-weight: bold; color: #495057;">{NumberUtils.format_price(price)}</span>
108
+ <span style="color: {status_color}; font-weight: 600;">{status}</span>
109
+ </div>
110
+ """
111
+
112
+ return f"""
113
+ <div style="background: white; border-radius: 8px; padding: 20px; border: 1px solid #dee2e6;">
114
+ <h3 style="color: #495057; margin-top: 0; border-bottom: 2px solid #ffc107; padding-bottom: 10px;">
115
+ 📐 Análise de Fibonacci
116
+ </h3>
117
+
118
+ <div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 15px; margin-bottom: 15px;">
119
+ <strong style="color: #856404;">Nível Atual: {current_level}</strong>
120
+ </div>
121
+
122
+ <h4 style="color: #495057; margin-bottom: 10px;">📊 Níveis de Fibonacci</h4>
123
+ <div style="background: #f8f9fa; border-radius: 6px; padding: 15px;">
124
+ <div style="display: flex; justify-content: space-between; font-weight: bold; color: #495057; border-bottom: 2px solid #dee2e6; padding-bottom: 8px; margin-bottom: 10px;">
125
+ <span>Nível</span>
126
+ <span>Preço</span>
127
+ <span>Status</span>
128
+ </div>
129
+ {levels_html}
130
+ </div>
131
+ </div>
132
+ """
133
+
134
+ @staticmethod
135
+ def format_bot_analysis_result(analysis_result: Dict[str, Any]) -> str:
136
+ """Formata resultado específico da análise do bot externo."""
137
+ try:
138
+ bot_data = analysis_result.get('bot_data', {})
139
+ fibonacci_alerts = bot_data.get('fibonacci_alerts', 0)
140
+ fibonacci_signal = bot_data.get('fibonacci_signal', 'UNKNOWN')
141
+ technical_indicators = bot_data.get('technical_indicators', {})
142
+
143
+ # Formatação do sinal Fibonacci
144
+ signal_color = {
145
+ 'BUY': '#28a745',
146
+ 'SELL': '#dc3545',
147
+ 'HOLD': '#ffc107',
148
+ 'UNKNOWN': '#6c757d'
149
+ }.get(fibonacci_signal, '#6c757d')
150
+
151
+ signal_emoji = {
152
+ 'BUY': '📈',
153
+ 'SELL': '📉',
154
+ 'HOLD': '⏸️',
155
+ 'UNKNOWN': '❓'
156
+ }.get(fibonacci_signal, '❓')
157
+
158
+ # Indicadores técnicos do bot
159
+ indicators_html = ""
160
+ for indicator, value in technical_indicators.items():
161
+ if value is not None:
162
+ indicators_html += f"""
163
+ <div style="display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee;">
164
+ <span style="color: #495057; text-transform: uppercase;">{indicator}</span>
165
+ <span style="font-weight: bold; color: #495057;">{value}</span>
166
+ </div>
167
+ """
168
+
169
+ return f"""
170
+ <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; padding: 25px; color: white; margin-bottom: 20px;">
171
+ <h2 style="margin-top: 0; display: flex; align-items: center; gap: 10px;">
172
+ 🤖 Análise do Bot de Trading
173
+ </h2>
174
+
175
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px;">
176
+ <div style="background: rgba(255,255,255,0.1); border-radius: 8px; padding: 15px;">
177
+ <h4 style="margin-top: 0; color: #f8f9fa;">📐 Fibonacci</h4>
178
+ <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
179
+ <span style="font-size: 1.5em;">{signal_emoji}</span>
180
+ <div>
181
+ <div style="font-weight: bold; font-size: 1.1em; color: {signal_color};">{fibonacci_signal}</div>
182
+ <div style="font-size: 0.9em; opacity: 0.8;">Sinal Atual</div>
183
+ </div>
184
+ </div>
185
+ <div style="font-size: 0.9em; opacity: 0.8;">Alertas: {fibonacci_alerts}</div>
186
+ </div>
187
+
188
+ <div style="background: rgba(255,255,255,0.1); border-radius: 8px; padding: 15px;">
189
+ <h4 style="margin-top: 0; color: #f8f9fa;">📊 Indicadores</h4>
190
+ <div style="font-size: 0.9em;">
191
+ {indicators_html if indicators_html else '<div style="opacity: 0.8;">Dados não disponíveis</div>'}
192
+ </div>
193
+ </div>
194
+ </div>
195
+ </div>
196
+
197
+ {ResultFormatter.format_main_result(analysis_result)}
198
+ """
199
+
200
+ except Exception as e:
201
+ return f"""
202
+ <div style="background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 8px; padding: 15px; color: #721c24;">
203
+ <h4 style="margin-top: 0;">❌ Erro na Formatação</h4>
204
+ <p style="margin: 0;">Erro ao formatar resultado do bot: {str(e)}</p>
205
+ </div>
206
+ """
207
+
208
  @staticmethod
209
  def create_header() -> str:
210
  """Cria cabeçalho da aplicação."""
 
232
  </div>
233
  """)
234
 
235
+ # Abas para diferentes tipos de entrada
236
+ with gr.Tabs():
237
+ with gr.Tab("📊 Análise Manual"):
238
+ symbol_input = gr.Textbox(
239
+ label="Símbolo do Ativo",
240
+ placeholder="Ex: BTCUSDT",
241
+ lines=1
242
+ )
243
+ price_input = gr.Number(
244
+ label="Preço Atual",
245
+ placeholder="Ex: 45000.50"
246
+ )
247
+ volume_input = gr.Number(
248
+ label="Volume (Opcional)",
249
+ placeholder="Ex: 1000000"
250
+ )
251
+ sentiment_input = gr.Textbox(
252
+ label="Texto para Análise de Sentimento (Opcional)",
253
+ placeholder="Ex: Notícias ou comentários sobre o ativo",
254
+ lines=3
255
+ )
256
+ analyze_manual_btn = gr.Button(
257
+ "🔍 Analisar Manualmente",
258
+ variant="primary",
259
+ size="lg"
260
+ )
261
+
262
+ with gr.Tab("🤖 Log do Bot"):
263
+ market_input = gr.Textbox(
264
+ label="Log do Bot de Trading",
265
+ placeholder=AppConfig.EXAMPLE_INPUT,
266
+ lines=8,
267
+ max_lines=15
268
+ )
269
+ analyze_btn = gr.Button(
270
+ "🔍 Analisar Log do Bot",
271
+ variant="primary",
272
+ size="lg"
273
+ )
274
 
275
+ return input_section, market_input, analyze_btn, symbol_input, price_input, volume_input, sentiment_input, analyze_manual_btn
276
 
277
  @staticmethod
278
  def create_output_section() -> Tuple[gr.Column, Dict[str, Any]]:
 
302
  with gr.Tab("💡 Recomendações"):
303
  outputs['recommendations'] = gr.HTML()
304
 
305
+ # Aba de Padrões Harmônicos
306
+ with gr.Tab("🎵 Padrões Harmônicos"):
307
+ outputs['harmonic_patterns'] = gr.HTML()
308
+
309
+ # Aba de Alertas Fibonacci
310
+ with gr.Tab("📐 Fibonacci"):
311
+ outputs['fibonacci_alerts'] = gr.HTML()
312
+
313
  # Aba de Dados Brutos
314
  with gr.Tab("🔍 Dados Detalhados"):
315
  outputs['raw_data'] = gr.JSON()
316
 
317
+ # Adicionar novos outputs ao dicionário
318
+ if 'harmonic_patterns' not in outputs:
319
+ outputs['harmonic_patterns'] = gr.HTML()
320
+ if 'fibonacci_alerts' not in outputs:
321
+ outputs['fibonacci_alerts'] = gr.HTML()
322
+
323
+ return output_section, outputs
324
 
325
  @staticmethod
326
  def create_footer(model_info: Optional[Dict[str, Any]] = None) -> str:
 
558
  self.model_info = model_info or {'available': False}
559
  self.interface = None
560
 
561
+ def analyze_market(self, symbol, price, volume, sentiment_text):
562
+ """Função principal de análise"""
563
+ try:
564
+ # Validar entrada
565
+ if not symbol or not price:
566
+ return "❌ Erro: Símbolo e preço são obrigatórios"
567
+
568
+ price = float(price)
569
+ volume = float(volume) if volume else 0
570
+
571
+ # Criar dados de mercado
572
+ market_data = {
573
+ 'price': price,
574
+ 'variation': 0, # Será calculado se necessário
575
+ 'rsi': 50, # Valor padrão
576
+ 'ema_trend': 'NEUTRO',
577
+ 'bb_position': 'DENTRO',
578
+ 'volume': volume
579
+ }
580
+
581
+ # Executar análise
582
+ result = self.analysis_function(f"{symbol}: {price}")
583
+
584
+ # Formatar resultado
585
+ return self.format_analysis_result(result, sentiment_text, symbol)
586
+
587
+ except Exception as e:
588
+ return f"❌ Erro na análise: {str(e)}"
589
+
590
+ def analyze_bot_log(self, log_content):
591
+ """Função para analisar logs do bot externo"""
592
+ try:
593
+ if not log_content.strip():
594
+ return "❌ Erro: Conteúdo do log é obrigatório"
595
+
596
+ # Executar análise do log
597
+ result = self.analysis_function(log_content)
598
+
599
+ if 'error' in result:
600
+ return f"❌ {result['error']}"
601
+
602
+ # Formatar resultado específico do bot
603
+ return self.format_bot_analysis_result(result)
604
+
605
+ except Exception as e:
606
+ return f"❌ Erro na análise do log: {str(e)}"
607
+
608
+ def format_analysis_result(self, result, sentiment_text, symbol):
609
+ """Formata resultado da análise"""
610
+ return ResultFormatter.format_main_result(result)
611
+
612
+ def format_bot_analysis_result(self, result):
613
+ """Formata resultado específico da análise do bot"""
614
+ return ResultFormatter.format_main_result(result)
615
+
616
  def create_interface(self) -> gr.Blocks:
617
  """Cria interface completa do Gradio."""
618
  with gr.Blocks(
 
627
  with gr.Row():
628
  # Coluna de entrada (40%)
629
  with gr.Column(scale=2):
630
+ input_section, market_input, analyze_btn, symbol_input, price_input, volume_input, sentiment_input, analyze_manual_btn = UIComponents.create_input_section()
631
 
632
  # Coluna de saída (60%)
633
  with gr.Column(scale=3):
 
636
  # Rodapé
637
  gr.HTML(UIComponents.create_footer(self.model_info))
638
 
639
+ # Configurar eventos de análise
640
  analyze_btn.click(
641
  fn=self._analyze_wrapper,
642
  inputs=[market_input],
 
646
  outputs['technical_analysis'],
647
  outputs['sentiment_analysis'],
648
  outputs['recommendations'],
649
+ outputs['harmonic_patterns'],
650
+ outputs['fibonacci_alerts'],
651
+ outputs['raw_data']
652
+ ]
653
+ )
654
+
655
+ analyze_manual_btn.click(
656
+ fn=self._analyze_manual_wrapper,
657
+ inputs=[symbol_input, price_input, volume_input, sentiment_input],
658
+ outputs=[
659
+ outputs['ai_status'],
660
+ outputs['main_result'],
661
+ outputs['technical_analysis'],
662
+ outputs['sentiment_analysis'],
663
+ outputs['recommendations'],
664
+ outputs['harmonic_patterns'],
665
+ outputs['fibonacci_alerts'],
666
  outputs['raw_data']
667
  ]
668
  )
 
679
  self.interface = interface
680
  return interface
681
 
682
+ def _analyze_wrapper(self, market_input: str) -> Tuple[str, str, str, str, str, str, str, Dict[str, Any]]:
683
  """Wrapper para função de análise com formatação de saída."""
684
  try:
685
  # Executar análise
 
695
  technical_analysis = ResultFormatter.format_technical_analysis(analysis_result)
696
  sentiment_analysis = ResultFormatter.format_sentiment_analysis(analysis_result)
697
  recommendations = ResultFormatter.format_recommendations(analysis_result)
698
+ harmonic_patterns = ResultFormatter.format_harmonic_patterns(analysis_result)
699
+ fibonacci_alerts = ResultFormatter.format_fibonacci_alerts(analysis_result)
700
 
701
  # Dados brutos para debug
702
  raw_data = {
 
710
  technical_analysis,
711
  sentiment_analysis,
712
  recommendations,
713
+ harmonic_patterns,
714
+ fibonacci_alerts,
715
  raw_data
716
  )
717
 
 
730
  error_html,
731
  error_html,
732
  error_html,
733
+ error_html,
734
+ error_html,
735
+ {'error': error_msg}
736
+ )
737
+
738
+ def _analyze_manual_wrapper(self, symbol: str, price: float, volume: float, sentiment_text: str) -> Tuple[str, str, str, str, str, str, str, Dict[str, Any]]:
739
+ """Wrapper para análise manual com formatação de saída."""
740
+ try:
741
+ # Validar entrada
742
+ if not symbol or not price:
743
+ raise ValueError("Símbolo e preço são obrigatórios")
744
+
745
+ # Criar entrada formatada
746
+ market_input = f"{symbol}: Preço={price}, Volume={volume or 0}"
747
+ if sentiment_text:
748
+ market_input += f", Sentimento={sentiment_text}"
749
+
750
+ # Executar análise usando o wrapper padrão
751
+ return self._analyze_wrapper(market_input)
752
+
753
+ except Exception as e:
754
+ error_msg = f"Erro na análise manual: {str(e)}"
755
+ error_html = f"""
756
+ <div style="background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 8px; padding: 15px; color: #721c24;">
757
+ <h4 style="margin-top: 0;">❌ Erro na Análise Manual</h4>
758
+ <p style="margin: 0;">{error_msg}</p>
759
+ </div>
760
+ """
761
+
762
+ return (
763
+ UIComponents._get_ai_status_html(False),
764
+ error_html,
765
+ error_html,
766
+ error_html,
767
+ error_html,
768
+ error_html,
769
+ error_html,
770
  {'error': error_msg}
771
  )
772