Spaces:
Running
Running
Update ML.py
Browse files
ML.py
CHANGED
|
@@ -19,7 +19,7 @@ class AdvancedTechnicalAnalyzer:
|
|
| 19 |
|
| 20 |
def calculate_all_indicators(self, dataframe, timeframe):
|
| 21 |
"""حساب جميع المؤشرات الفنية للإطار الزمني المحدد"""
|
| 22 |
-
if dataframe.empty:
|
| 23 |
return {}
|
| 24 |
|
| 25 |
indicators = {}
|
|
@@ -40,46 +40,57 @@ class AdvancedTechnicalAnalyzer:
|
|
| 40 |
trend = {}
|
| 41 |
|
| 42 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
# المتوسطات المتحركة
|
| 44 |
if len(dataframe) >= 9:
|
| 45 |
ema_9 = ta.ema(dataframe['close'], length=9)
|
| 46 |
-
if ema_9 is not None and not ema_9.empty:
|
| 47 |
trend['ema_9'] = float(ema_9.iloc[-1])
|
| 48 |
|
| 49 |
if len(dataframe) >= 21:
|
| 50 |
ema_21 = ta.ema(dataframe['close'], length=21)
|
| 51 |
-
if ema_21 is not None and not ema_21.empty:
|
| 52 |
trend['ema_21'] = float(ema_21.iloc[-1])
|
| 53 |
|
| 54 |
if len(dataframe) >= 50:
|
| 55 |
ema_50 = ta.ema(dataframe['close'], length=50)
|
| 56 |
-
if ema_50 is not None and not ema_50.empty:
|
| 57 |
trend['ema_50'] = float(ema_50.iloc[-1])
|
| 58 |
|
| 59 |
if len(dataframe) >= 200:
|
| 60 |
ema_200 = ta.ema(dataframe['close'], length=200)
|
| 61 |
-
if ema_200 is not None and not ema_200.empty:
|
| 62 |
trend['ema_200'] = float(ema_200.iloc[-1])
|
| 63 |
|
| 64 |
# إيشيموكو
|
| 65 |
if len(dataframe) >= 26:
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
# ADX - قوة الاتجاه
|
| 77 |
if len(dataframe) >= 14:
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
except Exception as e:
|
| 85 |
print(f"⚠️ خطأ في حساب مؤشرات الاتجاه: {e}")
|
|
@@ -91,10 +102,14 @@ class AdvancedTechnicalAnalyzer:
|
|
| 91 |
momentum = {}
|
| 92 |
|
| 93 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
# RSI
|
| 95 |
if len(dataframe) >= 14:
|
| 96 |
rsi = ta.rsi(dataframe['close'], length=14)
|
| 97 |
-
if rsi is not None and not rsi.empty:
|
| 98 |
momentum['rsi'] = float(rsi.iloc[-1])
|
| 99 |
|
| 100 |
# MACD
|
|
@@ -104,9 +119,9 @@ class AdvancedTechnicalAnalyzer:
|
|
| 104 |
macd_hist = macd.get('MACDh_12_26_9')
|
| 105 |
macd_line = macd.get('MACD_12_26_9')
|
| 106 |
|
| 107 |
-
if macd_hist is not None and not macd_hist.empty:
|
| 108 |
momentum['macd_hist'] = float(macd_hist.iloc[-1])
|
| 109 |
-
if macd_line is not None and not macd_line.empty:
|
| 110 |
momentum['macd_line'] = float(macd_line.iloc[-1])
|
| 111 |
|
| 112 |
# ستوكاستك RSI
|
|
@@ -114,13 +129,13 @@ class AdvancedTechnicalAnalyzer:
|
|
| 114 |
stoch_rsi = ta.stochrsi(dataframe['close'], length=14)
|
| 115 |
if stoch_rsi is not None and not stoch_rsi.empty:
|
| 116 |
stoch_k = stoch_rsi.get('STOCHRSIk_14_14_3_3')
|
| 117 |
-
if stoch_k is not None and not stoch_k.empty:
|
| 118 |
momentum['stoch_rsi_k'] = float(stoch_k.iloc[-1])
|
| 119 |
|
| 120 |
# ويليامز %R
|
| 121 |
if len(dataframe) >= 14:
|
| 122 |
williams = ta.willr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
|
| 123 |
-
if williams is not None and not williams.empty:
|
| 124 |
momentum['williams_r'] = float(williams.iloc[-1])
|
| 125 |
|
| 126 |
except Exception as e:
|
|
@@ -133,6 +148,10 @@ class AdvancedTechnicalAnalyzer:
|
|
| 133 |
volatility = {}
|
| 134 |
|
| 135 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
# بولينجر باندز
|
| 137 |
if len(dataframe) >= 20:
|
| 138 |
bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2)
|
|
@@ -141,21 +160,22 @@ class AdvancedTechnicalAnalyzer:
|
|
| 141 |
bb_upper = bollinger_bands.get('BBU_20_2.0')
|
| 142 |
bb_middle = bollinger_bands.get('BBM_20_2.0')
|
| 143 |
|
| 144 |
-
if bb_lower is not None and not bb_lower.empty:
|
| 145 |
volatility['bb_lower'] = float(bb_lower.iloc[-1])
|
| 146 |
-
if bb_upper is not None and not bb_upper.empty:
|
| 147 |
volatility['bb_upper'] = float(bb_upper.iloc[-1])
|
| 148 |
-
if bb_middle is not None and not bb_middle.empty:
|
| 149 |
volatility['bb_middle'] = float(bb_middle.iloc[-1])
|
| 150 |
|
| 151 |
# متوسط المدى الحقيقي (ATR)
|
| 152 |
if len(dataframe) >= 14:
|
| 153 |
average_true_range = ta.atr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
|
| 154 |
-
if average_true_range is not None and not average_true_range.empty:
|
| 155 |
atr_value = float(average_true_range.iloc[-1])
|
| 156 |
volatility['atr'] = atr_value
|
| 157 |
-
|
| 158 |
-
|
|
|
|
| 159 |
|
| 160 |
except Exception as e:
|
| 161 |
print(f"⚠️ خطأ في حساب مؤشرات التقلب: {e}")
|
|
@@ -167,16 +187,21 @@ class AdvancedTechnicalAnalyzer:
|
|
| 167 |
volume = {}
|
| 168 |
|
| 169 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
# VWAP - إصلاح المشكلة هنا
|
| 171 |
-
if len(dataframe) >= 1
|
| 172 |
try:
|
| 173 |
# إنشاء نسخة من البيانات مع DatetimeIndex مرتب
|
| 174 |
df_vwap = dataframe.copy()
|
| 175 |
|
| 176 |
# تحويل timestamp إلى datetime وضبطه كـ index
|
| 177 |
if not isinstance(df_vwap.index, pd.DatetimeIndex):
|
| 178 |
-
|
| 179 |
-
|
|
|
|
| 180 |
|
| 181 |
# التأكد من أن الفهرس مرتب
|
| 182 |
df_vwap.sort_index(inplace=True)
|
|
@@ -189,21 +214,25 @@ class AdvancedTechnicalAnalyzer:
|
|
| 189 |
volume=df_vwap['volume']
|
| 190 |
)
|
| 191 |
|
| 192 |
-
if volume_weighted_average_price is not None and not volume_weighted_average_price.empty:
|
| 193 |
volume['vwap'] = float(volume_weighted_average_price.iloc[-1])
|
| 194 |
|
| 195 |
except Exception as vwap_error:
|
| 196 |
print(f"⚠️ خطأ في حساب VWAP لـ {timeframe}: {vwap_error}")
|
| 197 |
# استخدام بديل لـ VWAP في حالة الخطأ
|
| 198 |
if len(dataframe) >= 20:
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
|
| 203 |
# OBV
|
| 204 |
try:
|
| 205 |
on_balance_volume = ta.obv(dataframe['close'], dataframe['volume'])
|
| 206 |
-
if on_balance_volume is not None and not on_balance_volume.empty:
|
| 207 |
volume['obv'] = float(on_balance_volume.iloc[-1])
|
| 208 |
except Exception as obv_error:
|
| 209 |
print(f"⚠️ خطأ في حساب OBV: {obv_error}")
|
|
@@ -212,7 +241,7 @@ class AdvancedTechnicalAnalyzer:
|
|
| 212 |
if len(dataframe) >= 14:
|
| 213 |
try:
|
| 214 |
money_flow_index = ta.mfi(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'], length=14)
|
| 215 |
-
if money_flow_index is not None and not money_flow_index.empty:
|
| 216 |
volume['mfi'] = float(money_flow_index.iloc[-1])
|
| 217 |
except Exception as mfi_error:
|
| 218 |
print(f"⚠️ خطأ في حساب MFI: {mfi_error}")
|
|
@@ -221,8 +250,11 @@ class AdvancedTechnicalAnalyzer:
|
|
| 221 |
if len(dataframe) >= 20:
|
| 222 |
try:
|
| 223 |
volume_avg_20 = float(dataframe['volume'].tail(20).mean())
|
| 224 |
-
if
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
| 226 |
except Exception as volume_error:
|
| 227 |
print(f"⚠️ خطأ في حساب نسبة الحجم: {volume_error}")
|
| 228 |
|
|
@@ -236,10 +268,14 @@ class AdvancedTechnicalAnalyzer:
|
|
| 236 |
cycle = {}
|
| 237 |
|
| 238 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
# هول موفينج افريج
|
| 240 |
if len(dataframe) >= 9:
|
| 241 |
hull_moving_average = ta.hma(dataframe['close'], length=9)
|
| 242 |
-
if hull_moving_average is not None and not hull_moving_average.empty:
|
| 243 |
cycle['hull_ma'] = float(hull_moving_average.iloc[-1])
|
| 244 |
|
| 245 |
# سوبرتريند
|
|
@@ -247,7 +283,7 @@ class AdvancedTechnicalAnalyzer:
|
|
| 247 |
supertrend = ta.supertrend(dataframe['high'], dataframe['low'], dataframe['close'], length=10, multiplier=3)
|
| 248 |
if supertrend is not None and not supertrend.empty:
|
| 249 |
supertrend_value = supertrend.get('SUPERT_10_3.0')
|
| 250 |
-
if supertrend_value is not None and not supertrend_value.empty:
|
| 251 |
cycle['supertrend'] = float(supertrend_value.iloc[-1])
|
| 252 |
|
| 253 |
except Exception as e:
|
|
@@ -474,9 +510,13 @@ class ChartPatternAnalyzer:
|
|
| 474 |
|
| 475 |
def _create_dataframe(self, candles):
|
| 476 |
"""إنشاء DataFrame من بيانات الشموع"""
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 480 |
|
| 481 |
async def _analyze_timeframe_patterns(self, dataframe, timeframe):
|
| 482 |
"""تحليل الأنماط لإطار زمني محدد"""
|
|
@@ -489,7 +529,7 @@ class ChartPatternAnalyzer:
|
|
| 489 |
}
|
| 490 |
|
| 491 |
try:
|
| 492 |
-
if len(dataframe) < 20:
|
| 493 |
return pattern_info
|
| 494 |
|
| 495 |
closes = dataframe['close'].values
|
|
@@ -638,7 +678,7 @@ class ChartPatternAnalyzer:
|
|
| 638 |
def _detect_trend_pattern(self, dataframe):
|
| 639 |
"""كشف نمط الاتجاه"""
|
| 640 |
try:
|
| 641 |
-
if len(dataframe) < 20:
|
| 642 |
return {'detected': False}
|
| 643 |
|
| 644 |
closes = dataframe['close'].values
|
|
@@ -1115,17 +1155,21 @@ class MLProcessor:
|
|
| 1115 |
|
| 1116 |
def _create_dataframe(self, candles):
|
| 1117 |
"""إنشاء DataFrame من بيانات الشموع مع DatetimeIndex مرتب"""
|
| 1118 |
-
|
| 1119 |
-
|
| 1120 |
-
|
| 1121 |
-
|
| 1122 |
-
|
| 1123 |
-
|
| 1124 |
-
|
| 1125 |
-
|
| 1126 |
-
|
| 1127 |
-
|
| 1128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1129 |
|
| 1130 |
def _calculate_enhanced_final_score(self, analysis):
|
| 1131 |
"""حساب الدرجة النهائية المحسنة"""
|
|
@@ -1219,4 +1263,4 @@ def safe_json_parse(json_string):
|
|
| 1219 |
print(f"❌ فشل تحليل JSON بعد الإصلاح: {e}")
|
| 1220 |
return None
|
| 1221 |
|
| 1222 |
-
print("✅ ML Processor loaded - Fixed
|
|
|
|
| 19 |
|
| 20 |
def calculate_all_indicators(self, dataframe, timeframe):
|
| 21 |
"""حساب جميع المؤشرات الفنية للإطار الزمني المحدد"""
|
| 22 |
+
if dataframe.empty or dataframe is None:
|
| 23 |
return {}
|
| 24 |
|
| 25 |
indicators = {}
|
|
|
|
| 40 |
trend = {}
|
| 41 |
|
| 42 |
try:
|
| 43 |
+
# التحقق من وجود البيانات الأساسية
|
| 44 |
+
if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
|
| 45 |
+
return {}
|
| 46 |
+
|
| 47 |
# المتوسطات المتحركة
|
| 48 |
if len(dataframe) >= 9:
|
| 49 |
ema_9 = ta.ema(dataframe['close'], length=9)
|
| 50 |
+
if ema_9 is not None and not ema_9.empty and not pd.isna(ema_9.iloc[-1]):
|
| 51 |
trend['ema_9'] = float(ema_9.iloc[-1])
|
| 52 |
|
| 53 |
if len(dataframe) >= 21:
|
| 54 |
ema_21 = ta.ema(dataframe['close'], length=21)
|
| 55 |
+
if ema_21 is not None and not ema_21.empty and not pd.isna(ema_21.iloc[-1]):
|
| 56 |
trend['ema_21'] = float(ema_21.iloc[-1])
|
| 57 |
|
| 58 |
if len(dataframe) >= 50:
|
| 59 |
ema_50 = ta.ema(dataframe['close'], length=50)
|
| 60 |
+
if ema_50 is not None and not ema_50.empty and not pd.isna(ema_50.iloc[-1]):
|
| 61 |
trend['ema_50'] = float(ema_50.iloc[-1])
|
| 62 |
|
| 63 |
if len(dataframe) >= 200:
|
| 64 |
ema_200 = ta.ema(dataframe['close'], length=200)
|
| 65 |
+
if ema_200 is not None and not ema_200.empty and not pd.isna(ema_200.iloc[-1]):
|
| 66 |
trend['ema_200'] = float(ema_200.iloc[-1])
|
| 67 |
|
| 68 |
# إيشيموكو
|
| 69 |
if len(dataframe) >= 26:
|
| 70 |
+
try:
|
| 71 |
+
ichimoku = ta.ichimoku(dataframe['high'], dataframe['low'], dataframe['close'])
|
| 72 |
+
if ichimoku is not None and len(ichimoku) > 0:
|
| 73 |
+
# التحقق من أن ichimoku ليس None وأنه يحتوي على بيانات
|
| 74 |
+
conversion_line = ichimoku[0].get('ITS_9') if ichimoku[0] is not None else None
|
| 75 |
+
base_line = ichimoku[0].get('IKS_26') if ichimoku[0] is not None else None
|
| 76 |
+
|
| 77 |
+
if conversion_line is not None and not conversion_line.empty and not pd.isna(conversion_line.iloc[-1]):
|
| 78 |
+
trend['ichimoku_conversion'] = float(conversion_line.iloc[-1])
|
| 79 |
+
if base_line is not None and not base_line.empty and not pd.isna(base_line.iloc[-1]):
|
| 80 |
+
trend['ichimoku_base'] = float(base_line.iloc[-1])
|
| 81 |
+
except Exception as ichimoku_error:
|
| 82 |
+
print(f"⚠️ خطأ في حساب إيشيموكو: {ichimoku_error}")
|
| 83 |
|
| 84 |
# ADX - قوة الاتجاه
|
| 85 |
if len(dataframe) >= 14:
|
| 86 |
+
try:
|
| 87 |
+
adx_result = ta.adx(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
|
| 88 |
+
if adx_result is not None and not adx_result.empty:
|
| 89 |
+
adx_value = adx_result.get('ADX_14')
|
| 90 |
+
if adx_value is not None and not adx_value.empty and not pd.isna(adx_value.iloc[-1]):
|
| 91 |
+
trend['adx'] = float(adx_value.iloc[-1])
|
| 92 |
+
except Exception as adx_error:
|
| 93 |
+
print(f"⚠️ خطأ في حساب ADX: {adx_error}")
|
| 94 |
|
| 95 |
except Exception as e:
|
| 96 |
print(f"⚠️ خطأ في حساب مؤشرات الاتجاه: {e}")
|
|
|
|
| 102 |
momentum = {}
|
| 103 |
|
| 104 |
try:
|
| 105 |
+
# التحقق من وجود البيانات الأساسية
|
| 106 |
+
if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
|
| 107 |
+
return {}
|
| 108 |
+
|
| 109 |
# RSI
|
| 110 |
if len(dataframe) >= 14:
|
| 111 |
rsi = ta.rsi(dataframe['close'], length=14)
|
| 112 |
+
if rsi is not None and not rsi.empty and not pd.isna(rsi.iloc[-1]):
|
| 113 |
momentum['rsi'] = float(rsi.iloc[-1])
|
| 114 |
|
| 115 |
# MACD
|
|
|
|
| 119 |
macd_hist = macd.get('MACDh_12_26_9')
|
| 120 |
macd_line = macd.get('MACD_12_26_9')
|
| 121 |
|
| 122 |
+
if macd_hist is not None and not macd_hist.empty and not pd.isna(macd_hist.iloc[-1]):
|
| 123 |
momentum['macd_hist'] = float(macd_hist.iloc[-1])
|
| 124 |
+
if macd_line is not None and not macd_line.empty and not pd.isna(macd_line.iloc[-1]):
|
| 125 |
momentum['macd_line'] = float(macd_line.iloc[-1])
|
| 126 |
|
| 127 |
# ستوكاستك RSI
|
|
|
|
| 129 |
stoch_rsi = ta.stochrsi(dataframe['close'], length=14)
|
| 130 |
if stoch_rsi is not None and not stoch_rsi.empty:
|
| 131 |
stoch_k = stoch_rsi.get('STOCHRSIk_14_14_3_3')
|
| 132 |
+
if stoch_k is not None and not stoch_k.empty and not pd.isna(stoch_k.iloc[-1]):
|
| 133 |
momentum['stoch_rsi_k'] = float(stoch_k.iloc[-1])
|
| 134 |
|
| 135 |
# ويليامز %R
|
| 136 |
if len(dataframe) >= 14:
|
| 137 |
williams = ta.willr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
|
| 138 |
+
if williams is not None and not williams.empty and not pd.isna(williams.iloc[-1]):
|
| 139 |
momentum['williams_r'] = float(williams.iloc[-1])
|
| 140 |
|
| 141 |
except Exception as e:
|
|
|
|
| 148 |
volatility = {}
|
| 149 |
|
| 150 |
try:
|
| 151 |
+
# التحقق من وجود البيانات الأساسية
|
| 152 |
+
if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
|
| 153 |
+
return {}
|
| 154 |
+
|
| 155 |
# بولينجر باندز
|
| 156 |
if len(dataframe) >= 20:
|
| 157 |
bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2)
|
|
|
|
| 160 |
bb_upper = bollinger_bands.get('BBU_20_2.0')
|
| 161 |
bb_middle = bollinger_bands.get('BBM_20_2.0')
|
| 162 |
|
| 163 |
+
if bb_lower is not None and not bb_lower.empty and not pd.isna(bb_lower.iloc[-1]):
|
| 164 |
volatility['bb_lower'] = float(bb_lower.iloc[-1])
|
| 165 |
+
if bb_upper is not None and not bb_upper.empty and not pd.isna(bb_upper.iloc[-1]):
|
| 166 |
volatility['bb_upper'] = float(bb_upper.iloc[-1])
|
| 167 |
+
if bb_middle is not None and not bb_middle.empty and not pd.isna(bb_middle.iloc[-1]):
|
| 168 |
volatility['bb_middle'] = float(bb_middle.iloc[-1])
|
| 169 |
|
| 170 |
# متوسط المدى الحقيقي (ATR)
|
| 171 |
if len(dataframe) >= 14:
|
| 172 |
average_true_range = ta.atr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
|
| 173 |
+
if average_true_range is not None and not average_true_range.empty and not pd.isna(average_true_range.iloc[-1]):
|
| 174 |
atr_value = float(average_true_range.iloc[-1])
|
| 175 |
volatility['atr'] = atr_value
|
| 176 |
+
current_close = dataframe['close'].iloc[-1] if not dataframe['close'].empty else 0
|
| 177 |
+
if atr_value and current_close > 0:
|
| 178 |
+
volatility['atr_percent'] = (atr_value / current_close) * 100
|
| 179 |
|
| 180 |
except Exception as e:
|
| 181 |
print(f"⚠️ خطأ في حساب مؤشرات التقلب: {e}")
|
|
|
|
| 187 |
volume = {}
|
| 188 |
|
| 189 |
try:
|
| 190 |
+
# التحقق من وجود البيانات الأساسية
|
| 191 |
+
if dataframe is None or dataframe.empty or 'close' not in dataframe.columns or 'volume' not in dataframe.columns:
|
| 192 |
+
return {}
|
| 193 |
+
|
| 194 |
# VWAP - إصلاح المشكلة هنا
|
| 195 |
+
if len(dataframe) >= 1:
|
| 196 |
try:
|
| 197 |
# إنشاء نسخة من البيانات مع DatetimeIndex مرتب
|
| 198 |
df_vwap = dataframe.copy()
|
| 199 |
|
| 200 |
# تحويل timestamp إلى datetime وضبطه كـ index
|
| 201 |
if not isinstance(df_vwap.index, pd.DatetimeIndex):
|
| 202 |
+
if 'timestamp' in df_vwap.columns:
|
| 203 |
+
df_vwap['timestamp'] = pd.to_datetime(df_vwap['timestamp'], unit='ms')
|
| 204 |
+
df_vwap.set_index('timestamp', inplace=True)
|
| 205 |
|
| 206 |
# التأكد من أن الفهرس مرتب
|
| 207 |
df_vwap.sort_index(inplace=True)
|
|
|
|
| 214 |
volume=df_vwap['volume']
|
| 215 |
)
|
| 216 |
|
| 217 |
+
if volume_weighted_average_price is not None and not volume_weighted_average_price.empty and not pd.isna(volume_weighted_average_price.iloc[-1]):
|
| 218 |
volume['vwap'] = float(volume_weighted_average_price.iloc[-1])
|
| 219 |
|
| 220 |
except Exception as vwap_error:
|
| 221 |
print(f"⚠️ خطأ في حساب VWAP لـ {timeframe}: {vwap_error}")
|
| 222 |
# استخدام بديل لـ VWAP في حالة الخطأ
|
| 223 |
if len(dataframe) >= 20:
|
| 224 |
+
try:
|
| 225 |
+
typical_price = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3
|
| 226 |
+
vwap_simple = (typical_price * dataframe['volume']).sum() / dataframe['volume'].sum()
|
| 227 |
+
if not np.isnan(vwap_simple):
|
| 228 |
+
volume['vwap'] = float(vwap_simple)
|
| 229 |
+
except Exception as simple_vwap_error:
|
| 230 |
+
print(f"⚠️ خطأ في حساب VWAP البديل: {simple_vwap_error}")
|
| 231 |
|
| 232 |
# OBV
|
| 233 |
try:
|
| 234 |
on_balance_volume = ta.obv(dataframe['close'], dataframe['volume'])
|
| 235 |
+
if on_balance_volume is not None and not on_balance_volume.empty and not pd.isna(on_balance_volume.iloc[-1]):
|
| 236 |
volume['obv'] = float(on_balance_volume.iloc[-1])
|
| 237 |
except Exception as obv_error:
|
| 238 |
print(f"⚠️ خطأ في حساب OBV: {obv_error}")
|
|
|
|
| 241 |
if len(dataframe) >= 14:
|
| 242 |
try:
|
| 243 |
money_flow_index = ta.mfi(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'], length=14)
|
| 244 |
+
if money_flow_index is not None and not money_flow_index.empty and not pd.isna(money_flow_index.iloc[-1]):
|
| 245 |
volume['mfi'] = float(money_flow_index.iloc[-1])
|
| 246 |
except Exception as mfi_error:
|
| 247 |
print(f"⚠️ خطأ في حساب MFI: {mfi_error}")
|
|
|
|
| 250 |
if len(dataframe) >= 20:
|
| 251 |
try:
|
| 252 |
volume_avg_20 = float(dataframe['volume'].tail(20).mean())
|
| 253 |
+
current_volume = float(dataframe['volume'].iloc[-1]) if not dataframe['volume'].empty else 0
|
| 254 |
+
if volume_avg_20 and volume_avg_20 > 0 and current_volume > 0:
|
| 255 |
+
volume_ratio = current_volume / volume_avg_20
|
| 256 |
+
if not np.isnan(volume_ratio):
|
| 257 |
+
volume['volume_ratio'] = volume_ratio
|
| 258 |
except Exception as volume_error:
|
| 259 |
print(f"⚠️ خطأ في حساب نسبة الحجم: {volume_error}")
|
| 260 |
|
|
|
|
| 268 |
cycle = {}
|
| 269 |
|
| 270 |
try:
|
| 271 |
+
# التحقق من وجود البيانات الأساسية
|
| 272 |
+
if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
|
| 273 |
+
return {}
|
| 274 |
+
|
| 275 |
# هول موفينج افريج
|
| 276 |
if len(dataframe) >= 9:
|
| 277 |
hull_moving_average = ta.hma(dataframe['close'], length=9)
|
| 278 |
+
if hull_moving_average is not None and not hull_moving_average.empty and not pd.isna(hull_moving_average.iloc[-1]):
|
| 279 |
cycle['hull_ma'] = float(hull_moving_average.iloc[-1])
|
| 280 |
|
| 281 |
# سوبرتريند
|
|
|
|
| 283 |
supertrend = ta.supertrend(dataframe['high'], dataframe['low'], dataframe['close'], length=10, multiplier=3)
|
| 284 |
if supertrend is not None and not supertrend.empty:
|
| 285 |
supertrend_value = supertrend.get('SUPERT_10_3.0')
|
| 286 |
+
if supertrend_value is not None and not supertrend_value.empty and not pd.isna(supertrend_value.iloc[-1]):
|
| 287 |
cycle['supertrend'] = float(supertrend_value.iloc[-1])
|
| 288 |
|
| 289 |
except Exception as e:
|
|
|
|
| 510 |
|
| 511 |
def _create_dataframe(self, candles):
|
| 512 |
"""إنشاء DataFrame من بيانات الشموع"""
|
| 513 |
+
try:
|
| 514 |
+
df = pd.DataFrame(candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
| 515 |
+
df[['open', 'high', 'low', 'close', 'volume']] = df[['open', 'high', 'low', 'close', 'volume']].astype(float)
|
| 516 |
+
return df
|
| 517 |
+
except Exception as e:
|
| 518 |
+
print(f"❌ خطأ في إنشاء DataFrame: {e}")
|
| 519 |
+
return pd.DataFrame()
|
| 520 |
|
| 521 |
async def _analyze_timeframe_patterns(self, dataframe, timeframe):
|
| 522 |
"""تحليل الأنماط لإطار زمني محدد"""
|
|
|
|
| 529 |
}
|
| 530 |
|
| 531 |
try:
|
| 532 |
+
if dataframe is None or dataframe.empty or len(dataframe) < 20:
|
| 533 |
return pattern_info
|
| 534 |
|
| 535 |
closes = dataframe['close'].values
|
|
|
|
| 678 |
def _detect_trend_pattern(self, dataframe):
|
| 679 |
"""كشف نمط الاتجاه"""
|
| 680 |
try:
|
| 681 |
+
if dataframe is None or dataframe.empty or len(dataframe) < 20:
|
| 682 |
return {'detected': False}
|
| 683 |
|
| 684 |
closes = dataframe['close'].values
|
|
|
|
| 1155 |
|
| 1156 |
def _create_dataframe(self, candles):
|
| 1157 |
"""إنشاء DataFrame من بيانات الشموع مع DatetimeIndex مرتب"""
|
| 1158 |
+
try:
|
| 1159 |
+
df = pd.DataFrame(candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
| 1160 |
+
df[['open', 'high', 'low', 'close', 'volume']] = df[['open', 'high', 'low', 'close', 'volume']].astype(float)
|
| 1161 |
+
|
| 1162 |
+
# تحويل timestamp إلى datetime وضبطه كـ index
|
| 1163 |
+
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
|
| 1164 |
+
df.set_index('timestamp', inplace=True)
|
| 1165 |
+
|
| 1166 |
+
# التأكد من أن الفهرس مرتب
|
| 1167 |
+
df.sort_index(inplace=True)
|
| 1168 |
+
|
| 1169 |
+
return df
|
| 1170 |
+
except Exception as e:
|
| 1171 |
+
print(f"❌ خطأ في إنشاء DataFrame: {e}")
|
| 1172 |
+
return pd.DataFrame()
|
| 1173 |
|
| 1174 |
def _calculate_enhanced_final_score(self, analysis):
|
| 1175 |
"""حساب الدرجة النهائية المحسنة"""
|
|
|
|
| 1263 |
print(f"❌ فشل تحليل JSON بعد الإصلاح: {e}")
|
| 1264 |
return None
|
| 1265 |
|
| 1266 |
+
print("✅ ML Processor loaded - Fixed NoneType Errors & Enhanced Analysis")
|