Spaces:
Paused
Paused
Update ml_engine/guard_engine.py
Browse files- ml_engine/guard_engine.py +31 -5
ml_engine/guard_engine.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# ml_engine/guard_engine.py
|
| 2 |
-
# (V1.
|
| 3 |
|
| 4 |
import os
|
| 5 |
import joblib
|
|
@@ -48,7 +48,7 @@ class GuardEngine:
|
|
| 48 |
traceback.print_exc()
|
| 49 |
|
| 50 |
def _engineer_features(self, df_raw):
|
| 51 |
-
"""مصنع الميزات الحي"""
|
| 52 |
df = df_raw.copy()
|
| 53 |
|
| 54 |
# 1. ميزات تيتان (Titan Features)
|
|
@@ -69,10 +69,25 @@ class GuardEngine:
|
|
| 69 |
df['ATR_14'] = ta.atr(df['high'], df['low'], df['close'], length=14)
|
| 70 |
df['ATR_Pct'] = df['ATR_14'] / df['close']
|
| 71 |
|
|
|
|
|
|
|
| 72 |
bb = ta.bbands(df['close'], length=20, std=2)
|
| 73 |
if bb is not None:
|
|
|
|
| 74 |
df['BB_Width'] = (bb.iloc[:, 2] - bb.iloc[:, 0]) / bb.iloc[:, 1]
|
| 75 |
df['BB_Pos'] = (df['close'] - bb.iloc[:, 0]) / (bb.iloc[:, 2] - bb.iloc[:, 0])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
# 2. ميزات الأنماط (Pattern Features)
|
| 78 |
for i in range(1, 13):
|
|
@@ -96,7 +111,7 @@ class GuardEngine:
|
|
| 96 |
if len(ohlcv_5m) < 200:
|
| 97 |
return {'action': 'HOLD', 'confidence': 0.0, 'reason': f'Not enough data ({len(ohlcv_5m)})'}
|
| 98 |
|
| 99 |
-
# [Log Stamp] تأك
|
| 100 |
# print(f"🛡️ [Guard Internal] Processing {len(ohlcv_5m)} candles...")
|
| 101 |
|
| 102 |
df = pd.DataFrame(ohlcv_5m, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
|
@@ -104,10 +119,21 @@ class GuardEngine:
|
|
| 104 |
|
| 105 |
latest_row = df.iloc[-1:].copy()
|
| 106 |
|
| 107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
prob = self.exit_model.predict(dmatrix)[0]
|
| 109 |
|
| 110 |
-
# [Log Stamp] طباعة النتيجة
|
| 111 |
# print(f"🛡️ [Guard Internal] Result: {prob:.4f} (Threshold: {self.EXIT_THRESHOLD})")
|
| 112 |
|
| 113 |
if prob >= self.EXIT_THRESHOLD:
|
|
|
|
| 1 |
# ml_engine/guard_engine.py
|
| 2 |
+
# (V1.4 - GEM-Architect Fix: Full Visibility, Async Wrapper & Column Fix)
|
| 3 |
|
| 4 |
import os
|
| 5 |
import joblib
|
|
|
|
| 48 |
traceback.print_exc()
|
| 49 |
|
| 50 |
def _engineer_features(self, df_raw):
|
| 51 |
+
"""مصنع الميزات الحي (مع إصلاح الأعمدة المفقودة)"""
|
| 52 |
df = df_raw.copy()
|
| 53 |
|
| 54 |
# 1. ميزات تيتان (Titan Features)
|
|
|
|
| 69 |
df['ATR_14'] = ta.atr(df['high'], df['low'], df['close'], length=14)
|
| 70 |
df['ATR_Pct'] = df['ATR_14'] / df['close']
|
| 71 |
|
| 72 |
+
# --- [ FIX START: Bollinger Bands Robustness ] ---
|
| 73 |
+
# حساب البولنجر باند
|
| 74 |
bb = ta.bbands(df['close'], length=20, std=2)
|
| 75 |
if bb is not None:
|
| 76 |
+
# 1. الحسابات المشتقة
|
| 77 |
df['BB_Width'] = (bb.iloc[:, 2] - bb.iloc[:, 0]) / bb.iloc[:, 1]
|
| 78 |
df['BB_Pos'] = (df['close'] - bb.iloc[:, 0]) / (bb.iloc[:, 2] - bb.iloc[:, 0])
|
| 79 |
+
|
| 80 |
+
# 2. دمج الأعمدة الخام (لأن النموذج يطلبها)
|
| 81 |
+
df = pd.concat([df, bb], axis=1)
|
| 82 |
+
|
| 83 |
+
# 3. التحوط ضد التسميات الغريبة (Double Suffix Fix)
|
| 84 |
+
# النموذج يطلب 'BBU_20_2.0_2.0' بدلاً من 'BBU_20_2.0'
|
| 85 |
+
# نقوم بنسخ الأعمدة بالأسماء المتوقعة لتجنب الانهيار
|
| 86 |
+
if 'BBU_20_2.0' in df.columns:
|
| 87 |
+
df['BBU_20_2.0_2.0'] = df['BBU_20_2.0']
|
| 88 |
+
df['BBL_20_2.0_2.0'] = df['BBL_20_2.0']
|
| 89 |
+
df['BBM_20_2.0_2.0'] = df['BBM_20_2.0']
|
| 90 |
+
# --- [ FIX END ] ---
|
| 91 |
|
| 92 |
# 2. ميزات الأنماط (Pattern Features)
|
| 93 |
for i in range(1, 13):
|
|
|
|
| 111 |
if len(ohlcv_5m) < 200:
|
| 112 |
return {'action': 'HOLD', 'confidence': 0.0, 'reason': f'Not enough data ({len(ohlcv_5m)})'}
|
| 113 |
|
| 114 |
+
# [Log Stamp] طباعة للتأكد من ان الحارس يعمل
|
| 115 |
# print(f"🛡️ [Guard Internal] Processing {len(ohlcv_5m)} candles...")
|
| 116 |
|
| 117 |
df = pd.DataFrame(ohlcv_5m, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
|
|
|
| 119 |
|
| 120 |
latest_row = df.iloc[-1:].copy()
|
| 121 |
|
| 122 |
+
# التأكد من وجود جميع الميزات المطلوبة
|
| 123 |
+
# يتم ملء أي ميزة مفقودة بـ 0 لتجنب الانهيار التام، لكن السجل سيظهر تحذيراً إذا تكرر
|
| 124 |
+
try:
|
| 125 |
+
dmatrix = xgb.DMatrix(latest_row[self.exit_features])
|
| 126 |
+
except KeyError as e:
|
| 127 |
+
# محاولة أخيرة: طباعة الأعمدة المفقودة بدقة للمعالجة
|
| 128 |
+
missing = list(set(self.exit_features) - set(latest_row.columns))
|
| 129 |
+
print(f"⚠️ [Guard Fix Attempt] Missing cols: {missing}. Filling with 0.")
|
| 130 |
+
for col in missing:
|
| 131 |
+
latest_row[col] = 0.0
|
| 132 |
+
dmatrix = xgb.DMatrix(latest_row[self.exit_features])
|
| 133 |
+
|
| 134 |
prob = self.exit_model.predict(dmatrix)[0]
|
| 135 |
|
| 136 |
+
# [Log Stamp] طباعة النتيجة
|
| 137 |
# print(f"🛡️ [Guard Internal] Result: {prob:.4f} (Threshold: {self.EXIT_THRESHOLD})")
|
| 138 |
|
| 139 |
if prob >= self.EXIT_THRESHOLD:
|