Riy777 commited on
Commit
116ef05
·
1 Parent(s): 6598c39

Update data_manager.py

Browse files
Files changed (1) hide show
  1. data_manager.py +202 -87
data_manager.py CHANGED
@@ -22,6 +22,7 @@ class DataManager:
22
  })
23
  self.exchange.rateLimit = 800
24
  except Exception as e:
 
25
  self.exchange = None
26
 
27
  self._whale_data_cache = {}
@@ -98,11 +99,12 @@ class DataManager:
98
  if price and price > 0:
99
  return float(price)
100
  except Exception as e:
101
- pass
102
 
103
  return None
104
 
105
  except Exception as e:
 
106
  return None
107
 
108
  async def _get_price_from_coingecko_fallback(self, network):
@@ -127,6 +129,7 @@ class DataManager:
127
  return price
128
  return None
129
  except Exception as e:
 
130
  return None
131
 
132
  async def get_sentiment_safe_async(self):
@@ -149,6 +152,7 @@ class DataManager:
149
  "timestamp": datetime.now().isoformat()
150
  }
151
  except Exception as e:
 
152
  if attempt < max_retries - 1:
153
  await asyncio.sleep(1)
154
 
@@ -212,6 +216,7 @@ class DataManager:
212
  return market_context
213
 
214
  except Exception as e:
 
215
  if attempt < max_retries - 1:
216
  await asyncio.sleep(3)
217
 
@@ -336,6 +341,7 @@ class DataManager:
336
  return {'bitcoin': None, 'ethereum': None}
337
 
338
  except Exception as e:
 
339
  return {'bitcoin': None, 'ethereum': None}
340
 
341
  async def _get_prices_from_kucoin_safe(self):
@@ -351,8 +357,9 @@ class DataManager:
351
  if btc_price and btc_price > 0:
352
  prices['bitcoin'] = btc_price
353
  self.price_cache['bitcoin'] = btc_price
 
354
  except Exception as e:
355
- pass
356
 
357
  try:
358
  eth_ticker = await self.exchange.fetch_ticker('ETH/USDT')
@@ -360,12 +367,14 @@ class DataManager:
360
  if eth_price and eth_price > 0:
361
  prices['ethereum'] = eth_price
362
  self.price_cache['ethereum'] = eth_price
 
363
  except Exception as e:
364
- pass
365
 
366
  return prices
367
 
368
  except Exception as e:
 
369
  return {'bitcoin': None, 'ethereum': None}
370
 
371
  async def _get_prices_from_coingecko(self):
@@ -383,11 +392,14 @@ class DataManager:
383
  if btc_price and eth_price:
384
  self.price_cache['bitcoin'] = btc_price
385
  self.price_cache['ethereum'] = eth_price
 
 
386
  return {'bitcoin': btc_price, 'ethereum': eth_price}
387
 
388
  return {'bitcoin': None, 'ethereum': None}
389
 
390
  except Exception as e:
 
391
  return {'bitcoin': None, 'ethereum': None}
392
 
393
  def _get_minimal_market_context(self):
@@ -485,40 +497,145 @@ class DataManager:
485
  async def get_whale_trading_signal(self, symbol, whale_data, market_context):
486
  return await self.whale_monitor.generate_whale_trading_signal(symbol, whale_data, market_context)
487
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
  async def find_high_potential_candidates(self, count=20):
489
  """
490
- إرجاع قائمة بالرموز ذات الإمكانات العالية للتداول.
491
- هذه دالة أساسية تحتاج للتطوير لتعمل مع بيانات حقيقية.
492
  """
493
  try:
494
- print(f"🔍 البحث عن {count} رمز ذو إمكانات عالية...")
495
-
496
- # قائمة بالرموز الشائعة للتداول
497
- common_symbols = [
498
- 'BTC/USDT', 'ETH/USDT', 'ADA/USDT', 'DOT/USDT', 'LINK/USDT',
499
- 'LTC/USDT', 'XRP/USDT', 'BCH/USDT', 'EOS/USDT', 'XLM/USDT',
500
- 'TRX/USDT', 'ETC/USDT', 'XTZ/USDT', 'ATOM/USDT', 'ALGO/USDT',
501
- 'SOL/USDT', 'MATIC/USDT', 'AVAX/USDT', 'FTM/USDT', 'NEAR/USDT'
 
 
 
 
 
502
  ]
503
 
504
- candidates = []
505
- for symbol in common_symbols[:count]:
506
- # إضافة أسباب متنوعة للمرشحين
507
- reasons = []
508
- if 'BTC' in symbol or 'ETH' in symbol:
509
- reasons.extend(['high_liquidity', 'market_leader', 'high_volume'])
510
- elif any(alt in symbol for alt in ['ADA', 'DOT', 'SOL']):
511
- reasons.extend(['smart_contract_platform', 'active_development'])
512
- else:
513
- reasons.extend(['altcoin_potential', 'volatility_opportunity'])
514
-
515
- candidates.append({
516
- 'symbol': symbol,
517
- 'reasons': reasons
518
- })
519
 
520
- print(f"✅ تم العثور على {len(candidates)} مرشح محتمل")
521
- return candidates
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
522
 
523
  except Exception as e:
524
  print(f"❌ خطأ في find_high_potential_candidates: {e}")
@@ -526,67 +643,62 @@ class DataManager:
526
 
527
  async def get_fast_pass_data_async(self, candidates):
528
  """
529
- جلب بيانات OHLCV للرموز المرشحة.
530
- هذه دالة أساسية تحتاج للتطوير لتعمل مع بيانات حقيقية من KuCoin.
531
  """
532
  try:
533
- print(f"📊 جلب بيانات OHLCV لـ {len(candidates)} مرشح...")
534
  results = []
535
 
 
 
 
 
 
 
 
 
 
 
536
  for candidate in candidates:
537
  symbol = candidate['symbol']
538
 
539
  try:
540
- # محاولة جلب بيانات حقيقية من KuCoin
541
- if self.exchange:
542
- # جلب بيانات الإطار الزمني 1 ساعة
543
- ohlcv_1h = await self.exchange.fetch_ohlcv(symbol, '1h', limit=100)
544
-
545
- # جلب بيانات الإطار الزمني 4 ساعات
546
- ohlcv_4h = await self.exchange.fetch_ohlcv(symbol, '4h', limit=50)
547
-
548
- # جلب بيانات الإطار الزمني 1 يوم
549
- ohlcv_1d = await self.exchange.fetch_ohlcv(symbol, '1d', limit=30)
550
-
551
- ohlcv_data = {
552
- '1h': ohlcv_1h,
553
- '4h': ohlcv_4h,
554
- '1d': ohlcv_1d
555
- }
556
- else:
557
- # بيانات افتراضية إذا فشل الاتصال بالتبادل
558
- current_time = int(time.time() * 1000)
559
- base_price = 100.0
560
-
561
- ohlcv_data = {
562
- '1h': [
563
- [current_time - i * 3600000, base_price, base_price * 1.05, base_price * 0.95, base_price * 1.02, 1000000]
564
- for i in range(100, 0, -1)
565
- ],
566
- '4h': [
567
- [current_time - i * 14400000, base_price, base_price * 1.08, base_price * 0.92, base_price * 1.04, 2000000]
568
- for i in range(50, 0, -1)
569
- ],
570
- '1d': [
571
- [current_time - i * 86400000, base_price, base_price * 1.10, base_price * 0.90, base_price * 1.06, 5000000]
572
- for i in range(30, 0, -1)
573
- ]
574
- }
575
 
576
- result_data = {
577
- 'symbol': symbol,
578
- 'ohlcv': ohlcv_data,
579
- 'reasons': candidate.get('reasons', [])
580
- }
 
 
 
 
 
 
 
 
 
 
 
