Riy777 commited on
Commit
bf478e8
·
1 Parent(s): 6c7250f

Update ml_engine/patterns.py

Browse files
Files changed (1) hide show
  1. ml_engine/patterns.py +84 -68
ml_engine/patterns.py CHANGED
@@ -1,5 +1,5 @@
1
  # ml_engine/patterns.py
2
- # (V8.2 - إصلاح التوافق: تغذية المؤشرات يدوياً (H/L/C/V) لإصلاح KeyError)
3
 
4
  import pandas as pd
5
  import numpy as np
@@ -87,92 +87,106 @@ class ChartPatternAnalyzer:
87
  self.scaler = None
88
  return False
89
 
90
- # 🔴 --- START OF CHANGE (V8.2) --- 🔴
 
91
  def _extract_features(self, df_window: pd.DataFrame) -> pd.DataFrame:
92
  """
93
- (الوصفة V8 - معدلة - V8.2)
94
- حساب الـ 30 مؤشراً (يدوياً) مع تمرير الأعمدة صراحة لإصلاح KeyError
95
  """
96
  if not ta:
97
  raise ImportError("مكتبة pandas-ta غير مثبتة.")
98
 
99
- df = df_window.copy()
100
- c = df['close']
101
- h = df['high']
102
- l = df['low']
103
- v = df['volume']
 
 
 
 
104
 
105
  try:
106
- # (RSI)
107
- df.ta.rsi(close=c, length=14, append=True)
108
- # (MACD)
109
- df.ta.macd(close=c, fast=12, slow=26, signal=9, append=True)
110
- # (SMA, EMA)
111
- df.ta.sma(close=c, length=20, append=True)
112
- df.ta.ema(close=c, length=20, append=True)
113
- # (BBands)
114
- df.ta.bbands(close=c, length=5, std=2.0, append=True)
115
- # (Stoch)
116
- df.ta.stoch(high=h, low=l, close=c, k=14, d=3, smooth_k=3, append=True)
117
- # (ADX)
118
- df.ta.adx(high=h, low=l, close=c, length=14, adxr=2, append=True)
119
- # (VWAP)
120
- df.ta.vwap(high=h, low=l, close=c, volume=v, append=True)
121
- # (Midpoint)
122
- df.ta.midpoint(close=c, length=14, append=True)
123
- # (TEMA)
124
- df.ta.tema(close=c, length=20, append=True)
125
- # (OBV, AD)
126
- df.ta.obv(close=c, volume=v, append=True)
127
- df.ta.ad(high=h, low=l, close=c, volume=v, append=True)
128
- # (ATRr)
129
- df.ta.atr(high=h, low=l, close=c, percent=True, length=14, append=True)
130
- # (DPO)
131
- df.ta.dpo(close=c, length=20, append=True)
132
- # (KVO)
133
- df.ta.kvo(high=h, low=l, close=c, volume=v, fast=34, slow=55, signal=13, append=True)
134
- # (CMO)
135
- df.ta.cmo(close=c, length=14, append=True)
136
- # (ROC)
137
- df.ta.roc(close=c, length=10, append=True)
138
- # (Williams %R)
139
- df.ta.willr(high=h, low=l, close=c, length=14, append=True)
140
- except Exception as e:
141
- print(f"❌ [PatternEngineV8.2] خطأ أثناء حساب المؤشرات يدوياً: {e}")
142
- pass
143
 
