Riy777 commited on
Commit
0c195bb
·
1 Parent(s): e424c99

Update ml_engine/patterns.py

Browse files
Files changed (1) hide show
  1. ml_engine/patterns.py +30 -33
ml_engine/patterns.py CHANGED
@@ -1,5 +1,5 @@
1
  # ml_engine/patterns.py
2
- # (V8.3 - إصلاح KeyError: استخدام الاستدعاء الوظيفي المباشر)
3
 
4
  import pandas as pd
5
  import numpy as np
@@ -87,32 +87,33 @@ class ChartPatternAnalyzer:
87
  self.scaler = None
88
  return False
89
 
90
- # 🔴 --- START OF CHANGE (V8.3) --- 🔴
91
- # (V8.3 - إصلاح KeyError: استخدام الاستدعاء الوظيفي المباشر بدلاً من ملحق .ta)
92
  def _extract_features(self, df_window: pd.DataFrame) -> pd.DataFrame:
93
  """
94
- (الوصفة V8 - معدلة - V8.3)
95
- حساب الـ 30 مؤشراً (وظيفياً) لتجنب أخطاء ملحق .ta
96
  """
97
  if not ta:
98
  raise ImportError("مكتبة pandas-ta غير مثبتة.")
99
 
100
  # (إنشاء DF فارغ بنفس الفهرس (Index) الخاص بآخر صف)
101
- # (هذا يضمن أننا نأخذ آخر قيمة فقط من حسابات المؤشرات)
102
  df = pd.DataFrame(index=df_window.iloc[-1:].index)
103
 
104
- # (تمرير الأعمدة كسلاسل (Series) مباشرة)
105
- c = df_window['close']
106
- h = df_window['high']
107
- l = df_window['low']
108
- v = df_window['volume']
 
109
 
110
  try:
111
  # --- حساب المؤشرات وظيفياً ---
112
  df['RSI_14'] = ta.rsi(c, length=14)
113
 
114
  macd_data = ta.macd(c, fast=12, slow=26, signal=9)
115
- if macd_data is not None and not macd_data.empty:
 
116
  df['MACD_12_26_9'] = macd_data['MACD_12_26_9']
117
  df['MACDh_12_26_9'] = macd_data['MACDh_12_26_9']
118
  df['MACDs_12_26_9'] = macd_data['MACDs_12_26_9']
@@ -121,8 +122,8 @@ class ChartPatternAnalyzer:
121
  df['EMA_20'] = ta.ema(c, length=20)
122
 
123
  bb_data = ta.bbands(c, length=5, std=2.0)
124
- if bb_data is not None and not bb_data.empty:
125
- # (إعادة التسمية لتطابق توقعات النموذج)
126
  df['BBL_5_2.0_2.0'] = bb_data['BBL_5_2.0']
127
  df['BBM_5_2.0_2.0'] = bb_data['BBM_5_2.0']
128
  df['BBU_5_2.0_2.0'] = bb_data['BBU_5_2.0']
@@ -130,19 +131,20 @@ class ChartPatternAnalyzer:
130
  df['BBP_5_2.0_2.0'] = bb_data['BBP_5_2.0']
131
 
132
  stoch_data = ta.stoch(h, l, c, k=14, d=3, smooth_k=3)
133
- if stoch_data is not None and not stoch_data.empty:
 
134
  df['STOCHk_14_3_3'] = stoch_data['STOCHk_14_3_3']
135
  df['STOCHd_14_3_3'] = stoch_data['STOCHd_14_3_3']
136
  df['STOCHh_14_3_3'] = stoch_data['STOCHh_14_3_3']
137
 
138
  adx_data = ta.adx(h, l, c, length=14, adxr=2)
139
- if adx_data is not None and not adx_data.empty:
 
140
  df['ADX_14'] = adx_data['ADX_14']
141
  df['ADXR_14_2'] = adx_data['ADXR_14_2']
142
  df['DMP_14'] = adx_data['DMP_14']
143
  df['DMN_14'] = adx_data['DMN_14']
144
 
145
- # (VWAP يحتاج تمرير البيانات بهذه الطريقة)
146
  vwap_series = ta.vwap(h, l, c, v)
147
  if vwap_series is not None: df['VWAP_D'] = vwap_series
148
 
@@ -154,7 +156,8 @@ class ChartPatternAnalyzer:
154
  df['DPO_20'] = ta.dpo(c, length=20)
155
 
156
  kvo_data = ta.kvo(h, l, c, v, fast=34, slow=55, signal=13)
157
- if kvo_data is not None and not kvo_data.empty:
 
158
  df['KVO_34_55_13'] = kvo_data['KVO_34_55_13']
159
  df['KVOs_34_55_13'] = kvo_data['KVOs_34_55_13']
160
 
@@ -163,15 +166,13 @@ class ChartPatternAnalyzer:
163
  df['WILLR_14'] = ta.willr(h, l, c, length=14)
164
 
165
  except Exception as e:
166
- print(f"❌ [PatternEngineV8.3] خطأ أثناء حساب المؤشرات وظيفياً: {e}")
167
- # (سنستمر، والصفوف المفقودة سيتم ملؤها بـ 0)
168
  pass
