Riy777 commited on
Commit
1b0c9db
·
1 Parent(s): 90767a7

Update ML.py

Browse files
Files changed (1) hide show
  1. ML.py +205 -807
ML.py CHANGED
@@ -1,4 +1,3 @@
1
- # ML.py - الإصدار المحدث مع إصلاح الأخطاء الحرجة
2
  import pandas as pd
3
  import pandas_ta as ta
4
  import numpy as np
@@ -17,8 +16,7 @@ class AdvancedTechnicalAnalyzer:
17
  }
18
 
19
  def calculate_all_indicators(self, dataframe, timeframe):
20
- if dataframe.empty:
21
- return {}
22
  indicators = {}
23
  indicators.update(self._calculate_trend_indicators(dataframe))
24
  indicators.update(self._calculate_momentum_indicators(dataframe))
@@ -29,66 +27,56 @@ class AdvancedTechnicalAnalyzer:
29
 
30
  def _calculate_trend_indicators(self, dataframe):
31
  trend = {}
32
- trend['ema_9'] = float(ta.ema(dataframe['close'], length=9).iloc[-1]) if len(dataframe) >= 9 else None
33
- trend['ema_21'] = float(ta.ema(dataframe['close'], length=21).iloc[-1]) if len(dataframe) >= 21 else None
34
- trend['ema_50'] = float(ta.ema(dataframe['close'], length=50).iloc[-1]) if len(dataframe) >= 50 else None
35
- trend['ema_200'] = float(ta.ema(dataframe['close'], length=200).iloc[-1]) if len(dataframe) >= 200 else None
36
-
37
  if len(dataframe) >= 26:
38
  ichimoku = ta.ichimoku(dataframe['high'], dataframe['low'], dataframe['close'])
39
  if ichimoku is not None:
40
- trend['ichimoku_conversion'] = float(ichimoku[0]['ITS_9'].iloc[-1]) if not ichimoku[0]['ITS_9'].empty else None
41
- trend['ichimoku_base'] = float(ichimoku[0]['IKS_26'].iloc[-1]) if not ichimoku[0]['IKS_26'].empty else None
42
- trend['ichimoku_span_a'] = float(ichimoku[0]['ISA_9'].iloc[-1]) if not ichimoku[0]['ISA_9'].empty else None
43
- trend['ichimoku_span_b'] = float(ichimoku[0]['ISB_26'].iloc[-1]) if not ichimoku[0]['ISB_26'].empty else None
44
-
45
  if len(dataframe) >= 14:
46
  adx_result = ta.adx(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
47
  if adx_result is not None:
48
- trend['adx'] = float(adx_result['ADX_14'].iloc[-1]) if not adx_result['ADX_14'].empty else None
49
- trend['dmi_plus'] = float(adx_result['DMP_14'].iloc[-1]) if not adx_result['DMP_14'].empty else None
50
- trend['dmi_minus'] = float(adx_result['DMN_14'].iloc[-1]) if not adx_result['DMN_14'].empty else None
51
-
52
  if len(dataframe) >= 5:
53
  psar = ta.psar(dataframe['high'], dataframe['low'], dataframe['close'])
54
- if psar is not None:
55
- trend['psar'] = float(psar['PSARl_0.02_0.2'].iloc[-1]) if not psar['PSARl_0.02_0.2'].empty else None
56
  return {key: value for key, value in trend.items() if value is not None}
57
 
58
  def _calculate_momentum_indicators(self, dataframe):
59
  momentum = {}
60
  if len(dataframe) >= 14:
61
  rsi = ta.rsi(dataframe['close'], length=14)
62
- momentum['rsi'] = float(rsi.iloc[-1]) if not rsi.empty else None
63
-
64
  if len(dataframe) >= 14:
65
  stoch_rsi = ta.stochrsi(dataframe['close'], length=14)
66
  if stoch_rsi is not None:
67
- momentum['stoch_rsi_k'] = float(stoch_rsi['STOCHRSIk_14_14_3_3'].iloc[-1]) if not stoch_rsi['STOCHRSIk_14_14_3_3'].empty else None
68
- momentum['stoch_rsi_d'] = float(stoch_rsi['STOCHRSId_14_14_3_3'].iloc[-1]) if not stoch_rsi['STOCHRSId_14_14_3_3'].empty else None
69
-
70
  if len(dataframe) >= 26:
71
  macd = ta.macd(dataframe['close'])
72
  if macd is not None:
73
- momentum['macd_line'] = float(macd['MACD_12_26_9'].iloc[-1]) if not macd['MACD_12_26_9'].empty else None
74
- momentum['macd_signal'] = float(macd['MACDs_12_26_9'].iloc[-1]) if not macd['MACDs_12_26_9'].empty else None
75
- momentum['macd_hist'] = float(macd['MACDh_12_26_9'].iloc[-1]) if not macd['MACDh_12_26_9'].empty else None
76
-
77
  if len(dataframe) >= 14:
78
  williams = ta.willr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
79
- momentum['williams_r'] = float(williams.iloc[-1]) if not williams.empty else None
80
-
81
  if len(dataframe) >= 20:
82
  cci = ta.cci(dataframe['high'], dataframe['low'], dataframe['close'], length=20)
83
- momentum['cci'] = float(cci.iloc[-1]) if not cci.empty else None
84
-
85
  if len(dataframe) >= 34:
86
  awesome_oscillator = ta.ao(dataframe['high'], dataframe['low'])
87
- momentum['awesome_oscillator'] = float(awesome_oscillator.iloc[-1]) if not awesome_oscillator.empty else None
88
-
89
  if len(dataframe) >= 10:
90
  momentum_indicator = ta.mom(dataframe['close'], length=10)
91
- momentum['momentum'] = float(momentum_indicator.iloc[-1]) if not momentum_indicator.empty else None
92
  return {key: value for key, value in momentum.items() if value is not None}
93
 
94
  def _calculate_volatility_indicators(self, dataframe):
@@ -96,185 +84,125 @@ class AdvancedTechnicalAnalyzer:
96
  if len(dataframe) >= 20:
97
  bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2)
98
  if bollinger_bands is not None:
99
- volatility['bb_upper'] = float(bollinger_bands['BBU_20_2.0'].iloc[-1]) if not bollinger_bands['BBU_20_2.0'].empty else None
100
- volatility['bb_middle'] = float(bollinger_bands['BBM_20_2.0'].iloc[-1]) if not bollinger_bands['BBM_20_2.0'].empty else None
101
- volatility['bb_lower'] = float(bollinger_bands['BBL_20_2.0'].iloc[-1]) if not bollinger_bands['BBL_20_2.0'].empty else None
102
- if all(key in volatility for key in ['bb_upper', 'bb_lower', 'bb_middle']):
103
- volatility['bb_width'] = (volatility['bb_upper'] - volatility['bb_lower']) / volatility['bb_middle']
104
-
105
  if len(dataframe) >= 14:
106
  average_true_range = ta.atr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
107
- volatility['atr'] = float(average_true_range.iloc[-1]) if not average_true_range.empty else None
108
- if volatility['atr']:
109
- volatility['atr_percent'] = volatility['atr'] / dataframe['close'].iloc[-1]
110
-
111
  if len(dataframe) >= 20:
112
  keltner_channel = ta.kc(dataframe['high'], dataframe['low'], dataframe['close'], length=20)
113
  if keltner_channel is not None:
114
- volatility['kc_upper'] = float(keltner_channel['KCUe_20_2'].iloc[-1]) if not keltner_channel['KCUe_20_2'].empty else None
115
- volatility['kc_lower'] = float(keltner_channel['KCLe_20_2'].iloc[-1]) if not keltner_channel['KCLe_20_2'].empty else None
116
-
117
  if len(dataframe) >= 20:
118
  donchian_channel = ta.donchian(dataframe['high'], dataframe['low'], length=20)
119
  if donchian_channel is not None:
120
- volatility['dc_upper'] = float(donchian_channel['DCU_20_20'].iloc[-1]) if not donchian_channel['DCU_20_20'].empty else None
121
- volatility['dc_lower'] = float(donchian_channel['DCL_20_20'].iloc[-1]) if not donchian_channel['DCL_20_20'].empty else None
122
-
123
  if len(dataframe) >= 14:
124
  relative_volatility_index = ta.rvi(dataframe['close'], length=14)
125
- volatility['rvi'] = float(relative_volatility_index.iloc[-1]) if not relative_volatility_index.empty else None
126
  return {key: value for key, value in volatility.items() if value is not None}
127
 
128
  def _calculate_volume_indicators(self, dataframe):
129
  volume = {}
130
  if len(dataframe) >= 1:
