Spaces:
Running
Running
| # ML.py - الإصدار المحدث مع إصلاح الأخطاء الحرجة | |
| import pandas as pd | |
| import pandas_ta as ta | |
| import numpy as np | |
| from datetime import datetime | |
| import asyncio | |
| from data_manager import DataManager | |
| class AdvancedTechnicalAnalyzer: | |
| def __init__(self): | |
| self.indicators_config = { | |
| 'trend': ['ema_9', 'ema_21', 'ema_50', 'ema_200', 'ichimoku', 'adx', 'parabolic_sar', 'dmi'], | |
| 'momentum': ['rsi', 'stoch_rsi', 'macd', 'williams_r', 'cci', 'awesome_oscillator', 'momentum'], | |
| 'volatility': ['bbands', 'atr', 'keltner', 'donchian', 'rvi'], | |
| 'volume': ['vwap', 'obv', 'mfi', 'volume_profile', 'ad', 'volume_oscillator'], | |
| 'cycle': ['hull_ma', 'supertrend', 'zigzag', 'fisher_transform'] | |
| } | |
| def calculate_all_indicators(self, dataframe, timeframe): | |
| if dataframe.empty: | |
| return {} | |
| indicators = {} | |
| indicators.update(self._calculate_trend_indicators(dataframe)) | |
| indicators.update(self._calculate_momentum_indicators(dataframe)) | |
| indicators.update(self._calculate_volatility_indicators(dataframe)) | |
| indicators.update(self._calculate_volume_indicators(dataframe)) | |
| indicators.update(self._calculate_cycle_indicators(dataframe)) | |
| return indicators | |
| def _calculate_trend_indicators(self, dataframe): | |
| trend = {} | |
| trend['ema_9'] = float(ta.ema(dataframe['close'], length=9).iloc[-1]) if len(dataframe) >= 9 else None | |
| trend['ema_21'] = float(ta.ema(dataframe['close'], length=21).iloc[-1]) if len(dataframe) >= 21 else None | |
| trend['ema_50'] = float(ta.ema(dataframe['close'], length=50).iloc[-1]) if len(dataframe) >= 50 else None | |
| trend['ema_200'] = float(ta.ema(dataframe['close'], length=200).iloc[-1]) if len(dataframe) >= 200 else None | |
| if len(dataframe) >= 26: | |
| ichimoku = ta.ichimoku(dataframe['high'], dataframe['low'], dataframe['close']) | |
| if ichimoku is not None: | |
| trend['ichimoku_conversion'] = float(ichimoku[0]['ITS_9'].iloc[-1]) if not ichimoku[0]['ITS_9'].empty else None | |
| trend['ichimoku_base'] = float(ichimoku[0]['IKS_26'].iloc[-1]) if not ichimoku[0]['IKS_26'].empty else None | |
| trend['ichimoku_span_a'] = float(ichimoku[0]['ISA_9'].iloc[-1]) if not ichimoku[0]['ISA_9'].empty else None | |
| trend['ichimoku_span_b'] = float(ichimoku[0]['ISB_26'].iloc[-1]) if not ichimoku[0]['ISB_26'].empty else None | |
| if len(dataframe) >= 14: | |
| adx_result = ta.adx(dataframe['high'], dataframe['low'], dataframe['close'], length=14) | |
| if adx_result is not None: | |
| trend['adx'] = float(adx_result['ADX_14'].iloc[-1]) if not adx_result['ADX_14'].empty else None | |
| trend['dmi_plus'] = float(adx_result['DMP_14'].iloc[-1]) if not adx_result['DMP_14'].empty else None | |
| trend['dmi_minus'] = float(adx_result['DMN_14'].iloc[-1]) if not adx_result['DMN_14'].empty else None | |
| if len(dataframe) >= 5: | |
| psar = ta.psar(dataframe['high'], dataframe['low'], dataframe['close']) | |
| if psar is not None: | |
| trend['psar'] = float(psar['PSARl_0.02_0.2'].iloc[-1]) if not psar['PSARl_0.02_0.2'].empty else None | |
| return {key: value for key, value in trend.items() if value is not None} | |
| def _calculate_momentum_indicators(self, dataframe): | |
| momentum = {} | |
| if len(dataframe) >= 14: | |
| rsi = ta.rsi(dataframe['close'], length=14) | |
| momentum['rsi'] = float(rsi.iloc[-1]) if not rsi.empty else None | |
| if len(dataframe) >= 14: | |
| stoch_rsi = ta.stochrsi(dataframe['close'], length=14) | |
| if stoch_rsi is not None: | |
| 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 | |
| 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 | |
| if len(dataframe) >= 26: | |
| macd = ta.macd(dataframe['close']) | |
| if macd is not None: | |
| momentum['macd_line'] = float(macd['MACD_12_26_9'].iloc[-1]) if not macd['MACD_12_26_9'].empty else None | |
| momentum['macd_signal'] = float(macd['MACDs_12_26_9'].iloc[-1]) if not macd['MACDs_12_26_9'].empty else None | |
| momentum['macd_hist'] = float(macd['MACDh_12_26_9'].iloc[-1]) if not macd['MACDh_12_26_9'].empty else None | |
| if len(dataframe) >= 14: | |
| williams = ta.willr(dataframe['high'], dataframe['low'], dataframe['close'], length=14) | |
| momentum['williams_r'] = float(williams.iloc[-1]) if not williams.empty else None | |
| if len(dataframe) >= 20: | |
| cci = ta.cci(dataframe['high'], dataframe['low'], dataframe['close'], length=20) | |
| momentum['cci'] = float(cci.iloc[-1]) if not cci.empty else None | |
| if len(dataframe) >= 34: | |
| awesome_oscillator = ta.ao(dataframe['high'], dataframe['low']) | |
| momentum['awesome_oscillator'] = float(awesome_oscillator.iloc[-1]) if not awesome_oscillator.empty else None | |
| if len(dataframe) >= 10: | |
| momentum_indicator = ta.mom(dataframe['close'], length=10) | |
| momentum['momentum'] = float(momentum_indicator.iloc[-1]) if not momentum_indicator.empty else None | |
| return {key: value for key, value in momentum.items() if value is not None} | |
| def _calculate_volatility_indicators(self, dataframe): | |
| volatility = {} | |
| if len(dataframe) >= 20: | |
| bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2) | |
| if bollinger_bands is not None: | |
| volatility['bb_upper'] = float(bollinger_bands['BBU_20_2.0'].iloc[-1]) if not bollinger_bands['BBU_20_2.0'].empty else None | |
| volatility['bb_middle'] = float(bollinger_bands['BBM_20_2.0'].iloc[-1]) if not bollinger_bands['BBM_20_2.0'].empty else None | |
| volatility['bb_lower'] = float(bollinger_bands['BBL_20_2.0'].iloc[-1]) if not bollinger_bands['BBL_20_2.0'].empty else None | |
| 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'] | |
| if len(dataframe) >= 14: | |
| average_true_range = ta.atr(dataframe['high'], dataframe['low'], dataframe['close'], length=14) | |
| volatility['atr'] = float(average_true_range.iloc[-1]) if not average_true_range.empty else None | |
| if volatility['atr']: | |
| volatility['atr_percent'] = volatility['atr'] / dataframe['close'].iloc[-1] | |
| if len(dataframe) >= 20: | |
| keltner_channel = ta.kc(dataframe['high'], dataframe['low'], dataframe['close'], length=20) | |
| if keltner_channel is not None: | |
| volatility['kc_upper'] = float(keltner_channel['KCUe_20_2'].iloc[-1]) if not keltner_channel['KCUe_20_2'].empty else None | |
| volatility['kc_lower'] = float(keltner_channel['KCLe_20_2'].iloc[-1]) if not keltner_channel['KCLe_20_2'].empty else None | |
| if len(dataframe) >= 20: | |
| donchian_channel = ta.donchian(dataframe['high'], dataframe['low'], length=20) | |
| if donchian_channel is not None: | |
| volatility['dc_upper'] = float(donchian_channel['DCU_20_20'].iloc[-1]) if not donchian_channel['DCU_20_20'].empty else None | |
| volatility['dc_lower'] = float(donchian_channel['DCL_20_20'].iloc[-1]) if not donchian_channel['DCL_20_20'].empty else None | |
| if len(dataframe) >= 14: | |
| relative_volatility_index = ta.rvi(dataframe['close'], length=14) | |
| volatility['rvi'] = float(relative_volatility_index.iloc[-1]) if not relative_volatility_index.empty else None | |
| return {key: value for key, value in volatility.items() if value is not None} | |
| def _calculate_volume_indicators(self, dataframe): | |
| volume = {} | |
| if len(dataframe) >= 1: | |
| volume_weighted_average_price = ta.vwap(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume']) | |
| volume['vwap'] = float(volume_weighted_average_price.iloc[-1]) if not volume_weighted_average_price.empty else None | |
| on_balance_volume = ta.obv(dataframe['close'], dataframe['volume']) | |
| volume['obv'] = float(on_balance_volume.iloc[-1]) if not on_balance_volume.empty else None | |
| if len(dataframe) >= 14: | |
| money_flow_index = ta.mfi(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'], length=14) | |
| volume['mfi'] = float(money_flow_index.iloc[-1]) if not money_flow_index.empty else None | |
| accumulation_distribution = ta.ad(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume']) | |
| volume['ad_line'] = float(accumulation_distribution.iloc[-1]) if not accumulation_distribution.empty else None | |
| if len(dataframe) >= 20: | |
| volume_oscillator = ta.pvo(dataframe['volume']) | |
| if volume_oscillator is not None: | |
| volume['volume_oscillator'] = float(volume_oscillator['PVO_12_26_9'].iloc[-1]) if not volume_oscillator['PVO_12_26_9'].empty else None | |
| volume['volume_avg_20'] = float(dataframe['volume'].tail(20).mean()) if len(dataframe) >= 20 else None | |
| if volume['volume_avg_20'] and volume['volume_avg_20'] > 0: | |
| volume['volume_ratio'] = float(dataframe['volume'].iloc[-1] / volume['volume_avg_20']) | |
| return {key: value for key, value in volume.items() if value is not None} | |
| def _calculate_cycle_indicators(self, dataframe): | |
| cycle = {} | |
| if len(dataframe) >= 9: | |
| hull_moving_average = ta.hma(dataframe['close'], length=9) | |
| cycle['hull_ma'] = float(hull_moving_average.iloc[-1]) if not hull_moving_average.empty else None | |
| if len(dataframe) >= 10: | |
| supertrend = ta.supertrend(dataframe['high'], dataframe['low'], dataframe['close'], length=10, multiplier=3) | |
| if supertrend is not None: | |
| cycle['supertrend'] = float(supertrend['SUPERT_10_3.0'].iloc[-1]) if not supertrend['SUPERT_10_3.0'].empty else None | |
| cycle['supertrend_direction'] = float(supertrend['SUPERTd_10_3.0'].iloc[-1]) if not supertrend['SUPERTd_10_3.0'].empty else None | |
| if len(dataframe) >= 10: | |
| fisher_transform = ta.fisher(dataframe['high'], dataframe['low'], length=10) | |
| if fisher_transform is not None: | |
| cycle['fisher_transform'] = float(fisher_transform['FISHERT_10_1'].iloc[-1]) if not fisher_transform['FISHERT_10_1'].empty else None | |
| return {key: value for key, value in cycle.items() if value is not None} | |
| class PatternEnhancedStrategyEngine: | |
| """محرك استراتيجيات محسن مع دعم متقدم للأنماط البيانية""" | |
| def __init__(self, data_manager, learning_engine): | |
| self.data_manager = data_manager | |
| self.learning_engine = learning_engine | |
| self.pattern_success_tracker = PatternPerformanceTracker() | |
| async def enhance_strategy_with_patterns(self, strategy_scores, pattern_analysis, symbol): | |
| """تعزيز درجات الاستراتيجية بناءً على تحليل الأنماط""" | |
| if not pattern_analysis or pattern_analysis.get('pattern_detected') in ['no_clear_pattern', 'insufficient_data']: | |
| return strategy_scores | |
| pattern_confidence = pattern_analysis.get('pattern_confidence', 0) | |
| pattern_name = pattern_analysis.get('pattern_detected', '') | |
| predicted_direction = pattern_analysis.get('predicted_direction', '') | |
| # فقط تعزيز إذا كانت الثقة في النمط عالية | |
| if pattern_confidence >= 0.7: | |
| enhancement_factor = self._calculate_pattern_enhancement(pattern_confidence, pattern_name) | |
| # تحديد الاستراتيجيات المناسبة للنمط | |
| enhanced_strategies = self._get_pattern_appropriate_strategies(pattern_name, predicted_direction) | |
| for strategy in enhanced_strategies: | |
| if strategy in strategy_scores: | |
| strategy_scores[strategy] *= enhancement_factor | |
| print(f"🎯 Enhanced {strategy} for {symbol} by {enhancement_factor:.1%} due to {pattern_name} pattern") | |
| return strategy_scores | |
| def _calculate_pattern_enhancement(self, pattern_confidence, pattern_name): | |
| """حساب عامل التعزيز بناءً على ثقة النمط ونوعه""" | |
| base_enhancement = 1.0 + (pattern_confidence * 0.5) # حتى 50% زيادة | |
| # أنماط عالية المصداقية تحصل على تعزيز إضافي | |
| high_reliability_patterns = ['Double Top', 'Double Bottom', 'Head & Shoulders', 'Cup and Handle'] | |
| if pattern_name in high_reliability_patterns: | |
| base_enhancement *= 1.2 | |
| return min(base_enhancement, 2.0) # حد أقصى 100% زيادة | |
| def _get_pattern_appropriate_strategies(self, pattern_name, direction): | |
| """الحصول على الاستراتيجيات المناسبة لنوع النمط""" | |
| reversal_patterns = ['Double Top', 'Double Bottom', 'Head & Shoulders', 'Triple Top', 'Triple Bottom'] | |
| continuation_patterns = ['Flags', 'Pennants', 'Triangles', 'Rectangles'] | |
| if pattern_name in reversal_patterns: | |
| if direction == 'down': | |
| return ['breakout_momentum', 'trend_following'] | |
| else: | |
| return ['mean_reversion', 'breakout_momentum'] | |
| elif pattern_name in continuation_patterns: | |
| return ['trend_following', 'breakout_momentum'] | |
| else: # أنماط أخرى | |
| return ['breakout_momentum', 'hybrid_ai'] | |
| class PatternPerformanceTracker: | |
| """متتبع أداء الأنماط البيانية""" | |
| def __init__(self): | |
| self.pattern_performance = {} | |
| self.pattern_success_rates = {} | |
| async def track_pattern_outcome(self, symbol, pattern_analysis, success, profit_percent): | |
| """تتبع نتيجة النمط البياني""" | |
| if not pattern_analysis: | |
| return | |
| pattern_name = pattern_analysis.get('pattern_detected') | |
| confidence = pattern_analysis.get('pattern_confidence', 0) | |
| if pattern_name not in ['no_clear_pattern', 'insufficient_data']: | |
| if pattern_name not in self.pattern_performance: | |
| self.pattern_performance[pattern_name] = { | |
| 'total_trades': 0, | |
| 'successful_trades': 0, | |
| 'total_profit': 0, | |
| 'total_confidence': 0 | |
| } | |
| stats = self.pattern_performance[pattern_name] | |
| stats['total_trades'] += 1 | |
| stats['total_confidence'] += confidence | |
| if success: | |
| stats['successful_trades'] += 1 | |
| stats['total_profit'] += profit_percent | |
| success_rate = stats['successful_trades'] / stats['total_trades'] | |
| avg_profit = stats['total_profit'] / stats['successful_trades'] if stats['successful_trades'] > 0 else 0 | |
| avg_confidence = stats['total_confidence'] / stats['total_trades'] | |
| print(f"📊 Pattern Performance: {pattern_name} - " | |
| f"Success: {success_rate:.1%} - Avg Profit: {avg_profit:.2f}% - " | |
| f"Avg Confidence: {avg_confidence:.1%}") | |
| def get_pattern_reliability(self, pattern_name): | |
| """الحصول على موثوقية النمط""" | |
| if pattern_name in self.pattern_performance: | |
| stats = self.pattern_performance[pattern_name] | |
| if stats['total_trades'] > 0: | |
| return stats['successful_trades'] / stats['total_trades'] | |
| return 0.5 # قيمة افتراضية | |
| class MultiStrategyEngine: | |
| def __init__(self, data_manager, learning_engine): | |
| self.data_manager = data_manager | |
| self.learning_engine = learning_engine | |
| self.pattern_enhancer = PatternEnhancedStrategyEngine(data_manager, learning_engine) | |
| self.strategies = { | |
| 'trend_following': self._trend_following_strategy, | |
| 'mean_reversion': self._mean_reversion_strategy, | |
| 'breakout_momentum': self._breakout_momentum_strategy, | |
| 'volume_spike': self._volume_spike_strategy, | |
| 'whale_tracking': self._whale_tracking_strategy, | |
| 'pattern_recognition': self._pattern_recognition_strategy, | |
| 'hybrid_ai': self._hybrid_ai_strategy | |
| } | |
| async def evaluate_all_strategies(self, symbol_data, market_context): | |
| """تقييم جميع الاستراتيجيات مع استخدام أوزان نظام التعلم - الإصدار المحسّن""" | |
| try: | |
| # ✅ الحصول على الأوزان المحسنة من نظام التعلم | |
| market_condition = market_context.get('market_trend', 'sideways_market') | |
| # ✅ التحقق من وجود learning_engine وتهيئته | |
| if self.learning_engine and hasattr(self.learning_engine, 'initialized') and self.learning_engine.initialized: | |
| try: | |
| optimized_weights = await self.learning_engine.get_optimized_strategy_weights(market_condition) | |
| print(f"🎯 الأوزان المستخدمة: {optimized_weights}") | |
| except Exception as e: | |
| print(f"⚠️ فشل الحصول على الأوزان المحسنة: {e}") | |
| optimized_weights = await self.get_default_weights() | |
| else: | |
| print("⚠️ نظام التعلم غير متوفر، استخدام الأوزان الافتراضية") | |
| optimized_weights = await self.get_default_weights() | |
| strategy_scores = {} | |
| base_scores = {} # ✅ تخزين الدرجات الأساسية | |
| # ✅ تقييم كل استراتيجية مع تطبيق الأوزان | |
| for strategy_name, strategy_function in self.strategies.items(): | |
| try: | |
| base_score = await strategy_function(symbol_data, market_context) | |
| base_scores[strategy_name] = base_score # ✅ حفظ الدرجة الأساسية | |
| # ✅ تطبيق الوزن المحسن | |
| weight = optimized_weights.get(strategy_name, 0.1) | |
| weighted_score = base_score * weight | |
| strategy_scores[strategy_name] = min(weighted_score, 1.0) | |
| print(f"📊 {strategy_name}: {base_score:.3f} × {weight:.3f} = {weighted_score:.3f}") | |
| except Exception as error: | |
| print(f"⚠️ Strategy {strategy_name} failed: {error}") | |
| base_score = await self._fallback_strategy_score(strategy_name, symbol_data, market_context) | |
| base_scores[strategy_name] = base_score | |
| strategy_scores[strategy_name] = base_score * optimized_weights.get(strategy_name, 0.1) | |
| # ✅ تعزيز الاستراتيجيات بناءً على تحليل الأنماط | |
| pattern_analysis = symbol_data.get('pattern_analysis') | |
| if pattern_analysis: | |
| strategy_scores = await self.pattern_enhancer.enhance_strategy_with_patterns( | |
| strategy_scores, pattern_analysis, symbol_data.get('symbol') | |
| ) | |
| # ✅ تحديد أفضل استراتيجية بناءً على الدرجات الأساسية (بدون أوزان) | |
| if base_scores: | |
| best_strategy = max(base_scores.items(), key=lambda x: x[1]) | |
| best_strategy_name = best_strategy[0] | |
| best_strategy_score = best_strategy[1] | |
| symbol_data['recommended_strategy'] = best_strategy_name | |
| symbol_data['strategy_confidence'] = best_strategy_score | |
| print(f"🏆 أفضل استراتيجية (أساسي): {best_strategy_name} بدرجة {best_strategy_score:.3f}") | |
| # ✅ تعزيز اختيار الاستراتيجية إذا كان هناك نمط عالي الثقة | |
| if (pattern_analysis and | |
| pattern_analysis.get('pattern_confidence', 0) > 0.7 and | |
| self._is_strategy_pattern_aligned(best_strategy_name, pattern_analysis)): | |
| pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.3 | |
| enhanced_confidence = min(best_strategy_score + pattern_bonus, 1.0) | |
| symbol_data['strategy_confidence'] = enhanced_confidence | |
| print(f"🎯 تعزيز ثقة الاستراتيجية بواسطة النمط: {enhanced_confidence:.3f}") | |
| return strategy_scores, base_scores # ✅ إرجاع كلا النوعين | |
| except Exception as error: | |
| print(f"❌ فشل تقييم الاستراتيجيات: {error}") | |
| fallback_scores = await self.get_fallback_scores() | |
| return fallback_scores, fallback_scores | |
| def _is_strategy_pattern_aligned(self, strategy_name, pattern_analysis): | |
| """التحقق من محاذاة الاستراتيجية مع النمط البياني""" | |
| pattern_direction = pattern_analysis.get('predicted_direction', '') | |
| pattern_type = pattern_analysis.get('pattern_detected', '') | |
| # استراتيجيات التوجه الصعودي | |
| bullish_strategies = ['trend_following', 'breakout_momentum'] | |
| # استراتيجيات التوجه الهبوطي | |
| bearish_strategies = ['mean_reversion', 'breakout_momentum'] | |
| if pattern_direction == 'up' and strategy_name in bullish_strategies: | |
| return True | |
| elif pattern_direction == 'down' and strategy_name in bearish_strategies: | |
| return True | |
| return False | |
| async def get_default_weights(self): | |
| """الأوزان الافتراضية عندما لا يتوفر نظام التعلم""" | |
| 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 | |
| } | |
| async def get_fallback_scores(self): | |
| """درجات احتياطية عند فشل التقييم""" | |
| 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 | |
| } | |
| async def _trend_following_strategy(self, symbol_data, market_context): | |
| """استراتيجية تتبع الاتجاه المحسنة - درجات أعلى""" | |
| try: | |
| score = 0.0 | |
| indicators = symbol_data.get('advanced_indicators', {}) | |
| timeframes = ['4h', '1h', '15m'] | |
| for timeframe in timeframes: | |
| if timeframe in indicators: | |
| timeframe_indicators = indicators[timeframe] | |
| # تحقق من محاذاة المتوسطات المتحركة | |
| if self._check_ema_alignment(timeframe_indicators): | |
| score += 0.20 # ⬆️ زيادة من 0.15 إلى 0.20 | |
| # مؤشر ADX للقوة الاتجاهية | |
| adx_value = timeframe_indicators.get('adx', 0) | |
| if adx_value > 20: # ⬇️ تخفيض من 25 إلى 20 | |
| score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15 | |
| # تحليل الحجم | |
| volume_ratio = timeframe_indicators.get('volume_ratio', 0) | |
| if volume_ratio > 1.2: # ⬇️ تخفيض من 1.5 إلى 1.2 | |
| score += 0.10 # ⬆️ زيادة من 0.05 إلى 0.10 | |
| # ✅ تعزيز بناءً على تحليل الأنماط | |
| pattern_analysis = symbol_data.get('pattern_analysis') | |
| if (pattern_analysis and | |
| pattern_analysis.get('pattern_confidence', 0) > 0.7 and | |
| pattern_analysis.get('predicted_direction') == 'up'): | |
| pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.2 | |
| score += pattern_bonus | |
| print(f"📈 Trend following enhanced by pattern: +{pattern_bonus:.3f}") | |
| return min(score, 1.0) | |
| except Exception as error: | |
| print(f"⚠️ Trend following strategy error: {error}") | |
| return 0.3 # ⬆️ زيادة من 0.3 إلى 0.3 (نفس القيمة) | |
| def _check_ema_alignment(self, indicators): | |
| """التحقق من محاذاة المتوسطات المتحركة""" | |
| required_emas = ['ema_9', 'ema_21', 'ema_50'] | |
| if all(ema in indicators for ema in required_emas): | |
| return (indicators['ema_9'] > indicators['ema_21'] > indicators['ema_50']) | |
| return False | |
| async def _mean_reversion_strategy(self, symbol_data, market_context): | |
| """استراتيجية العودة إلى المتوسط المحسنة - درجات أعلى""" | |
| try: | |
| score = 0.0 | |
| current_price = symbol_data['current_price'] | |
| indicators = symbol_data.get('advanced_indicators', {}) | |
| if '1h' in indicators: | |
| hourly_indicators = indicators['1h'] | |
| # تحليل Bollinger Bands | |
| if all(key in hourly_indicators for key in ['bb_upper', 'bb_lower', 'bb_middle']): | |
| position_in_band = (current_price - hourly_indicators['bb_lower']) / (hourly_indicators['bb_upper'] - hourly_indicators['bb_lower']) | |
| if position_in_band < 0.1 and hourly_indicators.get('rsi', 50) < 35: | |
| score += 0.45 # ⬆️ زيادة من 0.4 إلى 0.45 | |
| if position_in_band > 0.9 and hourly_indicators.get('rsi', 50) > 65: | |
| score += 0.45 # ⬆️ زيادة من 0.4 إلى 0.45 | |
| # تحليل RSI | |
| rsi_value = hourly_indicators.get('rsi', 50) | |
| if rsi_value < 30: | |
| score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35 | |
| elif rsi_value > 70: | |
| score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35 | |
| # ✅ تعزيز بناءً على تحليل الأنماط | |
| pattern_analysis = symbol_data.get('pattern_analysis') | |
| if (pattern_analysis and | |
| pattern_analysis.get('pattern_confidence', 0) > 0.7 and | |
| pattern_analysis.get('predicted_direction') in ['up', 'down']): | |
| pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.15 | |
| score += pattern_bonus | |
| print(f"🔄 Mean reversion enhanced by pattern: +{pattern_bonus:.3f}") | |
| return min(score, 1.0) | |
| except Exception as error: | |
| print(f"⚠️ Mean reversion strategy error: {error}") | |
| return 0.3 | |
| async def _breakout_momentum_strategy(self, symbol_data, market_context): | |
| """استراتيجية كسر الزخم المحسنة - درجات أعلى""" | |
| try: | |
| score = 0.0 | |
| indicators = symbol_data.get('advanced_indicators', {}) | |
| for timeframe in ['1h', '15m', '5m']: # ✅ إضافة timeframe إضافية | |
| if timeframe in indicators: | |
| timeframe_indicators = indicators[timeframe] | |
| # ✅ تحليل الحجم - عتبات مخفضة | |
| volume_ratio = timeframe_indicators.get('volume_ratio', 0) | |
| if volume_ratio > 1.8: # ⬇️ تخفيض من 2.0 إلى 1.8 | |
| score += 0.25 # ⬆️ زيادة من 0.2 إلى 0.25 | |
| elif volume_ratio > 1.3: # ✅ إضافة شرط وسيط | |
| score += 0.15 | |
| # ✅ تحليل MACD | |
| if timeframe_indicators.get('macd_hist', 0) > 0: | |
| score += 0.20 # ⬆️ زيادة من 0.15 إلى 0.20 | |
| # ✅ تحليل VWAP | |
| if 'vwap' in timeframe_indicators and symbol_data['current_price'] > timeframe_indicators['vwap']: | |
| score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15 | |
| # ✅ إضافة شرط RSI إضافي | |
| rsi_value = timeframe_indicators.get('rsi', 50) | |
| if 40 <= rsi_value <= 70: # نطاق RSI صحي | |
| score += 0.10 | |
| # ✅ تعزيز بناءً على تحليل الأنماط - تأثير كبير على breakout | |
| pattern_analysis = symbol_data.get('pattern_analysis') | |
| if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.6: | |
| pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.3 | |
| score += pattern_bonus | |
| print(f"🚀 Breakout momentum significantly enhanced by pattern: +{pattern_bonus:.3f}") | |
| # ✅ ضمان حد أدنى للدرجة إذا كانت هناك إشارات إيجابية | |
| if score > 0.2: | |
| score = max(score, 0.4) # ⬆️ ضمان حد أدنى 0.4 إذا كانت هناك إشارات | |
| return min(score, 1.0) | |
| except Exception as error: | |
| print(f"⚠️ Breakout momentum strategy error: {error}") | |
| return 0.4 # ⬆️ زيادة من 0.3 إلى 0.4 | |
| async def _volume_spike_strategy(self, symbol_data, market_context): | |
| """استراتيجية ارتفاع الحجم المحسنة - درجات أعلى""" | |
| try: | |
| score = 0.0 | |
| indicators = symbol_data.get('advanced_indicators', {}) | |
| for timeframe in ['1h', '15m', '5m']: | |
| if timeframe in indicators: | |
| volume_ratio = indicators[timeframe].get('volume_ratio', 0) | |
| if volume_ratio > 3.0: | |
| score += 0.45 # ⬆️ زيادة من 0.4 إلى 0.45 | |
| elif volume_ratio > 2.0: | |
| score += 0.25 # ⬆️ زيادة من 0.2 إلى 0.25 | |
| elif volume_ratio > 1.5: # ✅ إضافة شرط وسيط | |
| score += 0.15 | |
| # ✅ تعزيز بناءً على تحليل الأنماط مع ارتفاع الحجم | |
| pattern_analysis = symbol_data.get('pattern_analysis') | |
| 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)): | |
| pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.2 | |
| score += pattern_bonus | |
| print(f"💧 Volume spike enhanced by pattern: +{pattern_bonus:.3f}") | |
| return min(score, 1.0) | |
| except Exception as error: | |
| print(f"⚠️ Volume spike strategy error: {error}") | |
| return 0.3 | |
| async def _whale_tracking_strategy(self, symbol_data, market_context): | |
| """استراتيجية تتبع الحيتان المحسنة - درجات أعلى""" | |
| try: | |
| score = 0.0 | |
| # ✅ الإصلاح: استخدام الدالة الآمنة الجديدة | |
| whale_data = await self.data_manager.get_whale_data_safe_async(symbol_data['symbol']) | |
| # استخدام البيانات الحقيقية فقط | |
| if not whale_data.get('data_available', False): | |
| return 0.2 # ⬆️ زيادة من 0.1 إلى 0.2 (قيمة أساسية أعلى) | |
| total_transactions = whale_data.get('transfer_count', 0) | |
| whale_volume = whale_data.get('total_volume', 0) | |
| # ✅ معايير مرنة للسماح بمزيد من المرشحين | |
| if total_transactions >= 2: # ⬇️ تخفيض من 3 إلى 2 | |
| score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35 | |
| elif total_transactions >= 1: # ⬇️ تخفيض من 5 إلى 1 | |
| score += 0.25 # ⬆️ زيادة من 0.15 إلى 0.25 | |
| if whale_volume > 25000: # ⬇️ تخفيض من 50000 إلى 25000 | |
| score += 0.25 # ⬆️ زيادة من 0.2 إلى 0.25 | |
| elif whale_volume > 5000: # ⬇️ تخفيض من 10000 إلى 5000 | |
| score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15 | |
| # ✅ إضافة نقاط إضافية بناءً على نشاط الحيتان العام | |
| general_whale = market_context.get('general_whale_activity', {}) | |
| if general_whale.get('data_available', False) and general_whale.get('transaction_count', 0) > 0: | |
| score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15 | |
| return min(score, 1.0) | |
| except Exception as error: | |
| print(f"⚠️ Whale tracking failed: {error}") | |
| return 0.2 # ⬆️ زيادة من 0.1 إلى 0.2 | |
| async def _pattern_recognition_strategy(self, symbol_data, market_context): | |
| """استراتيجية التعرف على الأنماط المحسنة - درجات أعلى""" | |
| try: | |
| score = 0.0 | |
| indicators = symbol_data.get('advanced_indicators', {}) | |
| # ✅ تعزيز كبير بناءً على تحليل الأنماط من LLM | |
| pattern_analysis = symbol_data.get('pattern_analysis') | |
| if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.6: | |
| score += pattern_analysis.get('pattern_confidence', 0) * 0.8 | |
| print(f"🎯 Pattern recognition significantly enhanced: +{score:.3f}") | |
| else: | |
| # التحليل التقليدي إذا لم يكن هناك نمط من LLM | |
| for timeframe in ['4h', '1h']: | |
| if timeframe in indicators: | |
| timeframe_indicators = indicators[timeframe] | |
| # نمط الزخم الصعودي | |
| 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 # ⬆️ زيادة من 0.3 إلى 0.35 | |
| # نمط الزخم الهبوطي | |
| if (timeframe_indicators.get('rsi', 50) < 40 and | |
| timeframe_indicators.get('stoch_rsi_k', 50) < 20): | |
| score += 0.35 # ⬆️ زيادة من 0.3 إلى 0.35 | |
| return min(score, 1.0) | |
| except Exception as error: | |
| print(f"⚠️ Pattern recognition strategy error: {error}") | |
| return 0.3 | |
| async def _hybrid_ai_strategy(self, symbol_data, market_context): | |
| """استراتيجية الهجين الذكية المحسنة - درجات أعلى""" | |
| try: | |
| score = 0.0 | |
| monte_carlo_probability = symbol_data.get('monte_carlo_probability', 0.5) | |
| final_score = symbol_data.get('final_score', 0.5) | |
| score += monte_carlo_probability * 0.4 | |
| score += final_score * 0.3 | |
| # تحليل سياق السوق | |
| if market_context.get('btc_sentiment') == 'BULLISH': | |
| score += 0.25 # ⬆️ زيادة من 0.2 إلى 0.25 | |
| elif market_context.get('btc_sentiment') == 'BEARISH': | |
| score -= 0.08 # ⬆️ تخفيض من 0.1 إلى 0.08 | |
| # تحليل نشاط الحيتان العام | |
| whale_activity = market_context.get('general_whale_activity', {}) | |
| if whale_activity.get('sentiment') == 'BULLISH': | |
| score += 0.15 # ⬆️ زيادة من 0.1 إلى 0.15 | |
| # ✅ تعزيز بناءً على تحليل الأنماط | |
| pattern_analysis = symbol_data.get('pattern_analysis') | |
| if pattern_analysis and pattern_analysis.get('pattern_confidence', 0) > 0.7: | |
| pattern_bonus = pattern_analysis.get('pattern_confidence', 0) * 0.25 | |
| score += pattern_bonus | |
| print(f"🤖 Hybrid AI enhanced by pattern: +{pattern_bonus:.3f}") | |
| return max(0.0, min(score, 1.0)) | |
| except Exception as error: | |
| print(f"⚠️ Hybrid AI strategy error: {error}") | |
| return 0.3 | |
| async def _fallback_strategy_score(self, strategy_name, symbol_data, market_context): | |
| """درجات استراتيجية احتياطية محسنة""" | |
| try: | |
| base_score = symbol_data.get('final_score', 0.5) | |
| if strategy_name == 'trend_following': | |
| indicators = symbol_data.get('advanced_indicators', {}) | |
| if '1h' in indicators: | |
| rsi_value = indicators['1h'].get('rsi', 50) | |
| ema_9 = indicators['1h'].get('ema_9') | |
| ema_21 = indicators['1h'].get('ema_21') | |
| if ema_9 and ema_21 and ema_9 > ema_21 and 40 <= rsi_value <= 60: | |
| return 0.6 | |
| return 0.4 | |
| elif strategy_name == 'mean_reversion': | |
| current_price = symbol_data.get('current_price', 0) | |
| indicators = symbol_data.get('advanced_indicators', {}) | |
| if '1h' in indicators: | |
| rsi_value = indicators['1h'].get('rsi', 50) | |
| bb_lower = indicators['1h'].get('bb_lower') | |
| if bb_lower and current_price <= bb_lower * 1.02 and rsi_value < 35: | |
| return 0.7 | |
| return 0.3 | |
| elif strategy_name == 'breakout_momentum': | |
| volume_ratio = symbol_data.get('advanced_indicators', {}).get('1h', {}).get('volume_ratio', 0) | |
| if volume_ratio > 1.5: | |
| return 0.6 | |
| return 0.4 | |
| elif strategy_name == 'whale_tracking': | |
| whale_data = symbol_data.get('whale_data', {}) | |
| if not whale_data.get('data_available', False): | |
| return 0.2 # ⬆️ زيادة من 0.1 إلى 0.2 | |
| total_transactions = whale_data.get('transfer_count', 0) | |
| if total_transactions >= 3: | |
| return 0.5 | |
| return 0.3 | |
| return base_score | |
| except Exception as error: | |
| print(f"⚠️ Fallback strategy failed for {strategy_name}: {error}") | |
| return 0.3 | |
| class MLProcessor: | |
| def __init__(self, market_context, data_manager, learning_engine): | |
| self.market_context = market_context | |
| self.data_manager = data_manager | |
| self.learning_engine = learning_engine | |
| self.technical_analyzer = AdvancedTechnicalAnalyzer() | |
| self.strategy_engine = MultiStrategyEngine(data_manager, learning_engine) | |
| self.pattern_tracker = PatternPerformanceTracker() | |
| def _validate_rsi_safety(self, indicators): | |
| """التحقق العاجل من سلامة مؤشر RSI""" | |
| rsi_warnings = [] | |
| critical_issues = 0 | |
| timeframes_to_check = ['5m', '15m', '1h', '4h'] | |
| for timeframe in timeframes_to_check: | |
| if timeframe in indicators: | |
| rsi_value = indicators[timeframe].get('rsi') | |
| if rsi_value: | |
| if rsi_value > 80: | |
| rsi_warnings.append(f"🚨 RSI CRITICAL in {timeframe}: {rsi_value} - EXTREME OVERBOUGHT") | |
| critical_issues += 1 | |
| elif rsi_value > 75: | |
| rsi_warnings.append(f"⚠️ RSI WARNING in {timeframe}: {rsi_value} - STRONG OVERBOUGHT") | |
| elif rsi_value > 70: | |
| rsi_warnings.append(f"📈 RSI HIGH in {timeframe}: {rsi_value} - OVERBOUGHT") | |
| # إذا كان هناك إطارين زمنيين أو أكثر في منطقة الخطر، نرفض المرشح | |
| is_safe = critical_issues < 2 | |
| return is_safe, rsi_warnings | |
| def _validate_indicators_quality_enhanced(self, indicators, current_price): | |
| """تحسين التحقق من جودة المؤشرات""" | |
| quality_issues = [] | |
| # التحقق من RSI | |
| rsi_safe, rsi_warnings = self._validate_rsi_safety(indicators) | |
| if not rsi_safe: | |
| quality_issues.extend(rsi_warnings) | |
| # التحقق من تناقض المؤشرات | |
| bullish_signals = 0 | |
| bearish_signals = 0 | |
| for timeframe, data in indicators.items(): | |
| # إشارات صعودية | |
| if data.get('macd_hist', 0) > 0: | |
| bullish_signals += 1 | |
| if data.get('rsi', 50) > 70: # RSI مرتفع يعتبر إشارة بيع | |
| bearish_signals += 1 | |
| if 'ema_9' in data and 'ema_21' in data: | |
| if data['ema_9'] > data['ema_21']: | |
| bullish_signals += 1 | |
| if bullish_signals > 0 and bearish_signals > bullish_signals: | |
| quality_issues.append("⚠️ Conflicting signals: More bearish than bullish indicators") | |
| return quality_issues | |
| def _calculate_enhanced_score_with_safety(self, base_analysis, strategy_scores, quality_issues): | |
| """حساب النقاط مع مراعاة عوامل السلامة""" | |
| base_score = base_analysis.get('final_score', 0.5) | |
| strategy_average = sum(strategy_scores.values()) / len(strategy_scores) if strategy_scores else 0.5 | |
| # خصم النقاط بناءً على مشاكل الجودة | |
| safety_penalty = 0.0 | |
| for issue in quality_issues: | |
| if '🚨 RSI CRITICAL' in issue: | |
| safety_penalty += 0.3 | |
| elif '⚠️ RSI WARNING' in issue: | |
| safety_penalty += 0.15 | |
| elif '📈 RSI HIGH' in issue: | |
| safety_penalty += 0.05 | |
| enhanced_score = (base_score * 0.4) + (strategy_average * 0.6) | |
| enhanced_score = max(0.0, enhanced_score - safety_penalty) | |
| return min(enhanced_score, 1.0) | |
| async def process_and_score_symbol_enhanced(self, raw_data): | |
| """معالجة وتحليل الرمز مع نظام التعلم والاستراتيجيات - الإصدار المحسّن""" | |
| try: | |
| if not raw_data or not raw_data.get('ohlcv'): | |
| print(f"⚠️ Skipping {raw_data.get('symbol', 'unknown')} - no OHLCV data") | |
| return None | |
| # ✅ تمرير بيانات الشموع الخام للتحليل اللاحق | |
| raw_data['raw_ohlcv'] = raw_data.get('ohlcv', {}) | |
| base_analysis = await self.process_and_score_symbol(raw_data) | |
| if not base_analysis: | |
| return None | |
| try: | |
| # التحقق المحسن من الجودة | |
| current_price = base_analysis.get('current_price', 0) | |
| quality_issues = self._validate_indicators_quality_enhanced( | |
| base_analysis.get('advanced_indicators', {}), | |
| current_price | |
| ) | |
| # طباعة تحذيرات الجودة | |
| if quality_issues: | |
| print(f"🔍 Quality issues for {base_analysis.get('symbol')}:") | |
| for issue in quality_issues: | |
| print(f" {issue}") | |
| # ✅ تقييم الاستراتيجيات باستخدام نظام التعلم مع التحقق من الوجود | |
| if hasattr(self, 'strategy_engine') and self.strategy_engine: | |
| strategy_scores, base_scores = await self.strategy_engine.evaluate_all_strategies(base_analysis, self.market_context) | |
| base_analysis['strategy_scores'] = strategy_scores | |
| base_analysis['base_strategy_scores'] = base_scores # ✅ حفظ الدرجات الأساسية | |
| # ✅ تحديد أفضل استراتيجية بناءً على الدرجات الأساسية (بدون أوزان) | |
| if base_scores: | |
| best_strategy = max(base_scores.items(), key=lambda x: x[1]) | |
| best_strategy_name = best_strategy[0] | |
| best_strategy_score = best_strategy[1] | |
| base_analysis['recommended_strategy'] = best_strategy_name | |
| base_analysis['strategy_confidence'] = best_strategy_score | |
| print(f"🎯 أفضل استراتيجية لـ {base_analysis.get('symbol')}: {best_strategy_name} (ثقة: {best_strategy_score:.3f})") | |
| # ✅ تخفيض عتبة الثقة للسماح بمزيد من الاستراتيجيات | |
| if best_strategy_score > 0.3: # ⬇️ تخفيض من 0.6 إلى 0.3 | |
| base_analysis['target_strategy'] = best_strategy_name | |
| print(f"✅ استخدام استراتيجية متخصصة: {best_strategy_name}") | |
| else: | |
| base_analysis['target_strategy'] = 'GENERIC' | |
| print(f"🔄 استخدام استراتيجية عامة (ثقة منخفضة: {best_strategy_score:.3f})") | |
| else: | |
| base_analysis['recommended_strategy'] = 'GENERIC' | |
| base_analysis['strategy_confidence'] = 0.3 # ⬆️ زيادة من 0.5 إلى 0.3 | |
| base_analysis['target_strategy'] = 'GENERIC' | |
| print("🔄 استخدام استراتيجية عامة (لا توجد درجات استراتيجية)") | |
| # ✅ استخدام الدالة المحسنة لحساب النقاط | |
| enhanced_score = self._calculate_enhanced_score_with_safety( | |
| base_analysis, strategy_scores, quality_issues | |
| ) | |
| base_analysis['enhanced_final_score'] = enhanced_score | |
| else: | |
| print("⚠️ Strategy engine not available, using base analysis only") | |
| base_analysis['strategy_scores'] = {} | |
| base_analysis['enhanced_final_score'] = base_analysis.get('final_score', 0.5) | |
| base_analysis['recommended_strategy'] = 'GENERIC' | |
| base_analysis['strategy_confidence'] = 0.3 | |
| base_analysis['target_strategy'] = 'GENERIC' | |
| base_analysis['quality_warnings'] = quality_issues | |
| except Exception as strategy_error: | |
| print(f"⚠️ Strategy evaluation failed for {base_analysis.get('symbol')}: {strategy_error}") | |
| base_analysis['strategy_scores'] = {} | |
| base_analysis['enhanced_final_score'] = base_analysis.get('final_score', 0.5) | |
| base_analysis['recommended_strategy'] = 'GENERIC' | |
| base_analysis['strategy_confidence'] = 0.3 # ⬆️ زيادة من 0.5 إلى 0.3 | |
| base_analysis['target_strategy'] = 'GENERIC' | |
| base_analysis['quality_warnings'] = ['Strategy evaluation failed'] | |
| return base_analysis | |
| except Exception as error: | |
| print(f"❌ Enhanced processing failed for {raw_data.get('symbol')}: {error}") | |
| return await self.process_and_score_symbol(raw_data) | |
| def _improve_fibonacci_levels(self, daily_dataframe, current_price): | |
| """تحسين حساب مستويات Fibonacci لتتوافق مع السعر الحالي""" | |
| if len(daily_dataframe) < 50: | |
| return {} | |
| # استخدام آخر 50 يومًا لحساب القمة والقاع | |
| recent_high = float(daily_dataframe['high'].iloc[-50:].max()) | |
| recent_low = float(daily_dataframe['low'].iloc[-50:].min()) | |
| # إذا كان السعر الحالي خارج النطاق، نعدل النطاق | |
| if current_price > recent_high: | |
| recent_high = current_price * 1.05 # نضيف هامش 5% | |
| if current_price < recent_low: | |
| recent_low = current_price * 0.95 # نخصم هامش 5% | |
| difference = recent_high - recent_low | |
| if difference <= 0: # تجنب القسمة على الصفر | |
| return {} | |
| return { | |
| "0.0%": recent_high, | |
| "23.6%": recent_high - 0.236 * difference, | |
| "38.2%": recent_high - 0.382 * difference, | |
| "50.0%": recent_high - 0.50 * difference, | |
| "61.8%": recent_high - 0.618 * difference, | |
| "78.6%": recent_high - 0.786 * difference, | |
| "100.0%": recent_low | |
| } | |
| async def process_and_score_symbol(self, raw_data): | |
| """معالجة وتحليل الرمز الأساسي""" | |
| symbol = raw_data['symbol'] | |
| ohlcv_data = raw_data['ohlcv'] | |
| reasons_for_candidacy = raw_data.get('reasons', []) | |
| if not ohlcv_data: | |
| print(f"❌ No OHLCV data for {symbol}") | |
| return None | |
| try: | |
| all_indicators = {} | |
| for timeframe, candles in ohlcv_data.items(): | |
| if candles: | |
| dataframe = pd.DataFrame(candles, columns=['time', 'open', 'high', 'low', 'close', 'volume']) | |
| dataframe[['open', 'high', 'low', 'close', 'volume']] = dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float) | |
| all_indicators[timeframe] = self._calculate_indicators(dataframe, timeframe) | |
| hourly_dataframe = pd.DataFrame(ohlcv_data.get('1h', []), columns=['time', 'open', 'high', 'low', 'close', 'volume']) | |
| if hourly_dataframe.empty: | |
| print(f"❌ Skipping {symbol} due to insufficient 1h data.") | |
| return None | |
| hourly_dataframe[['open', 'high', 'low', 'close', 'volume']] = hourly_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float) | |
| try: | |
| current_price = float(hourly_dataframe['close'].iloc[-1]) | |
| if ohlcv_data.get('5m'): | |
| five_minute_dataframe = pd.DataFrame(ohlcv_data['5m'], columns=['time', 'open', 'high', 'low', 'close', 'volume']) | |
| if not five_minute_dataframe.empty: | |
| five_minute_dataframe[['open', 'high', 'low', 'close', 'volume']] = five_minute_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float) | |
| current_price = float(five_minute_dataframe['close'].iloc[-1]) | |
| liquidity_score = self._calculate_liquidity_score(hourly_dataframe) | |
| daily_dataframe = pd.DataFrame(ohlcv_data.get('1d', []), columns=['time', 'open', 'high', 'low', 'close', 'volume']) | |
| if not daily_dataframe.empty: | |
| daily_dataframe[['open', 'high', 'low', 'close', 'volume']] = daily_dataframe[['open', 'high', 'low', 'close', 'volume']].astype(float) | |
| average_daily_volume = float(daily_dataframe['volume'].mean()) if not daily_dataframe.empty else 0.0 | |
| # استخدام الدالة المحسنة لحساب مستويات Fibonacci | |
| fibonacci_levels = self._improve_fibonacci_levels(daily_dataframe, current_price) | |
| try: | |
| whale_data = await self.data_manager.get_whale_data_safe_async(symbol) | |
| except Exception as whale_error: | |
| print(f"⚠️ Whale data failed for {symbol}: {whale_error}. No whale data available.") | |
| whale_data = { | |
| "transfer_count": 0, | |
| "total_volume": 0, | |
| "source": "no_data", | |
| "data_available": False | |
| } | |
| whale_score = self._calculate_whale_activity_score(whale_data) | |
| opportunity_classification = self.classify_opportunity_type(all_indicators, current_price) | |
| initial_score = self._calculate_initial_score(all_indicators, current_price, self.market_context) | |
| monte_carlo_probability = self._run_monte_carlo_simulation(hourly_dataframe) | |
| print(f"🎲 Monte Carlo Simulation for {symbol}: Success Probability = {monte_carlo_probability:.2%}") | |
| final_score = (0.35 * initial_score) + (0.50 * monte_carlo_probability) + (0.15 * whale_score) | |
| final_score *= opportunity_classification['confidence'] | |
| normalized_indicators = {timeframe: self._normalize_features_corrected(indicators) for timeframe, indicators in all_indicators.items()} | |
| return { | |
| 'symbol': symbol, 'reasons_for_candidacy': reasons_for_candidacy, 'current_price': float(current_price), | |
| 'liquidity_score': float(liquidity_score) if not np.isnan(liquidity_score) else 0.0, 'avg_daily_volume': float(average_daily_volume), | |
| 'whale_data': whale_data, 'whale_score': float(whale_score), 'opportunity_type': opportunity_classification, | |
| 'sentiment_data': self.market_context, 'fibonacci_levels': fibonacci_levels, 'final_score': float(final_score), | |
| 'initial_score': float(initial_score), 'monte_carlo_probability': float(monte_carlo_probability), | |
| 'indicators': normalized_indicators, 'advanced_indicators': all_indicators, 'strategy_scores': {}, | |
| 'recommended_strategy': 'GENERIC', 'enhanced_final_score': float(final_score), 'target_strategy': 'GENERIC', | |
| 'raw_ohlcv': ohlcv_data # ✅ إضافة بيانات الشموع الخام | |
| } | |
| except (KeyError, IndexError) as error: | |
| print(f"⚠️ Missing data for {symbol}: {error}") | |
| return None | |
| except Exception as error: | |
| print(f"❌ Failed to process {symbol}: {error}") | |
| import traceback | |
| traceback.print_exc() | |
| return None | |
| def _calculate_indicators(self, dataframe, timeframe): | |
| """حساب المؤشرات الفنية""" | |
| indicators = {} | |
| if dataframe.empty: | |
| return indicators | |
| if not isinstance(dataframe.index, pd.DatetimeIndex): | |
| try: | |
| dataframe['time'] = pd.to_datetime(dataframe['time'], unit='ms') | |
| dataframe = dataframe.set_index('time', drop=True) | |
| except: | |
| dataframe['time'] = pd.to_datetime(dataframe['time']) | |
| dataframe = dataframe.set_index('time', drop=True) | |
| dataframe = dataframe.sort_index() | |
| if len(dataframe) >= 1 and all(column in dataframe.columns for column in ['high', 'low', 'close', 'volume']): | |
| try: | |
| typical_price = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3 | |
| volume_weighted_average_price = (typical_price * dataframe['volume']).cumsum() / dataframe['volume'].cumsum() | |
| 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]) | |
| except Exception as error: | |
| print(f"⚠️ VWAP calculation failed for {timeframe}: {error}") | |
| if len(dataframe) >= 14: | |
| rsi_series = ta.rsi(dataframe['close'], length=14) | |
| 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]) | |
| if len(dataframe) >= 26: | |
| macd = ta.macd(dataframe['close']) | |
| if macd is not None and not macd.empty: | |
| 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]) | |
| 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]) | |
| 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]) | |
| if len(dataframe) >= 20: | |
| bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2) | |
| if bollinger_bands is not None and not bollinger_bands.empty: | |
| 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]) | |
| 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]) | |
| 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]) | |
| if len(dataframe) >= 14: | |
| average_true_range = ta.atr(high=dataframe['high'], low=dataframe['low'], close=dataframe['close'], length=14) | |
| 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]) | |
| if len(dataframe) >= 26: | |
| ema_12 = ta.ema(dataframe['close'], length=12) | |
| ema_26 = ta.ema(dataframe['close'], length=26) | |
| 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]) | |
| 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]) | |
| return indicators | |
| def _normalize_features_corrected(self, features): | |
| """تطبيع الميزات بشكل صحيح""" | |
| normalized_features = {} | |
| for key, value in features.items(): | |
| if value is None: | |
| normalized_features[key] = 0.0 | |
| continue | |
| if key == 'rsi': | |
| normalized_features[key] = max(0, min(100, value)) | |
| elif key in ['macd_hist', 'macd_line', 'macd_signal', 'vwap', 'atr']: | |
| normalized_features[key] = value | |
| elif 'ema' in key or 'bb_' in key: | |
| normalized_features[key] = value | |
| else: | |
| try: | |
| if abs(value) > 1000: | |
| normalized_features[key] = value / 1000 | |
| else: | |
| normalized_features[key] = value | |
| except: | |
| normalized_features[key] = value | |
| return normalized_features | |
| def _run_monte_carlo_simulation(self, dataframe, number_of_simulations=1000, number_of_steps=20): | |
| """تشغيل محاكاة مونت كارلو""" | |
| if dataframe.empty or len(dataframe) < 2: | |
| return 0.0 | |
| log_returns = np.log(dataframe['close'] / dataframe['close'].shift(1)).dropna() | |
| if log_returns.empty: | |
| return 0.0 | |
| mean_return = log_returns.mean() | |
| volatility = log_returns.std() | |
| initial_price = dataframe['close'].iloc[-1] | |
| success_count = 0 | |
| for _ in range(number_of_simulations): | |
| random_values = np.random.normal(0, 1, number_of_steps) | |
| daily_returns = np.exp(mean_return - 0.5 * volatility**2 + volatility * random_values) | |
| simulated_prices = initial_price * daily_returns.cumprod() | |
| if (simulated_prices[-1] / initial_price) > 1.02: | |
| success_count += 1 | |
| return success_count / number_of_simulations | |
| def _calculate_initial_score(self, indicators, current_price, market_context): | |
| """حساب النقاط الأولية""" | |
| score = 0.5 | |
| fast_timeframes = ['5m', '15m'] | |
| for timeframe in fast_timeframes: | |
| timeframe_indicators = indicators.get(timeframe, {}) | |
| if not timeframe_indicators: | |
| continue | |
| if 'rsi' in timeframe_indicators: | |
| rsi_value = timeframe_indicators['rsi'] | |
| if isinstance(rsi_value, (int, float)): | |
| if rsi_value < 30: | |
| score += 0.2 | |
| elif rsi_value < 40: | |
| score += 0.1 | |
| elif rsi_value > 70: | |
| score -= 0.1 | |
| if 'macd_hist' in timeframe_indicators and timeframe_indicators['macd_hist'] > 0: | |
| score += 0.15 | |
| if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']): | |
| if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']: | |
| score += 0.15 | |
| slow_timeframes = ['1h', '4h', '1d'] | |
| for timeframe in slow_timeframes: | |
| timeframe_indicators = indicators.get(timeframe, {}) | |
| if not timeframe_indicators: | |
| continue | |
| if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']): | |
| if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']: | |
| score += 0.10 | |
| if all(key in timeframe_indicators for key in ['bb_upper', 'bb_lower']): | |
| if current_price > timeframe_indicators['bb_upper']: | |
| score += 0.10 | |
| elif current_price <= timeframe_indicators['bb_lower']: | |
| score += 0.05 | |
| if '5m' in indicators and 'vwap' in indicators['5m'] and current_price > indicators['5m']['vwap']: | |
| score += 0.10 | |
| if market_context: | |
| bitcoin_sentiment = market_context.get('btc_sentiment') | |
| fear_greed_index = market_context.get('fear_and_greed_index', 50) | |
| if bitcoin_sentiment == 'BULLISH' and fear_greed_index > 60: | |
| score *= 1.2 | |
| elif bitcoin_sentiment == 'BEARISH' or fear_greed_index < 30: | |
| score *= 0.8 | |
| return min(max(score, 0.0), 1.0) | |
| def _normalize_features(self, features): | |
| return self._normalize_features_corrected(features) | |
| def _prepare_data_for_ml(self, all_indicators, current_price): | |
| feature_vector = [] | |
| timeframes = ['5m', '15m', '1h', '4h', '1d'] | |
| indicator_keys = ['rsi', 'macd_hist', 'macd_line', 'bb_upper', 'bb_lower', 'atr', 'ema_12', 'ema_26', 'vwap'] | |
| for timeframe in timeframes: | |
| timeframe_indicators = all_indicators.get(timeframe, {}) | |
| for key in indicator_keys: | |
| feature_vector.append(timeframe_indicators.get(key, 0.0)) | |
| feature_vector.append(current_price) | |
| return feature_vector | |
| def _calculate_liquidity_score(self, hourly_dataframe): | |
| if hourly_dataframe.empty: | |
| return 0.0 | |
| hourly_dataframe['dollar_volume'] = hourly_dataframe['volume'] * hourly_dataframe['close'] | |
| return float(hourly_dataframe['dollar_volume'].mean()) | |
| def _calculate_fibonacci_levels(self, daily_dataframe): | |
| """مهملة: استخدام _improve_fibonacci_levels بدلاً من ذلك""" | |
| return self._improve_fibonacci_levels(daily_dataframe, 0) | |
| def classify_opportunity_type(self, indicators, current_price): | |
| fast_signals = 0 | |
| slow_signals = 0 | |
| for timeframe in ['5m', '15m']: | |
| timeframe_indicators = indicators.get(timeframe, {}) | |
| if not timeframe_indicators: | |
| continue | |
| if timeframe_indicators.get('rsi', 100) < 35: | |
| fast_signals += 1 | |
| if timeframe_indicators.get('macd_hist', 0) > 0: | |
| fast_signals += 1 | |
| if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']): | |
| if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']: | |
| fast_signals += 1 | |
| if timeframe == '5m' and timeframe_indicators.get('vwap') and current_price > timeframe_indicators['vwap'] * 1.02: | |
| fast_signals += 1 | |
| for timeframe in ['1h', '4h', '1d']: | |
| timeframe_indicators = indicators.get(timeframe, {}) | |
| if not timeframe_indicators: | |
| continue | |
| if 40 <= timeframe_indicators.get('rsi', 50) <= 60: | |
| slow_signals += 1 | |
| if all(key in timeframe_indicators for key in ['ema_12', 'ema_26']): | |
| if timeframe_indicators['ema_12'] > timeframe_indicators['ema_26']: | |
| slow_signals += 1 | |
| if timeframe_indicators.get('bb_middle') and current_price > timeframe_indicators['bb_middle']: | |
| slow_signals += 1 | |
| if fast_signals >= 3: | |
| return { | |
| "type": "FAST_PUMP", "timeframe": "15m-1h", "take_profit_multiplier": 1.08, "stop_loss_multiplier": 0.97, | |
| "confidence": min(fast_signals / 6.0, 1.0), "description": "فرصة صعود سريع قوية على الأطر الزمنية القصيرة" | |
| } | |
| elif slow_signals >= 3: | |
| return { | |
| "type": "SLOW_GROWTH", "timeframe": "4h-1d", "take_profit_multiplier": 1.05, "stop_loss_multiplier": 0.95, | |
| "confidence": min(slow_signals / 6.0, 1.0), "description": "فرصة نمو مستدام على الأطر الزمنية الطويلة" | |
| } | |
| return { | |
| "type": "NEUTRAL", "timeframe": "N/A", "take_profit_multiplier": 1.05, "stop_loss_multiplier": 0.95, | |
| "confidence": 0.3, "description": "لا توجد إشارات واضحة لنوع محدد من الفرص" | |
| } | |
| def _calculate_whale_activity_score(self, whale_data): | |
| """حساب درجة نشاط الحيتان بناءً على البيانات الحقيقية فقط""" | |
| if not whale_data.get('data_available', False): | |
| return 0.0 | |
| total_transactions = whale_data.get('transfer_count', 0) | |
| total_volume = whale_data.get('total_volume', 0) | |
| score = 0.0 | |
| if total_transactions >= 10: | |
| score += 0.3 | |
| elif total_transactions >= 5: | |
| score += 0.15 | |
| if total_volume > 500000: | |
| score += 0.2 | |
| elif total_volume > 100000: | |
| score += 0.1 | |
| return min(score, 0.5) | |
| def filter_top_candidates(self, candidates, number_of_candidates=10): | |
| """تصفية أفضل المرشحين""" | |
| valid_candidates = [candidate for candidate in candidates if candidate is not None] | |
| return sorted(valid_candidates, key=lambda candidate: candidate.get('enhanced_final_score', candidate.get('final_score', 0)), reverse=True)[:number_of_candidates] | |
| # دوال المحاكاة المحلية للاستخدام كبديل | |
| def local_analyze_opportunity(candidate_data): | |
| """تحليل محسن مع مراعاة مخاطر RSI""" | |
| score = candidate_data.get('enhanced_final_score', candidate_data.get('final_score', 0)) | |
| quality_warnings = candidate_data.get('quality_warnings', []) | |
| # التحقق من تحذيرات RSI | |
| rsi_critical = any('🚨 RSI CRITICAL' in warning for warning in quality_warnings) | |
| rsi_warning = any('⚠️ RSI WARNING' in warning for warning in quality_warnings) | |
| if rsi_critical: | |
| return { | |
| "action": "HOLD", | |
| "reasoning": "Local analysis: CRITICAL RSI levels detected - extreme overbought condition. High risk of correction.", | |
| "trade_type": "NONE", | |
| "stop_loss": None, | |
| "take_profit": None, | |
| "expected_target_minutes": 15, | |
| "confidence_level": 0.1, | |
| "model_source": "local_safety_filter", | |
| "strategy": "GENERIC" | |
| } | |
| advanced_indicators = candidate_data.get('advanced_indicators', {}) | |
| strategy_scores = candidate_data.get('strategy_scores', {}) | |
| if not advanced_indicators: | |
| return { | |
| "action": "HOLD", | |
| "reasoning": "Local analysis: Insufficient advanced indicator data.", | |
| "trade_type": "NONE", | |
| "stop_loss": None, | |
| "take_profit": None, | |
| "expected_target_minutes": 15, | |
| "confidence_level": 0.3, | |
| "model_source": "local", | |
| "strategy": "GENERIC" | |
| } | |
| action = "HOLD" | |
| reasoning = "Local analysis: No strong buy signal based on enhanced rules." | |
| trade_type = "NONE" | |
| stop_loss = None | |
| take_profit = None | |
| expected_minutes = 15 | |
| confidence = 0.3 | |
| five_minute_indicators = advanced_indicators.get('5m', {}) | |
| one_hour_indicators = advanced_indicators.get('1h', {}) | |
| buy_conditions = 0 | |
| total_conditions = 0 | |
| if isinstance(score, (int, float)) and score > 0.70: | |
| buy_conditions += 1 | |
| total_conditions += 1 | |
| # شرط RSI أكثر تحفظاً | |
| rsi_five_minute = five_minute_indicators.get('rsi', 50) | |
| if 30 <= rsi_five_minute <= 65: # نطاق آمن لـ RSI | |
| buy_conditions += 1 | |
| total_conditions += 1 | |
| if five_minute_indicators.get('macd_hist', 0) > 0: | |
| buy_conditions += 1 | |
| total_conditions += 1 | |
| if (five_minute_indicators.get('ema_9', 0) > five_minute_indicators.get('ema_21', 0) and | |
| one_hour_indicators.get('ema_9', 0) > one_hour_indicators.get('ema_21', 0)): | |
| buy_conditions += 1 | |
| total_conditions += 1 | |
| if five_minute_indicators.get('volume_ratio', 0) > 1.5: | |
| buy_conditions += 1 | |
| total_conditions += 1 | |
| confidence = buy_conditions / total_conditions if total_conditions > 0 else 0.3 | |
| # خصم الثقة بناءً على تحذيرات RSI | |
| if rsi_warning: | |
| confidence *= 0.7 # خصم 30% للتحذيرات | |
| reasoning += " RSI warning applied." | |
| if confidence >= 0.6: | |
| action = "BUY" | |
| current_price = candidate_data['current_price'] | |
| trade_type = "LONG" | |
| # وقف خسارة أكثر تحفظاً لـ RSI المرتفع | |
| if rsi_warning: | |
| stop_loss = current_price * 0.93 # 7% stop loss للتحذيرات | |
| else: | |
| stop_loss = current_price * 0.95 # 5% stop loss عادي | |
| if 'bb_upper' in five_minute_indicators: | |
| take_profit = five_minute_indicators['bb_upper'] * 1.02 | |
| else: | |
| take_profit = current_price * 1.05 | |
| if confidence >= 0.8: | |
| expected_minutes = 10 | |
| elif confidence >= 0.6: | |
| expected_minutes = 18 | |
| else: | |
| expected_minutes = 25 | |
| reasoning = f"Local enhanced analysis: Strong buy signal with {buy_conditions}/{total_conditions} conditions met. Confidence: {confidence:.2f}" | |
| if rsi_warning: | |
| reasoning += " (RSI warning - trading with caution)" | |
| return { | |
| "action": action, | |
| "reasoning": reasoning, | |
| "trade_type": trade_type, | |
| "stop_loss": stop_loss, | |
| "take_profit": take_profit, | |
| "expected_target_minutes": expected_minutes, | |
| "confidence_level": confidence, | |
| "model_source": "local", | |
| "strategy": "GENERIC" | |
| } | |
| def local_re_analyze_trade(trade_data, processed_data): | |
| current_price = processed_data['current_price'] | |
| stop_loss = trade_data['stop_loss'] | |
| take_profit = trade_data['take_profit'] | |
| action = "HOLD" | |
| reasoning = "Local re-analysis: No significant change to trigger an update or close." | |
| if stop_loss and current_price <= stop_loss: | |
| action = "CLOSE_TRADE" | |
| reasoning = "Local re-analysis: Stop loss has been hit." | |
| elif take_profit and current_price >= take_profit: | |
| action = "CLOSE_TRADE" | |
| reasoning = "Local re-analysis: Take profit has been hit." | |
| strategy = trade_data.get('strategy', 'GENERIC') | |
| if strategy == 'unknown': | |
| strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC') | |
| return { | |
| "action": action, | |
| "reasoning": reasoning, | |
| "new_stop_loss": None, | |
| "new_take_profit": None, | |
| "new_expected_minutes": None, | |
| "model_source": "local", | |
| "strategy": strategy | |
| } | |
| print("✅ Enhanced ML System Loaded - Integrated with Learning Engine - REAL DATA ONLY - Optimized Strategy Scoring with Pattern Enhancement") |