169
  # --- (نهاية حساب المؤشرات) ---
170
 
171
- # (نأخذ الصف الأخير فقط، لأن المؤشرات السابقة حسبت كل شيء)
172
  last_features = df.iloc[-1:].copy()
173
 
174
- # (إصلاح FutureWarning)
175
  last_features.ffill(inplace=True)
176
  last_features.fillna(0, inplace=True)
177
 
@@ -182,16 +183,14 @@ class ChartPatternAnalyzer:
182
  if col in last_features:
183
  final_features[col] = last_features[col].values
184
  else:
185
- # (إذا فشل حساب المؤشر، نضع 0)
186
  final_features[col] = 0
187
 
188
  return final_features
189
- # 🔴 --- END OF CHANGE (V8.3) --- 🔴
190
 
191
  async def detect_chart_patterns(self, ohlcv_data: dict) -> dict:
192
  """
193
  (الدالة الرئيسية التي يستدعيها النظام)
194
- تستخدم نموذج 58% للتنبؤ بالنمط.
195
  """
196
  best_match = {
197
  'pattern_detected': 'no_clear_pattern',
@@ -210,24 +209,21 @@ class ChartPatternAnalyzer:
210
  all_results = []
211
 
212
  for timeframe, candles in ohlcv_data.items():
213
- # (نحتاج إلى بيانات كافية لحساب المؤشرات، 200 شمعة هي الأفضل)
214
  if len(candles) >= max(self.window_size, 200):
215
  try:
216
  window_candles = candles[-200:]
217
  df_window = pd.DataFrame(window_candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
218
 
219
- # (V8.3) ملاحظة: لا نضع 'timestamp' كفهرس هنا
220
- # df_window['timestamp'] = pd.to_datetime(df_window['timestamp'], unit='ms')
221
- # df_window.set_index('timestamp', inplace=True)
222
 
223
- # 1. استخراج الخصائص (الوصفة V8.3 اليدوية)
224
  features_df = self._extract_features(df_window)
225
 
226
  if features_df is None or features_df.empty:
227
  continue
228
 
229
  # 2. تطبيع الخصائص (Scaler)
230
- # (التأكد من مطابقة الأسماء التي يتوقعها المقياس)
231
  features_df_ordered = features_df[self.scaler.feature_names_in_]
232
  features_scaled = self.scaler.transform(features_df_ordered)
233
 
@@ -246,7 +242,8 @@ class ChartPatternAnalyzer:
246
  })
247
 
248
  except Exception as e:
249
- print(f"❌ [PatternEngineV8.3] فشل التنبؤ لـ {timeframe}: {e}")
 
250
 
251
  # 4. اختيار أفضل نمط من *جميع* الأطر الزمنية
252
  if all_results:
@@ -264,4 +261,4 @@ class ChartPatternAnalyzer:
264
 
265
  return best_match
266
 
267
- print("✅ ML Module: Pattern Engine V8.3 (Direct Functional Calls) loaded")
 
1
  # ml_engine/patterns.py
2
+ # (V8.4 - إصلاح KeyError: استخدام .copy() لعزل السلاسل (Series) + فحوصات أقوى للأعمدة)
3
 
4
  import pandas as pd
5
  import numpy as np
 
87
  self.scaler = None
88
  return False
89
 
90
+ # 🔴 --- START OF CHANGE (V8.4) --- 🔴
91
+ # (V8.4 - إصلاح KeyError: استخدام .copy() لعزل السلاسل (Series) + فحوصات أقوى للأعمدة)
92
  def _extract_features(self, df_window: pd.DataFrame) -> pd.DataFrame:
93
  """
94
+ (الوصفة V8 - معدلة - V8.4)
95
+ حساب الـ 30 مؤشراً (وظيفياً) مع عزل البيانات
96
  """
97
  if not ta:
98
  raise ImportError("مكتبة pandas-ta غير مثبتة.")
99
 
100
  # (إنشاء DF فارغ بنفس الفهرس (Index) الخاص بآخر صف)
 
101
  df = pd.DataFrame(index=df_window.iloc[-1:].index)
102
 
103
+ # (تمرير الأعمدة كـ "نسخ" (.copy()) لعزلها عن df_window)
104
+ # (هذا يمنع pandas-ta من محاولة الوصول للـ DataFrame الأصلي)
105
+ c = df_window['close'].copy()
106
+ h = df_window['high'].copy()
107
+ l = df_window['low'].copy()
108
+ v = df_window['volume'].copy()
109
 
110
  try:
111
  # --- حساب المؤشرات وظيفياً ---
112
  df['RSI_14'] = ta.rsi(c, length=14)
113
 
114
  macd_data = ta.macd(c, fast=12, slow=26, signal=9)
115
+ # (فحص الحماية V8.4)
116
+ if macd_data is not None and not macd_data.empty and 'MACD_12_26_9' in macd_data.columns:
117
  df['MACD_12_26_9'] = macd_data['MACD_12_26_9']
118
  df['MACDh_12_26_9'] = macd_data['MACDh_12_26_9']
