Riy777 commited on
Commit
0efffff
·
1 Parent(s): ac2081d

Update ml_engine/indicators.py

Browse files
Files changed (1) hide show
  1. ml_engine/indicators.py +30 -40
ml_engine/indicators.py CHANGED
@@ -1,4 +1,4 @@
1
- # ml_engine/indicators.py
2
  import pandas as pd
3
  import pandas_ta as ta
4
  import numpy as np
@@ -36,11 +36,9 @@ class AdvancedTechnicalAnalyzer:
36
  trend = {}
37
 
38
  try:
39
- # التحقق من وجود البيانات الأساسية
40
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
41
  return {}
42
 
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 and not pd.isna(ema_9.iloc[-1]):
@@ -61,12 +59,10 @@ class AdvancedTechnicalAnalyzer:
61
  if ema_200 is not None and not ema_200.empty and not pd.isna(ema_200.iloc[-1]):
62
  trend['ema_200'] = float(ema_200.iloc[-1])
63
 
64
- # إيشيموكو
65
  if len(dataframe) >= 26:
66
  try:
67
  ichimoku = ta.ichimoku(dataframe['high'], dataframe['low'], dataframe['close'])
68
  if ichimoku is not None and len(ichimoku) > 0:
69
- # التحقق من أن ichimoku ليس None وأنه يحتوي على بيانات
70
  conversion_line = ichimoku[0].get('ITS_9') if ichimoku[0] is not None else None
71
  base_line = ichimoku[0].get('IKS_26') if ichimoku[0] is not None else None
72
 
@@ -75,9 +71,8 @@ class AdvancedTechnicalAnalyzer:
75
  if base_line is not None and not base_line.empty and not pd.isna(base_line.iloc[-1]):
76
  trend['ichimoku_base'] = float(base_line.iloc[-1])
77
  except Exception as ichimoku_error:
78
- print(f"⚠️ خطأ في حساب إيشيموكو: {ichimoku_error}")
79
 
80
- # ADX - قوة الاتجاه
81
  if len(dataframe) >= 14:
82
  try:
83
  adx_result = ta.adx(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
@@ -86,7 +81,7 @@ class AdvancedTechnicalAnalyzer:
86
  if adx_value is not None and not adx_value.empty and not pd.isna(adx_value.iloc[-1]):
87
  trend['adx'] = float(adx_value.iloc[-1])
88
  except Exception as adx_error:
89
- print(f"⚠️ خطأ في حساب ADX: {adx_error}")
90
 
91
  except Exception as e:
92
  print(f"⚠️ خطأ في حساب مؤشرات الاتجاه: {e}")
@@ -98,17 +93,14 @@ class AdvancedTechnicalAnalyzer:
98
  momentum = {}
99
 
100
  try:
101
- # التحقق من وجود البيانات الأساسية
102
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
103
  return {}
104
 
105
- # RSI
106
  if len(dataframe) >= 14:
107
  rsi = ta.rsi(dataframe['close'], length=14)
108
  if rsi is not None and not rsi.empty and not pd.isna(rsi.iloc[-1]):
109
  momentum['rsi'] = float(rsi.iloc[-1])
110
 
111
- # MACD
112
  if len(dataframe) >= 26:
113
  macd = ta.macd(dataframe['close'])
114
  if macd is not None and not macd.empty:
@@ -120,7 +112,6 @@ class AdvancedTechnicalAnalyzer:
120
  if macd_line is not None and not macd_line.empty and not pd.isna(macd_line.iloc[-1]):
121
  momentum['macd_line'] = float(macd_line.iloc[-1])
122
 
123
- # ستوكاستك RSI
124
  if len(dataframe) >= 14:
125
  stoch_rsi = ta.stochrsi(dataframe['close'], length=14)
126
  if stoch_rsi is not None and not stoch_rsi.empty:
@@ -128,7 +119,6 @@ class AdvancedTechnicalAnalyzer:
128
  if stoch_k is not None and not stoch_k.empty and not pd.isna(stoch_k.iloc[-1]):
129
  momentum['stoch_rsi_k'] = float(stoch_k.iloc[-1])
130
 
131
- # ويليامز %R
132
  if len(dataframe) >= 14:
133
  williams = ta.willr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
134
  if williams is not None and not williams.empty and not pd.isna(williams.iloc[-1]):
@@ -144,11 +134,9 @@ class AdvancedTechnicalAnalyzer:
144
  volatility = {}
145
 
146
  try:
147
- # التحقق من وجود البيانات الأساسية
148
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
149
  return {}
150
 
151
- # بولينجر باندز
152
  if len(dataframe) >= 20:
153
  bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2)
