Riy777 commited on
Commit
11a5219
·
1 Parent(s): d1e5af1

Update ml_engine/titan_engine.py

Browse files
Files changed (1) hide show
  1. ml_engine/titan_engine.py +84 -41
ml_engine/titan_engine.py CHANGED
@@ -1,5 +1,5 @@
1
  # ml_engine/titan_engine.py
2
- # (V1.0 - Titan Inference Engine)
3
 
4
  import os
5
  import joblib
@@ -8,6 +8,7 @@ import pandas as pd
8
  import pandas_ta as ta
9
  import xgboost as xgb
10
  import json
 
11
 
12
  class TitanEngine:
13
  def __init__(self, model_dir="ml_models/layer2"):
@@ -37,45 +38,85 @@ class TitanEngine:
37
  print(f"❌ [Titan] خطأ فادح أثناء التهيئة: {e}")
38
 
39
  def apply_inverted_pyramid(self, df, tf):
40
- """نفس منطق هندسة الميزات المستخدم في التدريب تماماً"""
41
  df = df.copy().sort_values('timestamp').reset_index(drop=True)
42
  # تعيين الفهرس للسهولة في pandas_ta
43
  df = df.set_index(pd.DatetimeIndex(pd.to_datetime(df['timestamp'], unit='ms')))
44
 
45
- # --- المستوى 1: دقيق (5m, 15m) ---
46
- if tf in ['5m', '15m']:
47
- df['RSI'] = ta.rsi(df['close'], length=14)
48
- df['MACD'] = ta.macd(df['close']).iloc[:, 0]
49
- df['MACD_h'] = ta.macd(df['close']).iloc[:, 1]
50
- df['CCI'] = ta.cci(df['high'], df['low'], df['close'], length=20)
51
- df['ADX'] = ta.adx(df['high'], df['low'], df['close'], length=14).iloc[:, 0]
52
- for p in [9, 21, 50, 200]:
53
- ema = ta.ema(df['close'], length=p)
54
- df[f'EMA_{p}_dist'] = (df['close'] / ema) - 1
55
- bb = ta.bbands(df['close'], length=20, std=2.0)
56
- df['BB_w'] = (bb.iloc[:, 2] - bb.iloc[:, 0]) / bb.iloc[:, 1]
57
- df['BB_p'] = (df['close'] - bb.iloc[:, 0]) / (bb.iloc[:, 2] - bb.iloc[:, 0])
58
- df['MFI'] = ta.mfi(df['high'], df['low'], df['close'], df['volume'], length=14)
59
- vwap = ta.vwap(df['high'], df['low'], df['close'], df['volume'])
60
- df['VWAP_dist'] = (df['close'] / vwap) - 1
61
-
62
- # --- المستوى 2: تكتيكي (1h, 4h) ---
63
- elif tf in ['1h', '4h']:
64
- df['RSI'] = ta.rsi(df['close'], length=14)
65
- df['MACD_h'] = ta.macd(df['close']).iloc[:, 1]
66
- df['EMA_50_dist'] = (df['close'] / ta.ema(df['close'], length=50)) - 1
67
- df['EMA_200_dist'] = (df['close'] / ta.ema(df['close'], length=200)) - 1
68
- df['ATR_pct'] = ta.atr(df['high'], df['low'], df['close'], length=14) / df['close']
69
-
70
- # --- المستوى 3: استراتيجي (1d) ---
71
- elif tf == '1d':
72
- df['RSI'] = ta.rsi(df['close'], length=14)
73
- df['EMA_200_dist'] = (df['close'] / ta.ema(df['close'], length=200)) - 1
74
- adx = ta.adx(df['high'], df['low'], df['close'])
75
- if adx is not None and not adx.empty:
76
- df['Trend_Strong'] = np.where(adx.iloc[:, 0] > 25, 1, 0)
77
- else:
78
- df['Trend_Strong'] = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
  return df.reset_index(drop=True)
81
 
@@ -98,12 +139,14 @@ class TitanEngine:
98
  else:
99
  df = data.copy()
100
 
101
- # تطبيق المؤشرات حسب الإطار
 
 
102
  df = self.apply_inverted_pyramid(df, tf)
103
  processed_tfs[tf] = df
104
 