581
 
582
- results.append(result_data)
 
 
 
 
 
 
 
 
 
583
 
584
  except Exception as symbol_error:
585
- print(f"⚠️ خطأ في جلب بيانات {symbol}: {symbol_error}")
586
- # تخطي هذا الرمز والمتابعة للرمز التالي
587
  continue
588
 
589
- print(f"✅ تم جلب بيانات لـ {len(results)} مرشح بنجاح")
590
  return results
591
 
592
  except Exception as e:
@@ -595,18 +707,21 @@ class DataManager:
595
 
596
  async def get_latest_price_async(self, symbol):
597
  """
598
- جلب السعر الحالي للرمز.
599
  """
600
  try:
601
- if self.exchange:
602
- # محاولة جلب السعر الحالي من KuCoin
603
- ticker = await self.exchange.fetch_ticker(symbol)
604
- current_price = ticker.get('last')
605
- if current_price:
606
- return float(current_price)
607
-
608
- # سعر افتراضي إذا فشل الجلب
609
- return 100.0
 
 
 
610
 
611
  except Exception as e:
612
  print(f"❌ خطأ في get_latest_price_async لـ {symbol}: {e}")
 
22
  })
23
  self.exchange.rateLimit = 800
24
  except Exception as e:
25
+ print(f"❌ فشل تهيئة اتصال KuCoin: {e}")
26
  self.exchange = None
27
 
28
  self._whale_data_cache = {}
 
99
  if price and price > 0:
100
  return float(price)
101
  except Exception as e:
102
+ print(f"❌ فشل جلب سعر {symbol} من KuCoin: {e}")
103
 
104
  return None
105
 
106
  except Exception as e:
107
+ print(f"❌ خطأ في _get_price_from_kucoin لـ {symbol}: {e}")
108
  return None
109
 
110
  async def _get_price_from_coingecko_fallback(self, network):
 
129
  return price
130
  return None
131
  except Exception as e:
132
+ print(f"❌ فشل جلب سعر {network} من CoinGecko: {e}")
133
  return None
134
 
135
  async def get_sentiment_safe_async(self):
 
152
  "timestamp": datetime.now().isoformat()
153
  }
154
  except Exception as e:
155
+ print(f"❌ فشل جلب بيانات المشاعر (المحاولة {attempt + 1}): {e}")
156
  if attempt < max_retries - 1:
157
  await asyncio.sleep(1)
158
 
 
216
  return market_context
217
 
218
  except Exception as e:
219
+ print(f"❌ فشل جلب سياق السوق (المحاولة {attempt + 1}): {e}")
220
  if attempt < max_retries - 1:
221
  await asyncio.sleep(3)
222
 
 
341
  return {'bitcoin': None, 'ethereum': None}
342
 
343
  except Exception as e:
344
+ print(f"❌ فشل جلب الأسعار: {e}")
345
  return {'bitcoin': None, 'ethereum': None}
346
 
347
  async def _get_prices_from_kucoin_safe(self):
 
357
  if btc_price and btc_price > 0:
358
  prices['bitcoin'] = btc_price
359
  self.price_cache['bitcoin'] = btc_price
360
+ print(f"✅ سعر BTC: ${btc_price:,.2f}")
361
  except Exception as e:
362
+ print(f"❌ فشل جلب سعر BTC: {e}")
363
 
364
  try:
365
  eth_ticker = await self.exchange.fetch_ticker('ETH/USDT')
 
367
  if eth_price and eth_price > 0:
368
  prices['ethereum'] = eth_price
369
  self.price_cache['ethereum'] = eth_price
370
+ print(f"✅ سعر ETH: ${eth_price:,.2f}")
371
  except Exception as e:
372
+ print(f"❌ فشل جلب سعر ETH: {e}")
373
 
374
  return prices
375
 
376
  except Exception as e:
377
+ print(f"❌ خطأ في _get_prices_from_kucoin_safe: {e}")
378
  return {'bitcoin': None, 'ethereum': None}