131
  volume_weighted_average_price = ta.vwap(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'])
132
- volume['vwap'] = float(volume_weighted_average_price.iloc[-1]) if not volume_weighted_average_price.empty else None
133
-
134
  on_balance_volume = ta.obv(dataframe['close'], dataframe['volume'])
135
- volume['obv'] = float(on_balance_volume.iloc[-1]) if not on_balance_volume.empty else None
136
-
137
  if len(dataframe) >= 14:
138
  money_flow_index = ta.mfi(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'], length=14)
139
- volume['mfi'] = float(money_flow_index.iloc[-1]) if not money_flow_index.empty else None
140
-
141
  accumulation_distribution = ta.ad(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'])
142
- volume['ad_line'] = float(accumulation_distribution.iloc[-1]) if not accumulation_distribution.empty else None
143
-
144
  if len(dataframe) >= 20:
145
  volume_oscillator = ta.pvo(dataframe['volume'])
146
- if volume_oscillator is not None:
147
- volume['volume_oscillator'] = float(volume_oscillator['PVO_12_26_9'].iloc[-1]) if not volume_oscillator['PVO_12_26_9'].empty else None
148
-
149
  volume['volume_avg_20'] = float(dataframe['volume'].tail(20).mean()) if len(dataframe) >= 20 else None
150
- if volume['volume_avg_20'] and volume['volume_avg_20'] > 0:
151
- volume['volume_ratio'] = float(dataframe['volume'].iloc[-1] / volume['volume_avg_20'])
152
  return {key: value for key, value in volume.items() if value is not None}
153
 
154
  def _calculate_cycle_indicators(self, dataframe):
155
  cycle = {}
156
  if len(dataframe) >= 9:
157
  hull_moving_average = ta.hma(dataframe['close'], length=9)
158
- cycle['hull_ma'] = float(hull_moving_average.iloc[-1]) if not hull_moving_average.empty else None
159
-
160
  if len(dataframe) >= 10:
161
  supertrend = ta.supertrend(dataframe['high'], dataframe['low'], dataframe['close'], length=10, multiplier=3)
162
  if supertrend is not None:
163
- cycle['supertrend'] = float(supertrend['SUPERT_10_3.0'].iloc[-1]) if not supertrend['SUPERT_10_3.0'].empty else None
164
- cycle['supertrend_direction'] = float(supertrend['SUPERTd_10_3.0'].iloc[-1]) if not supertrend['SUPERTd_10_3.0'].empty else None
165
-
166
  if len(dataframe) >= 10:
167
  fisher_transform = ta.fisher(dataframe['high'], dataframe['low'], length=10)
168
- if fisher_transform is not None:
169
- cycle['fisher_transform'] = float(fisher_transform['FISHERT_10_1'].iloc[-1]) if not fisher_transform['FISHERT_10_1'].empty else None
170
  return {key: value for key, value in cycle.items() if value is not None}
171
 
172
  class PatternEnhancedStrategyEngine:
173
- """محرك استراتيجيات محسن مع دعم متقدم للأنماط البيانية"""
174
-
175
  def __init__(self, data_manager, learning_engine):
176
  self.data_manager = data_manager
177
  self.learning_engine = learning_engine
178
  self.pattern_success_tracker = PatternPerformanceTracker()
179
 
180
  async def enhance_strategy_with_patterns(self, strategy_scores, pattern_analysis, symbol):
181
- """تعزيز درجات الاستراتيجية بناءً على تحليل الأنماط"""
182
- if not pattern_analysis or pattern_analysis.get('pattern_detected') in ['no_clear_pattern', 'insufficient_data']:
183
- return strategy_scores
184
-
185
  pattern_confidence = pattern_analysis.get('pattern_confidence', 0)
186
  pattern_name = pattern_analysis.get('pattern_detected', '')
187
  predicted_direction = pattern_analysis.get('predicted_direction', '')
188
-
189
- # فقط تعزيز إذا كانت الثقة في النمط عالية
190
  if pattern_confidence >= 0.7:
191
  enhancement_factor = self._calculate_pattern_enhancement(pattern_confidence, pattern_name)
192
-
193
- # تحديد الاستراتيجيات المناسبة للنمط
194
  enhanced_strategies = self._get_pattern_appropriate_strategies(pattern_name, predicted_direction)
195
-
196
  for strategy in enhanced_strategies:
197
  if strategy in strategy_scores:
198
  strategy_scores[strategy] *= enhancement_factor
199
- print(f"🎯 Enhanced {strategy} for {symbol} by {enhancement_factor:.1%} due to {pattern_name} pattern")
200
-
201
  return strategy_scores
202
 
203
  def _calculate_pattern_enhancement(self, pattern_confidence, pattern_name):
204
- """حساب عامل التعزيز بناءً على ثقة النمط ونوعه"""
205
- base_enhancement = 1.0 + (pattern_confidence * 0.5) # حتى 50% زيادة
206
-
207
- # أنماط عالية المصداقية تحصل على تعزيز إضافي
208
  high_reliability_patterns = ['Double Top', 'Double Bottom', 'Head & Shoulders', 'Cup and Handle']
209
- if pattern_name in high_reliability_patterns:
210
- base_enhancement *= 1.2
211
-
212
- return min(base_enhancement, 2.0) # حد أقصى 100% زيادة
213
 
214
  def _get_pattern_appropriate_strategies(self, pattern_name, direction):
215
- """الحصول على الاستراتيجيات المناسبة لنوع النمط"""
216
  reversal_patterns = ['Double Top', 'Double Bottom', 'Head & Shoulders', 'Triple Top', 'Triple Bottom']
217
  continuation_patterns = ['Flags', 'Pennants', 'Triangles', 'Rectangles']
218
-
219
  if pattern_name in reversal_patterns:
220
- if direction == 'down':
221
- return ['breakout_momentum', 'trend_following']
222
- else:
223
- return ['mean_reversion', 'breakout_momentum']
224
-
225
- elif pattern_name in continuation_patterns:
226
- return ['trend_following', 'breakout_momentum']
227
-
228
- else: # أنماط أخرى
229
- return ['breakout_momentum', 'hybrid_ai']
230
 
231
  class PatternPerformanceTracker:
232
- """متتبع أداء الأنماط البيانية"""
233
-
234
  def __init__(self):
235
  self.pattern_performance = {}
236
  self.pattern_success_rates = {}
237
 
238
  async def track_pattern_outcome(self, symbol, pattern_analysis, success, profit_percent):
239
- """تتبع نتيجة النمط البياني"""
240
- if not pattern_analysis:
241
- return
242
-
243
  pattern_name = pattern_analysis.get('pattern_detected')
244
  confidence = pattern_analysis.get('pattern_confidence', 0)
245
-
246
  if pattern_name not in ['no_clear_pattern', 'insufficient_data']:
247
  if pattern_name not in self.pattern_performance:
248
- self.pattern_performance[pattern_name] = {
249
- 'total_trades': 0,
250
- 'successful_trades': 0,
251
- 'total_profit': 0,
252
- 'total_confidence': 0
253
- }
254
-
255
  stats = self.pattern_performance[pattern_name]
256
  stats['total_trades'] += 1
257
  stats['total_confidence'] += confidence
258
-
259
  if success:
260
  stats['successful_trades'] += 1
261
  stats['total_profit'] += profit_percent
262
-
263
  success_rate = stats['successful_trades'] / stats['total_trades']
264
  avg_profit = stats['total_profit'] / stats['successful_trades'] if stats['successful_trades'] > 0 else 0
265
  avg_confidence = stats['total_confidence'] / stats['total_trades']
266
-
267
- print(f"📊 Pattern Performance: {pattern_name} - "
268
- f"Success: {success_rate:.1%} - Avg Profit: {avg_profit:.2f}% - "
269
- f"Avg Confidence: {avg_confidence:.1%}")
270
 
271
  def get_pattern_reliability(self, pattern_name):
272
- """الحصول على موثوقية النمط"""
273
  if pattern_name in self.pattern_performance:
274
  stats = self.pattern_performance[pattern_name]
275
- if stats['total_trades'] > 0:
276
- return stats['successful_trades'] / stats['total_trades']
277
- return 0.5 # قيمة افتراضية
278
 
279
  class MultiStrategyEngine:
280
  def __init__(self, data_manager, learning_engine):
@@ -292,431 +220,242 @@ class MultiStrategyEngine:
292
  }
293
 
294
  async def evaluate_all_strategies(self, symbol_data, market_context):
295
- """تقييم جميع الاستراتيجيات مع استخدام أوزان نظام التعلم - الإصدار المحسّن"""
296
  try:
297
- # ✅ الحصول على الأوزان المحسنة من نظام التعلم
298
  market_condition = market_context.get('market_trend', 'sideways_market')
299
-
300
- # ✅ التحقق من وجود learning_engine وتهيئته
301
  if self.learning_engine and hasattr(self.learning_engine, 'initialized') and self.learning_engine.initialized:
302
- try:
303
- optimized_weights = await self.learning_engine.get_optimized_strategy_weights(market_condition)
304
- print(f"🎯 الأوزان المستخدمة: {optimized_weights}")
305
- except Exception as e:
306
- print(f"⚠️ فشل الحصول على الأوزان المحسنة: {e}")
307
  optimized_weights = await self.get_default_weights()
308
  else:
309
- print("⚠️ نظام التعلم غير متوفر، استخدام الأوزان الافتراضية")
310
  optimized_weights = await self.get_default_weights()
311
-
312
  strategy_scores = {}
313
- base_scores = {} # ✅ تخزين الدرجات الأساسية
314
-
315
- # ✅ تقييم كل استراتيجية مع تطبيق الأوزان
316
  for strategy_name, strategy_function in self.strategies.items():
317
  try:
318
  base_score = await strategy_function(symbol_data, market_context)
319
- base_scores[strategy_name] = base_score # ✅ حفظ الدرجة الأساسية
320
-
321
- # ✅ تطبيق الوزن المحسن
322
  weight = optimized_weights.get(strategy_name, 0.1)
323
  weighted_score = base_score * weight
324
-
325
  strategy_scores[strategy_name] = min(weighted_score, 1.0)
326
-
327
- print(f"📊 {strategy_name}: {base_score:.3f} × {weight:.3f} = {weighted_score:.3f}")
328
-
329
  except Exception as error:
330
  print(f"⚠️ Strategy {strategy_name} failed: {error}")
331
  base_score = await self._fallback_strategy_score(strategy_name, symbol_data, market_context)
332
  base_scores[strategy_name] = base_score
333
  strategy_scores[strategy_name] = base_score * optimized_weights.get(strategy_name, 0.1)
334
-
335
- # ✅ تعزيز الاستراتيجيات بناءً على تحليل الأنماط
336
  pattern_analysis = symbol_data.get('pattern_analysis')
337
- if pattern_analysis:
338
- strategy_scores = await self.pattern_enhancer.enhance_strategy_with_patterns(
339
- strategy_scores, pattern_analysis, symbol_data.get('symbol')
340
- )
341
-
342
- # ✅ تحديد أفضل استراتيجية بناءً على الدرجات الأساسية (بدون أوزان)
343
  if base_scores:
344
  best_strategy = max(base_scores.items(), key=lambda x: x[1])
345
  best_strategy_name = best_strategy[0]
346
  best_strategy_score = best_strategy[1]
347
-
348
  symbol_data['recommended_strategy'] = best_strategy_name
349
  symbol_data['strategy_confidence'] = best_strategy_score
350
-
351
- print(f"🏆 أفضل استراتيجية (أساسي): {best_strategy_name} بدرجة {best_strategy_score:.3f}")
352
-
353
- # ✅ تعزيز اختيار الاستراتيجية إذا كان هناك نمط عالي الثقة
354
- if (pattern_analysis and
355
- pattern_analysis.get('pattern_confidence', 0) > 0.7 and
356
- self._is_strategy_pattern_aligned(best_strategy_name, pattern_analysis)):
357
-
358
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.3
359
  enhanced_confidence = min(best_strategy_score + pattern_bonus, 1.0)
360
  symbol_data['strategy_confidence'] = enhanced_confidence
361
- print(f"🎯 تعزيز ثقة الاستراتيجية بواسطة النمط: {enhanced_confidence:.3f}")
362
-
363
- return strategy_scores, base_scores # ✅ إرجاع كلا النوعين
364
-
365
  except Exception as error:
366
- print(f"❌ فشل تقييم الاستراتيجيات: {error}")
367
  fallback_scores = await self.get_fallback_scores()
368
  return fallback_scores, fallback_scores
369
 
370
  def _is_strategy_pattern_aligned(self, strategy_name, pattern_analysis):
371
- """التحقق من محاذاة الاستراتيجية مع النمط البياني"""
372
  pattern_direction = pattern_analysis.get('predicted_direction', '')
373
  pattern_type = pattern_analysis.get('pattern_detected', '')
374
-
375
- # استراتيجيات التوجه الصعودي
376
  bullish_strategies = ['trend_following', 'breakout_momentum']
377
- # استراتيجيات التوجه الهبوطي
378
  bearish_strategies = ['mean_reversion', 'breakout_momentum']
379
-
380
- if pattern_direction == 'up' and strategy_name in bullish_strategies:
381
- return True
382
- elif pattern_direction == 'down' and strategy_name in bearish_strategies:
383
- return True
384
-
385
  return False
386
 
387
  async def get_default_weights(self):
388
- """الأوزان الافتراضية عندما لا يتوفر نظام التعلم"""
389
- return {
390
- 'trend_following': 0.15, 'mean_reversion': 0.12,
391
- 'breakout_momentum': 0.18, 'volume_spike': 0.10,
392
- 'whale_tracking': 0.20, 'pattern_recognition': 0.15,
393
- 'hybrid_ai': 0.10
394
- }
395
 
396
  async def get_fallback_scores(self):
397
- """درجات احتياطية عند فشل التقييم"""
398
- return {
399
- 'trend_following': 0.5, 'mean_reversion': 0.5,
400
- 'breakout_momentum': 0.5, 'volume_spike': 0.5,
401
- 'whale_tracking': 0.5, 'pattern_recognition': 0.5,
402
- 'hybrid_ai': 0.5
403
- }
404
 
405
  async def _trend_following_strategy(self, symbol_data, market_context):
406
- """استراتيجية تتبع الاتجاه المحسنة - درجات أعلى"""
407
  try:
408
  score = 0.0
409
  indicators = symbol_data.get('advanced_indicators', {})
410
  timeframes = ['4h', '1h', '15m']
411
-
412
  for timeframe in timeframes:
413
  if timeframe in indicators:
414
  timeframe_indicators = indicators[timeframe]
415
-
416
- # تحقق من محاذاة المتوسطات المتحركة
417
- if self._check_ema_alignment(timeframe_indicators):
418
- score += 0.20 # ⬆️ زيادة من 0.15 إلى 0.20
419
-
420
- # مؤشر ADX للقوة الاتجاهية
421
  adx_value = timeframe_indicators.get('adx', 0)
422
- if adx_value > 20: # ⬇️ تخفيض من 25 إلى 20
423
- score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15
424
-
425
- # تحليل الحجم
426
  volume_ratio = timeframe_indicators.get('volume_ratio', 0)
427
- if volume_ratio > 1.2: # ⬇️ تخفيض من 1.5 إلى 1.2
428
- score += 0.10 # ⬆️ زيادة من 0.05 إلى 0.10
429
-
430
- # ✅ تعزيز بناءً على تحليل الأنماط
431
  pattern_analysis = symbol_data.get('pattern_analysis')
432
- if (pattern_analysis and
433
- pattern_analysis.get('pattern_confidence', 0) > 0.7 and
434
- pattern_analysis.get('predicted_direction') == 'up'):
435
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.2
436
  score += pattern_bonus
437
- print(f"📈 Trend following enhanced by pattern: +{pattern_bonus:.3f}")
438
-
439
  return min(score, 1.0)
440
-
441
  except Exception as error:
442
  print(f"⚠️ Trend following strategy error: {error}")
443
- return 0.3 # ⬆️ زيادة من 0.3 إلى 0.3 (نفس القيمة)
444
 
445
  def _check_ema_alignment(self, indicators):
446
- """التحقق من محاذاة المتوسطات المتحركة"""
447
  required_emas = ['ema_9', 'ema_21', 'ema_50']
448
- if all(ema in indicators for ema in required_emas):
449
- return (indicators['ema_9'] > indicators['ema_21'] > indicators['ema_50'])
450
  return False
451
 
452
  async def _mean_reversion_strategy(self, symbol_data, market_context):
453
- """استراتيجية العودة إلى المتوسط المحسنة - درجات أعلى"""
454
  try:
455
  score = 0.0
456
  current_price = symbol_data['current_price']
457
  indicators = symbol_data.get('advanced_indicators', {})
458
-
459
  if '1h' in indicators:
460
  hourly_indicators = indicators['1h']
461
-
462
- # تحليل Bollinger Bands
463
  if all(key in hourly_indicators for key in ['bb_upper', 'bb_lower', 'bb_middle']):
464
  position_in_band = (current_price - hourly_indicators['bb_lower']) / (hourly_indicators['bb_upper'] - hourly_indicators['bb_lower'])
465
-
466
- if position_in_band < 0.1 and hourly_indicators.get('rsi', 50) < 35:
467
- score += 0.45 # ⬆️ زيادة من 0.4 إلى 0.45
468
- if position_in_band > 0.9 and hourly_indicators.get('rsi', 50) > 65:
469
- score += 0.45 # ⬆️ زيادة من 0.4 إلى 0.45
470
-
471
- # تحليل RSI
472
  rsi_value = hourly_indicators.get('rsi', 50)
473
- if rsi_value < 30:
474
- score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35
475
- elif rsi_value > 70:
476
- score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35
477
-
478
- # ✅ تعزيز بناءً على تحليل الأنماط
479
  pattern_analysis = symbol_data.get('pattern_analysis')
480
- if (pattern_analysis and
481
- pattern_analysis.get('pattern_confidence', 0) > 0.7 and
482
- pattern_analysis.get('predicted_direction') in ['up', 'down']):
483
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.15
484
  score += pattern_bonus
485
- print(f"🔄 Mean reversion enhanced by pattern: +{pattern_bonus:.3f}")
486
-
487
  return min(score, 1.0)
488
-
489
  except Exception as error:
490
  print(f"⚠️ Mean reversion strategy error: {error}")
491
  return 0.3
492
 
493
  async def _breakout_momentum_strategy(self, symbol_data, market_context):
494
- """استراتيجية كسر الزخم المحسنة - درجات أعلى"""
495
  try:
496
  score = 0.0
497
  indicators = symbol_data.get('advanced_indicators', {})
498
-
499
- for timeframe in ['1h', '15m', '5m']: # ✅ إضافة timeframe إضافية
500
  if timeframe in indicators:
501
  timeframe_indicators = indicators[timeframe]
502
-
503
- # ✅ تحليل الحجم - عتبات مخفضة
504
  volume_ratio = timeframe_indicators.get('volume_ratio', 0)
505
- if volume_ratio > 1.8: # ⬇️ تخفيض من 2.0 إلى 1.8
506
- score += 0.25 # ⬆️ زيادة من 0.2 إلى 0.25
507
- elif volume_ratio > 1.3: # إضافة شرط وسيط
508
- score += 0.15
509
-
510
- # ✅ تحليل MACD
511
- if timeframe_indicators.get('macd_hist', 0) > 0:
512
- score += 0.20 # ⬆️ زيادة من 0.15 إلى 0.20
513
-
514
- # ✅ تحليل VWAP
515
- if 'vwap' in timeframe_indicators and symbol_data['current_price'] > timeframe_indicators['vwap']:
516
- score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15
517
-
518
- # ✅ إضافة شرط RSI إضافي
519
  rsi_value = timeframe_indicators.get('rsi', 50)
520
- if 40 <= rsi_value <= 70: # نطاق RSI صحي
521
- score += 0.10
522
-
523
- # ✅ تعزيز بناءً على تحليل الأنماط - تأثير كبير على breakout
524
  pattern_analysis = symbol_data.get('pattern_analysis')
525
  if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.6:
526
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.3
527
  score += pattern_bonus
528
- print(f"🚀 Breakout momentum significantly enhanced by pattern: +{pattern_bonus:.3f}")
529
-
530
- # ✅ ضمان حد أدنى للدرجة إذا كانت هناك إشارات إيجابية
531
- if score > 0.2:
532
- score = max(score, 0.4) # ⬆️ ضمان حد أدنى 0.4 إذا كانت هناك إشارات
533
-
534
  return min(score, 1.0)
535
-
536
  except Exception as error:
537
  print(f"⚠️ Breakout momentum strategy error: {error}")
538
- return 0.4 # ⬆️ زيادة من 0.3 إلى 0.4
539
 
540
  async def _volume_spike_strategy(self, symbol_data, market_context):
541
- """استراتيجية ارتفاع الحجم المحسنة - درجات أعلى"""
542
  try:
543
  score = 0.0
544
  indicators = symbol_data.get('advanced_indicators', {})
545
-
546
  for timeframe in ['1h', '15m', '5m']:
547
  if timeframe in indicators:
548
  volume_ratio = indicators[timeframe].get('volume_ratio', 0)
549
- if volume_ratio > 3.0:
550
- score += 0.45 # ⬆️ زيادة من 0.4 إلى 0.45
551
- elif volume_ratio > 2.0:
552
- score += 0.25 # ⬆️ زيادة من 0.2 إلى 0.25
553
- elif volume_ratio > 1.5: # ✅ إضافة شرط وسيط
554
- score += 0.15
555
-
556
- # ✅ تعزيز بناءً على تحليل الأنماط مع ارتفاع الحجم
557
  pattern_analysis = symbol_data.get('pattern_analysis')
558
- if (pattern_analysis and
559
- pattern_analysis.get('pattern_confidence', 0) > 0.7 and
560
- any(indicators[tf].get('volume_ratio', 0) > 2.0 for tf in ['1h', '15m'] if tf in indicators)):
561
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.2
562
  score += pattern_bonus
563
- print(f"💧 Volume spike enhanced by pattern: +{pattern_bonus:.3f}")
564
-
565
  return min(score, 1.0)
566
-
567
  except Exception as error:
568
  print(f"⚠️ Volume spike strategy error: {error}")
569
  return 0.3
570
 
571
  async def _whale_tracking_strategy(self, symbol_data, market_context):
572
- """استراتيجية تتبع الحيتان المحسنة - درجات أعلى"""
573
  try:
574
  score = 0.0
575
- # ✅ الإصلاح: استخدام الدالة الآمنة الجديدة
576
  whale_data = await self.data_manager.get_whale_data_safe_async(symbol_data['symbol'])
577
-
578
- # استخدام البيانات الحقيقية فقط
579
- if not whale_data.get('data_available', False):
580
- return 0.2 # ⬆️ زيادة من 0.1 إلى 0.2 (قيمة أساسية أعلى)
581
-
582
  total_transactions = whale_data.get('transfer_count', 0)
583
  whale_volume = whale_data.get('total_volume', 0)
584
-
585
- # معايير مرنة للسماح بمزيد من المرشحين
586
- if total_transactions >= 2: # ⬇️ تخفيض من 3 إلى 2
587
- score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35
588
- elif total_transactions >= 1: # ⬇️ تخفيض من 5 إلى 1
589
- score += 0.25 # ⬆️ زيادة من 0.15 إلى 0.25
590
-
591
- if whale_volume > 25000: # ⬇️ تخفيض من 50000 إلى 25000
592
- score += 0.25 # ⬆️ زيادة من 0.2 إلى 0.25
593
- elif whale_volume > 5000: # ⬇️ تخفيض من 10000 إلى 5000
594
- score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15
595
-
596
- # ✅ إضافة نقاط إضافية بناءً على نشاط الحيتان العام
597
  general_whale = market_context.get('general_whale_activity', {})
598
- if general_whale.get('data_available', False) and general_whale.get('transaction_count', 0) > 0:
599
- score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15
600
-
601
  return min(score, 1.0)
602
-
603
  except Exception as error:
604
  print(f"⚠️ Whale tracking failed: {error}")
605
- return 0.2 # ⬆️ زيادة من 0.1 إلى 0.2
606
 
607
  async def _pattern_recognition_strategy(self, symbol_data, market_context):
608
- """استراتيجية التعرف على الأنماط المحسنة - درجات أعلى"""
609
  try:
610
  score = 0.0
611
  indicators = symbol_data.get('advanced_indicators', {})
612
-
613
- # ✅ تعزيز كبير بناءً على تحليل الأنماط من LLM
614
  pattern_analysis = symbol_data.get('pattern_analysis')
615
  if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.6:
616
  score += pattern_analysis.get('pattern_confidence', 0) * 0.8
617
- print(f"🎯 Pattern recognition significantly enhanced: +{score:.3f}")
618
  else:
619
- # التحليل التقليدي إذا لم يكن هناك نمط من LLM
620
  for timeframe in ['4h', '1h']:
621
  if timeframe in indicators:
622
  timeframe_indicators = indicators[timeframe]
623
-
624
- # نمط الزخم الصعودي
625
- if (timeframe_indicators.get('rsi', 50) > 60 and
626
- timeframe_indicators.get('macd_hist', 0) > 0 and
627
- timeframe_indicators.get('volume_ratio', 0) > 1.5):
628
- score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35
629
-
630
- # نمط الزخم الهبوطي
631
- if (timeframe_indicators.get('rsi', 50) < 40 and
632
- timeframe_indicators.get('stoch_rsi_k', 50) < 20):
633
- score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35
634
-
635
  return min(score, 1.0)
636
-
637
  except Exception as error:
638
  print(f"⚠️ Pattern recognition strategy error: {error}")
639
  return 0.3
640
 
641
  async def _hybrid_ai_strategy(self, symbol_data, market_context):
642
- """استراتيجية الهجين الذكية المحسنة - درجات أعلى"""
643
  try:
644
  score = 0.0
645
  monte_carlo_probability = symbol_data.get('monte_carlo_probability', 0.5)
646
  final_score = symbol_data.get('final_score', 0.5)
647
-
648
  score += monte_carlo_probability * 0.4
649
  score += final_score * 0.3
650
-
651
- # تحليل سياق السوق
652
- if market_context.get('btc_sentiment') == 'BULLISH':
653
- score += 0.25 # ⬆️ زيادة من 0.2 إلى 0.25
654
- elif market_context.get('btc_sentiment') == 'BEARISH':
655
- score -= 0.08 # ⬆️ تخفيض من 0.1 إلى 0.08
656
-
657
- # تحليل نشاط الحيتان العام
658
  whale_activity = market_context.get('general_whale_activity', {})
659
- if whale_activity.get('sentiment') == 'BULLISH':
660
- score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15
661
-
662
- # ✅ تعزيز بناءً على تحليل الأنماط
663
  pattern_analysis = symbol_data.get('pattern_analysis')
664
  if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.7:
665
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.25
666
  score += pattern_bonus
667
- print(f"🤖 Hybrid AI enhanced by pattern: +{pattern_bonus:.3f}")
668
-
669
  return max(0.0, min(score, 1.0))
670
-
671
  except Exception as error:
672
  print(f"⚠️ Hybrid AI strategy error: {error}")
673
  return 0.3
674
 
675
  async def _fallback_strategy_score(self, strategy_name, symbol_data, market_context):
676
- """درجات استراتيجية احتياطية محسنة"""
677
  try:
678
  base_score = symbol_data.get('final_score', 0.5)
679
-
680
  if strategy_name == 'trend_following':
681
  indicators = symbol_data.get('advanced_indicators', {})
682
  if '1h' in indicators:
683
  rsi_value = indicators['1h'].get('rsi', 50)
684
  ema_9 = indicators['1h'].get('ema_9')
685
  ema_21 = indicators['1h'].get('ema_21')
686
-
687
- if ema_9 and ema_21 and ema_9 > ema_21 and 40 <= rsi_value <= 60:
688
- return 0.6
689
  return 0.4
690
-
691
  elif strategy_name == 'mean_reversion':
692
  current_price = symbol_data.get('current_price', 0)
693
  indicators = symbol_data.get('advanced_indicators', {})
694
  if '1h' in indicators:
695
  rsi_value = indicators['1h'].get('rsi', 50)
696
  bb_lower = indicators['1h'].get('bb_lower')
697
-
698
- if bb_lower and current_price <= bb_lower * 1.02 and rsi_value < 35:
699
- return 0.7
700
  return 0.3
701
-
702
  elif strategy_name == 'breakout_momentum':
703
  volume_ratio = symbol_data.get('advanced_indicators', {}).get('1h', {}).get('volume_ratio', 0)
704
- if volume_ratio > 1.5:
705
- return 0.6
706
  return 0.4
707
-
708
  elif strategy_name == 'whale_tracking':
709
  whale_data = symbol_data.get('whale_data', {})
710
- if not whale_data.get('data_available', False):
711
- return 0.2 # ⬆️ زيادة من 0.1 إلى 0.2
712
-
713
  total_transactions = whale_data.get('transfer_count', 0)
714
- if total_transactions >= 3:
715
- return 0.5
716
  return 0.3
717
-
718
  return base_score
719
-
720
  except Exception as error:
721
  print(f"⚠️ Fallback strategy failed for {strategy_name}: {error}")
722
  return 0.3
@@ -731,10 +470,8 @@ class MLProcessor:
731
  self.pattern_tracker = PatternPerformanceTracker()
732
 
733
  def _validate_rsi_safety(self, indicators):
734
- """التحقق العاجل من سلامة مؤشر RSI"""
735
  rsi_warnings = []
736
  critical_issues = 0
737
-
738
  timeframes_to_check = ['5m', '15m', '1h', '4h']
739
  for timeframe in timeframes_to_check:
740
  if timeframe in indicators:
@@ -743,191 +480,106 @@ class MLProcessor:
743
  if rsi_value > 80:
744
  rsi_warnings.append(f"🚨 RSI CRITICAL in {timeframe}: {rsi_value} - EXTREME OVERBOUGHT")
745
  critical_issues += 1
746
- elif rsi_value > 75:
747
- rsi_warnings.append(f"⚠️ RSI WARNING in {timeframe}: {rsi_value} - STRONG OVERBOUGHT")
748
- elif rsi_value > 70:
749
- rsi_warnings.append(f"📈 RSI HIGH in {timeframe}: {rsi_value} - OVERBOUGHT")
750
-
751
- # إذا كان هناك إطارين زمنيين أو أكثر في منطقة الخطر، نرفض المرشح
752
  is_safe = critical_issues < 2
753
  return is_safe, rsi_warnings
754
 
755
  def _validate_indicators_quality_enhanced(self, indicators, current_price):
756
- """تحسين التحقق من جودة المؤشرات"""
757
  quality_issues = []
758
-
759
- # التحقق من RSI
760
  rsi_safe, rsi_warnings = self._validate_rsi_safety(indicators)
761
- if not rsi_safe:
762
- quality_issues.extend(rsi_warnings)
763
-
764
- # التحقق من تناقض المؤشرات
765
- bullish_signals = 0
766
- bearish_signals = 0
767
-
768
  for timeframe, data in indicators.items():
769
- # إشارات صعودية
770
- if data.get('macd_hist', 0) > 0:
771
- bullish_signals += 1
772
- if data.get('rsi', 50) > 70: # RSI مرتفع يعتبر إشارة بيع
773
- bearish_signals += 1
774
  if 'ema_9' in data and 'ema_21' in data:
775
- if data['ema_9'] > data['ema_21']:
776
- bullish_signals += 1
777
-
778
- if bullish_signals > 0 and bearish_signals > bullish_signals:
779
- quality_issues.append("⚠️ Conflicting signals: More bearish than bullish indicators")
780
-
781
  return quality_issues
782
 
783
  def _calculate_enhanced_score_with_safety(self, base_analysis, strategy_scores, quality_issues):
784
- """حساب النقاط مع مراعاة عوامل السلامة"""
785
  base_score = base_analysis.get('final_score', 0.5)
786
  strategy_average = sum(strategy_scores.values()) / len(strategy_scores) if strategy_scores else 0.5
787
-
788
- # خصم النقاط بناءً على مشاكل الجودة
789
  safety_penalty = 0.0
790
  for issue in quality_issues:
791
- if '🚨 RSI CRITICAL' in issue:
792
- safety_penalty += 0.3
793
- elif '⚠️ RSI WARNING' in issue:
794
- safety_penalty += 0.15
795
- elif '📈 RSI HIGH' in issue:
796
- safety_penalty += 0.05
797
-
798
  enhanced_score = (base_score * 0.4) + (strategy_average * 0.6)
799
  enhanced_score = max(0.0, enhanced_score - safety_penalty)
800
-
801
  return min(enhanced_score, 1.0)
802
 
803
  async def process_and_score_symbol_enhanced(self, raw_data):
804
- """معالجة وتحليل الرمز مع نظام التعلم والاستراتيجيات - الإصدار المحسّن"""
805
  try:
806
- if not raw_data or not raw_data.get('ohlcv'):
807
- print(f"⚠️ Skipping {raw_data.get('symbol', 'unknown')} - no OHLCV data")
808
- return None
809
-
810
- # ✅ تمرير بيانات الشموع الخام للتحليل اللاحق
811
  raw_data['raw_ohlcv'] = raw_data.get('ohlcv', {})
812
-
813
  base_analysis = await self.process_and_score_symbol(raw_data)
814
- if not base_analysis:
815
- return None
816
-
817
  try:
818
- # التحقق المحسن من الجودة
819
  current_price = base_analysis.get('current_price', 0)
820
- quality_issues = self._validate_indicators_quality_enhanced(
821
- base_analysis.get('advanced_indicators', {}),
822
- current_price
823
- )
824
-
825
- # طباعة تحذيرات الجودة
826
  if quality_issues:
827
  print(f"🔍 Quality issues for {base_analysis.get('symbol')}:")
828
- for issue in quality_issues:
829
- print(f" {issue}")
830
-
831
- # ✅ تقييم الاستراتيجيات باستخدام نظام التعلم مع التحقق من الوجود
832
  if hasattr(self, 'strategy_engine') and self.strategy_engine:
833
  strategy_scores, base_scores = await self.strategy_engine.evaluate_all_strategies(base_analysis, self.market_context)
834
  base_analysis['strategy_scores'] = strategy_scores
835
- base_analysis['base_strategy_scores'] = base_scores # ✅ حفظ الدرجات الأساسية
836
-
837
- # ✅ تحديد أفضل استراتيجية بناءً على الدرجات الأساسية (بدون أوزان)
838
  if base_scores:
839
  best_strategy = max(base_scores.items(), key=lambda x: x[1])
840
  best_strategy_name = best_strategy[0]
841
  best_strategy_score = best_strategy[1]
842
-
843
  base_analysis['recommended_strategy'] = best_strategy_name
844
  base_analysis['strategy_confidence'] = best_strategy_score
845
-
846
- print(f"🎯 أفضل استراتيجية لـ {base_analysis.get('symbol')}: {best_strategy_name} (ثقة: {best_strategy_score:.3f})")
847
-
848
- # ✅ تخفيض عتبة الثقة للسماح بمزيد من الاستراتيجيات
849
- if best_strategy_score > 0.3: # ⬇️ تخفيض من 0.6 إلى 0.3
850
- base_analysis['target_strategy'] = best_strategy_name
851
- print(f"✅ استخدام استراتيجية متخصصة: {best_strategy_name}")
852
- else:
853
- base_analysis['target_strategy'] = 'GENERIC'
854
- print(f"🔄 استخدام استراتيجية عامة (ثقة منخفضة: {best_strategy_score:.3f})")
855
  else:
856
  base_analysis['recommended_strategy'] = 'GENERIC'
857
- base_analysis['strategy_confidence'] = 0.3 # ⬆️ زيادة من 0.5 إلى 0.3
858
  base_analysis['target_strategy'] = 'GENERIC'
859
- print("🔄 استخدام استراتيجية عامة (لا توجد درجات استراتيجية)")
860
-
861
- # ✅ استخدام الدالة المحسنة لحساب النقاط
862
- enhanced_score = self._calculate_enhanced_score_with_safety(
863
- base_analysis, strategy_scores, quality_issues
864
- )
865
-
866
  base_analysis['enhanced_final_score'] = enhanced_score
867
  else:
868
- print("⚠️ Strategy engine not available, using base analysis only")
869
  base_analysis['strategy_scores'] = {}
870
  base_analysis['enhanced_final_score'] = base_analysis.get('final_score', 0.5)
871
  base_analysis['recommended_strategy'] = 'GENERIC'
872
  base_analysis['strategy_confidence'] = 0.3
873
  base_analysis['target_strategy'] = 'GENERIC'
874
-
875
  base_analysis['quality_warnings'] = quality_issues
876
-
877
  except Exception as strategy_error:
878
  print(f"⚠️ Strategy evaluation failed for {base_analysis.get('symbol')}: {strategy_error}")
879
  base_analysis['strategy_scores'] = {}
880
  base_analysis['enhanced_final_score'] = base_analysis.get('final_score', 0.5)
881
  base_analysis['recommended_strategy'] = 'GENERIC'
882
- base_analysis['strategy_confidence'] = 0.3 # ⬆️ زيادة من 0.5 إلى 0.3
883
  base_analysis['target_strategy'] = 'GENERIC'
884
  base_analysis['quality_warnings'] = ['Strategy evaluation failed']
885
-
886
  return base_analysis
887
-
888
  except Exception as error:
889
  print(f"❌ Enhanced processing failed for {raw_data.get('symbol')}: {error}")
890
  return await self.process_and_score_symbol(raw_data)
891
 
892
  def _improve_fibonacci_levels(self, daily_dataframe, current_price):
893
- """تحسين حساب مستويات Fibonacci لتتوافق مع السعر الحالي"""
894
- if len(daily_dataframe) < 50:
895
- return {}
896
-
897
- # استخدام آخر 50 يومًا لحساب القمة والقاع
898
  recent_high = float(daily_dataframe['high'].iloc[-50:].max())
899
  recent_low = float(daily_dataframe['low'].iloc[-50:].min())
900
-
901
- # إذا كان السعر الحالي خارج النطاق، نعدل النطاق
902
- if current_price > recent_high:
903
- recent_high = current_price * 1.05 # نضيف هامش 5%
904
- if current_price < recent_low:
905
- recent_low = current_price * 0.95 # نخصم هامش 5%
906
-
907
  difference = recent_high - recent_low
908
- if difference <= 0: # تجنب القسمة على الصفر
909
- return {}
910
-
911
  return {
912
- "0.0%": recent_high,
913
- "23.6%": recent_high - 0.236 * difference,
914
- "38.2%": recent_high - 0.382 * difference,
915
- "50.0%": recent_high - 0.50 * difference,
916
- "61.8%": recent_high - 0.618 * difference,
917
- "78.6%": recent_high - 0.786 * difference,
918
  "100.0%": recent_low
919
  }
920
 
921
  async def process_and_score_symbol(self, raw_data):
922
- """معالجة وتحليل الرمز الأساسي"""
923
  symbol = raw_data['symbol']
924
  ohlcv_data = raw_data['ohlcv']
925
  reasons_for_candidacy = raw_data.get('reasons', [])
926
-
927
- if not ohlcv_data:
928
- print(f"❌ No OHLCV data for {symbol}")
929
- return None
930
-
931
  try:
932
  all_indicators = {}
933
  for timeframe, candles in ohlcv_data.items():
@@ -935,14 +587,9 @@ class MLProcessor:
935
  dataframe = pd.DataFrame(candles, columns=['time', 'open', 'high', 'low', 'close', 'volume'])
936
  dataframe[['open', 'high', 'low', 'close', 'volume']] = dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float)
937
  all_indicators[timeframe] = self._calculate_indicators(dataframe, timeframe)
938
-
939
  hourly_dataframe = pd.DataFrame(ohlcv_data.get('1h', []), columns=['time', 'open', 'high', 'low', 'close', 'volume'])
940
- if hourly_dataframe.empty:
941
- print(f"❌ Skipping {symbol} due to insufficient 1h data.")
942
- return None
943
-
944
  hourly_dataframe[['open', 'high', 'low', 'close', 'volume']] = hourly_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float)
