Riy777 commited on
Commit
6c7250f
·
1 Parent(s): e84aa61

Update data_manager.py

Browse files
Files changed (1) hide show
  1. data_manager.py +115 -65
data_manager.py CHANGED
@@ -1,4 +1,4 @@
1
- # data_manager.py (Updated to V7.3 - V8 Pattern Engine Init)
2
  import os
3
  import asyncio
4
  import httpx
@@ -67,7 +67,7 @@ class DataManager:
67
  self.pattern_analyzer = ChartPatternAnalyzer(r2_service=None)
68
  # --- (نهاية الإضافة) ---
69
 
70
- print("✅ DataManager initialized - V7.3 (L1 Threshold @ 0.50)")
71
 
72
  async def _load_markets(self):
73
  try:
@@ -227,81 +227,132 @@ class DataManager:
227
  print(f"❌ خطأ في إنشاء DataFrame لمرشح 1H: {e}")
228
  return pd.DataFrame()
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  def _calculate_1h_filter_score(self, analysis: Dict) -> float:
231
  """
232
- (محدث V7.2) - "الكاشف المصغر"
233
- يحتوي الآن على "واقي العملات المستقرة"
 
 
 
 
 
234
  """
235
  try:
236
- # (V7.2) واقي العملات المستقرة
237
- if 'ohlcv_1h' in analysis and '1h' in analysis['ohlcv_1h']:
238
- closes_1h = [c[4] for c in analysis['ohlcv_1h']['1h']]
239
- if len(closes_1h) > 20:
240
- std_dev = np.std(closes_1h[-20:])
241
- if std_dev < 1e-5:
242
- print(f" - {analysis.get('symbol', 'N/A')}: تم الاستبعاد (عملة مستقرة)")
243
- return 0.0
244
-
245
- # 1. درجة الأنماط (Pattern Score)
246
- pattern_confidence = analysis.get('pattern_analysis', {}).get('pattern_confidence', 0)
247
 
248
- # 2. درجة مونت كارلو (Monte Carlo Score)
249
- mc_distribution = analysis.get('monte_carlo_distribution')
250
- monte_carlo_score = 0
251
-
252
- if mc_distribution and mc_distribution.get('error') is None:
253
- prob_gain = mc_distribution.get('probability_of_gain', 0)
254
- var_95_value = mc_distribution.get('risk_metrics', {}).get('VaR_95_value', 0)
255
- current_price = analysis.get('current_price', 1)
256
-
257
- if current_price > 0:
258
- normalized_var = var_95_value / current_price
259
- risk_penalty = 1.0
260
- if normalized_var > 0.05: risk_penalty = 0.5
261
- elif normalized_var > 0.03: risk_penalty = 0.8
262
-
263
- normalized_prob_score = max(0.0, (prob_gain - 0.5) * 2)
264
- monte_carlo_score = normalized_prob_score * risk_penalty
 
265
 
266
- # 3. درجة المؤشرات (Indicator Score)
267
- indicator_score = 0
268
  indicators = analysis.get('advanced_indicators', {}).get('1h', {})
269
- if indicators:
270
- rsi = indicators.get('rsi', 50)
271
- macd_hist = indicators.get('macd_hist', 0)
272
- ema_9 = indicators.get('ema_9', 0)
273
- ema_21 = indicators.get('ema_21', 0)
274
-
275
- if rsi > 55 and macd_hist > 0 and ema_9 > ema_21:
276
- indicator_score = min(0.5 + (rsi - 55) / 50 + (macd_hist / (analysis.get('current_price', 1) * 0.001)), 1.0)
277
- elif rsi < 35:
278
- indicator_score = min(0.4 + (35 - rsi) / 35, 0.8)
279
-
280
- # 4. حساب النتيجة النهائية (بدون استراتيجيات أو حيتان)
281
- components = []
282
- weights = []
283
 
284
- if monte_carlo_score > 0: components.append(monte_carlo_score); weights.append(0.40)
285
- if pattern_confidence > 0: components.append(pattern_confidence); weights.append(0.30)
286
- if indicator_score > 0: components.append(indicator_score); weights.append(0.30)
287
 
288
- if not components: return 0
289
- total_weight = sum(weights)
290
- if total_weight == 0: return 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
 