379
 
380
  async def _get_prices_from_coingecko(self):
 
392
  if btc_price and eth_price:
393
  self.price_cache['bitcoin'] = btc_price
394
  self.price_cache['ethereum'] = eth_price
395
+ print(f"✅ سعر BTC (CoinGecko): ${btc_price:,.2f}")
396
+ print(f"✅ سعر ETH (CoinGecko): ${eth_price:,.2f}")
397
  return {'bitcoin': btc_price, 'ethereum': eth_price}
398
 
399
  return {'bitcoin': None, 'ethereum': None}
400
 
401
  except Exception as e:
402
+ print(f"❌ فشل جلب الأسعار من CoinGecko: {e}")
403
  return {'bitcoin': None, 'ethereum': None}
404
 
405
  def _get_minimal_market_context(self):
 
497
  async def get_whale_trading_signal(self, symbol, whale_data, market_context):
498
  return await self.whale_monitor.generate_whale_trading_signal(symbol, whale_data, market_context)
499
 
500
+ async def _calculate_technical_score(self, symbol, ohlcv_data):
501
+ """حساب درجة تقنية بناءً على السيولة والحجم والتقلب والزخم"""
502
+ try:
503
+ if not ohlcv_data or '1h' not in ohlcv_data:
504
+ return 0.0
505
+
506
+ hourly_data = ohlcv_data['1h']
507
+ if len(hourly_data) < 50:
508
+ return 0.0
509
+
510
+ # تحويل إلى numpy array للحسابات
511
+ closes = np.array([candle[4] for candle in hourly_data])
512
+ volumes = np.array([candle[5] for candle in hourly_data])
513
+ highs = np.array([candle[2] for candle in hourly_data])
514
+ lows = np.array([candle[3] for candle in hourly_data])
515
+
516
+ # 1. السيولة (متوسط الحجم بالدولار)
517
+ avg_volume = np.mean(volumes[-50:]) * np.mean(closes[-50:])
518
+ liquidity_score = min(avg_volume / 1000000, 1.0) # تطبيع إلى 0-1
519
+
520
+ # 2. حجم التداول (الحجم النسبي)
521
+ recent_volume = np.mean(volumes[-10:])
522
+ avg_volume_50 = np.mean(volumes[-50:])
523
+ volume_ratio = recent_volume / avg_volume_50 if avg_volume_50 > 0 else 1.0
524
+ volume_score = min(volume_ratio / 3.0, 1.0) # تطبيع
525
+
526
+ # 3. التقلب (ATR النسبي)
527
+ true_ranges = []
528
+ for i in range(1, len(hourly_data)):
529
+ high, low, prev_close = highs[i], lows[i], closes[i-1]
530
+ tr1 = high - low
531
+ tr2 = abs(high - prev_close)
532
+ tr3 = abs(low - prev_close)
533
+ true_ranges.append(max(tr1, tr2, tr3))
534
+
535
+ atr = np.mean(true_ranges[-14:]) if true_ranges else 0
536
+ current_price = closes[-1]
537
+ volatility_score = min((atr / current_price) * 100 / 10, 1.0) # تطبيع
538
+
539
+ # 4. الزخم (معدل التغير)
540
+ price_change_1h = ((closes[-1] - closes[-2]) / closes[-2]) * 100 if len(closes) > 1 else 0
541
+ price_change_4h = ((closes[-1] - closes[-5]) / closes[-5]) * 100 if len(closes) > 5 else 0
542
+ price_change_24h = ((closes[-1] - closes[-24]) / closes[-24]) * 100 if len(closes) > 24 else 0
543
+
544
+ momentum_score = (abs(price_change_1h) + abs(price_change_4h) + abs(price_change_24h)) / 30
545
+ momentum_score = min(momentum_score, 1.0) # تطبيع
546
+
547
+ # الدرجة النهائية (مرجحة)
548
+ final_score = (
549
+ liquidity_score * 0.3 +
550
+ volume_score * 0.25 +
551
+ volatility_score * 0.2 +
552
+ momentum_score * 0.25
553
+ )
554
+
555
+ return final_score
556
+
557
+ except Exception as e:
558
+ print(f"❌ خطأ في حساب الدرجة التقنية لـ {symbol}: {e}")
559
+ return 0.0
560
+
561
  async def find_high_potential_candidates(self, count=20):