945
-
946
  try:
947
  current_price = float(hourly_dataframe['close'].iloc[-1])
948
  if ohlcv_data.get('5m'):
@@ -950,40 +597,22 @@ class MLProcessor:
950
  if not five_minute_dataframe.empty:
951
  five_minute_dataframe[['open', 'high', 'low', 'close', 'volume']] = five_minute_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float)
952
  current_price = float(five_minute_dataframe['close'].iloc[-1])
953
-
954
  liquidity_score = self._calculate_liquidity_score(hourly_dataframe)
955
  daily_dataframe = pd.DataFrame(ohlcv_data.get('1d', []), columns=['time', 'open', 'high', 'low', 'close', 'volume'])
956
- if not daily_dataframe.empty:
957
- daily_dataframe[['open', 'high', 'low', 'close', 'volume']] = daily_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float)
958
-
959
  average_daily_volume = float(daily_dataframe['volume'].mean()) if not daily_dataframe.empty else 0.0
960
-
961
- # استخدام الدالة المحسنة لحساب مستويات Fibonacci
962
  fibonacci_levels = self._improve_fibonacci_levels(daily_dataframe, current_price)
963
-
964
- try:
965
- whale_data = await self.data_manager.get_whale_data_safe_async(symbol)
966
  except Exception as whale_error:
967
- print(f"⚠️ Whale data failed for {symbol}: {whale_error}. No whale data available.")
968
- whale_data = {
969
- "transfer_count": 0,
970
- "total_volume": 0,
971
- "source": "no_data",
972
- "data_available": False
973
- }
974
-
975
  whale_score = self._calculate_whale_activity_score(whale_data)
976
  opportunity_classification = self.classify_opportunity_type(all_indicators, current_price)
977
  initial_score = self._calculate_initial_score(all_indicators, current_price, self.market_context)
978
  monte_carlo_probability = self._run_monte_carlo_simulation(hourly_dataframe)
979
-
980
- print(f"🎲 Monte Carlo Simulation for {symbol}: Success Probability = {monte_carlo_probability:.2%}")
981
-
982
  final_score = (0.35 * initial_score) + (0.50 * monte_carlo_probability) + (0.15 * whale_score)
983
  final_score *= opportunity_classification['confidence']
984
-
985
  normalized_indicators = {timeframe: self._normalize_features_corrected(indicators) for timeframe, indicators in all_indicators.items()}
986
-
987
  return {
988
  'symbol': symbol, 'reasons_for_candidacy': reasons_for_candidacy, 'current_price': float(current_price),
989
  'liquidity_score': float(liquidity_score) if not np.isnan(liquidity_score) else 0.0, 'avg_daily_volume': float(average_daily_volume),
@@ -992,25 +621,16 @@ class MLProcessor:
992
  'initial_score': float(initial_score), 'monte_carlo_probability': float(monte_carlo_probability),
993
  'indicators': normalized_indicators, 'advanced_indicators': all_indicators, 'strategy_scores': {},
994
  'recommended_strategy': 'GENERIC', 'enhanced_final_score': float(final_score), 'target_strategy': 'GENERIC',
995
- 'raw_ohlcv': ohlcv_data # ✅ إضافة بيانات الشموع الخام
996
  }
997
-
998
- except (KeyError, IndexError) as error:
999
- print(f"⚠️ Missing data for {symbol}: {error}")
1000
- return None
1001
-
1002
  except Exception as error:
1003
  print(f"❌ Failed to process {symbol}: {error}")
1004
- import traceback
1005
- traceback.print_exc()
1006
  return None
1007
 
1008
  def _calculate_indicators(self, dataframe, timeframe):
1009
- """حساب المؤشرات الفنية"""
1010
  indicators = {}
1011
- if dataframe.empty:
1012
- return indicators
1013
-
1014
  if not isinstance(dataframe.index, pd.DatetimeIndex):
1015
  try:
1016
  dataframe['time'] = pd.to_datetime(dataframe['time'], unit='ms')
@@ -1018,88 +638,56 @@ class MLProcessor:
1018
  except:
1019
  dataframe['time'] = pd.to_datetime(dataframe['time'])
1020
  dataframe = dataframe.set_index('time', drop=True)
1021
-
1022
  dataframe = dataframe.sort_index()
1023
-
1024
  if len(dataframe) >= 1 and all(column in dataframe.columns for column in ['high', 'low', 'close', 'volume']):
1025
  try:
1026
  typical_price = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3
1027
  volume_weighted_average_price = (typical_price * dataframe['volume']).cumsum() / dataframe['volume'].cumsum()
1028
- if not volume_weighted_average_price.empty and not pd.isna(volume_weighted_average_price.iloc[-1]):
1029
- indicators['vwap'] = float(volume_weighted_average_price.iloc[-1])
1030
- except Exception as error:
1031
- print(f"⚠️ VWAP calculation failed for {timeframe}: {error}")
1032
-
1033
  if len(dataframe) >= 14:
1034
  rsi_series = ta.rsi(dataframe['close'], length=14)
1035
- if rsi_series is not None and not rsi_series.empty and rsi_series.iloc[-1] is not np.nan:
1036
- indicators['rsi'] = float(rsi_series.iloc[-1])
1037
-
1038
  if len(dataframe) >= 26:
1039
  macd = ta.macd(dataframe['close'])
1040
  if macd is not None and not macd.empty:
1041
- if 'MACDh_12_26_9' in macd.columns and macd['MACDh_12_26_9'].iloc[-1] is not np.nan:
1042
- indicators['macd_hist'] = float(macd['MACDh_12_26_9'].iloc[-1])
1043
- if 'MACD_12_26_9' in macd.columns and macd['MACD_12_26_9'].iloc[-1] is not np.nan:
1044
- indicators['macd_line'] = float(macd['MACD_12_26_9'].iloc[-1])
1045
- if 'MACDs_12_26_9' in macd.columns and macd['MACDs_12_26_9'].iloc[-1] is not np.nan:
1046
- indicators['macd_signal'] = float(macd['MACDs_12_26_9'].iloc[-1])
1047
-
1048
  if len(dataframe) >= 20:
1049
  bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2)
1050
  if bollinger_bands is not None and not bollinger_bands.empty:
1051
- if 'BBL_20_2.0' in bollinger_bands.columns and bollinger_bands['BBL_20_2.0'].iloc[-1] is not np.nan:
1052
- indicators['bb_lower'] = float(bollinger_bands['BBL_20_2.0'].iloc[-1])
1053
- if 'BBU_20_2.0' in bollinger_bands.columns and bollinger_bands['BBU_20_2.0'].iloc[-1] is not np.nan:
1054
- indicators['bb_upper'] = float(bollinger_bands['BBU_20_2.0'].iloc[-1])
1055
- if 'BBM_20_2.0' in bollinger_bands.columns and bollinger_bands['BBM_20_2.0'].iloc[-1] is not np.nan:
1056
- indicators['bb_middle'] = float(bollinger_bands['BBM_20_2.0'].iloc[-1])
1057
-
1058
  if len(dataframe) >= 14:
1059
  average_true_range = ta.atr(high=dataframe['high'], low=dataframe['low'], close=dataframe['close'], length=14)
1060
- if average_true_range is not None and not average_true_range.empty and average_true_range.iloc[-1] is not np.nan:
1061
- indicators['atr'] = float(average_true_range.iloc[-1])
1062
-
1063
  if len(dataframe) >= 26:
1064
  ema_12 = ta.ema(dataframe['close'], length=12)
1065
  ema_26 = ta.ema(dataframe['close'], length=26)
1066
- if ema_12 is not None and not ema_12.empty and ema_12.iloc[-1] is not np.nan:
1067
- indicators['ema_12'] = float(ema_12.iloc[-1])
1068
- if ema_26 is not None and not ema_26.empty and ema_26.iloc[-1] is not np.nan:
1069
- indicators['ema_26'] = float(ema_26.iloc[-1])
1070
-
1071
  return indicators
1072
 
1073
  def _normalize_features_corrected(self, features):
1074
- """تطبيع الميزات بشكل صحيح"""
1075
  normalized_features = {}
1076
  for key, value in features.items():
1077
- if value is None:
1078
- normalized_features[key] = 0.0
1079
- continue
1080
- if key == 'rsi':
1081
- normalized_features[key] = max(0, min(100, value))
1082
- elif key in ['macd_hist', 'macd_line', 'macd_signal', 'vwap', 'atr']:
1083
- normalized_features[key] = value
1084
- elif 'ema' in key or 'bb_' in key:
1085
- normalized_features[key] = value
1086
  else:
1087
  try:
1088
- if abs(value) > 1000:
1089
- normalized_features[key] = value / 1000
1090
- else:
1091
- normalized_features[key] = value
1092
- except:
1093
- normalized_features[key] = value
1094
  return normalized_features
1095
 
1096
  def _run_monte_carlo_simulation(self, dataframe, number_of_simulations=1000, number_of_steps=20):
1097
- """تشغيل محاكاة مونت كارلو"""
1098
- if dataframe.empty or len(dataframe) < 2:
1099
- return 0.0
1100
  log_returns = np.log(dataframe['close'] / dataframe['close'].shift(1)).dropna()
1101
- if log_returns.empty:
1102
- return 0.0
1103
  mean_return = log_returns.mean()
1104
  volatility = log_returns.std()
1105
  initial_price = dataframe['close'].iloc[-1]
@@ -1108,58 +696,42 @@ class MLProcessor:
1108
  random_values = np.random.normal(0, 1, number_of_steps)
1109
  daily_returns = np.exp(mean_return - 0.5 * volatility**2 + volatility * random_values)
1110
  simulated_prices = initial_price * daily_returns.cumprod()
1111
- if (simulated_prices[-1] / initial_price) > 1.02:
1112
- success_count += 1
1113
  return success_count / number_of_simulations
1114
 
1115
  def _calculate_initial_score(self, indicators, current_price, market_context):
1116
- """حساب النقاط الأولية"""
1117
  score = 0.5
1118
  fast_timeframes = ['5m', '15m']
1119
  for timeframe in fast_timeframes:
1120
  timeframe_indicators = indicators.get(timeframe, {})
1121
- if not timeframe_indicators:
1122
- continue
1123
  if 'rsi' in timeframe_indicators:
1124
  rsi_value = timeframe_indicators['rsi']
1125
  if isinstance(rsi_value, (int, float)):
1126
- if rsi_value < 30:
1127
- score += 0.2
1128
- elif rsi_value < 40:
1129
- score += 0.1
1130
- elif rsi_value > 70:
1131
- score -= 0.1
1132
- if 'macd_hist' in timeframe_indicators and timeframe_indicators['macd_hist'] > 0:
1133
- score += 0.15
1134
  if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']):
1135
- if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']:
1136
- score += 0.15
1137
  slow_timeframes = ['1h', '4h', '1d']
1138
  for timeframe in slow_timeframes:
1139
  timeframe_indicators = indicators.get(timeframe, {})
1140
- if not timeframe_indicators:
1141
- continue
1142
  if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']):
1143
- if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']:
1144
- score += 0.10
1145
  if all(key in timeframe_indicators for key in ['bb_upper', 'bb_lower']):
1146
- if current_price > timeframe_indicators['bb_upper']:
1147
- score += 0.10
1148
- elif current_price <= timeframe_indicators['bb_lower']:
1149
- score += 0.05
1150
- if '5m' in indicators and 'vwap' in indicators['5m'] and current_price > indicators['5m']['vwap']:
1151
- score += 0.10
1152
  if market_context:
1153
  bitcoin_sentiment = market_context.get('btc_sentiment')
1154
  fear_greed_index = market_context.get('fear_and_greed_index', 50)
1155
- if bitcoin_sentiment == 'BULLISH' and fear_greed_index > 60:
1156
- score *= 1.2
1157
- elif bitcoin_sentiment == 'BEARISH' or fear_greed_index < 30:
1158
- score *= 0.8
1159
  return min(max(score, 0.0), 1.0)
1160
 
1161
- def _normalize_features(self, features):
1162
- return self._normalize_features_corrected(features)
1163
 
1164
  def _prepare_data_for_ml(self, all_indicators, current_price):
1165
  feature_vector = []
@@ -1167,236 +739,62 @@ class MLProcessor:
1167
  indicator_keys = ['rsi', 'macd_hist', 'macd_line', 'bb_upper', 'bb_lower', 'atr', 'ema_12', 'ema_26', 'vwap']
1168
  for timeframe in timeframes:
1169
  timeframe_indicators = all_indicators.get(timeframe, {})
1170
- for key in indicator_keys:
1171
- feature_vector.append(timeframe_indicators.get(key, 0.0))
1172
  feature_vector.append(current_price)
1173
  return feature_vector
1174
 
1175
  def _calculate_liquidity_score(self, hourly_dataframe):
1176
- if hourly_dataframe.empty:
1177
- return 0.0
1178
  hourly_dataframe['dollar_volume'] = hourly_dataframe['volume'] * hourly_dataframe['close']
1179
  return float(hourly_dataframe['dollar_volume'].mean())
1180
 