105
  # 2. الدمج (Alignment) للحصول على آخر لقطة (Latest Snapshot)
106
- if '5m' not in processed_tfs:
107
  return {'score': 0.0, 'error': 'Missing 5m base timeframe'}
108
 
109
  # نأخذ آخر صف فقط من الـ 5m كأساس
@@ -114,7 +157,7 @@ class TitanEngine:
114
 
115
  # دمج باقي الأطر (نأخذ آخر شمعة أغلقت قبل أو مع شمعة الـ 5m الحالية)
116
  for tf, df in processed_tfs.items():
117
- if tf == '5m': continue
118
  # العثور على الشمعة المناسبة زمنياً
119
  relevant_row = df[df['timestamp'] <= latest_ts].iloc[-1:].copy()
120
  if relevant_row.empty: continue
@@ -136,7 +179,8 @@ class TitanEngine:
136
 
137
  # 4. التنبؤ
138
  # تحويل إلى DMatrix (تنسيق XGBoost السريع)
139
- dtest = xgb.DMatrix([input_data], feature_names=self.feature_names)
 
140
  prediction = self.model.predict(dtest)[0] # إرجاع الاحتمالية الأولى
141
 
142
  return {
@@ -147,6 +191,5 @@ class TitanEngine:
147
 
148
  except Exception as e:
149
  # print(f"⚠️ [Titan Error] {e}")
150
- import traceback
151
  traceback.print_exc()
152
  return {'score': 0.0, 'error': str(e)}
 
1
  # ml_engine/titan_engine.py
2
+ # (V1.1 - Titan Inference Engine - Robust Fix)
3
 
4
  import os
5
  import joblib
 
8
  import pandas_ta as ta
9
  import xgboost as xgb
10
  import json
11
+ import traceback
12
 
13
  class TitanEngine:
14
  def __init__(self, model_dir="ml_models/layer2"):
 
38
  print(f"❌ [Titan] خطأ فادح أثناء التهيئة: {e}")
39
 
40
  def apply_inverted_pyramid(self, df, tf):
41
+ """نفس منطق هندسة الميزات المستخدم في التدريب تماماً مع تحصين ضد الأخطاء"""
42
  df = df.copy().sort_values('timestamp').reset_index(drop=True)
43
  # تعيين الفهرس للسهولة في pandas_ta
44
  df = df.set_index(pd.DatetimeIndex(pd.to_datetime(df['timestamp'], unit='ms')))
45
 
46
+ try:
47
+ # --- المستوى 1: دقيق (5m, 15m) ---
48
+ if tf in ['5m', '15m']:
49
+ df['RSI'] = ta.rsi(df['close'], length=14)
50
+
51
+ macd = ta.macd(df['close'])
52
+ if macd is not None and not macd.empty:
53
+ df['MACD'] = macd.iloc[:, 0]
54
+ df['MACD_h'] = macd.iloc[:, 1]
55
+ else:
56
+ df['MACD'] = np.nan
57
+ df['MACD_h'] = np.nan
58
+
59
+ df['CCI'] = ta.cci(df['high'], df['low'], df['close'], length=20)
60
+
61
+ adx = ta.adx(df['high'], df['low'], df['close'], length=14)
62
+ df['ADX'] = adx.iloc[:, 0] if adx is not None and not adx.empty else np.nan
63
+
64
+ for p in [9, 21, 50, 200]:
65
+ ema = ta.ema(df['close'], length=p)
66
+ # تحصين ضد القسمة على None
67
+ if ema is not None and not ema.empty:
68
+ df[f'EMA_{p}_dist'] = (df['close'] / ema) - 1
69
+ else:
70
+ df[f'EMA_{p}_dist'] = np.nan
71
+
72
+ bb = ta.bbands(df['close'], length=20, std=2.0)
73
+ if bb is not None and not bb.empty:
74
+ df['BB_w'] = (bb.iloc[:, 2] - bb.iloc[:, 0]) / bb.iloc[:, 1]
75
+ df['BB_p'] = (df['close'] - bb.iloc[:, 0]) / (bb.iloc[:, 2] - bb.iloc[:, 0])
76
+ else:
77
+ df['BB_w'] = np.nan
78
+ df['BB_p'] = np.nan
79
+
80
+ df['MFI'] = ta.mfi(df['high'], df['low'], df['close'], df['volume'], length=14)
81
+
82
+ vwap = ta.vwap(df['high'], df['low'], df['close'], df['volume'])
83
+ if vwap is not None and not vwap.empty:
84
+ df['VWAP_dist'] = (df['close'] / vwap) - 1
85
+ else:
86
+ df['VWAP_dist'] = np.nan
87
+
88
+ # --- المستوى 2: تكتيكي (1h, 4h) ---
89
+ elif tf in ['1h', '4h']:
90
+ df['RSI'] = ta.rsi(df['close'], length=14)
91
+
92
+ macd = ta.macd(df['close'])
93
+ df['MACD_h'] = macd.iloc[:, 1] if macd is not None and not macd.empty else np.nan
94
+
95
+ ema50 = ta.ema(df['close'], length=50)
96
+ df['EMA_50_dist'] = (df['close'] / ema50) - 1 if ema50 is not None and not ema50.empty else np.nan
97
+
98
+ ema200 = ta.ema(df['close'], length=200)
99
+ df['EMA_200_dist'] = (df['close'] / ema200) - 1 if ema200 is not None and not ema200.empty else np.nan
100
+
101
+ atr = ta.atr(df['high'], df['low'], df['close'], length=14)
102
+ df['ATR_pct'] = (atr / df['close']) if atr is not None and not atr.empty else np.nan
103
+
104
+ # --- المستوى 3: استراتيجي (1d) ---
105
+ elif tf == '1d':
106
+ df['RSI'] = ta.rsi(df['close'], length=14)
107
+
108
+ ema200 = ta.ema(df['close'], length=200)
109
+ df['EMA_200_dist'] = (df['close'] / ema200) - 1 if ema200 is not None and not ema200.empty else np.nan
110
+
111
+ adx = ta.adx(df['high'], df['low'], df['close'])
112
+ if adx is not None and not adx.empty:
113
+ df['Trend_Strong'] = np.where(adx.iloc[:, 0] > 25, 1, 0)
114
+ else:
115
+ df['Trend_Strong'] = 0
116
+
117
+ except Exception as e:
118
+ print(f"⚠️ [Titan Warning] Error calculating indicators for {tf}: {e}")
119
+ # في حال حدوث خطأ، نترك الأعمدة كما هي (ستكون NaN إذا لم يتم إنشاؤها)
120
 
121
  return df.reset_index(drop=True)
122
 
 
139
  else:
140
  df = data.copy()
141
 
142
+ if df.empty: continue
143
+
144
+ # تطبيق المؤشرات حسب الإطار (النسخة المحصنة)
145
  df = self.apply_inverted_pyramid(df, tf)
146
  processed_tfs[tf] = df
147
 
148
  # 2. الدمج (Alignment) للحصول على آخر لقطة (Latest Snapshot)
149
+ if '5m' not in processed_tfs or processed_tfs['5m'].empty:
150
  return {'score': 0.0, 'error': 'Missing 5m base timeframe'}
151
 
152
  # نأخذ آخر صف فقط من الـ 5m كأساس
 
157
 
158
  # دمج باقي الأطر (نأخذ آخر شمعة أغلقت قبل أو مع شمعة الـ 5m الحالية)
159
  for tf, df in processed_tfs.items():
160
+ if tf == '5m' or df.empty: continue
161
  # العثور على الشمعة المناسبة زمنياً
162
  relevant_row = df[df['timestamp'] <= latest_ts].iloc[-1:].copy()
163
  if relevant_row.empty: continue
 
179
 
180
  # 4. التنبؤ
181
  # تحويل إلى DMatrix (تنسيق XGBoost السريع)
182
+ # نستخدم np.nan القيم المفقودة ليقوم XGBoost بمعالجتها تلقائياً
183
+ dtest = xgb.DMatrix([input_data], feature_names=self.feature_names, missing=np.nan)
184
  prediction = self.model.predict(dtest)[0] # إرجاع الاحتمالية الأولى
185
 
186
  return {
 
191
 
192
  except Exception as e:
193
  # print(f"⚠️ [Titan Error] {e}")
 
194
  traceback.print_exc()
195
  return {'score': 0.0, 'error': str(e)}