562
  """
563
+ إرجاع قائمة بالرموز ذات الإمكانات العالية بناءً على مؤشرات السيولة والحجم والتقلب والزخم.
 
564
  """
565
  try:
566
+ print(f"🔍 البحث عن {count} رمز ذو إمكانات عالية بناءً على المؤشرات التقنية...")
567
+
568
+ if not self.exchange:
569
+ print("❌ لا يوجد اتصال بـ KuCoin")
570
+ return []
571
+
572
+ # جلب جميع الأسواق المتاحة من KuCoin
573
+ markets = await self.exchange.load_markets()
574
+
575
+ # تصفية الرموز USDT فقط وتجنب الرموز ذات السيولة المنخفضة
576
+ usdt_symbols = [
577
+ symbol for symbol in markets.keys()
578
+ if symbol.endswith('/USDT') and markets[symbol].get('active', False)
579
  ]
580
 
581
+ print(f"✅ تم العثور على {len(usdt_symbols)} رمز USDT نشط في KuCoin")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
582
 
583
+ candidates_with_scores = []
584
+ analyzed_count = 0
585
+
586
+ for symbol in usdt_symbols[:100]: # تحليل أول 100 رمز فقط للكفاءة
587
+ try:
588
+ analyzed_count += 1
589
+ if analyzed_count % 10 == 0:
590
+ print(f"📊 تم تحليل {analyzed_count} رمز من أصل {min(100, len(usdt_symbols))}")
591
+
592
+ # جلب بيانات OHLCV للإطار 1 ساعة (50 شمعة كافية للتقييم الأولي)
593
+ ohlcv_1h = await self.exchange.fetch_ohlcv(symbol, '1h', limit=50)
594
+
595
+ if not ohlcv_1h or len(ohlcv_1h) < 20:
596
+ continue
597
+
598
+ ohlcv_data = {'1h': ohlcv_1h}
599
+
600
+ # حساب الدرجة التقنية
601
+ technical_score = await self._calculate_technical_score(symbol, ohlcv_data)
602
+
603
+ if technical_score > 0.3: # تجاهل الرموز ذات الدرجة المنخفضة جداً
604
+ # جلب بيانات إضافية للتقييم
605
+ ticker = await self.exchange.fetch_ticker(symbol)
606
+
607
+ reasons = []
608
+ if technical_score > 0.7:
609
+ reasons.append('high_technical_score')
610
+ if ticker.get('baseVolume', 0) > 1000000:
611
+ reasons.append('high_liquidity')
612
+ if abs(ticker.get('percentage', 0)) > 5:
613
+ reasons.append('significant_momentum')
614
+
615
+ candidates_with_scores.append({
616
+ 'symbol': symbol,
617
+ 'technical_score': technical_score,
618
+ 'reasons': reasons,
619
+ 'volume': ticker.get('baseVolume', 0),
620
+ 'price_change': ticker.get('percentage', 0),
621
+ 'current_price': ticker.get('last', 0)
622
+ })
623
+
624
+ except Exception as e:
625
+ if "rate limit" not in str(e).lower():
626
+ print(f"⚠️ خطأ في تحليل الرمز {symbol}: {e}")
627
+ continue
628
+
629
+ # ترتيب المرشحين بناءً على الدرجة التقنية
630
+ candidates_with_scores.sort(key=lambda x: x['technical_score'], reverse=True)
631
+ top_candidates = candidates_with_scores[:count]
632
+
633
+ print(f"✅ تم العثور على {len(top_candidates)} مرشح عالي الجودة من أصل {analyzed_count} رمز تم تحليله")
634
+
635
+ for candidate in top_candidates[:5]: # عرض أفضل 5 مرشحين
636
+ print(f" 🥇 {candidate['symbol']}: درجة {candidate['technical_score']:.3f}")
637
+
638
+ return top_candidates
639
 