1181
- def _calculate_fibonacci_levels(self, daily_dataframe):
1182
- """مهملة: استخدام _improve_fibonacci_levels بدلاً من ذلك"""
1183
- return self._improve_fibonacci_levels(daily_dataframe, 0)
1184
 
1185
  def classify_opportunity_type(self, indicators, current_price):
1186
- fast_signals = 0
1187
- slow_signals = 0
1188
  for timeframe in ['5m', '15m']:
1189
  timeframe_indicators = indicators.get(timeframe, {})
1190
- if not timeframe_indicators:
1191
- continue
1192
- if timeframe_indicators.get('rsi', 100) < 35:
1193
- fast_signals += 1
1194
- if timeframe_indicators.get('macd_hist', 0) > 0:
1195
- fast_signals += 1
1196
  if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']):
1197
- if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']:
1198
- fast_signals += 1
1199
- if timeframe == '5m' and timeframe_indicators.get('vwap') and current_price > timeframe_indicators['vwap'] * 1.02:
1200
- fast_signals += 1
1201
  for timeframe in ['1h', '4h', '1d']:
1202
  timeframe_indicators = indicators.get(timeframe, {})
1203
- if not timeframe_indicators:
1204
- continue
1205
- if 40 <= timeframe_indicators.get('rsi', 50) <= 60:
1206
- slow_signals += 1
1207
  if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']):
1208
- if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']:
1209
- slow_signals += 1
1210
- if timeframe_indicators.get('bb_middle') and current_price > timeframe_indicators['bb_middle']:
1211
- slow_signals += 1
1212
  if fast_signals >= 3:
1213
  return {
1214
  "type": "FAST_PUMP", "timeframe": "15m-1h", "take_profit_multiplier": 1.08, "stop_loss_multiplier": 0.97,
1215
- "confidence": min(fast_signals / 6.0, 1.0), "description": "فرصة صعود سريع قوية على الأطر الزمنية القصيرة"
1216
  }
1217
  elif slow_signals >= 3:
1218
  return {
1219
  "type": "SLOW_GROWTH", "timeframe": "4h-1d", "take_profit_multiplier": 1.05, "stop_loss_multiplier": 0.95,
1220
- "confidence": min(slow_signals / 6.0, 1.0), "description": "فرصة نمو مستدام على الأطر الزمنية الطويلة"
1221
  }
1222
  return {
1223
  "type": "NEUTRAL", "timeframe": "N/A", "take_profit_multiplier": 1.05, "stop_loss_multiplier": 0.95,
1224
- "confidence": 0.3, "description": "لا توجد إشارات واضحة لنوع محدد من الفرص"
1225
  }
1226
 
1227
  def _calculate_whale_activity_score(self, whale_data):
1228
- """حساب درجة نشاط الحيتان بناءً على البيانات الحقيقية فقط"""
1229
- if not whale_data.get('data_available', False):
1230
- return 0.0
1231
-
1232
  total_transactions = whale_data.get('transfer_count', 0)
1233
  total_volume = whale_data.get('total_volume', 0)
1234
-
1235
  score = 0.0
1236
- if total_transactions >= 10:
1237
- score += 0.3
1238
- elif total_transactions >= 5:
1239
- score += 0.15
1240
-
1241
- if total_volume > 500000:
1242
- score += 0.2
1243
- elif total_volume > 100000:
1244
- score += 0.1
1245
-
1246
  return min(score, 0.5)
1247
 
1248
  def filter_top_candidates(self, candidates, number_of_candidates=10):
1249
- """تصفية أفضل المرشحين"""
1250
  valid_candidates = [candidate for candidate in candidates if candidate is not None]
1251
  return sorted(valid_candidates, key=lambda candidate: candidate.get('enhanced_final_score', candidate.get('final_score', 0)), reverse=True)[:number_of_candidates]
1252
 
1253
- # دوال المحاكاة المحلية للاستخدام كبديل
1254
- def local_analyze_opportunity(candidate_data):
1255
- """تحليل محسن مع مراعاة مخاطر RSI"""
1256
- score = candidate_data.get('enhanced_final_score', candidate_data.get('final_score', 0))
1257
- quality_warnings = candidate_data.get('quality_warnings', [])
1258
-
1259
- # التحقق من تحذيرات RSI
1260
- rsi_critical = any('🚨 RSI CRITICAL' in warning for warning in quality_warnings)
1261
- rsi_warning = any('⚠️ RSI WARNING' in warning for warning in quality_warnings)
1262
-
1263
- if rsi_critical:
1264
- return {
1265
- "action": "HOLD",
1266
- "reasoning": "Local analysis: CRITICAL RSI levels detected - extreme overbought condition. High risk of correction.",
1267
- "trade_type": "NONE",
1268
- "stop_loss": None,
1269
- "take_profit": None,
1270
- "expected_target_minutes": 15,
1271
- "confidence_level": 0.1,
1272
- "model_source": "local_safety_filter",
1273
- "strategy": "GENERIC"
1274
- }
1275
-
1276
- advanced_indicators = candidate_data.get('advanced_indicators', {})
1277
- strategy_scores = candidate_data.get('strategy_scores', {})
1278
-
1279
- if not advanced_indicators:
1280
- return {
1281
- "action": "HOLD",
1282
- "reasoning": "Local analysis: Insufficient advanced indicator data.",
1283
- "trade_type": "NONE",
1284
- "stop_loss": None,
1285
- "take_profit": None,
1286
- "expected_target_minutes": 15,
1287
- "confidence_level": 0.3,
1288
- "model_source": "local",
1289
- "strategy": "GENERIC"
1290
- }
1291
-
1292
- action = "HOLD"
1293
- reasoning = "Local analysis: No strong buy signal based on enhanced rules."
1294
- trade_type = "NONE"
1295
- stop_loss = None
1296
- take_profit = None
1297
- expected_minutes = 15
1298
- confidence = 0.3
1299
-
1300
- five_minute_indicators = advanced_indicators.get('5m', {})
1301
- one_hour_indicators = advanced_indicators.get('1h', {})
1302
-
1303
- buy_conditions = 0
1304
- total_conditions = 0
1305
-
1306
- if isinstance(score, (int, float)) and score > 0.70:
1307
- buy_conditions += 1
1308
- total_conditions += 1
1309
-
1310
- # شرط RSI أكثر تحفظاً
1311
- rsi_five_minute = five_minute_indicators.get('rsi', 50)
1312
- if 30 <= rsi_five_minute <= 65: # نطاق آمن لـ RSI
1313
- buy_conditions += 1
1314
- total_conditions += 1
1315
-
1316
- if five_minute_indicators.get('macd_hist', 0) > 0:
1317
- buy_conditions += 1
1318
- total_conditions += 1
1319
-
1320
- if (five_minute_indicators.get('ema_9', 0) > five_minute_indicators.get('ema_21', 0) and
1321
- one_hour_indicators.get('ema_9', 0) > one_hour_indicators.get('ema_21', 0)):
1322
- buy_conditions += 1
1323
- total_conditions += 1
1324
-
1325
- if five_minute_indicators.get('volume_ratio', 0) > 1.5:
1326
- buy_conditions += 1
1327
- total_conditions += 1
1328
-
1329
- confidence = buy_conditions / total_conditions if total_conditions > 0 else 0.3
1330
-
1331
- # خصم الثقة بناءً على تحذيرات RSI
1332
- if rsi_warning:
1333
- confidence *= 0.7 # خصم 30% للتحذيرات
1334
- reasoning += " RSI warning applied."
1335
-
1336
- if confidence >= 0.6:
1337
- action = "BUY"
1338
- current_price = candidate_data['current_price']
1339
- trade_type = "LONG"
1340
-
1341
- # وقف خسارة أكثر تحفظاً لـ RSI المرتفع
1342
- if rsi_warning:
1343
- stop_loss = current_price * 0.93 # 7% stop loss للتحذيرات
1344
- else:
1345
- stop_loss = current_price * 0.95 # 5% stop loss عادي
1346
-
1347
- if 'bb_upper' in five_minute_indicators:
1348
- take_profit = five_minute_indicators['bb_upper'] * 1.02
1349
- else:
1350
- take_profit = current_price * 1.05
1351
-
1352
- if confidence >= 0.8:
1353
- expected_minutes = 10
1354
- elif confidence >= 0.6:
1355
- expected_minutes = 18
1356
- else:
1357
- expected_minutes = 25
1358
-
1359
- reasoning = f"Local enhanced analysis: Strong buy signal with {buy_conditions}/{total_conditions} conditions met. Confidence: {confidence:.2f}"
1360
- if rsi_warning:
1361
- reasoning += " (RSI warning - trading with caution)"
1362
-
1363
- return {
1364
- "action": action,
1365
- "reasoning": reasoning,
1366
- "trade_type": trade_type,
1367
- "stop_loss": stop_loss,
1368
- "take_profit": take_profit,
1369
- "expected_target_minutes": expected_minutes,
1370
- "confidence_level": confidence,
1371
- "model_source": "local",
1372
- "strategy": "GENERIC"
1373
- }
1374
-
1375
- def local_re_analyze_trade(trade_data, processed_data):
1376
- current_price = processed_data['current_price']
1377
- stop_loss = trade_data['stop_loss']
1378
- take_profit = trade_data['take_profit']
1379
- action = "HOLD"
1380
- reasoning = "Local re-analysis: No significant change to trigger an update or close."
1381
- if stop_loss and current_price <= stop_loss:
1382
- action = "CLOSE_TRADE"
1383
- reasoning = "Local re-analysis: Stop loss has been hit."
1384
- elif take_profit and current_price >= take_profit:
1385
- action = "CLOSE_TRADE"
1386
- reasoning = "Local re-analysis: Take profit has been hit."
1387
-
1388
- strategy = trade_data.get('strategy', 'GENERIC')
1389
- if strategy == 'unknown':
1390
- strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC')
1391
-
1392
- return {
1393
- "action": action,
1394
- "reasoning": reasoning,
1395
- "new_stop_loss": None,
1396
- "new_take_profit": None,
1397
- "new_expected_minutes": None,
1398
- "model_source": "local",
1399
- "strategy": strategy
1400
- }
1401
-
1402
  print("✅ Enhanced ML System Loaded - Integrated with Learning Engine - REAL DATA ONLY - Optimized Strategy Scoring with Pattern Enhancement")
 
 
1
  import pandas as pd
2
  import pandas_ta as ta
3
  import numpy as np
 
16
  }
17
 
18
  def calculate_all_indicators(self, dataframe, timeframe):
19
+ if dataframe.empty: return {}
 
20
  indicators = {}
21
  indicators.update(self._calculate_trend_indicators(dataframe))
22
  indicators.update(self._calculate_momentum_indicators(dataframe))
 
27
 
28
  def _calculate_trend_indicators(self, dataframe):
29
  trend = {}
30
+ if len(dataframe) >= 9: trend['ema_9'] = float(ta.ema(dataframe['close'], length=9).iloc[-1])
31
+ if len(dataframe) >= 21: trend['ema_21'] = float(ta.ema(dataframe['close'], length=21).iloc[-1])
32
+ if len(dataframe) >= 50: trend['ema_50'] = float(ta.ema(dataframe['close'], length=50).iloc[-1])
33
+ if len(dataframe) >= 200: trend['ema_200'] = float(ta.ema(dataframe['close'], length=200).iloc[-1])
 
34
  if len(dataframe) >= 26:
35
  ichimoku = ta.ichimoku(dataframe['high'], dataframe['low'], dataframe['close'])
36
  if ichimoku is not None:
37
+ if not ichimoku[0]['ITS_9'].empty: trend['ichimoku_conversion'] = float(ichimoku[0]['ITS_9'].iloc[-1])
38
+ if not ichimoku[0]['IKS_26'].empty: trend['ichimoku_base'] = float(ichimoku[0]['IKS_26'].iloc[-1])
39
+ if not ichimoku[0]['ISA_9'].empty: trend['ichimoku_span_a'] = float(ichimoku[0]['ISA_9'].iloc[-1])
40
+ if not ichimoku[0]['ISB_26'].empty: trend['ichimoku_span_b'] = float(ichimoku[0]['ISB_26'].iloc[-1])
 
41
  if len(dataframe) >= 14:
42
  adx_result = ta.adx(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
43
  if adx_result is not None:
44
+ if not adx_result['ADX_14'].empty: trend['adx'] = float(adx_result['ADX_14'].iloc[-1])
45
+ if not adx_result['DMP_14'].empty: trend['dmi_plus'] = float(adx_result['DMP_14'].iloc[-1])
46
+ if not adx_result['DMN_14'].empty: trend['dmi_minus'] = float(adx_result['DMN_14'].iloc[-1])
 
47
  if len(dataframe) >= 5:
48
  psar = ta.psar(dataframe['high'], dataframe['low'], dataframe['close'])
49
+ if psar is not None and not psar['PSARl_0.02_0.2'].empty: trend['psar'] = float(psar['PSARl_0.02_0.2'].iloc[-1])
 
50
  return {key: value for key, value in trend.items() if value is not None}
51
 
52
  def _calculate_momentum_indicators(self, dataframe):
53
  momentum = {}
54
  if len(dataframe) >= 14:
55
  rsi = ta.rsi(dataframe['close'], length=14)
56
+ if not rsi.empty: momentum['rsi'] = float(rsi.iloc[-1])
 
57
  if len(dataframe) >= 14:
58
  stoch_rsi = ta.stochrsi(dataframe['close'], length=14)
59
  if stoch_rsi is not None:
60
+ if not stoch_rsi['STOCHRSIk_14_14_3_3'].empty: momentum['stoch_rsi_k'] = float(stoch_rsi['STOCHRSIk_14_14_3_3'].iloc[-1])
61
+ if not stoch_rsi['STOCHRSId_14_14_3_3'].empty: momentum['stoch_rsi_d'] = float(stoch_rsi['STOCHRSId_14_14_3_3'].iloc[-1])
 
62
  if len(dataframe) >= 26:
63
  macd = ta.macd(dataframe['close'])
64
  if macd is not None:
65
+ if not macd['MACD_12_26_9'].empty: momentum['macd_line'] = float(macd['MACD_12_26_9'].iloc[-1])
66
+ if not macd['MACDs_12_26_9'].empty: momentum['macd_signal'] = float(macd['MACDs_12_26_9'].iloc[-1])
67
+ if not macd['MACDh_12_26_9'].empty: momentum['macd_hist'] = float(macd['MACDh_12_26_9'].iloc[-1])
 
68
  if len(dataframe) >= 14:
69
  williams = ta.willr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
70
+ if not williams.empty: momentum['williams_r'] = float(williams.iloc[-1])
 
71
  if len(dataframe) >= 20:
72
  cci = ta.cci(dataframe['high'], dataframe['low'], dataframe['close'], length=20)
73
+ if not cci.empty: momentum['cci'] = float(cci.iloc[-1])
 
74
  if len(dataframe) >= 34:
75
  awesome_oscillator = ta.ao(dataframe['high'], dataframe['low'])
76
+ if not awesome_oscillator.empty: momentum['awesome_oscillator'] = float(awesome_oscillator.iloc[-1])
 
77
  if len(dataframe) >= 10:
78
  momentum_indicator = ta.mom(dataframe['close'], length=10)
79
+ if not momentum_indicator.empty: momentum['momentum'] = float(momentum_indicator.iloc[-1])
80
  return {key: value for key, value in momentum.items() if value is not None}
81
 
82
  def _calculate_volatility_indicators(self, dataframe):
 
84
  if len(dataframe) >= 20:
85
  bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2)
86
  if bollinger_bands is not None:
87
+ if not bollinger_bands['BBU_20_2.0'].empty: volatility['bb_upper'] = float(bollinger_bands['BBU_20_2.0'].iloc[-1])
88
+ if not bollinger_bands['BBM_20_2.0'].empty: volatility['bb_middle'] = float(bollinger_bands['BBM_20_2.0'].iloc[-1])
89
+ if not bollinger_bands['BBL_20_2.0'].empty: volatility['bb_lower'] = float(bollinger_bands['BBL_20_2.0'].iloc[-1])
90
+ if all(key in volatility for key in ['bb_upper', 'bb_lower', 'bb_middle']): volatility['bb_width'] = (volatility['bb_upper'] - volatility['bb_lower']) / volatility['bb_middle']
 
 
91
  if len(dataframe) >= 14:
92
  average_true_range = ta.atr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
93
+ if not average_true_range.empty:
94
+ volatility['atr'] = float(average_true_range.iloc[-1])
95
+ if volatility['atr']: volatility['atr_percent'] = volatility['atr'] / dataframe['close'].iloc[-1]
 
96
  if len(dataframe) >= 20:
97
  keltner_channel = ta.kc(dataframe['high'], dataframe['low'], dataframe['close'], length=20)
98
  if keltner_channel is not None:
99
+ if not keltner_channel['KCUe_20_2'].empty: volatility['kc_upper'] = float(keltner_channel['KCUe_20_2'].iloc[-1])
100
+ if not keltner_channel['KCLe_20_2'].empty: volatility['kc_lower'] = float(keltner_channel['KCLe_20_2'].iloc[-1])
 
101
  if len(dataframe) >= 20:
102
  donchian_channel = ta.donchian(dataframe['high'], dataframe['low'], length=20)
103
  if donchian_channel is not None:
104
+ if not donchian_channel['DCU_20_20'].empty: volatility['dc_upper'] = float(donchian_channel['DCU_20_20'].iloc[-1])
105
+ if not donchian_channel['DCL_20_20'].empty: volatility['dc_lower'] = float(donchian_channel['DCL_20_20'].iloc[-1])
 
106
  if len(dataframe) >= 14:
107
  relative_volatility_index = ta.rvi(dataframe['close'], length=14)
108
+ if not relative_volatility_index.empty: volatility['rvi'] = float(relative_volatility_index.iloc[-1])
109
  return {key: value for key, value in volatility.items() if value is not None}
110
 
111
  def _calculate_volume_indicators(self, dataframe):
112
  volume = {}
113
  if len(dataframe) >= 1:
114
  volume_weighted_average_price = ta.vwap(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'])
115
+ if not volume_weighted_average_price.empty: volume['vwap'] = float(volume_weighted_average_price.iloc[-1])
 
116
  on_balance_volume = ta.obv(dataframe['close'], dataframe['volume'])
117
+ if not on_balance_volume.empty: volume['obv'] = float(on_balance_volume.iloc[-1])
 
118
  if len(dataframe) >= 14:
119
  money_flow_index = ta.mfi(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'], length=14)
120
+ if not money_flow_index.empty: volume['mfi'] = float(money_flow_index.iloc[-1])
 
121
  accumulation_distribution = ta.ad(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'])
122
+ if not accumulation_distribution.empty: volume['ad_line'] = float(accumulation_distribution.iloc[-1])
 
123
  if len(dataframe) >= 20:
124
  volume_oscillator = ta.pvo(dataframe['volume'])
125
+ if volume_oscillator is not None and not volume_oscillator['PVO_12_26_9'].empty: volume['volume_oscillator'] = float(volume_oscillator['PVO_12_26_9'].iloc[-1])
 
 
126
  volume['volume_avg_20'] = float(dataframe['volume'].tail(20).mean()) if len(dataframe) >= 20 else None
127
+ if volume['volume_avg_20'] and volume['volume_avg_20'] > 0: volume['volume_ratio'] = float(dataframe['volume'].iloc[-1] / volume['volume_avg_20'])
 
128
  return {key: value for key, value in volume.items() if value is not None}
129
 
130
  def _calculate_cycle_indicators(self, dataframe):
131
  cycle = {}
132
  if len(dataframe) >= 9:
133
  hull_moving_average = ta.hma(dataframe['close'], length=9)
134
+ if not hull_moving_average.empty: cycle['hull_ma'] = float(hull_moving_average.iloc[-1])
 
135
  if len(dataframe) >= 10:
136
  supertrend = ta.supertrend(dataframe['high'], dataframe['low'], dataframe['close'], length=10, multiplier=3)
137
  if supertrend is not None:
138
+ if not supertrend['SUPERT_10_3.0'].empty: cycle['supertrend'] = float(supertrend['SUPERT_10_3.0'].iloc[-1])
139
+ if not supertrend['SUPERTd_10_3.0'].empty: cycle['supertrend_direction'] = float(supertrend['SUPERTd_10_3.0'].iloc[-1])
 
140
  if len(dataframe) >= 10:
141
  fisher_transform = ta.fisher(dataframe['high'], dataframe['low'], length=10)
142
+ if fisher_transform is not None and not fisher_transform['FISHERT_10_1'].empty: cycle['fisher_transform'] = float(fisher_transform['FISHERT_10_1'].iloc[-1])
 
143
  return {key: value for key, value in cycle.items() if value is not None}
144
 
145
  class PatternEnhancedStrategyEngine:
 
 
146
  def __init__(self, data_manager, learning_engine):
147
  self.data_manager = data_manager
148
  self.learning_engine = learning_engine
149
  self.pattern_success_tracker = PatternPerformanceTracker()
150
 
151
  async def enhance_strategy_with_patterns(self, strategy_scores, pattern_analysis, symbol):
152
+ if not pattern_analysis or pattern_analysis.get('pattern_detected') in ['no_clear_pattern', 'insufficient_data']: return strategy_scores
 
 
 
153
  pattern_confidence = pattern_analysis.get('pattern_confidence', 0)
154
  pattern_name = pattern_analysis.get('pattern_detected', '')
155
  predicted_direction = pattern_analysis.get('predicted_direction', '')
 
 
156
  if pattern_confidence >= 0.7:
157
  enhancement_factor = self._calculate_pattern_enhancement(pattern_confidence, pattern_name)
 
 
158
  enhanced_strategies = self._get_pattern_appropriate_strategies(pattern_name, predicted_direction)
 
159
  for strategy in enhanced_strategies:
160
  if strategy in strategy_scores:
161
  strategy_scores[strategy] *= enhancement_factor
 
 
162
  return strategy_scores
163
 
164
  def _calculate_pattern_enhancement(self, pattern_confidence, pattern_name):
165
+ base_enhancement = 1.0 + (pattern_confidence * 0.5)
 
 
 
166
  high_reliability_patterns = ['Double Top', 'Double Bottom', 'Head & Shoulders', 'Cup and Handle']
167
+ if pattern_name in high_reliability_patterns: base_enhancement *= 1.2
168
+ return min(base_enhancement, 2.0)
 
 
169
 
170
  def _get_pattern_appropriate_strategies(self, pattern_name, direction):
 
171
  reversal_patterns = ['Double Top', 'Double Bottom', 'Head & Shoulders', 'Triple Top', 'Triple Bottom']
172
  continuation_patterns = ['Flags', 'Pennants', 'Triangles', 'Rectangles']
 
173
  if pattern_name in reversal_patterns:
174
+ if direction == 'down': return ['breakout_momentum', 'trend_following']
175
+ else: return ['mean_reversion', 'breakout_momentum']
176
+ elif pattern_name in continuation_patterns: return ['trend_following', 'breakout_momentum']
177
+ else: return ['breakout_momentum', 'hybrid_ai']
 
 
 
 
 
 
178
 
179
  class PatternPerformanceTracker:
 
 
180
  def __init__(self):
181
  self.pattern_performance = {}
182
  self.pattern_success_rates = {}
183
 
184
  async def track_pattern_outcome(self, symbol, pattern_analysis, success, profit_percent):
185
+ if not pattern_analysis: return
 
 
 
186
  pattern_name = pattern_analysis.get('pattern_detected')
187
  confidence = pattern_analysis.get('pattern_confidence', 0)
 
188
  if pattern_name not in ['no_clear_pattern', 'insufficient_data']:
189
  if pattern_name not in self.pattern_performance:
190
+ self.pattern_performance[pattern_name] = {'total_trades': 0,'successful_trades': 0,'total_profit': 0,'total_confidence': 0}
 
 
 
 
 
 
191
  stats = self.pattern_performance[pattern_name]
192
  stats['total_trades'] += 1
193
  stats['total_confidence'] += confidence
 
194
  if success:
195
  stats['successful_trades'] += 1
196
  stats['total_profit'] += profit_percent
 
197
  success_rate = stats['successful_trades'] / stats['total_trades']
198
  avg_profit = stats['total_profit'] / stats['successful_trades'] if stats['successful_trades'] > 0 else 0
199
  avg_confidence = stats['total_confidence'] / stats['total_trades']
 
 
 
 
200
 
201
  def get_pattern_reliability(self, pattern_name):
 
202
  if pattern_name in self.pattern_performance:
203
  stats = self.pattern_performance[pattern_name]
204
+ if stats['total_trades'] > 0: return stats['successful_trades'] / stats['total_trades']
205
+ return 0.5
 
206
 
207
  class MultiStrategyEngine:
208
  def __init__(self, data_manager, learning_engine):
 
220
  }
221
 
222
  async def evaluate_all_strategies(self, symbol_data, market_context):
 
223
  try:
 
224
  market_condition = market_context.get('market_trend', 'sideways_market')
 
 
225
  if self.learning_engine and hasattr(self.learning_engine, 'initialized') and self.learning_engine.initialized:
226
+ try: optimized_weights = await self.learning_engine.get_optimized_strategy_weights(market_condition)
227
+ except Exception as e:
228
+ print(f"⚠️ Failed to get optimized weights: {e}")
 
 
229
  optimized_weights = await self.get_default_weights()
230
  else:
231
+ print("⚠️ Learning engine not available, using default weights")
232
  optimized_weights = await self.get_default_weights()
 
233
  strategy_scores = {}
234
+ base_scores = {}
 
 
235
  for strategy_name, strategy_function in self.strategies.items():
236
  try:
237
  base_score = await strategy_function(symbol_data, market_context)
238
+ base_scores[strategy_name] = base_score
 
 
239
  weight = optimized_weights.get(strategy_name, 0.1)
240
  weighted_score = base_score * weight
 
241
  strategy_scores[strategy_name] = min(weighted_score, 1.0)
 
 
 
242
  except Exception as error:
243
  print(f"⚠️ Strategy {strategy_name} failed: {error}")
244
  base_score = await self._fallback_strategy_score(strategy_name, symbol_data, market_context)
245
  base_scores[strategy_name] = base_score
246
  strategy_scores[strategy_name] = base_score * optimized_weights.get(strategy_name, 0.1)
 
 
247
  pattern_analysis = symbol_data.get('pattern_analysis')
248
+ if pattern_analysis: strategy_scores = await self.pattern_enhancer.enhance_strategy_with_patterns(strategy_scores, pattern_analysis, symbol_data.get('symbol'))
 
 
 
 
 
249
  if base_scores:
250
  best_strategy = max(base_scores.items(), key=lambda x: x[1])
251
  best_strategy_name = best_strategy[0]
252
  best_strategy_score = best_strategy[1]
 
253
  symbol_data['recommended_strategy'] = best_strategy_name
254
  symbol_data['strategy_confidence'] = best_strategy_score
255
+ if (pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.7 and self._is_strategy_pattern_aligned(best_strategy_name, pattern_analysis)):
 
 
 
 
 
 
 
256
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.3
257
  enhanced_confidence = min(best_strategy_score + pattern_bonus, 1.0)
258
  symbol_data['strategy_confidence'] = enhanced_confidence
259
+ return strategy_scores, base_scores
 
 
 
260
  except Exception as error:
261
+ print(f"❌ Strategy evaluation failed: {error}")
262
  fallback_scores = await self.get_fallback_scores()
263
  return fallback_scores, fallback_scores
264
 
265
  def _is_strategy_pattern_aligned(self, strategy_name, pattern_analysis):
 
266
  pattern_direction = pattern_analysis.get('predicted_direction', '')
267
  pattern_type = pattern_analysis.get('pattern_detected', '')
 
 
268
  bullish_strategies = ['trend_following', 'breakout_momentum']
 
269
  bearish_strategies = ['mean_reversion', 'breakout_momentum']
270
+ if pattern_direction == 'up' and strategy_name in bullish_strategies: return True
271
+ elif pattern_direction == 'down' and strategy_name in bearish_strategies: return True
 
 
 
 
272
  return False
273
 
274
  async def get_default_weights(self):
275
+ return {'trend_following': 0.15, 'mean_reversion': 0.12,'breakout_momentum': 0.18, 'volume_spike': 0.10,'whale_tracking': 0.20, 'pattern_recognition': 0.15,'hybrid_ai': 0.10}
 
 
 
 
 
 
276
 
277
  async def get_fallback_scores(self):
278
+ return {'trend_following': 0.5, 'mean_reversion': 0.5,'breakout_momentum': 0.5, 'volume_spike': 0.5,'whale_tracking': 0.5, 'pattern_recognition': 0.5,'hybrid_ai': 0.5}
 
 
 
 
 
 
279
 
280
  async def _trend_following_strategy(self, symbol_data, market_context):
 
281
  try:
282
  score = 0.0
283
  indicators = symbol_data.get('advanced_indicators', {})
284
  timeframes = ['4h', '1h', '15m']
 
285
  for timeframe in timeframes:
286
  if timeframe in indicators:
287
  timeframe_indicators = indicators[timeframe]
288
+ if self._check_ema_alignment(timeframe_indicators): score += 0.20
 
 
 
 
 
289
  adx_value = timeframe_indicators.get('adx', 0)
290
+ if adx_value > 20: score += 0.15
 
 
 
291
  volume_ratio = timeframe_indicators.get('volume_ratio', 0)
292
+ if volume_ratio > 1.2: score += 0.10
 
 
 
293
  pattern_analysis = symbol_data.get('pattern_analysis')
294
+ if (pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.7 and pattern_analysis.get('predicted_direction') == 'up'):
 
 
295
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.2
296
  score += pattern_bonus
 
 
297
  return min(score, 1.0)
 
298
  except Exception as error:
299
  print(f"⚠️ Trend following strategy error: {error}")
300
+ return 0.3
301
 
302
  def _check_ema_alignment(self, indicators):
 
303
  required_emas = ['ema_9', 'ema_21', 'ema_50']
304
+ if all(ema in indicators for ema in required_emas): return (indicators['ema_9'] > indicators['ema_21'] > indicators['ema_50'])
 
305
  return False
306
 
307
  async def _mean_reversion_strategy(self, symbol_data, market_context):
 
308
  try:
309
  score = 0.0
310
  current_price = symbol_data['current_price']
311
  indicators = symbol_data.get('advanced_indicators', {})
 
312
  if '1h' in indicators:
313
  hourly_indicators = indicators['1h']
 
 
314
  if all(key in hourly_indicators for key in ['bb_upper', 'bb_lower', 'bb_middle']):
315
  position_in_band = (current_price - hourly_indicators['bb_lower']) / (hourly_indicators['bb_upper'] - hourly_indicators['bb_lower'])
316
+ if position_in_band < 0.1 and hourly_indicators.get('rsi', 50) < 35: score += 0.45
317
+ if position_in_band > 0.9 and hourly_indicators.get('rsi', 50) > 65: score += 0.45
 
 
 
 
 
318
  rsi_value = hourly_indicators.get('rsi', 50)
319
+ if rsi_value < 30: score += 0.35
320
+ elif rsi_value > 70: score += 0.35
 
 
 
 
321
  pattern_analysis = symbol_data.get('pattern_analysis')
322
+ if (pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.7 and pattern_analysis.get('predicted_direction') in ['up', 'down']):
 
 
323
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.15
324
  score += pattern_bonus
 
 
325
  return min(score, 1.0)
 
326
  except Exception as error:
327
  print(f"⚠️ Mean reversion strategy error: {error}")
328
  return 0.3
329
 
330
  async def _breakout_momentum_strategy(self, symbol_data, market_context):
 
331
  try:
332
  score = 0.0
333
  indicators = symbol_data.get('advanced_indicators', {})
334
+ for timeframe in ['1h', '15m', '5m']:
 
335
  if timeframe in indicators:
336
  timeframe_indicators = indicators[timeframe]
 
 
337
  volume_ratio = timeframe_indicators.get('volume_ratio', 0)
338
+ if volume_ratio > 1.8: score += 0.25
339
+ elif volume_ratio > 1.3: score += 0.15
340
+ if timeframe_indicators.get('macd_hist', 0) > 0: score += 0.20
341
+ if 'vwap' in timeframe_indicators and symbol_data['current_price'] > timeframe_indicators['vwap']: score += 0.15
 
 
 
 
 
 
 
 
 
 
342
  rsi_value = timeframe_indicators.get('rsi', 50)
343
+ if 40 <= rsi_value <= 70: score += 0.10
 
 
 
344
  pattern_analysis = symbol_data.get('pattern_analysis')
345
  if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.6:
346
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.3
347
  score += pattern_bonus
348
+ if score > 0.2: score = max(score, 0.4)
 
 
 
 
 
349
  return min(score, 1.0)
 
350
  except Exception as error:
351
  print(f"⚠️ Breakout momentum strategy error: {error}")
352
+ return 0.4
353
 
354
  async def _volume_spike_strategy(self, symbol_data, market_context):
 
355
  try:
356
  score = 0.0
357
  indicators = symbol_data.get('advanced_indicators', {})
 
358
  for timeframe in ['1h', '15m', '5m']:
359
  if timeframe in indicators:
360
  volume_ratio = indicators[timeframe].get('volume_ratio', 0)
361
+ if volume_ratio > 3.0: score += 0.45
362
+ elif volume_ratio > 2.0: score += 0.25
363
+ elif volume_ratio > 1.5: score += 0.15
 
 
 
 
 
364
  pattern_analysis = symbol_data.get('pattern_analysis')
365
+ if (pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.7 and any(indicators[tf].get('volume_ratio', 0) > 2.0 for tf in ['1h', '15m'] if tf in indicators)):
 
 
366
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.2
367
  score += pattern_bonus
 
 
368
  return min(score, 1.0)
 
369
  except Exception as error:
370
  print(f"⚠️ Volume spike strategy error: {error}")
371
  return 0.3
372
 
373
  async def _whale_tracking_strategy(self, symbol_data, market_context):
 
374
  try:
375
  score = 0.0
 
376
  whale_data = await self.data_manager.get_whale_data_safe_async(symbol_data['symbol'])
377
+ if not whale_data.get('data_available', False): return 0.2
 
 
 
 
378
  total_transactions = whale_data.get('transfer_count', 0)
379
  whale_volume = whale_data.get('total_volume', 0)
380
+ if total_transactions >= 2: score += 0.35
381
+ elif total_transactions >= 1: score += 0.25
382
+ if whale_volume > 25000: score += 0.25
383
+ elif whale_volume > 5000: score += 0.15
 
 
 
 
 
 
 
 
 
384
  general_whale = market_context.get('general_whale_activity', {})
385
+ if general_whale.get('data_available', False) and general_whale.get('transaction_count', 0) > 0: score += 0.15
 
 
386
  return min(score, 1.0)
 
387
  except Exception as error:
388
  print(f"⚠️ Whale tracking failed: {error}")
389
+ return 0.2
390
 
391
  async def _pattern_recognition_strategy(self, symbol_data, market_context):
 
392
  try:
393
  score = 0.0
394
  indicators = symbol_data.get('advanced_indicators', {})
 
 
395
  pattern_analysis = symbol_data.get('pattern_analysis')
396
  if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.6:
397
  score += pattern_analysis.get('pattern_confidence', 0) * 0.8
 
398
  else:
 
399
  for timeframe in ['4h', '1h']:
400
  if timeframe in indicators:
401
  timeframe_indicators = indicators[timeframe]
402
+ if (timeframe_indicators.get('rsi', 50) > 60 and timeframe_indicators.get('macd_hist', 0) > 0 and timeframe_indicators.get('volume_ratio', 0) > 1.5): score += 0.35
403
+ if (timeframe_indicators.get('rsi', 50) < 40 and timeframe_indicators.get('stoch_rsi_k', 50) < 20): score += 0.35
 
 
 
 
 
 
 
 
 
 
404
  return min(score, 1.0)
 
405
  except Exception as error:
406
  print(f"⚠️ Pattern recognition strategy error: {error}")
407
  return 0.3
408
 
409
  async def _hybrid_ai_strategy(self, symbol_data, market_context):
 
410
  try:
411
  score = 0.0
412
  monte_carlo_probability = symbol_data.get('monte_carlo_probability', 0.5)
413
  final_score = symbol_data.get('final_score', 0.5)
 
414
  score += monte_carlo_probability * 0.4
415
  score += final_score * 0.3
416
+ if market_context.get('btc_sentiment') == 'BULLISH': score += 0.25
417
+ elif market_context.get('btc_sentiment') == 'BEARISH': score -= 0.08
 
 
 
 
 
 
418
  whale_activity = market_context.get('general_whale_activity', {})
419
+ if whale_activity.get('sentiment') == 'BULLISH': score += 0.15
 
 
 
420
  pattern_analysis = symbol_data.get('pattern_analysis')
421
  if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.7:
422
  pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.25
423
  score += pattern_bonus
 
 
424
  return max(0.0, min(score, 1.0))
 
425
  except Exception as error:
426
  print(f"⚠️ Hybrid AI strategy error: {error}")
427
  return 0.3
428
 
429
  async def _fallback_strategy_score(self, strategy_name, symbol_data, market_context):
 
430
  try:
431
  base_score = symbol_data.get('final_score', 0.5)
 
432
  if strategy_name == 'trend_following':
433
  indicators = symbol_data.get('advanced_indicators', {})
434
  if '1h' in indicators:
435
  rsi_value = indicators['1h'].get('rsi', 50)
436
  ema_9 = indicators['1h'].get('ema_9')
437
  ema_21 = indicators['1h'].get('ema_21')
438
+ if ema_9 and ema_21 and ema_9 > ema_21 and 40 <= rsi_value <= 60: return 0.6
 
 
439
  return 0.4
 
440
  elif strategy_name == 'mean_reversion':
441
  current_price = symbol_data.get('current_price', 0)
442
  indicators = symbol_data.get('advanced_indicators', {})
443
  if '1h' in indicators:
444
  rsi_value = indicators['1h'].get('rsi', 50)
445
  bb_lower = indicators['1h'].get('bb_lower')
446
+ if bb_lower and current_price <= bb_lower * 1.02 and rsi_value < 35: return 0.7
 
 
447
  return 0.3
 
448
  elif strategy_name == 'breakout_momentum':
449
  volume_ratio = symbol_data.get('advanced_indicators', {}).get('1h', {}).get('volume_ratio', 0)
450
+ if volume_ratio > 1.5: return 0.6
 
451
  return 0.4
 
452
  elif strategy_name == 'whale_tracking':
453
  whale_data = symbol_data.get('whale_data', {})
454
+ if not whale_data.get('data_available', False): return 0.2
 
 
455
  total_transactions = whale_data.get('transfer_count', 0)
456
+ if total_transactions >= 3: return 0.5
 
457
  return 0.3
 
458
  return base_score
 
459
  except Exception as error:
460
  print(f"⚠️ Fallback strategy failed for {strategy_name}: {error}")
461
  return 0.3
 
470
  self.pattern_tracker = PatternPerformanceTracker()
471
 
472
  def _validate_rsi_safety(self, indicators):
 
473
  rsi_warnings = []
474
  critical_issues = 0
 
475
  timeframes_to_check = ['5m', '15m', '1h', '4h']
476
  for timeframe in timeframes_to_check:
477
  if timeframe in indicators:
 
480
  if rsi_value > 80:
481
  rsi_warnings.append(f"🚨 RSI CRITICAL in {timeframe}: {rsi_value} - EXTREME OVERBOUGHT")
482
  critical_issues += 1
483
+ elif rsi_value > 75: rsi_warnings.append(f"⚠️ RSI WARNING in {timeframe}: {rsi_value} - STRONG OVERBOUGHT")
484
+ elif rsi_value > 70: rsi_warnings.append(f"📈 RSI HIGH in {timeframe}: {rsi_value} - OVERBOUGHT")
 
 
 
 
485
  is_safe = critical_issues < 2
486
  return is_safe, rsi_warnings
487
 
488
  def _validate_indicators_quality_enhanced(self, indicators, current_price):
 
489
  quality_issues = []
 
 
490
  rsi_safe, rsi_warnings = self._validate_rsi_safety(indicators)
491
+ if not rsi_safe: quality_issues.extend(rsi_warnings)
492
+ bullish_signals = bearish_signals = 0
 
 
 
 
 
493
  for timeframe, data in indicators.items():
494
+ if data.get('macd_hist', 0) > 0: bullish_signals += 1
495
+ if data.get('rsi', 50) > 70: bearish_signals += 1
 
 
 
496
  if 'ema_9' in data and 'ema_21' in data:
497
+ if data['ema_9'] > data['ema_21']: bullish_signals += 1
498
+ if bullish_signals > 0 and bearish_signals > bullish_signals: quality_issues.append("⚠️ Conflicting signals: More bearish than bullish indicators")
 
 
 
 
499
  return quality_issues
500
 
501
  def _calculate_enhanced_score_with_safety(self, base_analysis, strategy_scores, quality_issues):
 
502
  base_score = base_analysis.get('final_score', 0.5)
503
  strategy_average = sum(strategy_scores.values()) / len(strategy_scores) if strategy_scores else 0.5
 
 
504
  safety_penalty = 0.0
505
  for issue in quality_issues:
506
+ if '🚨 RSI CRITICAL' in issue: safety_penalty += 0.3
507
+ elif '⚠️ RSI WARNING' in issue: safety_penalty += 0.15
508
+ elif '📈 RSI HIGH' in issue: safety_penalty += 0.05
 
 
 
 
509
  enhanced_score = (base_score * 0.4) + (strategy_average * 0.6)
510
  enhanced_score = max(0.0, enhanced_score - safety_penalty)
 
511
  return min(enhanced_score, 1.0)
512
 
513
  async def process_and_score_symbol_enhanced(self, raw_data):
 
514
  try:
515
+ if not raw_data or not raw_data.get('ohlcv'): return None
 
 
 
 
516
  raw_data['raw_ohlcv'] = raw_data.get('ohlcv', {})
 
517
  base_analysis = await self.process_and_score_symbol(raw_data)
518
+ if not base_analysis: return None
 
 
519
  try:
 
520
  current_price = base_analysis.get('current_price', 0)
521
+ quality_issues = self._validate_indicators_quality_enhanced(base_analysis.get('advanced_indicators', {}), current_price)
 
 
 
 
 
522
  if quality_issues:
523
  print(f"🔍 Quality issues for {base_analysis.get('symbol')}:")
524
+ for issue in quality_issues: print(f" {issue}")
 
 
 
525
  if hasattr(self, 'strategy_engine') and self.strategy_engine:
526
  strategy_scores, base_scores = await self.strategy_engine.evaluate_all_strategies(base_analysis, self.market_context)
527
  base_analysis['strategy_scores'] = strategy_scores
528
+ base_analysis['base_strategy_scores'] = base_scores
 
 
529
  if base_scores:
530
  best_strategy = max(base_scores.items(), key=lambda x: x[1])
531
  best_strategy_name = best_strategy[0]
532
  best_strategy_score = best_strategy[1]
 
533
  base_analysis['recommended_strategy'] = best_strategy_name
534
  base_analysis['strategy_confidence'] = best_strategy_score
535
+ if best_strategy_score > 0.3: base_analysis['target_strategy'] = best_strategy_name
536
+ else: base_analysis['target_strategy'] = 'GENERIC'
 
 
 
 
 
 
 
 
537
  else:
538
  base_analysis['recommended_strategy'] = 'GENERIC'
539
+ base_analysis['strategy_confidence'] = 0.3
540
  base_analysis['target_strategy'] = 'GENERIC'
541
+ enhanced_score = self._calculate_enhanced_score_with_safety(base_analysis, strategy_scores, quality_issues)
 
 
 
 
 
 
542
  base_analysis['enhanced_final_score'] = enhanced_score
543
  else:
 
544
  base_analysis['strategy_scores'] = {}
545
  base_analysis['enhanced_final_score'] = base_analysis.get('final_score', 0.5)
546
  base_analysis['recommended_strategy'] = 'GENERIC'
547
  base_analysis['strategy_confidence'] = 0.3
548
  base_analysis['target_strategy'] = 'GENERIC'
 
549
  base_analysis['quality_warnings'] = quality_issues
 
550
  except Exception as strategy_error:
551
  print(f"⚠️ Strategy evaluation failed for {base_analysis.get('symbol')}: {strategy_error}")
552
  base_analysis['strategy_scores'] = {}
553
  base_analysis['enhanced_final_score'] = base_analysis.get('final_score', 0.5)
554
  base_analysis['recommended_strategy'] = 'GENERIC'
555
+ base_analysis['strategy_confidence'] = 0.3
556
  base_analysis['target_strategy'] = 'GENERIC'
557
  base_analysis['quality_warnings'] = ['Strategy evaluation failed']
 
558
  return base_analysis
 
559
  except Exception as error:
560
  print(f"❌ Enhanced processing failed for {raw_data.get('symbol')}: {error}")
561
  return await self.process_and_score_symbol(raw_data)
562
 
563
  def _improve_fibonacci_levels(self, daily_dataframe, current_price):
564
+ if len(daily_dataframe) < 50: return {}
 
 
 
 
565
  recent_high = float(daily_dataframe['high'].iloc[-50:].max())
566
  recent_low = float(daily_dataframe['low'].iloc[-50:].min())
567
+ if current_price > recent_high: recent_high = current_price * 1.05
568
+ if current_price < recent_low: recent_low = current_price * 0.95
 
 
 
 
 
569
  difference = recent_high - recent_low
570
+ if difference <= 0: return {}
 
 
571
  return {
572
+ "0.0%": recent_high, "23.6%": recent_high - 0.236 * difference,
573
+ "38.2%": recent_high - 0.382 * difference, "50.0%": recent_high - 0.50 * difference,
574
+ "61.8%": recent_high - 0.618 * difference, "78.6%": recent_high - 0.786 * difference,
 
 
 
575
  "100.0%": recent_low
576
  }
577
 
578
  async def process_and_score_symbol(self, raw_data):
 
579
  symbol = raw_data['symbol']
580
  ohlcv_data = raw_data['ohlcv']
581
  reasons_for_candidacy = raw_data.get('reasons', [])
582
+ if not ohlcv_data: return None
 
 
 
 
583
  try:
584
  all_indicators = {}
585
  for timeframe, candles in ohlcv_data.items():
 
587
  dataframe = pd.DataFrame(candles, columns=['time', 'open', 'high', 'low', 'close', 'volume'])
588
  dataframe[['open', 'high', 'low', 'close', 'volume']] = dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float)
589
  all_indicators[timeframe] = self._calculate_indicators(dataframe, timeframe)
 
590
  hourly_dataframe = pd.DataFrame(ohlcv_data.get('1h', []), columns=['time', 'open', 'high', 'low', 'close', 'volume'])
591
+ if hourly_dataframe.empty: return None
 
 
 
592
  hourly_dataframe[['open', 'high', 'low', 'close', 'volume']] = hourly_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float)
 
