Spaces:
Paused
Paused
Update ml_engine/data_manager.py
Browse files- ml_engine/data_manager.py +52 -26
ml_engine/data_manager.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# ============================================================
|
| 2 |
# 📂 ml_engine/data_manager.py
|
| 3 |
-
# (V18.
|
| 4 |
# ============================================================
|
| 5 |
|
| 6 |
import asyncio
|
|
@@ -31,10 +31,10 @@ logging.getLogger("ccxt").setLevel(logging.WARNING)
|
|
| 31 |
|
| 32 |
class DataManager:
|
| 33 |
"""
|
| 34 |
-
DataManager V18.
|
| 35 |
-
-----------------
|
| 36 |
المسؤول عن جلب البيانات من المنصة، فلترتها، وتجهيزها للمعالج.
|
| 37 |
-
ي
|
| 38 |
"""
|
| 39 |
|
| 40 |
def __init__(self, contracts_db, whale_monitor, r2_service=None):
|
|
@@ -67,9 +67,10 @@ class DataManager:
|
|
| 67 |
"""تهيئة مدير البيانات والاتصالات"""
|
| 68 |
print(" > [DataManager] Starting initialization...")
|
| 69 |
try:
|
| 70 |
-
|
|
|
|
| 71 |
await self._load_markets()
|
| 72 |
-
print(f"✅ [DataManager V18.
|
| 73 |
except Exception as e:
|
| 74 |
print(f"❌ [DataManager] Init Error: {e}")
|
| 75 |
traceback.print_exc()
|
|
@@ -113,15 +114,12 @@ class DataManager:
|
|
| 113 |
return self.contracts_db
|
| 114 |
|
| 115 |
# ==================================================================
|
| 116 |
-
# 🛡️ Layer 1: Synergy Screening (
|
| 117 |
# ==================================================================
|
| 118 |
async def layer1_rapid_screening(self) -> List[Dict[str, Any]]:
|
| 119 |
"""
|
| 120 |
-
الفلترة الذكية
|
| 121 |
-
تقوم
|
| 122 |
-
1. اتجاه المتوسطات (EMA Trend).
|
| 123 |
-
2. الدعم المؤسساتي في دفتر الطلبات (Order Book Depth).
|
| 124 |
-
3. مناطق الدخول الذكية (Smart RSI).
|
| 125 |
"""
|
| 126 |
print(f"🔍 [Layer 1] Initiating Synergy Matrix Screening...")
|
| 127 |
|
|
@@ -129,42 +127,70 @@ class DataManager:
|
|
| 129 |
initial_candidates = await self._stage0_universe_filter()
|
| 130 |
|
| 131 |
if not initial_candidates:
|
| 132 |
-
print("⚠️ [Layer 1] No candidates passed Stage 0.")
|
| 133 |
return []
|
| 134 |
|
| 135 |
-
#
|
| 136 |
-
#
|
| 137 |
-
top_liquid_candidates = initial_candidates[:
|
|
|
|
|
|
|
| 138 |
enriched_data = await self._fetch_technical_and_depth_batch(top_liquid_candidates)
|
| 139 |
|
| 140 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
scored_candidates = []
|
|
|
|
| 142 |
|
|
|
|
|
|
|
|
|
|
| 143 |
for item in enriched_data:
|
| 144 |
# استدعاء دالة التقييم الجديدة
|
| 145 |
affinity_result = self._calculate_synergy_score(item)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
# إذا حققت الحد الأدنى من النقاط، نضيفها للقائمة
|
| 148 |
-
if
|
| 149 |
-
item['l1_score'] = affinity_result['score']
|
| 150 |
-
item['tags'] = affinity_result['tags']
|
| 151 |
scored_candidates.append(item)
|
| 152 |
|
| 153 |
-
# 4.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
# ترتيب تنازلي حسب النقاط
|
| 155 |
scored_candidates.sort(key=lambda x: x['l1_score'], reverse=True)
|
| 156 |
|
| 157 |
-
# ✅
|
| 158 |
if len(scored_candidates) > 0:
|
| 159 |
print("-" * 75)
|
| 160 |
-
print(f"{'SYMBOL':<12} | {'SCORE':<6} | {'
|
| 161 |
print("-" * 75)
|
| 162 |
-
for
|
| 163 |
tags_str = ", ".join(item.get('tags', []))
|
| 164 |
print(f"{item['symbol']:<12} | {item['l1_score']:<6.1f} | {tags_str}")
|
| 165 |
print("-" * 75)
|
| 166 |
-
|
| 167 |
-
|
| 168 |
|
| 169 |
# نختار أفضل 40 عملة فقط لتمريرها للمعالجة العميقة (L2/L3)
|
| 170 |
final_selection = scored_candidates[:40]
|
|
|
|
| 1 |
# ============================================================
|
| 2 |
# 📂 ml_engine/data_manager.py
|
| 3 |
+
# (V18.3 - GEM-Architect: Adaptive Synergy + Rescue Mode)
|
| 4 |
# ============================================================
|
| 5 |
|
| 6 |
import asyncio
|
|
|
|
| 31 |
|
| 32 |
class DataManager:
|
| 33 |
"""
|
| 34 |
+
DataManager V18.3 (Adaptive)
|
| 35 |
+
----------------------------
|
| 36 |
المسؤول عن جلب البيانات من المنصة، فلترتها، وتجهيزها للمعالج.
|
| 37 |
+
يتميز بنظام 'Synergy Matrix' المرن الذي يتكيف مع ظروف السوق (Rescue Mode).
|
| 38 |
"""
|
| 39 |
|
| 40 |
def __init__(self, contracts_db, whale_monitor, r2_service=None):
|
|
|
|
| 67 |
"""تهيئة مدير البيانات والاتصالات"""
|
| 68 |
print(" > [DataManager] Starting initialization...")
|
| 69 |
try:
|
| 70 |
+
# ✅ GEM-Architect: زيادة الـ Timeout لتجنب مشاكل الشبكة أثناء الضغط
|
| 71 |
+
self.http_client = httpx.AsyncClient(timeout=60.0)
|
| 72 |
await self._load_markets()
|
| 73 |
+
print(f"✅ [DataManager V18.3] Ready (Mode: Synergy Matrix | Adaptive 100).")
|
| 74 |
except Exception as e:
|
| 75 |
print(f"❌ [DataManager] Init Error: {e}")
|
| 76 |
traceback.print_exc()
|
|
|
|
| 114 |
return self.contracts_db
|
| 115 |
|
| 116 |
# ==================================================================
|
| 117 |
+
# 🛡️ Layer 1: Synergy Screening (GEM-Architect Fix: Adaptive & Debuggable)
|
| 118 |
# ==================================================================
|
| 119 |
async def layer1_rapid_screening(self) -> List[Dict[str, Any]]:
|
| 120 |
"""
|
| 121 |
+
الفلترة الذكية (نسخة مصححة): تتكيف مع ظروف السوق وتعالج مشاكل البيانات.
|
| 122 |
+
تقوم بمسح أفضل 100 عملة وتفعيل وضع الإنقاذ إذا كانت النتائج صفرية.
|
|
|
|
|
|
|
|
|
|
| 123 |
"""
|
| 124 |
print(f"🔍 [Layer 1] Initiating Synergy Matrix Screening...")
|
| 125 |
|
|
|
|
| 127 |
initial_candidates = await self._stage0_universe_filter()
|
| 128 |
|
| 129 |
if not initial_candidates:
|
| 130 |
+
print("⚠️ [Layer 1] No candidates passed Stage 0 (Check Internet/API).")
|
| 131 |
return []
|
| 132 |
|
| 133 |
+
# ✅ GEM-Architect Update: فحص أفضل 100 عملة حسب الطلب
|
| 134 |
+
# تم تحديد العدد لضمان التوازن بين كفاءة المسح وتجنب الحظر
|
| 135 |
+
top_liquid_candidates = initial_candidates[:100]
|
| 136 |
+
|
| 137 |
+
print(f" -> Fetching deep data for top {len(top_liquid_candidates)} assets...")
|
| 138 |
enriched_data = await self._fetch_technical_and_depth_batch(top_liquid_candidates)
|
| 139 |
|
| 140 |
+
# 🚨 Debug Check: هل البيانات تصل فعلاً؟
|
| 141 |
+
if len(enriched_data) == 0:
|
| 142 |
+
print("❌ [CRITICAL] 0 assets returned data. API might be throttling or returning empty responses.")
|
| 143 |
+
return []
|
| 144 |
+
|
| 145 |
+
# 3. حساب النقاط (Synergy Score)
|
| 146 |
scored_candidates = []
|
| 147 |
+
debug_scores = [] # لتسجيل وتتبع لماذا تفشل العملات
|
| 148 |
|
| 149 |
+
# ✅ استخدام حد أدنى مرن (Adaptive Threshold)
|
| 150 |
+
current_threshold = SystemLimits.L1_MIN_AFFINITY_SCORE
|
| 151 |
+
|
| 152 |
for item in enriched_data:
|
| 153 |
# استدعاء دالة التقييم الجديدة
|
| 154 |
affinity_result = self._calculate_synergy_score(item)
|
| 155 |
+
score = affinity_result['score']
|
| 156 |
+
item['l1_score'] = score
|
| 157 |
+
item['tags'] = affinity_result['tags']
|
| 158 |
+
|
| 159 |
+
debug_scores.append(score)
|
| 160 |
|
| 161 |
# إذا حققت الحد الأدنى من النقاط، نضيفها للقائمة
|
| 162 |
+
if score >= current_threshold:
|
|
|
|
|
|
|
| 163 |
scored_candidates.append(item)
|
| 164 |
|
| 165 |
+
# 4. 🔥 نظام الإنقاذ (Rescue Mode)
|
| 166 |
+
# إذا لم نجد أي عملة بالفلتر القاسي، نخفض المعايير فوراً بدلاً من إرجاع قائمة فارغة
|
| 167 |
+
if len(scored_candidates) == 0 and len(enriched_data) > 0:
|
| 168 |
+
max_found_score = max(debug_scores) if debug_scores else 0
|
| 169 |
+
print(f"⚠️ [Layer 1] Too strict! Max score found was {max_found_score:.2f}. Activating Rescue Mode...")
|
| 170 |
+
|
| 171 |
+
# إعادة المحاولة بحد أدنى 0 (أي عملة إيجابية تقنياً)
|
| 172 |
+
for item in enriched_data:
|
| 173 |
+
if item['l1_score'] > 0:
|
| 174 |
+
scored_candidates.append(item)
|
| 175 |
+
|
| 176 |
+
if scored_candidates:
|
| 177 |
+
print(f" -> ✅ Rescue Mode found {len(scored_candidates)} candidates with Score > 0.")
|
| 178 |
+
|
| 179 |
+
# 5. الترتيب واختيار النخبة
|
| 180 |
# ترتيب تنازلي حسب النقاط
|
| 181 |
scored_candidates.sort(key=lambda x: x['l1_score'], reverse=True)
|
| 182 |
|
| 183 |
+
# ✅ طباعة النتائج للمراقبة
|
| 184 |
if len(scored_candidates) > 0:
|
| 185 |
print("-" * 75)
|
| 186 |
+
print(f"{'SYMBOL':<12} | {'SCORE':<6} | {'TAGS'}")
|
| 187 |
print("-" * 75)
|
| 188 |
+
for item in scored_candidates[:5]: # طباعة أفضل 5 فقط لعدم إغراق السجل
|
| 189 |
tags_str = ", ".join(item.get('tags', []))
|
| 190 |
print(f"{item['symbol']:<12} | {item['l1_score']:<6.1f} | {tags_str}")
|
| 191 |
print("-" * 75)
|
| 192 |
+
else:
|
| 193 |
+
print(f"❌ [Layer 1] Still 0 candidates after Rescue Mode. Market is extremely weird or Data is bad.")
|
| 194 |
|
| 195 |
# نختار أفضل 40 عملة فقط لتمريرها للمعالجة العميقة (L2/L3)
|
| 196 |
final_selection = scored_candidates[:40]
|