144
- # (إعادة تسمية الأعمدة لتطابق X_test_combined.csv بالضبط)
145
- rename_map = {
146
- 'RSI_14': 'RSI_14', 'MACD_12_26_9': 'MACD_12_26_9', 'MACDh_12_26_9': 'MACDh_12_26_9',
147
- 'MACDs_12_26_9': 'MACDs_12_26_9', 'SMA_20': 'SMA_20', 'EMA_20': 'EMA_20',
148
- 'BBL_5_2.0': 'BBL_5_2.0_2.0', 'BBM_5_2.0': 'BBM_5_2.0_2.0', 'BBU_5_2.0': 'BBU_5_2.0_2.0',
149
- 'BBB_5_2.0': 'BBB_5_2.0_2.0', 'BBP_5_2.0': 'BBP_5_2.0_2.0',
150
- 'STOCHk_14_3_3': 'STOCHk_14_3_3', 'STOCHd_14_3_3': 'STOCHd_14_3_3', 'STOCHh_14_3_3': 'STOCHh_14_3_3',
151
- 'ADX_14': 'ADX_14', 'ADXR_14_2': 'ADXR_14_2', 'DMP_14': 'DMP_14', 'DMN_14': 'DMN_14',
152
- 'VWAP_D': 'VWAP_D', 'MIDPOINT_14': 'MIDPOINT_14', 'TEMA_20': 'TEMA_20', 'OBV': 'OBV',
153
- 'AD': 'AD', 'ATRr_14': 'ATRr_14', 'DPO_20': 'DPO_20', 'KVO_34_55_13': 'KVO_34_55_13',
154
- 'KVOs_34_55_13': 'KVOs_34_55_13', 'CMO_14': 'CMO_14', 'ROC_10': 'ROC_10', 'WILLR_14': 'WILLR_14'
155
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
- df.rename(columns=rename_map, inplace=True)
 
 
 
 
158
 
159
- # (العودة بالصف الأخير فقط)
160
  last_features = df.iloc[-1:].copy()
161
 
162
  # (إصلاح FutureWarning)
163
  last_features.ffill(inplace=True)
164
  last_features.fillna(0, inplace=True)
165
 
 
166
  final_features = pd.DataFrame(columns=self.indicator_features)
167
 
168
  for col in self.indicator_features:
169
  if col in last_features:
170
  final_features[col] = last_features[col].values
171
  else:
 
172
  final_features[col] = 0
173
 
174
  return final_features
175
- # 🔴 --- END OF CHANGE (V8.2) --- 🔴
176
 
177
  async def detect_chart_patterns(self, ohlcv_data: dict) -> dict:
178
  """
@@ -202,18 +216,20 @@ class ChartPatternAnalyzer:
202
  window_candles = candles[-200:]
203
  df_window = pd.DataFrame(window_candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
204
 
205
- df_window['timestamp'] = pd.to_datetime(df_window['timestamp'], unit='ms')
206
- df_window.set_index('timestamp', inplace=True)
 
207
 
208
- # 1. استخراج الخصائص (الوصفة V8.2 اليدوية)
209
  features_df = self._extract_features(df_window)
210
 
211
  if features_df is None or features_df.empty:
212
  continue
213
 
214
  # 2. تطبيع الخصائص (Scaler)
215
- features_df = features_df[self.scaler.feature_names_in_]
216
- features_scaled = self.scaler.transform(features_df)
 
217
 
218
  # 3. التنبؤ بالاحتماليات (Probabilities)
219
  probabilities = self.model.predict_proba(features_scaled)[0]
@@ -230,7 +246,7 @@ class ChartPatternAnalyzer:
230
  })
231
 
232
  except Exception as e:
233
- print(f"❌ [PatternEngineV8.2] فشل التنبؤ لـ {timeframe}: {e}")
234
 
235
  # 4. اختيار أفضل نمط من *جميع* الأطر الزمنية
236
  if all_results:
@@ -248,4 +264,4 @@ class ChartPatternAnalyzer:
248
 
249
  return best_match
250
 
251
- print("✅ ML Module: Pattern Engine V8.2 (Manual Indicators Feed) loaded")
 
1
  # ml_engine/patterns.py
2
+ # (V8.3 - إصلاح KeyError: استخدام الاستدعاء الوظيفي المباشر)
3
 
4
  import pandas as pd
5
  import numpy as np
 
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']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
+ df['SMA_20'] = ta.sma(c, length=20)
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']
129
+ df['BBB_5_2.0_2.0'] = bb_data['BBB_5_2.0']
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
+
149
+ df['MIDPOINT_14'] = ta.midpoint(c, length=14)
150
+ df['TEMA_20'] = ta.tema(c, length=20)
151
+ df['OBV'] = ta.obv(c, v)
152
+ df['AD'] = ta.ad(h, l, c, v)
153
+ df['ATRr_14'] = ta.atr(h, l, c, percent=True, length=14)
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
+
161
+ df['CMO_14'] = ta.cmo(c, length=14)
162
+ df['ROC_10'] = ta.roc(c, length=10)
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
 
178
+ # (التأكد من أننا نمرر فقط الخصائص الـ 30 التي يتوقعها النموذج، وبالترتيب)
179
  final_features = pd.DataFrame(columns=self.indicator_features)
180
 
181
  for col in self.indicator_features:
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
  """
 
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
 
234
  # 3. التنبؤ بالاحتماليات (Probabilities)
235
  probabilities = self.model.predict_proba(features_scaled)[0]
 
246
  })
247
 
248
  except Exception as e:
249
+ print(f"❌ [PatternEngineV8.3] فشل التنبؤ لـ {timeframe}: {e}")
250
 
251
  # 4. اختيار أفضل نمط من *جميع* الأطر الزمنية
252
  if all_results:
 
264
 
265
  return best_match
266
 
267
+ print("✅ ML Module: Pattern Engine V8.3 (Direct Functional Calls) loaded")