154
  if bollinger_bands is not None and not bollinger_bands.empty:
@@ -163,7 +151,6 @@ class AdvancedTechnicalAnalyzer:
163
  if bb_middle is not None and not bb_middle.empty and not pd.isna(bb_middle.iloc[-1]):
164
  volatility['bb_middle'] = float(bb_middle.iloc[-1])
165
 
166
- # متوسط المدى الحقيقي (ATR)
167
  if len(dataframe) >= 14:
168
  average_true_range = ta.atr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
169
  if average_true_range is not None and not average_true_range.empty and not pd.isna(average_true_range.iloc[-1]):
@@ -176,46 +163,53 @@ class AdvancedTechnicalAnalyzer:
176
  except Exception as e:
177
  print(f"⚠️ خطأ في حساب مؤشرات التقلب: {e}")
178
 
179
- return {key: value for key, value in volatility.items() if value is not None and not np.isnan(value)}
180
 
 
181
  def _calculate_volume_indicators(self, dataframe, timeframe):
182
  """حساب مؤشرات الحجم"""
183
  volume = {}
184
 
185
  try:
186
- # التحقق من وجود البيانات الأساسية
187
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns or 'volume' not in dataframe.columns:
188
  return {}
189
 
190
- # VWAP - إصلاح المشكلة هنا
191
  if len(dataframe) >= 1:
192
  try:
193
- # إنشاء نسخة من البيانات مع DatetimeIndex مرتب
194
  df_vwap = dataframe.copy()
195
 
196
- # تحويل timestamp إلى datetime وضبطه كـ index
197
  if not isinstance(df_vwap.index, pd.DatetimeIndex):
198
  if 'timestamp' in df_vwap.columns:
199
  df_vwap['timestamp'] = pd.to_datetime(df_vwap['timestamp'], unit='ms')
200
  df_vwap.set_index('timestamp', inplace=True)
 
 
 
201
 
202
- # التأكد من أن الفهرس مرتب
203
  df_vwap.sort_index(inplace=True)
204
 
205
- # حساب VWAP
 
 
 
206
  volume_weighted_average_price = ta.vwap(
207
- high=df_vwap['high'],
208
- low=df_vwap['low'],
209
- close=df_vwap['close'],
210
- volume=df_vwap['volume']
211
  )
212
 
 
213
  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]):
214
  volume['vwap'] = float(volume_weighted_average_price.iloc[-1])
215
 
216
  except Exception as vwap_error:
217
- print(f"⚠️ خطأ في حساب VWAP لـ {timeframe}: {vwap_error}")
218
- # استخدام بديل لـ VWAP في حالة الخطأ
 
 
 
219
  if len(dataframe) >= 20:
220
  try:
221
  typical_price = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3
@@ -223,26 +217,24 @@ class AdvancedTechnicalAnalyzer:
223
  if not np.isnan(vwap_simple):
224
  volume['vwap'] = float(vwap_simple)
225
  except Exception as simple_vwap_error:
226
- print(f"⚠️ خطأ في حساب VWAP البديل: {simple_vwap_error}")
227
 
228
- # OBV
229
  try:
230
  on_balance_volume = ta.obv(dataframe['close'], dataframe['volume'])
231
  if on_balance_volume is not None and not on_balance_volume.empty and not pd.isna(on_balance_volume.iloc[-1]):
232
  volume['obv'] = float(on_balance_volume.iloc[-1])
