Update data_manager.py
Browse files- data_manager.py +5 -47
data_manager.py
CHANGED
|
@@ -80,7 +80,6 @@ class DataManager:
|
|
| 80 |
return market_context
|
| 81 |
|
| 82 |
except Exception as e:
|
| 83 |
-
print(f"❌ فشل جلب سياق السوق: {e}")
|
| 84 |
return self._get_minimal_market_context()
|
| 85 |
|
| 86 |
async def get_sentiment_safe_async(self):
|
|
@@ -102,7 +101,6 @@ class DataManager:
|
|
| 102 |
"timestamp": datetime.now().isoformat()
|
| 103 |
}
|
| 104 |
except Exception as e:
|
| 105 |
-
print(f"❌ فشل جلب بيانات المشاعر: {e}")
|
| 106 |
return None
|
| 107 |
|
| 108 |
def _determine_market_trend(self, bitcoin_price, sentiment_data):
|
|
@@ -148,7 +146,6 @@ class DataManager:
|
|
| 148 |
return prices
|
| 149 |
return await self._get_prices_from_coingecko()
|
| 150 |
except Exception as e:
|
| 151 |
-
print(f"❌ فشل جلب الأسعار: {e}")
|
| 152 |
return {'bitcoin': None, 'ethereum': None}
|
| 153 |
|
| 154 |
async def _get_prices_from_kucoin_safe(self):
|
|
@@ -171,7 +168,6 @@ class DataManager:
|
|
| 171 |
return prices
|
| 172 |
|
| 173 |
except Exception as e:
|
| 174 |
-
print(f"❌ خطأ في جلب الأسعار من KuCoin: {e}")
|
| 175 |
return {'bitcoin': None, 'ethereum': None}
|
| 176 |
|
| 177 |
async def _get_prices_from_coingecko(self):
|
|
@@ -190,7 +186,6 @@ class DataManager:
|
|
| 190 |
response = await client.get(url, timeout=10)
|
| 191 |
|
| 192 |
if response.status_code == 429:
|
| 193 |
-
print("⏰ Rate limit من CoinGecko - الانتظار 2 ثانية")
|
| 194 |
await asyncio.sleep(2)
|
| 195 |
response = await client.get(url, timeout=10)
|
| 196 |
|
|
@@ -206,7 +201,6 @@ class DataManager:
|
|
| 206 |
return {'bitcoin': None, 'ethereum': None}
|
| 207 |
|
| 208 |
except Exception as e:
|
| 209 |
-
print(f"❌ فشل جلب الأسعار من CoinGecko: {e}")
|
| 210 |
return {'bitcoin': None, 'ethereum': None}
|
| 211 |
|
| 212 |
def _get_minimal_market_context(self):
|
|
@@ -226,17 +220,14 @@ class DataManager:
|
|
| 226 |
print("📊 الطبقة 1: جلب أفضل 200 عملة حسب حجم التداول...")
|
| 227 |
|
| 228 |
# المحاولة 1: الطريقة المثلى - استخدام fetch_tickers
|
| 229 |
-
print(" 🔍 المحاولة 1: جلب جميع التاكرز مرة واحدة...")
|
| 230 |
volume_data = await self._get_volume_data_optimal()
|
| 231 |
|
| 232 |
if not volume_data:
|
| 233 |
# المحاولة 2: الطريقة البديلة - استخدام API المباشر
|
| 234 |
-
print(" 🔄 المحاولة 2: استخدام API المباشر...")
|
| 235 |
volume_data = await self._get_volume_data_direct_api()
|
| 236 |
|
| 237 |
if not volume_data:
|
| 238 |
# المحاولة 3: الطريقة التقليدية (الاحتياطية)
|
| 239 |
-
print(" ⚠️ المحاولة 3: استخدام الطريقة التقليدية...")
|
| 240 |
volume_data = await self._get_volume_data_traditional()
|
| 241 |
|
| 242 |
if not volume_data:
|
|
@@ -250,7 +241,6 @@ class DataManager:
|
|
| 250 |
print(f"✅ تم اختيار أفضل {len(top_200_by_volume)} عملة حسب الحجم")
|
| 251 |
|
| 252 |
# المرحلة 2: تطبيق المؤشرات الأخرى على الـ200 فقط
|
| 253 |
-
print(" 📈 تطبيق المؤشرات المتقدمة على أفضل 200 عملة...")
|
| 254 |
final_candidates = await self._apply_advanced_indicators(top_200_by_volume)
|
| 255 |
|
| 256 |
print(f"🎯 تم تحليل {len(final_candidates)} عملة للطبقة 2")
|
|
@@ -271,7 +261,6 @@ class DataManager:
|
|
| 271 |
if not self.exchange:
|
| 272 |
return []
|
| 273 |
|
| 274 |
-
print(" 📊 جلب جميع بيانات التداول مرة واحدة...")
|
| 275 |
tickers = self.exchange.fetch_tickers()
|
| 276 |
|
| 277 |
volume_data = []
|
|
@@ -310,17 +299,14 @@ class DataManager:
|
|
| 310 |
|
| 311 |
processed += 1
|
| 312 |
|
| 313 |
-
print(f" ✅ تم معالجة {processed} عملة من أصل {len(tickers)}")
|
| 314 |
return volume_data
|
| 315 |
|
| 316 |
except Exception as e:
|
| 317 |
-
print(f" ❌ فشل الطريقة المثلى: {e}")
|
| 318 |
return []
|
| 319 |
|
| 320 |
async def _get_volume_data_direct_api(self) -> List[Dict[str, Any]]:
|
| 321 |
"""الطريقة الثانية: استخدام KuCoin API مباشرة"""
|
| 322 |
try:
|
| 323 |
-
print(" 🌐 الاتصال بـ KuCoin API مباشرة...")
|
| 324 |
url = "https://api.kucoin.com/api/v1/market/allTickers"
|
| 325 |
|
| 326 |
async with httpx.AsyncClient(timeout=15) as client:
|
|
@@ -360,11 +346,9 @@ class DataManager:
|
|
| 360 |
except (ValueError, KeyError) as e:
|
| 361 |
continue
|
| 362 |
|
| 363 |
-
print(f" ✅ تم جلب {len(volume_data)} عملة من API المباشر")
|
| 364 |
return volume_data
|
| 365 |
|
| 366 |
except Exception as e:
|
| 367 |
-
print(f" ❌ فشل API المباشر: {e}")
|
| 368 |
return []
|
| 369 |
|
| 370 |
async def _get_volume_data_traditional(self) -> List[Dict[str, Any]]:
|
|
@@ -378,8 +362,6 @@ class DataManager:
|
|
| 378 |
if symbol.endswith('/USDT') and self.market_cache[symbol].get('active', False)
|
| 379 |
]
|
| 380 |
|
| 381 |
-
print(f" 🔄 معالجة {len(usdt_symbols)} عملة (طريقة تقليدية)...")
|
| 382 |
-
|
| 383 |
volume_data = []
|
| 384 |
processed = 0
|
| 385 |
|
|
@@ -395,17 +377,14 @@ class DataManager:
|
|
| 395 |
volume_data.append(result)
|
| 396 |
|
| 397 |
processed += len(batch)
|
| 398 |
-
print(f" ✅ تم معالجة {processed}/{len(usdt_symbols)} عملة...")
|
| 399 |
|
| 400 |
# انتظار قصير بين الدفعات
|
| 401 |
if i + batch_size < len(usdt_symbols):
|
| 402 |
await asyncio.sleep(1)
|
| 403 |
|
| 404 |
-
print(f" ✅ تم جمع بيانات {len(volume_data)} عملة مؤهلة")
|
| 405 |
return volume_data
|
| 406 |
|
| 407 |
except Exception as e:
|
| 408 |
-
print(f" ❌ فشل الطريقة التقليدية: {e}")
|
| 409 |
return []
|
| 410 |
|
| 411 |
async def _process_single_symbol(self, symbol: str) -> Dict[str, Any]:
|
|
@@ -441,8 +420,6 @@ class DataManager:
|
|
| 441 |
"""تطبيق المؤشرات المتقدمة على أفضل العملات حسب الحجم"""
|
| 442 |
candidates = []
|
| 443 |
|
| 444 |
-
print(" 🔧 تطبيق مؤشرات الزخم والتقلب وقوة السعر...")
|
| 445 |
-
|
| 446 |
for i, symbol_data in enumerate(volume_data):
|
| 447 |
try:
|
| 448 |
symbol = symbol_data['symbol']
|
|
@@ -460,9 +437,6 @@ class DataManager:
|
|
| 460 |
symbol_data['layer1_score'] = score
|
| 461 |
|
| 462 |
candidates.append(symbol_data)
|
| 463 |
-
|
| 464 |
-
if (i + 1) % 50 == 0:
|
| 465 |
-
print(f" ✅ تم تحليل {i + 1}/{len(volume_data)} عملة")
|
| 466 |
|
| 467 |
except Exception as e:
|
| 468 |
continue
|
|
@@ -617,7 +591,6 @@ class DataManager:
|
|
| 617 |
جلب بيانات OHLCV كاملة للرموز المحددة مع جميع الإطارات الزمنية بشكل متوازي
|
| 618 |
"""
|
| 619 |
print(f"📊 جلب بيانات OHLCV كاملة لـ {len(symbols)} عملة بشكل متوازي...")
|
| 620 |
-
print(" 📈 الإطارات الزمنية: 5m, 15m, 1h, 4h, 1d, 1w")
|
| 621 |
|
| 622 |
# تقسيم الرموز إلى دفعات لتجنب rate limits
|
| 623 |
batch_size = 15 # تقليل حجم الدفعة لتحسين الاستقرار
|
|
@@ -642,13 +615,15 @@ class DataManager:
|
|
| 642 |
for i, result in enumerate(batch_results):
|
| 643 |
symbol = batch[i]
|
| 644 |
if isinstance(result, Exception):
|
| 645 |
-
|
| 646 |
elif result is not None:
|
| 647 |
all_results.append(result)
|
| 648 |
successful_count += 1
|
| 649 |
-
|
|
|
|
|
|
|
| 650 |
else:
|
| 651 |
-
|
| 652 |
|
| 653 |
print(f" ✅ اكتملت الدفعة {batch_num + 1}: {successful_count}/{len(batch)} ناجحة")
|
| 654 |
|
|
@@ -692,15 +667,11 @@ class DataManager:
|
|
| 692 |
result = timeframe_results[i]
|
| 693 |
|
| 694 |
if isinstance(result, Exception):
|
| 695 |
-
print(f" ⚠️ فشل جلب بيانات {timeframe} لـ {symbol}: {result}")
|
| 696 |
continue
|
| 697 |
|
| 698 |
if result and len(result) >= 10: # تخفيف الشرط من 50 إلى 10 شموع
|
| 699 |
ohlcv_data[timeframe] = result
|
| 700 |
successful_timeframes += 1
|
| 701 |
-
print(f" ✅ {symbol} - {timeframe}: {len(result)} شمعة")
|
| 702 |
-
else:
|
| 703 |
-
print(f" ⚠️ {symbol} - {timeframe}: بيانات محدودة ({len(result) if result else 0} شمعة)")
|
| 704 |
|
| 705 |
# تحسين: قبول العملة إذا كان لديها عدد كافٍ من الأطر الزمنية
|
| 706 |
if successful_timeframes >= min_required_timeframes and ohlcv_data:
|
|
@@ -718,18 +689,14 @@ class DataManager:
|
|
| 718 |
'successful_timeframes': successful_timeframes
|
| 719 |
}
|
| 720 |
|
| 721 |
-
print(f" ✅ اكتمل جلب بيانات {symbol}: {result_data['candles_count']} (نجح {successful_timeframes}/6)")
|
| 722 |
return result_data
|
| 723 |
|
| 724 |
except Exception as price_error:
|
| 725 |
-
print(f" ❌ خطأ في جلب سعر {symbol}: {price_error}")
|
| 726 |
return None
|
| 727 |
else:
|
| 728 |
-
print(f" ❌ بيانات غير كافية لـ {symbol}: {successful_timeframes} أطر ناجحة فقط (المطلوب: {min_required_timeframes})")
|
| 729 |
return None
|
| 730 |
|
| 731 |
except Exception as e:
|
| 732 |
-
print(f" ❌ خطأ عام في جلب بيانات {symbol}: {e}")
|
| 733 |
return None
|
| 734 |
|
| 735 |
async def _fetch_single_timeframe_improved(self, symbol: str, timeframe: str, limit: int):
|
|
@@ -742,14 +709,11 @@ class DataManager:
|
|
| 742 |
ohlcv_data = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
|
| 743 |
|
| 744 |
if ohlcv_data and len(ohlcv_data) > 0:
|
| 745 |
-
print(f" 📊 {symbol} - {timeframe}: {len(ohlcv_data)} شمعة (المحاولة {attempt + 1})")
|
| 746 |
return ohlcv_data
|
| 747 |
else:
|
| 748 |
-
print(f" ⚠️ {symbol} - {timeframe}: لا توجد بيانات (المحاولة {attempt + 1})")
|
| 749 |
return []
|
| 750 |
|
| 751 |
except Exception as e:
|
| 752 |
-
print(f" ❌ فشل جلب {timeframe} لـ {symbol} (المحاولة {attempt + 1}): {e}")
|
| 753 |
if attempt < max_retries - 1:
|
| 754 |
await asyncio.sleep(retry_delay * (attempt + 1))
|
| 755 |
else:
|
|
@@ -789,7 +753,6 @@ class DataManager:
|
|
| 789 |
return usdt_symbols
|
| 790 |
|
| 791 |
except Exception as e:
|
| 792 |
-
print(f"❌ خطأ في جلب الرموز المتاحة: {e}")
|
| 793 |
return []
|
| 794 |
|
| 795 |
async def validate_symbol(self, symbol):
|
|
@@ -804,7 +767,6 @@ class DataManager:
|
|
| 804 |
return symbol in self.market_cache and self.market_cache[symbol].get('active', False)
|
| 805 |
|
| 806 |
except Exception as e:
|
| 807 |
-
print(f"❌ خطأ في التحقق من الرمز {symbol}: {e}")
|
| 808 |
return False
|
| 809 |
|
| 810 |
# === الدوال الجديدة لدعم بيانات الحيتان ===
|
|
@@ -813,14 +775,11 @@ class DataManager:
|
|
| 813 |
"""جلب بيانات الحيتان لعملة محددة"""
|
| 814 |
try:
|
| 815 |
if self.whale_monitor:
|
| 816 |
-
print(f"🔍 جلب بيانات الحيتان للعملة: {symbol}")
|
| 817 |
whale_data = await self.whale_monitor.get_symbol_whale_activity(symbol)
|
| 818 |
return whale_data
|
| 819 |
else:
|
| 820 |
-
print(f"⚠️ Whale monitor غير متوفر لـ {symbol}")
|
| 821 |
return None
|
| 822 |
except Exception as e:
|
| 823 |
-
print(f"❌ خطأ في جلب بيانات الحيتان لـ {symbol}: {e}")
|
| 824 |
return None
|
| 825 |
|
| 826 |
async def get_whale_trading_signal(self, symbol, whale_data, market_context):
|
|
@@ -836,7 +795,6 @@ class DataManager:
|
|
| 836 |
'source': 'whale_analysis'
|
| 837 |
}
|
| 838 |
except Exception as e:
|
| 839 |
-
print(f"❌ خطأ في جلب إشارة الحيتان لـ {symbol}: {e}")
|
| 840 |
return {
|
| 841 |
'action': 'HOLD',
|
| 842 |
'confidence': 0.3,
|
|
|
|
| 80 |
return market_context
|
| 81 |
|
| 82 |
except Exception as e:
|
|
|
|
| 83 |
return self._get_minimal_market_context()
|
| 84 |
|
| 85 |
async def get_sentiment_safe_async(self):
|
|
|
|
| 101 |
"timestamp": datetime.now().isoformat()
|
| 102 |
}
|
| 103 |
except Exception as e:
|
|
|
|
| 104 |
return None
|
| 105 |
|
| 106 |
def _determine_market_trend(self, bitcoin_price, sentiment_data):
|
|
|
|
| 146 |
return prices
|
| 147 |
return await self._get_prices_from_coingecko()
|
| 148 |
except Exception as e:
|
|
|
|
| 149 |
return {'bitcoin': None, 'ethereum': None}
|
| 150 |
|
| 151 |
async def _get_prices_from_kucoin_safe(self):
|
|
|
|
| 168 |
return prices
|
| 169 |
|
| 170 |
except Exception as e:
|
|
|
|
| 171 |
return {'bitcoin': None, 'ethereum': None}
|
| 172 |
|
| 173 |
async def _get_prices_from_coingecko(self):
|
|
|
|
| 186 |
response = await client.get(url, timeout=10)
|
| 187 |
|
| 188 |
if response.status_code == 429:
|
|
|
|
| 189 |
await asyncio.sleep(2)
|
| 190 |
response = await client.get(url, timeout=10)
|
| 191 |
|
|
|
|
| 201 |
return {'bitcoin': None, 'ethereum': None}
|
| 202 |
|
| 203 |
except Exception as e:
|
|
|
|
| 204 |
return {'bitcoin': None, 'ethereum': None}
|
| 205 |
|
| 206 |
def _get_minimal_market_context(self):
|
|
|
|
| 220 |
print("📊 الطبقة 1: جلب أفضل 200 عملة حسب حجم التداول...")
|
| 221 |
|
| 222 |
# المحاولة 1: الطريقة المثلى - استخدام fetch_tickers
|
|
|
|
| 223 |
volume_data = await self._get_volume_data_optimal()
|
| 224 |
|
| 225 |
if not volume_data:
|
| 226 |
# المحاولة 2: الطريقة البديلة - استخدام API المباشر
|
|
|
|
| 227 |
volume_data = await self._get_volume_data_direct_api()
|
| 228 |
|
| 229 |
if not volume_data:
|
| 230 |
# المحاولة 3: الطريقة التقليدية (الاحتياطية)
|
|
|
|
| 231 |
volume_data = await self._get_volume_data_traditional()
|
| 232 |
|
| 233 |
if not volume_data:
|
|
|
|
| 241 |
print(f"✅ تم اختيار أفضل {len(top_200_by_volume)} عملة حسب الحجم")
|
| 242 |
|
| 243 |
# المرحلة 2: تطبيق المؤشرات الأخرى على الـ200 فقط
|
|
|
|
| 244 |
final_candidates = await self._apply_advanced_indicators(top_200_by_volume)
|
| 245 |
|
| 246 |
print(f"🎯 تم تحليل {len(final_candidates)} عملة للطبقة 2")
|
|
|
|
| 261 |
if not self.exchange:
|
| 262 |
return []
|
| 263 |
|
|
|
|
| 264 |
tickers = self.exchange.fetch_tickers()
|
| 265 |
|
| 266 |
volume_data = []
|
|
|
|
| 299 |
|
| 300 |
processed += 1
|
| 301 |
|
|
|
|
| 302 |
return volume_data
|
| 303 |
|
| 304 |
except Exception as e:
|
|
|
|
| 305 |
return []
|
| 306 |
|
| 307 |
async def _get_volume_data_direct_api(self) -> List[Dict[str, Any]]:
|
| 308 |
"""الطريقة الثانية: استخدام KuCoin API مباشرة"""
|
| 309 |
try:
|
|
|
|
| 310 |
url = "https://api.kucoin.com/api/v1/market/allTickers"
|
| 311 |
|
| 312 |
async with httpx.AsyncClient(timeout=15) as client:
|
|
|
|
| 346 |
except (ValueError, KeyError) as e:
|
| 347 |
continue
|
| 348 |
|
|
|
|
| 349 |
return volume_data
|
| 350 |
|
| 351 |
except Exception as e:
|
|
|
|
| 352 |
return []
|
| 353 |
|
| 354 |
async def _get_volume_data_traditional(self) -> List[Dict[str, Any]]:
|
|
|
|
| 362 |
if symbol.endswith('/USDT') and self.market_cache[symbol].get('active', False)
|
| 363 |
]
|
| 364 |
|
|
|
|
|
|
|
| 365 |
volume_data = []
|
| 366 |
processed = 0
|
| 367 |
|
|
|
|
| 377 |
volume_data.append(result)
|
| 378 |
|
| 379 |
processed += len(batch)
|
|
|
|
| 380 |
|
| 381 |
# انتظار قصير بين الدفعات
|
| 382 |
if i + batch_size < len(usdt_symbols):
|
| 383 |
await asyncio.sleep(1)
|
| 384 |
|
|
|
|
| 385 |
return volume_data
|
| 386 |
|
| 387 |
except Exception as e:
|
|
|
|
| 388 |
return []
|
| 389 |
|
| 390 |
async def _process_single_symbol(self, symbol: str) -> Dict[str, Any]:
|
|
|
|
| 420 |
"""تطبيق المؤشرات المتقدمة على أفضل العملات حسب الحجم"""
|
| 421 |
candidates = []
|
| 422 |
|
|
|
|
|
|
|
| 423 |
for i, symbol_data in enumerate(volume_data):
|
| 424 |
try:
|
| 425 |
symbol = symbol_data['symbol']
|
|
|
|
| 437 |
symbol_data['layer1_score'] = score
|
| 438 |
|
| 439 |
candidates.append(symbol_data)
|
|
|
|
|
|
|
|
|
|
| 440 |
|
| 441 |
except Exception as e:
|
| 442 |
continue
|
|
|
|
| 591 |
جلب بيانات OHLCV كاملة للرموز المحددة مع جميع الإطارات الزمنية بشكل متوازي
|
| 592 |
"""
|
| 593 |
print(f"📊 جلب بيانات OHLCV كاملة لـ {len(symbols)} عملة بشكل متوازي...")
|
|
|
|
| 594 |
|
| 595 |
# تقسيم الرموز إلى دفعات لتجنب rate limits
|
| 596 |
batch_size = 15 # تقليل حجم الدفعة لتحسين الاستقرار
|
|
|
|
| 615 |
for i, result in enumerate(batch_results):
|
| 616 |
symbol = batch[i]
|
| 617 |
if isinstance(result, Exception):
|
| 618 |
+
pass
|
| 619 |
elif result is not None:
|
| 620 |
all_results.append(result)
|
| 621 |
successful_count += 1
|
| 622 |
+
# طباعة رسالة واحدة فقط لكل عملة توضح عدد الأطر الزمنية
|
| 623 |
+
timeframes_count = result.get('successful_timeframes', 0)
|
| 624 |
+
print(f" ✅ {symbol}: {timeframes_count}/6 أطر زمنية")
|
| 625 |
else:
|
| 626 |
+
pass
|
| 627 |
|
| 628 |
print(f" ✅ اكتملت الدفعة {batch_num + 1}: {successful_count}/{len(batch)} ناجحة")
|
| 629 |
|
|
|
|
| 667 |
result = timeframe_results[i]
|
| 668 |
|
| 669 |
if isinstance(result, Exception):
|
|
|
|
| 670 |
continue
|
| 671 |
|
| 672 |
if result and len(result) >= 10: # تخفيف الشرط من 50 إلى 10 شموع
|
| 673 |
ohlcv_data[timeframe] = result
|
| 674 |
successful_timeframes += 1
|
|
|
|
|
|
|
|
|
|
| 675 |
|
| 676 |
# تحسين: قبول العملة إذا كان لديها عدد كافٍ من الأطر الزمنية
|
| 677 |
if successful_timeframes >= min_required_timeframes and ohlcv_data:
|
|
|
|
| 689 |
'successful_timeframes': successful_timeframes
|
| 690 |
}
|
| 691 |
|
|
|
|
| 692 |
return result_data
|
| 693 |
|
| 694 |
except Exception as price_error:
|
|
|
|
| 695 |
return None
|
| 696 |
else:
|
|
|
|
| 697 |
return None
|
| 698 |
|
| 699 |
except Exception as e:
|
|
|
|
| 700 |
return None
|
| 701 |
|
| 702 |
async def _fetch_single_timeframe_improved(self, symbol: str, timeframe: str, limit: int):
|
|
|
|
| 709 |
ohlcv_data = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
|
| 710 |
|
| 711 |
if ohlcv_data and len(ohlcv_data) > 0:
|
|
|
|
| 712 |
return ohlcv_data
|
| 713 |
else:
|
|
|
|
| 714 |
return []
|
| 715 |
|
| 716 |
except Exception as e:
|
|
|
|
| 717 |
if attempt < max_retries - 1:
|
| 718 |
await asyncio.sleep(retry_delay * (attempt + 1))
|
| 719 |
else:
|
|
|
|
| 753 |
return usdt_symbols
|
| 754 |
|
| 755 |
except Exception as e:
|
|
|
|
| 756 |
return []
|
| 757 |
|
| 758 |
async def validate_symbol(self, symbol):
|
|
|
|
| 767 |
return symbol in self.market_cache and self.market_cache[symbol].get('active', False)
|
| 768 |
|
| 769 |
except Exception as e:
|
|
|
|
| 770 |
return False
|
| 771 |
|
| 772 |
# === الدوال الجديدة لدعم بيانات الحيتان ===
|
|
|
|
| 775 |
"""جلب بيانات الحيتان لعملة محددة"""
|
| 776 |
try:
|
| 777 |
if self.whale_monitor:
|
|
|
|
| 778 |
whale_data = await self.whale_monitor.get_symbol_whale_activity(symbol)
|
| 779 |
return whale_data
|
| 780 |
else:
|
|
|
|
| 781 |
return None
|
| 782 |
except Exception as e:
|
|
|
|
| 783 |
return None
|
| 784 |
|
| 785 |
async def get_whale_trading_signal(self, symbol, whale_data, market_context):
|
|
|
|
| 795 |
'source': 'whale_analysis'
|
| 796 |
}
|
| 797 |
except Exception as e:
|
|
|
|
| 798 |
return {
|
| 799 |
'action': 'HOLD',
|
| 800 |
'confidence': 0.3,
|