Riy777 commited on
Commit
572f435
·
verified ·
1 Parent(s): 1b1414d

Create ranker.py

Browse files
Files changed (1) hide show
  1. ml_engine/ranker.py +110 -0
ml_engine/ranker.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ml_engine/ranker.py (V9.1 - Layer 1 Smart Ranker)
2
+ import pandas as pd
3
+ import numpy as np
4
+ import os
5
+ from typing import List, Dict, Any
6
+
7
+ try:
8
+ import lightgbm as lgb
9
+ LGBM_AVAILABLE = True
10
+ except ImportError:
11
+ print("❌❌ [Ranker V9.1] مكتبة 'lightgbm' غير موجودة. الرانكر سيفشل.")
12
+ print(" -> قم بتثبيتها: pip install lightgbm")
13
+ LGBM_AVAILABLE = False
14
+
15
+ class Layer1Ranker:
16
+ def __init__(self, model_path: str = "ml_models/layer1_ranker.lgbm", r2_service=None):
17
+ """
18
+ تهيئة "العقل الذكي" (نموذج V9.1) للكاشف المصغر.
19
+
20
+ Args:
21
+ model_path (str): المسار المحلي إلى ملف نموذج LightGBM المدرب.
22
+ r2_service: (اختياري) خدمة R2 لتحميل النموذج من السحابة.
23
+ """
24
+ if not LGBM_AVAILABLE:
25
+ raise ImportError("مكتبة 'lightgbm' مطلوبة لتشغيل الرانكر.")
26
+
27
+ self.model_path = model_path
28
+ self.model_name = os.path.basename(model_path)
29
+ self.r2_service = r2_service # (للاستخدام المستقبلي لتحميل النموذج من R2)
30
+ self.model = None
31
+ self.features_in_ = None # (قائمة الميزات التي تدرب عليها النموذج)
32
+
33
+ async def initialize(self):
34
+ """
35
+ تحميل النموذج المدرب وميزاته.
36
+ (ملاحظة: حالياً يحمل من ملف محلي. يمكن تعديله ليحمل من R2)
37
+ """
38
+ print(f"🔄 [Ranker V9.1] بدء تحميل نموذج الكاشف المصغر: {self.model_name}...")
39
+ try:
40
+ # (الخطة أ: التحميل من R2 إذا كان متاحاً - غير مفعل حالياً)
41
+ # if self.r2_service:
42
+ # print(f" -> (محاولة التحميل من R2...)")
43
+ # model_bytes = await self.r2_service.load_model_from_r2(self.model_name)
44
+ # if model_bytes:
45
+ # self.model = lgb.Booster(model_str=model_bytes.decode('utf-8'))
46
+ # print(" -> (تم التحميل بنجاح من R2)")
47
+
48
+ # (الخطة ب: التحميل من ملف محلي إذا فشلت الخطة أ أو لم تكن مفعلة)
49
+ if self.model is None:
50
+ if not os.path.exists(self.model_path):
51
+ print(f"❌❌ [Ranker V9.1] خطأ فادح: ملف النموذج {self.model_path} غير موجود.")
52
+ print(" -> هل قمت بتنزيل النموذج 'layer1_ranker.lgbm' من Colab؟")
53
+ print(" -> سيتم استخدام 'نموذج وهمي' (Placeholder) مؤقت. هذا سيمنع أي تداول.")
54
+ self.model = None
55
+ # (هذه هي الميزات التي نتوقعها من 'indicators.py' V9.1)
56
+ self.features_in_ = [
57
+ 'price_to_ema_50', 'price_to_ema_200', 'price_to_min_100',
58
+ 'price_to_max_100', 'slope_14_50', 'volume_zscore_50',
59
+ 'vwap_gap', 'rsi_14', 'rsi_mean_10', 'rsi_std_10',
60
+ 'mfi_14', 'mfi_mean_10', 'adx_14', 'atr_percent',
61
+ 'atr_normalized_return'
62
+ ]
63
+ else:
64
+ # (التحميل الناجح من الملف المحلي)
65
+ self.model = lgb.Booster(model_file=self.model_path)
66
+ self.features_in_ = self.model.feature_name()
67
+ print(f"✅ [Ranker V9.1] تم تحميل النموذج {self.model_name} بنجاح من ملف محلي.")
68
+ print(f" -> عدد الميزات المطلوبة: {len(self.features_in_)}")
69
+
70
+ except Exception as e:
71
+ print(f"❌ [Ranker V9.1] فشل فادح في تحميل النموذج {self.model_name}: {e}")
72
+ self.model = None
73
+
74
+ def predict_proba(self, features_df: pd.DataFrame) -> np.ndarray:
75
+ """
76
+ التنبؤ باحتمالية "الانطلاقة" (الدرجة 0.0 إلى 1.0) لدفعة من العملات.
77
+ """
78
+ if self.model is None:
79
+ # (الوضع الآمن: إذا لم يتم تحميل النموذج، إرجاع أصفار)
80
+ print("⚠️ [Ranker V9.1] التنبؤ باستخدام 'الوضع الوهمي' (Placeholder). إرجاع 0.0")
81
+ return np.zeros(len(features_df))
82
+
83
+ try:
84
+ # (التأكد من أن DataFrame يحتوي على الميزات المطلوبة بنفس الترتيب)
85
+ # (هذا يحمي من أخطاء ترتيب الأعمدة)
86
+ if not all(feature in features_df.columns for feature in self.features_in_):
87
+ print("❌ [Ranker V9.1] خطأ: الميزات المدخلة لا تتطابق مع ميزات النموذج.")
88
+ missing_features = set(self.features_in_) - set(features_df.columns)
89
+ print(f" -> ميزات مفقودة: {missing_features}")
90
+ return np.zeros(len(features_df))
91
+
92
+ aligned_df = features_df[self.features_in_]
93
+
94
+ # (التنبؤ بالاحتمالية - [:, 1] هي احتمالية الفئة "1" (انطلاقة))
95
+ probabilities = self.model.predict(aligned_df)
96
+
97
+ # (التحقق مما إذا كان النموذج يعيد فئة واحدة أو اثنتين)
98
+ if probabilities.ndim == 2:
99
+ # (الحالة القياسية: [prob_0, prob_1])
100
+ return probabilities[:, 1]
101
+ else:
102
+ # (الحالة الأخرى: يعيد prob_1 فقط)
103
+ return probabilities
104
+
105
+ except Exception as e:
106
+ print(f"❌ [Ranker V9.1] خطأ أثناء التنبؤ: {e}")
107
+ # (إرجاع أصفار في حالة الفشل)
108
+ return np.zeros(len(features_df))
109
+
110
+ print("✅ ML Module: Layer 1 Ranker (V9.1) loaded.")