233
  except Exception as obv_error:
234
- print(f"⚠️ خطأ في حساب OBV: {obv_error}")
235
 
236
- # MFI
237
  if len(dataframe) >= 14:
238
  try:
239
  money_flow_index = ta.mfi(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'], length=14)
240
  if money_flow_index is not None and not money_flow_index.empty and not pd.isna(money_flow_index.iloc[-1]):
241
  volume['mfi'] = float(money_flow_index.iloc[-1])
242
  except Exception as mfi_error:
243
- print(f"⚠️ خطأ في حساب MFI: {mfi_error}")
244
 
245
- # نسبة الحجم
246
  if len(dataframe) >= 20:
247
  try:
248
  volume_avg_20 = float(dataframe['volume'].tail(20).mean())
@@ -252,29 +244,27 @@ class AdvancedTechnicalAnalyzer:
252
  if not np.isnan(volume_ratio):
253
  volume['volume_ratio'] = volume_ratio
254
  except Exception as volume_error:
255
- print(f"⚠️ خطأ في حساب نسبة الحجم: {volume_error}")
256
 
257
  except Exception as e:
258
  print(f"⚠️ خطأ في حساب مؤشرات الحجم: {e}")
259
 
260
  return {key: value for key, value in volume.items() if value is not None and not np.isnan(value)}
 
261
 
262
  def _calculate_cycle_indicators(self, dataframe):
263
  """حساب مؤشرات الدورة"""
264
  cycle = {}
265
 
266
  try:
267
- # التحقق من وجود البيانات الأساسية
268
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
269
  return {}
270
 
271
- # هول موفينج افريج
272
  if len(dataframe) >= 9:
273
  hull_moving_average = ta.hma(dataframe['close'], length=9)
274
  if hull_moving_average is not None and not hull_moving_average.empty and not pd.isna(hull_moving_average.iloc[-1]):
275
  cycle['hull_ma'] = float(hull_moving_average.iloc[-1])
276
 
277
- # سوبرتريند
278
  if len(dataframe) >= 10:
279
  supertrend = ta.supertrend(dataframe['high'], dataframe['low'], dataframe['close'], length=10, multiplier=3)
280
  if supertrend is not None and not supertrend.empty:
@@ -287,4 +277,4 @@ class AdvancedTechnicalAnalyzer:
287
 
288
  return {key: value for key, value in cycle.items() if value is not None and not np.isnan(value)}
289
 
290
- print("✅ ML Module: Technical Indicators loaded")
 
1
+ # ml_engine/indicators.py (V5.1 - Fixed VWAP DatetimeIndex Error)
2
  import pandas as pd
3
  import pandas_ta as ta
4
  import numpy as np
 
36
  trend = {}
37
 
38
  try:
 
39
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
40
  return {}
41
 
 
42
  if len(dataframe) >= 9:
43
  ema_9 = ta.ema(dataframe['close'], length=9)
44
  if ema_9 is not None and not ema_9.empty and not pd.isna(ema_9.iloc[-1]):
 
59
  if ema_200 is not None and not ema_200.empty and not pd.isna(ema_200.iloc[-1]):
60
  trend['ema_200'] = float(ema_200.iloc[-1])
61
 
 
62
  if len(dataframe) >= 26:
63
  try:
64
  ichimoku = ta.ichimoku(dataframe['high'], dataframe['low'], dataframe['close'])
65
  if ichimoku is not None and len(ichimoku) > 0:
 
66
  conversion_line = ichimoku[0].get('ITS_9') if ichimoku[0] is not None else None
67
  base_line = ichimoku[0].get('IKS_26') if ichimoku[0] is not None else None
68
 
 
71
  if base_line is not None and not base_line.empty and not pd.isna(base_line.iloc[-1]):
72
  trend['ichimoku_base'] = float(base_line.iloc[-1])
73
  except Exception as ichimoku_error:
74
+ pass # (تقليل التشويش)
75
 
 
76
  if len(dataframe) >= 14:
77
  try:
78
  adx_result = ta.adx(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
 
81
  if adx_value is not None and not adx_value.empty and not pd.isna(adx_value.iloc[-1]):
82
  trend['adx'] = float(adx_value.iloc[-1])
83
  except Exception as adx_error:
84
+ pass # (تقليل التشويش)
85
 
86
  except Exception as e:
87
  print(f"⚠️ خطأ في حساب مؤشرات الاتجاه: {e}")
 
93
  momentum = {}
94
 
95
  try:
 
96
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
97
  return {}
98
 
 
99
  if len(dataframe) >= 14:
100
  rsi = ta.rsi(dataframe['close'], length=14)
101
  if rsi is not None and not rsi.empty and not pd.isna(rsi.iloc[-1]):
102
  momentum['rsi'] = float(rsi.iloc[-1])
103
 
 
104
  if len(dataframe) >= 26:
105
  macd = ta.macd(dataframe['close'])
106
  if macd is not None and not macd.empty:
 
112
  if macd_line is not None and not macd_line.empty and not pd.isna(macd_line.iloc[-1]):
113
  momentum['macd_line'] = float(macd_line.iloc[-1])
114
 
 
115
  if len(dataframe) >= 14:
116
  stoch_rsi = ta.stochrsi(dataframe['close'], length=14)
117
  if stoch_rsi is not None and not stoch_rsi.empty:
 
119
  if stoch_k is not None and not stoch_k.empty and not pd.isna(stoch_k.iloc[-1]):
120
  momentum['stoch_rsi_k'] = float(stoch_k.iloc[-1])
121
 
 
122
  if len(dataframe) >= 14:
123
  williams = ta.willr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
124
  if williams is not None and not williams.empty and not pd.isna(williams.iloc[-1]):
 
134
  volatility = {}
135
 
136
  try:
 
137
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
138
  return {}
139
 
 
140
  if len(dataframe) >= 20:
141
  bollinger_bands = ta.bbands(dataframe['close'], length=20, std=2)
142
  if bollinger_bands is not None and not bollinger_bands.empty:
 
151
  if bb_middle is not None and not bb_middle.empty and not pd.isna(bb_middle.iloc[-1]):
152
  volatility['bb_middle'] = float(bb_middle.iloc[-1])
153
 
 
154
  if len(dataframe) >= 14:
155
  average_true_range = ta.atr(dataframe['high'], dataframe['low'], dataframe['close'], length=14)
156
  if average_true_range is not None and not average_true_range.empty and not pd.isna(average_true_range.iloc[-1]):
 
163
  except Exception as e:
164
  print(f"⚠️ خطأ في حساب مؤشرات التقلب: {e}")
165
 
166
+ return {key: value for key, value in volume.items() if value is not None and not np.isnan(value)}
167
 
168
+ # 🔴 --- START OF CHANGE (V5.1 - VWAP FIX) --- 🔴
169
  def _calculate_volume_indicators(self, dataframe, timeframe):
170
  """حساب مؤشرات الحجم"""
171
  volume = {}
172
 
173
  try:
 
174
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns or 'volume' not in dataframe.columns:
175
  return {}
176
 
 
177
  if len(dataframe) >= 1:
178
  try:
 
179
  df_vwap = dataframe.copy()
180
 
181
+ # (التحقق من الفهرس وترتيبه - كما كان)
182
  if not isinstance(df_vwap.index, pd.DatetimeIndex):
183
  if 'timestamp' in df_vwap.columns:
184
  df_vwap['timestamp'] = pd.to_datetime(df_vwap['timestamp'], unit='ms')
185
  df_vwap.set_index('timestamp', inplace=True)
186
+ else:
187
+ # (إذا لم يكن هناك فهرس زمني ولا عمود، لا يمكن المتابعة)
188
+ raise ValueError("DataFrame needs 'timestamp' column or DatetimeIndex")
189
 
 
190
  df_vwap.sort_index(inplace=True)
191
 
192
+ # (الإصلاح: إعادة تعيين الفهرس لتمرير أعمدة Series بسيطة إلى ta.vwap)
193
+ # (هذا يتجنب مشاكل مكتبة pandas_ta مع الفهرس الزمني)
194
+ df_vwap_reset = df_vwap.reset_index()
195
+
196
  volume_weighted_average_price = ta.vwap(
197
+ high=df_vwap_reset['high'],
198
+ low=df_vwap_reset['low'],
199
+ close=df_vwap_reset['close'],
200
+ volume=df_vwap_reset['volume']
201
  )
202
 
203
+ # (استخدام القيمة الأخيرة من السلسلة الناتجة)
204
  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]):