640
  except Exception as e:
641
  print(f"❌ خطأ في find_high_potential_candidates: {e}")
 
643
 
644
  async def get_fast_pass_data_async(self, candidates):
645
  """
646
+ جلب بيانات OHLCV للرموز المرشحة بجميع الأطر الزمنية المطلوبة (200 شمعة لكل إطار).
 
647
  """
648
  try:
649
+ print(f"📊 جلب بيانات OHLCV لـ {len(candidates)} مرشح من KuCoin...")
650
  results = []
651
 
652
+ # الأطر الزمنية المطلوبة
653
+ timeframes = [
654
+ ('5m', 200), # 5 دقائق - 200 شمعة
655
+ ('15m', 200), # 15 دقيقة - 200 شمعة
656
+ ('1h', 200), # 1 ساعة - 200 شمعة
657
+ ('4h', 200), # 4 ساعات - 200 شمعة
658
+ ('1d', 200), # 1 يوم - 200 شمعة
659
+ ('1w', 200) # 1 أسبوع - 200 شمعة
660
+ ]
661
+
662
  for candidate in candidates:
663
  symbol = candidate['symbol']
664
 
665
  try:
666
+ ohlcv_data = {}
667
+ has_sufficient_data = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
668
 
669
+ for timeframe, limit in timeframes:
670
+ try:
671
+ ohlcv = await self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
672
+
673
+ if not ohlcv or len(ohlcv) < 50: # تحتاج على الأقل 50 شمعة للتحليل
674
+ print(f"⚠️ بيانات غير كافية للرمز {symbol} في الإطار {timeframe}")
675
+ has_sufficient_data = False
676
+ break
677
+
678
+ ohlcv_data[timeframe] = ohlcv
679
+ print(f" ✅ {symbol} - {timeframe}: {len(ohlcv)} شمعة")
680
+
681
+ except Exception as e:
682
+ print(f"❌ خطأ في جلب بيانات {symbol} للإطار {timeframe}: {e}")
683
+ has_sufficient_data = False
684
+ break
685
 
686
+ if has_sufficient_data:
687
+ result_data = {
688
+ 'symbol': symbol,
689
+ 'ohlcv': ohlcv_data,
690
+ 'reasons': candidate.get('reasons', []),
691
+ 'technical_score': candidate.get('technical_score', 0)
692
+ }
693
+
694
+ results.append(result_data)
695
+ print(f"✅ تم تجميع بيانات {symbol} بنجاح")
696
 
697
  except Exception as symbol_error:
698
+ print(f" خطأ في معالجة الرمز {symbol}: {symbol_error}")
 
699
  continue
700
 
701
+ print(f"✅ تم تجميع بيانات لـ {len(results)} مرشح بنجاح")
702
  return results
703
 
704
  except Exception as e:
 
707
 
708
  async def get_latest_price_async(self, symbol):
709
  """
710
+ جلب السعر الحالي للرمز من KuCoin.
711
  """
712
  try:
713
+ if not self.exchange:
714
+ print("❌ لا يوجد اتصال بـ KuCoin")
715
+ return None
716
+
717
+ ticker = await self.exchange.fetch_ticker(symbol)
718
+ current_price = ticker.get('last')
719
+
720
+ if current_price:
721
+ return float(current_price)
722
+ else:
723
+ print(f"❌ لم يتم العثور على سعر لـ {symbol}")
724
+ return None
725
 
726
  except Exception as e:
727
  print(f"❌ خطأ في get_latest_price_async لـ {symbol}: {e}")