292
- enhanced_score = sum(comp * weight for comp, weight in zip(components, weights)) / total_weight
293
- return min(max(enhanced_score, 0.0), 1.0)
294
 
295
  except Exception as e:
296
- print(f"❌ خطأ في حساب درجة فلتر 1H: {e}")
297
  return 0.0
 
298
 
299
 
300
  async def layer1_rapid_screening(self) -> List[Dict[str, Any]]:
301
  """
302
  الطبقة 1: فحص سريع - (محدث بالكامل V7.3)
303
  """
304
- print("📊 الطبقة 1 (V7.3): بدء الغربلة (الكاشف المصغر 1H)...")
305
 
306
  # الخطوة 1: جلب أفضل 100 عملة حسب الحجم
307
  volume_data = await self._get_volume_data_optimal()
@@ -315,7 +366,7 @@ class DataManager:
315
  volume_data.sort(key=lambda x: x['dollar_volume'], reverse=True)
316
  top_100_by_volume = volume_data[:100]
317
 
318
- print(f"✅ تم تحديد أفضل {len(top_100_by_volume)} عملة. بدء تشغيل الكاشف المصغر (1H)...")
319
 
320
  final_candidates = []
321
 
@@ -362,21 +413,20 @@ class DataManager:
362
  analysis_output['ohlcv_1h'] = symbol_data['ohlcv_1h']
363
  analysis_output['symbol'] = symbol
364
 
 
365
  filter_score = self._calculate_1h_filter_score(analysis_output)
366
 
367
- # 🔴 --- START OF CHANGE (V7.3) --- 🔴
368
- # (رفع العتبة من 0.20 إلى 0.50)
369
  if filter_score >= 0.50:
370
- # 🔴 --- END OF CHANGE --- 🔴
371
  print(f" ✅ {symbol}: نجح (الدرجة: {filter_score:.2f})")
372
  symbol_data['layer1_score'] = filter_score
373
- symbol_data['reasons_for_candidacy'] = [f'1H_DETECTOR_PASS']
374
 
375
  if 'ohlcv_1h' in symbol_data: del symbol_data['ohlcv_1h']
376
 
377
  final_candidates.append(symbol_data)
378
 
379
- print(f"🎯 اكتملت الغربلة (V7.3). تم تأهيل {len(final_candidates)} عملة من أصل 100 للطبقة 2.")
380
 
381
  print("🏆 المرشحون الناجحون:")
382
  for k, candidate in enumerate(final_candidates[:15]):
@@ -656,4 +706,4 @@ class DataManager:
656
  except Exception as e:
657
  return {'action': 'HOLD', 'confidence': 0.3, 'reason': f'Error: {str(e)}', 'source': 'whale_analysis'}
658
 
659
- print("✅ DataManager loaded - V7.3 (L1 Threshold @ 0.50)")
 
1
+ # data_manager.py (Updated to V7.4 - 1H Momentum Burst Filter)
2
  import os
3
  import asyncio
4
  import httpx
 
67
  self.pattern_analyzer = ChartPatternAnalyzer(r2_service=None)
68
  # --- (نهاية الإضافة) ---
69
 
70
+ print("✅ DataManager initialized - V7.4 (1H Momentum Burst Filter)")
71
 
72
  async def _load_markets(self):
73
  try:
 
227
  print(f"❌ خطأ في إنشاء DataFrame لمرشح 1H: {e}")
228
  return pd.DataFrame()
229
 
230
+ # 🔴 --- START OF CHANGE (V7.4) --- 🔴
231
+ # (دالة مساعدة جديدة لتقسيم منطق MC)
232
+ def _get_mc_score_for_filter(self, analysis: Dict) -> float:
233
+ """(V7.4) (دالة مساعدة) لحساب درجة مونت كارلو للفلتر"""
234
+ mc_distribution = analysis.get('monte_carlo_distribution')
235
+ monte_carlo_score = 0
236
+
237
+ if mc_distribution and mc_distribution.get('error') is None:
238
+ prob_gain = mc_distribution.get('probability_of_gain', 0)
239
+ var_95_value = mc_distribution.get('risk_metrics', {}).get('VaR_95_value', 0)
240
+ current_price = analysis.get('current_price', 1)
241
+
242
+ if current_price > 0:
243
+ normalized_var = var_95_value / current_price
244
+ risk_penalty = 1.0
245
+ if normalized_var > 0.05: risk_penalty = 0.5
246
+ elif normalized_var > 0.03: risk_penalty = 0.8
247
+
248
+ normalized_prob_score = max(0.0, (prob_gain - 0.5) * 2)
249
+ monte_carlo_score = normalized_prob_score * risk_penalty
250
+ return monte_carlo_score
251
+
252
  def _calculate_1h_filter_score(self, analysis: Dict) -> float:
253
  """
254
+ (محدث V7.4 - فلتر الزخم المتفجر 1H)
255
+ "فلتر شمس منتصف الظهر"
256
+ يبحث عن:
257
+ 1. انفجار الحجم (Volume Explosion)
258
+ 2. قوة الاتجاه (Trend Strength - ADX)
259
+ 3. المنطقة الآمنة (RSI Safe Zone)
260
+ 4. (يحتوي على واقي العملات المستقرة V7.2)
261
  """
262
  try:
263
+ # (V7.2) واقي العملات المستقرة (لا تغيير)
264
+ ohlcv_candles = analysis.get('ohlcv_1h', {}).get('1h', [])
265
+ if not ohlcv_candles or len(ohlcv_candles) < 30: # (تحتاج 30 لـ ADX و Vol MA)
266
+ return 0.0
267
+
268
+ closes_1h = [c[4] for c in ohlcv_candles]
269
+ if len(closes_1h) > 20: # (التحقق من العملة المستقرة أولاً)
270
+ std_dev = np.std(closes_1h[-20:])
271
+ if std_dev < 1e-5:
272
+ # print(f" - {analysis.get('symbol', 'N/A')}: تم الاستبعاد (عملة مستقرة)")
273
+ return 0.0
274
 
275
+ # --- (الإضافة الجديدة: حساب المؤشرات المتقدمة للفلتر) ---
276
+ if ta is None: # (التحقق من pandas_ta)
277
+ return 0.0 # لا يمكن الحساب بدون المكتبة
278
+
279
+ df = self._create_dataframe(ohlcv_candles) # (إعادة إنشاء DF لحساب ADX/Vol)
280
+ if df.empty:
281
+ return 0.0
282
+
283
+ # 1. حساب مؤشرات الزخم المتفجر
284
+ volume = df['volume']
285
+ vol_ma = ta.sma(volume, length=20)
286
+ if vol_ma is None or vol_ma.empty: return 0.0
287
+
288
+ current_volume = volume.iloc[-1]
289
+ avg_volume = vol_ma.iloc[-1]
290
+
291
+ adx_data = ta.adx(df['high'], df['low'], df['close'], length=14)
292
+ current_adx = adx_data['ADX_14'].iloc[-1] if adx_data is not None and not adx_data.empty else 0
293
 
294
+ # 2. جلب المؤشرات الأساسية (المحسوبة مسبقاً)
 
295
  indicators = analysis.get('advanced_indicators', {}).get('1h', {})
296
+ rsi = indicators.get('rsi', 50)
297
+
298
+ # 3. جلب درجة مونت كارلو (المحسوبة مسبقاً)
299
+ monte_carlo_score = self._get_mc_score_for_filter(analysis)
 
 
 
 
 
 
 
 
 
 
300
 
301
+ # 4. جلب درجة الأنماط (المحسوبة مسبقاً)
302
+ pattern_confidence = analysis.get('pattern_analysis', {}).get('pattern_confidence', 0)
 
303
 