205
  volume['vwap'] = float(volume_weighted_average_price.iloc[-1])
206
 
207
  except Exception as vwap_error:
208
+ # (تقليل التشويش: طباعة فقط إذا كان الخطأ جوهرياً)
209
+ if "Index" not in str(vwap_error):
210
+ print(f"⚠️ خطأ في حساب VWAP لـ {timeframe}: {vwap_error}")
211
+
212
+ # (الكود الاحتياطي يبقى كما هو)
213
  if len(dataframe) >= 20:
214
  try:
215
  typical_price = (dataframe['high'] + dataframe['low'] + dataframe['close']) / 3
 
217
  if not np.isnan(vwap_simple):
218
  volume['vwap'] = float(vwap_simple)
219
  except Exception as simple_vwap_error:
220
+ pass
221
 
222
+ # (باقي مؤشرات الحجم - لا تغيير)
223
  try:
224
  on_balance_volume = ta.obv(dataframe['close'], dataframe['volume'])
225
  if on_balance_volume is not None and not on_balance_volume.empty and not pd.isna(on_balance_volume.iloc[-1]):
226
  volume['obv'] = float(on_balance_volume.iloc[-1])
227
  except Exception as obv_error:
228
+ pass
229
 
 
230
  if len(dataframe) >= 14:
231
  try:
232
  money_flow_index = ta.mfi(dataframe['high'], dataframe['low'], dataframe['close'], dataframe['volume'], length=14)
233
  if money_flow_index is not None and not money_flow_index.empty and not pd.isna(money_flow_index.iloc[-1]):
234
  volume['mfi'] = float(money_flow_index.iloc[-1])
235
  except Exception as mfi_error:
236
+ pass
237
 
 
238
  if len(dataframe) >= 20:
239
  try:
240
  volume_avg_20 = float(dataframe['volume'].tail(20).mean())
 
244
  if not np.isnan(volume_ratio):
245
  volume['volume_ratio'] = volume_ratio
246
  except Exception as volume_error:
247
+ pass
248
 
249
  except Exception as e:
250
  print(f"⚠️ خطأ في حساب مؤشرات الحجم: {e}")
251
 
252
  return {key: value for key, value in volume.items() if value is not None and not np.isnan(value)}
253
+ # 🔴 --- END OF CHANGE (V5.1 - VWAP FIX) --- 🔴
254
 
255
  def _calculate_cycle_indicators(self, dataframe):
256
  """حساب مؤشرات الدورة"""
257
  cycle = {}
258
 
259
  try:
 
260
  if dataframe is None or dataframe.empty or 'close' not in dataframe.columns:
261
  return {}
262
 
 
263
  if len(dataframe) >= 9:
264
  hull_moving_average = ta.hma(dataframe['close'], length=9)
265
  if hull_moving_average is not None and not hull_moving_average.empty and not pd.isna(hull_moving_average.iloc[-1]):
266
  cycle['hull_ma'] = float(hull_moving_average.iloc[-1])
267
 
 
268
  if len(dataframe) >= 10:
269
  supertrend = ta.supertrend(dataframe['high'], dataframe['low'], dataframe['close'], length=10, multiplier=3)
270
  if supertrend is not None and not supertrend.empty:
 
277
 
278
  return {key: value for key, value in cycle.items() if value is not None and not np.isnan(value)}
279
 
280
+ print("✅ ML Module: Technical Indicators loaded (V5.1 - VWAP Fix)")