119
  df['MACDs_12_26_9'] = macd_data['MACDs_12_26_9']
 
122
  df['EMA_20'] = ta.ema(c, length=20)
123
 
124
  bb_data = ta.bbands(c, length=5, std=2.0)
125
+ # (فحص الحماية V8.4)
126
+ if bb_data is not None and not bb_data.empty and 'BBL_5_2.0' in bb_data.columns:
127
  df['BBL_5_2.0_2.0'] = bb_data['BBL_5_2.0']
128
  df['BBM_5_2.0_2.0'] = bb_data['BBM_5_2.0']
129
  df['BBU_5_2.0_2.0'] = bb_data['BBU_5_2.0']
 
131
  df['BBP_5_2.0_2.0'] = bb_data['BBP_5_2.0']
132
 
133
  stoch_data = ta.stoch(h, l, c, k=14, d=3, smooth_k=3)
134
+ # (فحص الحماية V8.4)
135
+ if stoch_data is not None and not stoch_data.empty and 'STOCHk_14_3_3' in stoch_data.columns:
136
  df['STOCHk_14_3_3'] = stoch_data['STOCHk_14_3_3']
137
  df['STOCHd_14_3_3'] = stoch_data['STOCHd_14_3_3']
138
  df['STOCHh_14_3_3'] = stoch_data['STOCHh_14_3_3']
139
 
140
  adx_data = ta.adx(h, l, c, length=14, adxr=2)
141
+ # (فحص الحماية V8.4)
142
+ if adx_data is not None and not adx_data.empty and 'ADX_14' in adx_data.columns:
143
  df['ADX_14'] = adx_data['ADX_14']
144
  df['ADXR_14_2'] = adx_data['ADXR_14_2']
145
  df['DMP_14'] = adx_data['DMP_14']
146
  df['DMN_14'] = adx_data['DMN_14']
147
 
 
148
  vwap_series = ta.vwap(h, l, c, v)
149
  if vwap_series is not None: df['VWAP_D'] = vwap_series
150
 
 
156
  df['DPO_20'] = ta.dpo(c, length=20)
157
 
158
  kvo_data = ta.kvo(h, l, c, v, fast=34, slow=55, signal=13)
159
+ # (فحص الحماية V8.4)
160
+ if kvo_data is not None and not kvo_data.empty and 'KVO_34_55_13' in kvo_data.columns:
161
  df['KVO_34_55_13'] = kvo_data['KVO_34_55_13']
162
  df['KVOs_34_55_13'] = kvo_data['KVOs_34_55_13']
163
 
 
166
  df['WILLR_14'] = ta.willr(h, l, c, length=14)
167
 
168
  except Exception as e:
169
+ print(f"❌ [PatternEngineV8.4] خطأ أثناء حساب المؤشرات وظيفياً: {e}")
 
170
  pass
171
  # --- (نهاية حساب المؤشرات) ---
172
 
173
+ # (نأخذ الصف الأخير فقط)
174
  last_features = df.iloc[-1:].copy()
175
 
 
176
  last_features.ffill(inplace=True)
177
  last_features.fillna(0, inplace=True)
178
 
 
183
  if col in last_features:
184
  final_features[col] = last_features[col].values
185
  else:
 
186
  final_features[col] = 0
187
 
188
  return final_features
189
+ # 🔴 --- END OF CHANGE (V8.4) --- 🔴
190
 
191
  async def detect_chart_patterns(self, ohlcv_data: dict) -> dict:
192
  """
193
  (الدالة الرئيسية التي يستدعيها النظام)
 
194
  """
195
  best_match = {
196
  'pattern_detected': 'no_clear_pattern',
 
209
  all_results = []
210
 
211
  for timeframe, candles in ohlcv_data.items():
 
212
  if len(candles) >= max(self.window_size, 200):
213
  try:
214
  window_candles = candles[-200:]
215
  df_window = pd.DataFrame(window_candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
216
 
217
+ # (ملاحظة V8.4: لا نزال لا نحتاج إلى set_index هنا،
218
+ # لأن _extract_features V8.4 يتعامل مع الفهرس الرقمي بشكل صحيح)
 
219
 
220
+ # 1. استخراج الخصائص (الوصفة V8.4)
221
  features_df = self._extract_features(df_window)
222
 
223
  if features_df is None or features_df.empty:
224
  continue
225
 
226
  # 2. تطبيع الخصائص (Scaler)
 
227
  features_df_ordered = features_df[self.scaler.feature_names_in_]
228
  features_scaled = self.scaler.transform(features_df_ordered)
229
 
 
242
  })
243
 
244
  except Exception as e:
245
+ # (يجب أن تختفي أخطاء KeyError من هنا الآن)
246
+ print(f"❌ [PatternEngineV8.4] فشل التنبؤ لـ {timeframe}: {e}")
247
 
248
  # 4. اختيار أفضل نمط من *جميع* الأطر الزمنية
249
  if all_results:
 
261
 
262
  return best_match
263
 
264
+ print("✅ ML Module: Pattern Engine V8.4 (Isolated Series + Robust Checks) loaded")