304
+ # --- (منطق الفلترة الجديد) ---
305
+
306
+ # المعايير الصارمة لـ "شمس منتصف الظهر"
307
+ VOL_MULTIPLIER = 1.75 # (يجب أن يكون الحجم الحالي 1.75x المتوسط)
308
+ ADX_THRESHOLD = 25.0 # (يجب أن يكون الاتجاه قوياً)
309
+ RSI_MIN = 60 # (يجب أن يكون في منطقة صاعدة)
310
+ RSI_MAX = 85 # (يجب ألا يكون منهكاً تماماً)
311
+
312
+ vol_score = 0.0
313
+ if avg_volume > 0:
314
+ # (تطبيع درجة الحجم: 1.0 إذا كان يساوي أو يفوق المضاعف)
315
+ vol_score = min(1.0, max(0.0, (current_volume / avg_volume) / VOL_MULTIPLIER))
316
+
317
+ # (تطبيع درجة ADX: 0.0 عند 25، و 1.0 عند 40+)
318
+ adx_score = min(1.0, max(0.0, (current_adx - ADX_THRESHOLD) / 15.0))
319
+
320
+ rsi_score = 0.0
321
+ if RSI_MIN <= rsi <= RSI_MAX:
322
+ rsi_score = 1.0
323
+ elif rsi > RSI_MAX: # (عقوبة بسيطة للإرهاق)
324
+ rsi_score = 0.5
325
+
326
+ # (الأوزان الجديدة) - إعطاء الأولوية للزخم والحجم
327
+ WEIGHT_VOL = 0.30
328
+ WEIGHT_ADX = 0.30
329
+ WEIGHT_RSI = 0.15
330
+ WEIGHT_MC = 0.15
331
+ WEIGHT_PATTERN = 0.10 # (تقليل أهمية النمط أثناء الانفجار)
332
+
333
+ final_score = (
334
+ (vol_score * WEIGHT_VOL) +
335
+ (adx_score * WEIGHT_ADX) +
336
+ (rsi_score * WEIGHT_RSI) +
337
+ (monte_carlo_score * WEIGHT_MC) +
338
+ (pattern_confidence * WEIGHT_PATTERN)
339
+ )
340
+
341
+ # (العتبة (Threshold) لا تزال 0.50 كما هي في V7.3)
342
 
343
+ return min(max(final_score, 0.0), 1.0)
 
344
 
345
  except Exception as e:
346
+ # print(f"❌ خطأ في حساب درجة فلتر 1H (V-Burst): {e}")
347
  return 0.0
348
+ # 🔴 --- END OF CHANGE --- 🔴
349
 
350
 
351
  async def layer1_rapid_screening(self) -> List[Dict[str, Any]]:
352
  """
353
  الطبقة 1: فحص سريع - (محدث بالكامل V7.3)
354
  """
355
+ print("📊 الطبقة 1 (V7.4): بدء الغربلة (الكاشف المتفجر 1H)...")
356
 
357
  # الخطوة 1: جلب أفضل 100 عملة حسب الحجم
358
  volume_data = await self._get_volume_data_optimal()
 
366
  volume_data.sort(key=lambda x: x['dollar_volume'], reverse=True)
367
  top_100_by_volume = volume_data[:100]
368
 
369
+ print(f"✅ تم تحديد أفضل {len(top_100_by_volume)} عملة. بدء تشغيل الكاشف المتفجر (1H)...")
370
 
371
  final_candidates = []
372
 
 
413
  analysis_output['ohlcv_1h'] = symbol_data['ohlcv_1h']
414
  analysis_output['symbol'] = symbol
415
 
416
+ # (استدعاء الدالة الجديدة V7.4)
417
  filter_score = self._calculate_1h_filter_score(analysis_output)
418
 
419
+ # (لا تغيير في العتبة، V7.3)
 
420
  if filter_score >= 0.50:
 
421
  print(f" ✅ {symbol}: نجح (الدرجة: {filter_score:.2f})")
422
  symbol_data['layer1_score'] = filter_score
423
+ symbol_data['reasons_for_candidacy'] = [f'1H_MOMENTUM_BURST']
424
 
425
  if 'ohlcv_1h' in symbol_data: del symbol_data['ohlcv_1h']
426
 
427
  final_candidates.append(symbol_data)
428
 
429
+ print(f"🎯 اكتملت الغربلة (V7.4). تم تأهيل {len(final_candidates)} عملة من أصل 100 للطبقة 2.")
430
 
431
  print("🏆 المرشحون الناجحون:")
432
  for k, candidate in enumerate(final_candidates[:15]):
 
706
  except Exception as e:
707
  return {'action': 'HOLD', 'confidence': 0.3, 'reason': f'Error: {str(e)}', 'source': 'whale_analysis'}
708
 
709
+ print("✅ DataManager loaded - V7.4 (1H Momentum Burst Filter)")