Riy777 commited on
Commit
07e5c3f
·
1 Parent(s): 6a25eb4

Update ML.py

Browse files
Files changed (1) hide show
  1. ML.py +104 -60
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
- ichimoku = ta.ichimoku(dataframe['high'], dataframe['low'], dataframe['close'])
67
- if ichimoku is not None and len(ichimoku) > 0:
68
- conversion_line = ichimoku[0].get('ITS_9')
69
- base_line = ichimoku[0].get('IKS_26')
70
-
71
- if conversion_line is not None and not conversion_line.empty:
72
- trend['ichimoku_conversion'] = float(conversion_line.iloc[-1])
73
- if base_line is not None and not base_line.empty:
74
- trend['ichimoku_base'] = float(base_line.iloc[-1])
 
 
 
 
75
 
76
  # ADX - قوة الاتجاه
77
  if len(dataframe) >= 14:
78
- adx_result = ta.adx(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
79
- if adx_result is not None and not adx_result.empty:
80
- adx_value = adx_result.get('ADX_14')
81
- if adx_value is not None and not adx_value.empty:
82
- trend['adx'] = float(adx_value.iloc[-1])
 
 
 
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
- if atr_value and dataframe['close'].iloc[-1] > 0:
158
- volatility['atr_percent'] = (atr_value / dataframe['close'].iloc[-1]) * 100
 
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 and 'timestamp' in dataframe.columns:
172
  try:
173
  # إنشاء نسخة من البيانات مع DatetimeIndex مرتب
174
  df_vwap = dataframe.copy()
175
 
176
  # تحويل timestamp إلى datetime وضبطه كـ index
177
  if not isinstance(df_vwap.index, pd.DatetimeIndex):
178
- df_vwap['timestamp'] = pd.to_datetime(df_vwap['timestamp'], unit='ms')
179
- df_vwap.set_index('timestamp', inplace=True)
 
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
- typical_price = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3
200
- vwap_simple = (typical_price * dataframe['volume']).sum() / dataframe['volume'].sum()
201
- volume['vwap'] = float(vwap_simple)
 
 
 
 
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 volume_avg_20 and volume_avg_20 > 0:
225
- volume['volume_ratio'] = float(dataframe['volume'].iloc[-1] / volume_avg_20)
 
 
 
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
- df = pd.DataFrame(candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
478
- df[['open', 'high', 'low', 'close', 'volume']] = df[['open', 'high', 'low', 'close', 'volume']].astype(float)
479
- return df
 
 
 
 
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
- df = pd.DataFrame(candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
1119
- df[['open', 'high', 'low', 'close', 'volume']] = df[['open', 'high', 'low', 'close', 'volume']].astype(float)
1120
-
1121
- # تحويل timestamp إلى datetime وضبطه كـ index
1122
- df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
1123
- df.set_index('timestamp', inplace=True)
1124
-
1125
- # التأكد من أن الفهرس مرتب
1126
- df.sort_index(inplace=True)
1127
-
1128
- return df
 
 
 
 
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 VWAP Issue & Enhanced Analysis")
 
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")