Riy777 commited on
Commit
b61c69b
·
verified ·
1 Parent(s): c7a21ab

Update ml_engine/data_manager.py

Browse files
Files changed (1) hide show
  1. ml_engine/data_manager.py +35 -38
ml_engine/data_manager.py CHANGED
@@ -1,6 +1,6 @@
1
  # ============================================================
2
  # 📂 ml_engine/data_manager.py
3
- # (V60.2 - GEM-Architect: Robust Data Fix & Tuned Shield)
4
  # ============================================================
5
 
6
  import asyncio
@@ -12,7 +12,7 @@ import pandas as pd
12
  import numpy as np
13
  from typing import List, Dict, Any
14
 
15
- # محاولة استيراد حدود النظام (اختياري)
16
  try:
17
  from ml_engine.processor import SystemLimits
18
  except ImportError:
@@ -29,6 +29,7 @@ class DataManager:
29
  self.r2_service = r2_service
30
  self.adaptive_hub_ref = None # مرجع لملف التعلم
31
 
 
32
  self.exchange = ccxt.kucoin({
33
  'enableRateLimit': True,
34
  'timeout': 60000,
@@ -38,13 +39,13 @@ class DataManager:
38
  self.http_client = None
39
  self.market_cache = {}
40
 
41
- # قائمة العملات المحظورة
42
  self.BLACKLIST_TOKENS = [
43
  'USDT', 'USDC', 'DAI', 'TUSD', 'BUSD', 'FDUSD', 'EUR', 'PAX',
44
  'UP', 'DOWN', 'BEAR', 'BULL', '3S', '3L'
45
  ]
46
 
47
- print(f"📦 [DataManager V60.2] Robust Data Fix + Tuned Shield Active.")
48
 
49
  async def initialize(self):
50
  print(" > [DataManager] Starting initialization...")
@@ -73,17 +74,17 @@ class DataManager:
73
  return self.contracts_db
74
 
75
  # ==================================================================
76
- # 🧠 Layer 1: Screening + Diagnosis + Injection
77
  # ==================================================================
78
  async def layer1_rapid_screening(self, adaptive_hub_ref=None) -> List[Dict[str, Any]]:
79
  self.adaptive_hub_ref = adaptive_hub_ref
80
  print(f"🔍 [Layer 1] Initiating Robust Screening...")
81
 
82
- # 1. فلتر السيولة الأساسي (المصحح)
83
  initial_candidates = await self._stage0_universe_filter()
84
 
85
  if not initial_candidates:
86
- print("⚠️ [Layer 1] CRITICAL: Stage 0 returned 0 candidates.")
87
  return []
88
 
89
  # 2. جلب البيانات الفنية (لأفضل 120 عملة لضمان التنوع)
@@ -93,16 +94,16 @@ class DataManager:
93
  final_list = []
94
 
95
  for item in enriched_data:
96
- # 3. تطبيق الفلتر الفني (Tuned Anti-FOMO)
97
  classification = self._apply_strict_logic_tree(item)
98
 
99
  if classification['type'] != 'NONE':
100
- # 4. التشخيص والحقن
101
  regime_info = self._diagnose_asset_regime(item)
102
  item['asset_regime'] = regime_info['regime']
103
  item['asset_regime_conf'] = regime_info['conf']
104
 
105
- # حقن العتبات الديناميكية
106
  if self.adaptive_hub_ref:
107
  dynamic_config = self.adaptive_hub_ref.get_regime_config(regime_info['regime'])
108
  item['dynamic_limits'] = dynamic_config
@@ -119,7 +120,7 @@ class DataManager:
119
  return selection
120
 
121
  # ==================================================================
122
- # 🔍 Stage 0: Universe Filter (Debugged & Robust)
123
  # ==================================================================
124
  async def _stage0_universe_filter(self) -> List[Dict[str, Any]]:
125
  try:
@@ -127,8 +128,8 @@ class DataManager:
127
  tickers = await self.exchange.fetch_tickers()
128
  candidates = []
129
 
130
- # عداد لمعرفة سبب الرفض (للتشخيص)
131
- reject_stats = {"volume": 0, "change": 0, "blacklist": 0, "bad_data": 0}
132
  debug_printed = False
133
 
134
  for symbol, ticker in tickers.items():
@@ -140,31 +141,25 @@ class DataManager:
140
  reject_stats["blacklist"] += 1
141
  continue
142
 
143
- # 2. Robust Volume Calculation (الإصلاح الجذري)
144
- quote_vol = ticker.get('quoteVolume')
 
 
145
 
146
- # إذا كان غير موجود أو صفر، نحسبه يدوياً
147
- if quote_vol is None or float(quote_vol) == 0:
148
- base_vol = ticker.get('baseVolume')
149
- last_price = ticker.get('last')
150
- if base_vol is not None and last_price is not None:
151
- quote_vol = float(base_vol) * float(last_price)
152
- else:
153
- quote_vol = 0.0
154
 
155
- quote_vol = float(quote_vol)
156
-
157
- # طباعة فحص لعملة معروفة (BTC) للتأكد من صحة البيانات في السجل
158
  if "BTC/USDT" in symbol and not debug_printed:
159
- print(f" 🐛 [DEBUG] BTC Data Check: Vol=${quote_vol:,.2f} | Change={ticker.get('percentage')}%")
160
  debug_printed = True
161
 
162
  # فلتر السيولة (500k)
163
- if quote_vol < 500_000:
164
  reject_stats["volume"] += 1
165
  continue
166
 
167
- # فلتر التغير (20%)
168
  change_pct = ticker.get('percentage')
169
  if change_pct is None: change_pct = 0.0
170
 
@@ -174,13 +169,12 @@ class DataManager:
174
 
175
  candidates.append({
176
  'symbol': symbol,
177
- 'quote_volume': quote_vol,
178
- 'current_price': ticker.get('last'),
179
  'change_24h': change_pct
180
  })
181
 
182
- # طباعة تقرير الرفض
183
- print(f" 📊 [Filter Stats] Total Tickers: {len(tickers)} | Passed: {len(candidates)}")
184
  print(f" ❌ Rejected: Vol < 500k ({reject_stats['volume']}) | Change > 20% ({reject_stats['change']})")
185
 
186
  candidates.sort(key=lambda x: x['quote_volume'], reverse=True)
@@ -192,7 +186,7 @@ class DataManager:
192
  return []
193
 
194
  # ------------------------------------------------------------------
195
- # 🧭 The Diagnoser
196
  # ------------------------------------------------------------------
197
  def _diagnose_asset_regime(self, item: Dict[str, Any]) -> Dict[str, Any]:
198
  try:
@@ -210,6 +204,7 @@ class DataManager:
210
  conf = 0.5
211
 
212
  if atr_pct < 0.5: return {'regime': 'DEAD', 'conf': 0.9}
 
213
  if price > ema20 and ema20 > ema50 and rsi > 50:
214
  regime = "BULL"
215
  conf = 0.8 if rsi > 55 else 0.6
@@ -221,7 +216,7 @@ class DataManager:
221
  except Exception: return {'regime': 'RANGE', 'conf': 0.0}
222
 
223
  # ------------------------------------------------------------------
224
- # 🛡️ The Logic Tree (TUNED)
225
  # ------------------------------------------------------------------
226
  def _apply_strict_logic_tree(self, data: Dict[str, Any]) -> Dict[str, Any]:
227
  try:
@@ -238,11 +233,11 @@ class DataManager:
238
  change_4h = ((curr_1h['close'] - close_4h_ago) / close_4h_ago) * 100
239
  except: change_4h = 0.0
240
 
241
- # 🔧 TUNED GATES (فتحات التنفس)
242
  # 1. السماح بحركة 12% في 4 ساعات
243
  if change_4h > 12.0: return {'type': 'NONE', 'score': 0}
244
 
245
- # 2. السماح بـ RSI حتى 75
246
  if curr_1h['rsi'] > 75: return {'type': 'NONE', 'score': 0}
247
 
248
  # 3. السماح بانحراف 2.2 ATR
@@ -253,10 +248,12 @@ class DataManager:
253
 
254
  # A. Breakout (اختراق آمن)
255
  is_bullish = (curr_1h['ema20'] > curr_1h['ema50']) or (curr_1h['close'] > curr_1h['ema20'])
 
 
256
  if is_bullish and (45 <= curr_1h['rsi'] <= 75):
257
  vol_ma = df_15m['volume'].rolling(20).mean().iloc[-1]
258
 
259
- # 🔧 TUNED: 1.2x Volume
260
  if curr_15m['volume'] >= 1.2 * vol_ma:
261
  score = curr_15m['volume'] / vol_ma if vol_ma > 0 else 1.0
262
  return {'type': 'BREAKOUT', 'score': score}
 
1
  # ============================================================
2
  # 📂 ml_engine/data_manager.py
3
+ # (V60.3 - GEM-Architect: Critical Data Fix & Full Integration)
4
  # ============================================================
5
 
6
  import asyncio
 
12
  import numpy as np
13
  from typing import List, Dict, Any
14
 
15
+ # محاولة استيراد حدود النظام (اختياري للربط مع باقي النظام)
16
  try:
17
  from ml_engine.processor import SystemLimits
18
  except ImportError:
 
29
  self.r2_service = r2_service
30
  self.adaptive_hub_ref = None # مرجع لملف التعلم
31
 
32
+ # إعداد منصة KuCoin
33
  self.exchange = ccxt.kucoin({
34
  'enableRateLimit': True,
35
  'timeout': 60000,
 
39
  self.http_client = None
40
  self.market_cache = {}
41
 
42
+ # قائمة العملات المحظورة (Stablecoins + Leveraged Tokens)
43
  self.BLACKLIST_TOKENS = [
44
  'USDT', 'USDC', 'DAI', 'TUSD', 'BUSD', 'FDUSD', 'EUR', 'PAX',
45
  'UP', 'DOWN', 'BEAR', 'BULL', '3S', '3L'
46
  ]
47
 
48
+ print(f"📦 [DataManager V60.3] Critical Data Fix + Tuned Shield Active.")
49
 
50
  async def initialize(self):
51
  print(" > [DataManager] Starting initialization...")
 
74
  return self.contracts_db
75
 
76
  # ==================================================================
77
+ # 🧠 Layer 1: Screening + Diagnosis + Injection (The Pipeline)
78
  # ==================================================================
79
  async def layer1_rapid_screening(self, adaptive_hub_ref=None) -> List[Dict[str, Any]]:
80
  self.adaptive_hub_ref = adaptive_hub_ref
81
  print(f"🔍 [Layer 1] Initiating Robust Screening...")
82
 
83
+ # 1. فلتر السيولة الأساسي (المصحح جذرياً)
84
  initial_candidates = await self._stage0_universe_filter()
85
 
86
  if not initial_candidates:
87
+ print("⚠️ [Layer 1] CRITICAL: Stage 0 returned 0 candidates. Check Connection.")
88
  return []
89
 
90
  # 2. جلب البيانات الفنية (لأفضل 120 عملة لضمان التنوع)
 
94
  final_list = []
95
 
96
  for item in enriched_data:
97
+ # 3. تطبيق الفلتر الفني الصارم (Tuned Anti-FOMO)
98
  classification = self._apply_strict_logic_tree(item)
99
 
100
  if classification['type'] != 'NONE':
101
+ # 4. التشخيص والحقن (Context Injection)
102
  regime_info = self._diagnose_asset_regime(item)
103
  item['asset_regime'] = regime_info['regime']
104
  item['asset_regime_conf'] = regime_info['conf']
105
 
106
+ # حقن العتبات الديناميكية من ملف التعلم
107
  if self.adaptive_hub_ref:
108
  dynamic_config = self.adaptive_hub_ref.get_regime_config(regime_info['regime'])
109
  item['dynamic_limits'] = dynamic_config
 
120
  return selection
121
 
122
  # ==================================================================
123
+ # 🔍 Stage 0: Universe Filter (FIXED: Force USD Calculation)
124
  # ==================================================================
125
  async def _stage0_universe_filter(self) -> List[Dict[str, Any]]:
126
  try:
 
128
  tickers = await self.exchange.fetch_tickers()
129
  candidates = []
130
 
131
+ # إحصائيات الرفض للتشخيص
132
+ reject_stats = {"volume": 0, "change": 0, "blacklist": 0}
133
  debug_printed = False
134
 
135
  for symbol, ticker in tickers.items():
 
141
  reject_stats["blacklist"] += 1
142
  continue
143
 
144
+ # 2. 🔥 FORCE CALCULATED VOLUME (USD) - الإصلاح الجذري
145
+ # نتجاهل quoteVolume القادم من المنصة إذا كان مشكوكاً فيه
146
+ base_vol = float(ticker.get('baseVolume') or 0.0)
147
+ last_price = float(ticker.get('last') or 0.0)
148
 
149
+ # الحساب اليدوي: الحجم * السعر = السيولة بالدولار
150
+ calc_quote_vol = base_vol * last_price
 
 
 
 
 
 
151
 
152
+ # طباعة فحص BTC للتأكد من الإصلاح (مرة واحدة)
 
 
153
  if "BTC/USDT" in symbol and not debug_printed:
154
+ print(f" 🐛 [DEBUG] BTC Fixed Vol: ${calc_quote_vol:,.0f} (Verified USD)")
155
  debug_printed = True
156
 
157
  # فلتر السيولة (500k)
158
+ if calc_quote_vol < 500_000:
159
  reject_stats["volume"] += 1
160
  continue
161
 
162
+ # فلتر التغير (20%) - مسموح للحركة القوية
163
  change_pct = ticker.get('percentage')
164
  if change_pct is None: change_pct = 0.0
165
 
 
169
 
170
  candidates.append({
171
  'symbol': symbol,
172
+ 'quote_volume': calc_quote_vol, # نستخدم القيمة المحسوبة
173
+ 'current_price': last_price,
174
  'change_24h': change_pct
175
  })
176
 
177
+ print(f" 📊 [Filter Stats] Total: {len(tickers)} | Passed: {len(candidates)}")
 
178
  print(f" ❌ Rejected: Vol < 500k ({reject_stats['volume']}) | Change > 20% ({reject_stats['change']})")
179
 
180
  candidates.sort(key=lambda x: x['quote_volume'], reverse=True)
 
186
  return []
187
 
188
  # ------------------------------------------------------------------
189
+ # 🧭 The Diagnoser (يحدد حالة العملة لحقن العتبات)
190
  # ------------------------------------------------------------------
191
  def _diagnose_asset_regime(self, item: Dict[str, Any]) -> Dict[str, Any]:
192
  try:
 
204
  conf = 0.5
205
 
206
  if atr_pct < 0.5: return {'regime': 'DEAD', 'conf': 0.9}
207
+
208
  if price > ema20 and ema20 > ema50 and rsi > 50:
209
  regime = "BULL"
210
  conf = 0.8 if rsi > 55 else 0.6
 
216
  except Exception: return {'regime': 'RANGE', 'conf': 0.0}
217
 
218
  # ------------------------------------------------------------------
219
+ # 🛡️ The Logic Tree (TUNED Anti-FOMO)
220
  # ------------------------------------------------------------------
221
  def _apply_strict_logic_tree(self, data: Dict[str, Any]) -> Dict[str, Any]:
222
  try:
 
233
  change_4h = ((curr_1h['close'] - close_4h_ago) / close_4h_ago) * 100
234
  except: change_4h = 0.0
235
 
236
+ # 🔧 TUNED GATES (بوابات الأمان المخففة)
237
  # 1. السماح بحركة 12% في 4 ساعات
238
  if change_4h > 12.0: return {'type': 'NONE', 'score': 0}
239
 
240
+ # 2. السماح بـ RSI حتى 75 (منطقة الزخم القوي)
241
  if curr_1h['rsi'] > 75: return {'type': 'NONE', 'score': 0}
242
 
243
  # 3. السماح بانحراف 2.2 ATR
 
248
 
249
  # A. Breakout (اختراق آمن)
250
  is_bullish = (curr_1h['ema20'] > curr_1h['ema50']) or (curr_1h['close'] > curr_1h['ema20'])
251
+
252
+ # وسعنا النطاق قليلاً ليقبل الزخم القوي
253
  if is_bullish and (45 <= curr_1h['rsi'] <= 75):
254
  vol_ma = df_15m['volume'].rolling(20).mean().iloc[-1]
255
 
256
+ # خفضنا شرط الفوليوم لـ 1.2 لالتقاط البدايات
257
  if curr_15m['volume'] >= 1.2 * vol_ma:
258
  score = curr_15m['volume'] / vol_ma if vol_ma > 0 else 1.0
259
  return {'type': 'BREAKOUT', 'score': score}