593
  try:
594
  current_price = float(hourly_dataframe['close'].iloc[-1])
595
  if ohlcv_data.get('5m'):
 
597
  if not five_minute_dataframe.empty:
598
  five_minute_dataframe[['open', 'high', 'low', 'close', 'volume']] = five_minute_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float)
599
  current_price = float(five_minute_dataframe['close'].iloc[-1])
 
600
  liquidity_score = self._calculate_liquidity_score(hourly_dataframe)
601
  daily_dataframe = pd.DataFrame(ohlcv_data.get('1d', []), columns=['time', 'open', 'high', 'low', 'close', 'volume'])
602
+ if not daily_dataframe.empty: daily_dataframe[['open', 'high', 'low', 'close', 'volume']] = daily_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float)
 
 
603
  average_daily_volume = float(daily_dataframe['volume'].mean()) if not daily_dataframe.empty else 0.0
 
 
604
  fibonacci_levels = self._improve_fibonacci_levels(daily_dataframe, current_price)
605
+ try: whale_data = await self.data_manager.get_whale_data_safe_async(symbol)
 
 
606
  except Exception as whale_error:
607
+ print(f"⚠️ Whale data failed for {symbol}: {whale_error}.")
608
+ whale_data = {"transfer_count": 0, "total_volume": 0, "source": "no_data", "data_available": False}
 
 
 
 
 
 
609
  whale_score = self._calculate_whale_activity_score(whale_data)
610
  opportunity_classification = self.classify_opportunity_type(all_indicators, current_price)
611
  initial_score = self._calculate_initial_score(all_indicators, current_price, self.market_context)
612
  monte_carlo_probability = self._run_monte_carlo_simulation(hourly_dataframe)
 
 
 
613
  final_score = (0.35 * initial_score) + (0.50 * monte_carlo_probability) + (0.15 * whale_score)
614
  final_score *= opportunity_classification['confidence']
 
615
  normalized_indicators = {timeframe: self._normalize_features_corrected(indicators) for timeframe, indicators in all_indicators.items()}
 
616
  return {
617
  'symbol': symbol, 'reasons_for_candidacy': reasons_for_candidacy, 'current_price': float(current_price),
618
  'liquidity_score': float(liquidity_score) if not np.isnan(liquidity_score) else 0.0, 'avg_daily_volume': float(average_daily_volume),
 
621
  'initial_score': float(initial_score), 'monte_carlo_probability': float(monte_carlo_probability),
622
  'indicators': normalized_indicators, 'advanced_indicators': all_indicators, 'strategy_scores': {},
623
  'recommended_strategy': 'GENERIC', 'enhanced_final_score': float(final_score), 'target_strategy': 'GENERIC',
624
+ 'raw_ohlcv': ohlcv_data
625
  }
626
+ except (KeyError, IndexError) as error: return None
 
 
 
 
627
  except Exception as error:
628
  print(f"❌ Failed to process {symbol}: {error}")
 
 
629
  return None
630
 
631
  def _calculate_indicators(self, dataframe, timeframe):
 
632
  indicators = {}
633
+ if dataframe.empty: return indicators
 
 
634
  if not isinstance(dataframe.index, pd.DatetimeIndex):
635
  try:
636
  dataframe['time'] = pd.to_datetime(dataframe['time'], unit='ms')
 
638
  except:
639
  dataframe['time'] = pd.to_datetime(dataframe['time'])
640
  dataframe = dataframe.set_index('time', drop=True)
 
641
  dataframe = dataframe.sort_index()
 
642
  if len(dataframe) >= 1 and all(column in dataframe.columns for column in ['high', 'low', 'close', 'volume']):
643
  try:
644
  typical_price = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3
645
  volume_weighted_average_price = (typical_price * dataframe['volume']).cumsum() / dataframe['volume'].cumsum()
646
+ if not volume_weighted_average_price.empty and not pd.isna(volume_weighted_average_price.iloc[-1]): indicators['vwap'] = float(volume_weighted_average_price.iloc[-1])
647
+ except Exception as error: pass
 
 
 
648
  if len(dataframe) >= 14:
649
  rsi_series = ta.rsi(dataframe['close'], length=14)
650
+ if rsi_series is not None and not rsi_series.empty and rsi_series.iloc[-1] is not np.nan: indicators['rsi'] = float(rsi_series.iloc[-1])
 
 
651
  if len(dataframe) >= 26:
652
  macd = ta.macd(dataframe['close'])
653
  if macd is not None and not macd.empty:
654
+ if 'MACDh_12_26_9' in macd.columns and macd['MACDh_12_26_9'].iloc[-1] is not np.nan: indicators['macd_hist'] = float(macd['MACDh_12_26_9'].iloc[-1])
655
+ if 'MACD_12_26_9' in macd.columns and macd['MACD_12_26_9'].iloc[-1] is not np.nan: indicators['macd_line'] = float(macd['MACD_12_26_9'].iloc[-1])
656
+ if 'MACDs_12_26_9' in macd.columns and macd['MACDs_12_26_9'].iloc[-1] is not np.nan: indicators['macd_signal'] = float(macd['MACDs_12_26_9'].iloc[-1])
 
 
 
 
657
  if len(dataframe) >= 20:
658
  bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2)
659
  if bollinger_bands is not None and not bollinger_bands.empty:
660
+ if 'BBL_20_2.0' in bollinger_bands.columns and bollinger_bands['BBL_20_2.0'].iloc[-1] is not np.nan: indicators['bb_lower'] = float(bollinger_bands['BBL_20_2.0'].iloc[-1])
661
+ if 'BBU_20_2.0' in bollinger_bands.columns and bollinger_bands['BBU_20_2.0'].iloc[-1] is not np.nan: indicators['bb_upper'] = float(bollinger_bands['BBU_20_2.0'].iloc[-1])
662
+ if 'BBM_20_2.0' in bollinger_bands.columns and bollinger_bands['BBM_20_2.0'].iloc[-1] is not np.nan: indicators['bb_middle'] = float(bollinger_bands['BBM_20_2.0'].iloc[-1])
 
 
 
 
663
  if len(dataframe) >= 14:
664
  average_true_range = ta.atr(high=dataframe['high'], low=dataframe['low'], close=dataframe['close'], length=14)
665
+ if average_true_range is not None and not average_true_range.empty and average_true_range.iloc[-1] is not np.nan: indicators['atr'] = float(average_true_range.iloc[-1])
 
 
666
  if len(dataframe) >= 26:
667
  ema_12 = ta.ema(dataframe['close'], length=12)
668
  ema_26 = ta.ema(dataframe['close'], length=26)
669
+ if ema_12 is not None and not ema_12.empty and ema_12.iloc[-1] is not np.nan: indicators['ema_12'] = float(ema_12.iloc[-1])
670
+ if ema_26 is not None and not ema_26.empty and ema_26.iloc[-1] is not np.nan: indicators['ema_26'] = float(ema_26.iloc[-1])
 
 
 
671
  return indicators
672
 
673
  def _normalize_features_corrected(self, features):
 
674
  normalized_features = {}
675
  for key, value in features.items():
676
+ if value is None: normalized_features[key] = 0.0; continue
677
+ if key == 'rsi': normalized_features[key] = max(0, min(100, value))
678
+ elif key in ['macd_hist', 'macd_line', 'macd_signal', 'vwap', 'atr']: normalized_features[key] = value
679
+ elif 'ema' in key or 'bb_' in key: normalized_features[key] = value
 
 
 
 
 
680
  else:
681
  try:
682
+ if abs(value) > 1000: normalized_features[key] = value / 1000
683
+ else: normalized_features[key] = value
684
+ except: normalized_features[key] = value
 
 
 
685
  return normalized_features
686
 
687
  def _run_monte_carlo_simulation(self, dataframe, number_of_simulations=1000, number_of_steps=20):
688
+ if dataframe.empty or len(dataframe) < 2: return 0.0
 
 
689
  log_returns = np.log(dataframe['close'] / dataframe['close'].shift(1)).dropna()
690
+ if log_returns.empty: return 0.0
 
691
  mean_return = log_returns.mean()
692
  volatility = log_returns.std()
693
  initial_price = dataframe['close'].iloc[-1]
 
696
  random_values = np.random.normal(0, 1, number_of_steps)
697
  daily_returns = np.exp(mean_return - 0.5 * volatility**2 + volatility * random_values)
698
  simulated_prices = initial_price * daily_returns.cumprod()
699
+ if (simulated_prices[-1] / initial_price) > 1.02: success_count += 1
 
700
  return success_count / number_of_simulations
701
 
702
  def _calculate_initial_score(self, indicators, current_price, market_context):
 
703
  score = 0.5
704
  fast_timeframes = ['5m', '15m']
705
  for timeframe in fast_timeframes:
706
  timeframe_indicators = indicators.get(timeframe, {})
707
+ if not timeframe_indicators: continue
 
708
  if 'rsi' in timeframe_indicators:
709
  rsi_value = timeframe_indicators['rsi']
710
  if isinstance(rsi_value, (int, float)):
711
+ if rsi_value < 30: score += 0.2
712
+ elif rsi_value < 40: score += 0.1
713
+ elif rsi_value > 70: score -= 0.1
714
+ if 'macd_hist' in timeframe_indicators and timeframe_indicators['macd_hist'] > 0: score += 0.15
 
 
 
 
715
  if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']):
716
+ if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']: score += 0.15
 
717
  slow_timeframes = ['1h', '4h', '1d']
718
  for timeframe in slow_timeframes:
719
  timeframe_indicators = indicators.get(timeframe, {})
720
+ if not timeframe_indicators: continue
 
721
  if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']):
722
+ if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']: score += 0.10
 
723
  if all(key in timeframe_indicators for key in ['bb_upper', 'bb_lower']):
724
+ if current_price > timeframe_indicators['bb_upper']: score += 0.10
725
+ elif current_price <= timeframe_indicators['bb_lower']: score += 0.05
726
+ if '5m' in indicators and 'vwap' in indicators['5m'] and current_price > indicators['5m']['vwap']: score += 0.10
 
 
 
727
  if market_context:
728
  bitcoin_sentiment = market_context.get('btc_sentiment')
729
  fear_greed_index = market_context.get('fear_and_greed_index', 50)
730
+ if bitcoin_sentiment == 'BULLISH' and fear_greed_index > 60: score *= 1.2
731
+ elif bitcoin_sentiment == 'BEARISH' or fear_greed_index < 30: score *= 0.8
 
 
732
  return min(max(score, 0.0), 1.0)
733
 
734
+ def _normalize_features(self, features): return self._normalize_features_corrected(features)
 
735
 
736
  def _prepare_data_for_ml(self, all_indicators, current_price):
737
  feature_vector = []
 
739
  indicator_keys = ['rsi', 'macd_hist', 'macd_line', 'bb_upper', 'bb_lower', 'atr', 'ema_12', 'ema_26', 'vwap']
740
  for timeframe in timeframes:
741
  timeframe_indicators = all_indicators.get(timeframe, {})
742
+ for key in indicator_keys: feature_vector.append(timeframe_indicators.get(key, 0.0))
 
743
  feature_vector.append(current_price)
744
  return feature_vector
745
 
746
  def _calculate_liquidity_score(self, hourly_dataframe):
747
+ if hourly_dataframe.empty: return 0.0
 
748
  hourly_dataframe['dollar_volume'] = hourly_dataframe['volume'] * hourly_dataframe['close']
749
  return float(hourly_dataframe['dollar_volume'].mean())
750
 
751
+ def _calculate_fibonacci_levels(self, daily_dataframe): return self._improve_fibonacci_levels(daily_dataframe, 0)
 
 
752
 
753
  def classify_opportunity_type(self, indicators, current_price):
754
+ fast_signals = slow_signals = 0
 
755
  for timeframe in ['5m', '15m']:
756
  timeframe_indicators = indicators.get(timeframe, {})
757
+ if not timeframe_indicators: continue
758
+ if timeframe_indicators.get('rsi', 100) < 35: fast_signals += 1
759
+ if timeframe_indicators.get('macd_hist', 0) > 0: fast_signals += 1
 
 
 
760
  if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']):
761
+ if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']: fast_signals += 1
762
+ if timeframe == '5m' and timeframe_indicators.get('vwap') and current_price > timeframe_indicators['vwap'] * 1.02: fast_signals += 1
 
 
763
  for timeframe in ['1h', '4h', '1d']:
764
  timeframe_indicators = indicators.get(timeframe, {})
765
+ if not timeframe_indicators: continue
766
+ if 40 <= timeframe_indicators.get('rsi', 50) <= 60: slow_signals += 1
 
 
767
  if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']):
768
+ if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']: slow_signals += 1
769
+ if timeframe_indicators.get('bb_middle') and current_price > timeframe_indicators['bb_middle']: slow_signals += 1
 
 
770
  if fast_signals >= 3:
771
  return {
772
  "type": "FAST_PUMP", "timeframe": "15m-1h", "take_profit_multiplier": 1.08, "stop_loss_multiplier": 0.97,
773
+ "confidence": min(fast_signals / 6.0, 1.0), "description": "Strong fast pump opportunity on short timeframes"
774
  }
775
  elif slow_signals >= 3:
776
  return {
777
  "type": "SLOW_GROWTH", "timeframe": "4h-1d", "take_profit_multiplier": 1.05, "stop_loss_multiplier": 0.95,
778
+ "confidence": min(slow_signals / 6.0, 1.0), "description": "Sustainable growth opportunity on long timeframes"
779
  }
780
  return {
781
  "type": "NEUTRAL", "timeframe": "N/A", "take_profit_multiplier": 1.05, "stop_loss_multiplier": 0.95,
782
+ "confidence": 0.3, "description": "No clear signals for specific opportunity type"
783
  }
784
 
785
  def _calculate_whale_activity_score(self, whale_data):
786
+ if not whale_data.get('data_available', False): return 0.0
 
 
 
787
  total_transactions = whale_data.get('transfer_count', 0)
788
  total_volume = whale_data.get('total_volume', 0)
 
789
  score = 0.0
790
+ if total_transactions >= 10: score += 0.3
791
+ elif total_transactions >= 5: score += 0.15
792
+ if total_volume > 500000: score += 0.2
793
+ elif total_volume > 100000: score += 0.1
 
 
 
 
 
 
794
  return min(score, 0.5)
795
 
796
  def filter_top_candidates(self, candidates, number_of_candidates=10):
 
797
  valid_candidates = [candidate for candidate in candidates if candidate is not None]
798
  return sorted(valid_candidates, key=lambda candidate: candidate.get('enhanced_final_score', candidate.get('final_score', 0)), reverse=True)[:number_of_candidates]
799
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
800
  print("✅ Enhanced ML System Loaded - Integrated with Learning Engine - REAL DATA ONLY - Optimized Strategy Scoring with Pattern Enhancement")