Update data_manager.py
Browse files- data_manager.py +53 -34
data_manager.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# data_manager.py (Updated to
|
| 2 |
import os
|
| 3 |
import asyncio
|
| 4 |
import httpx
|
|
@@ -17,11 +17,12 @@ except ImportError:
|
|
| 17 |
print("⚠️ مكتبة pandas_ta غير موجودة. النظام سيفشل.")
|
| 18 |
ta = None
|
| 19 |
|
| 20 |
-
# (
|
| 21 |
from ml_engine.indicators import AdvancedTechnicalAnalyzer
|
| 22 |
-
|
|
|
|
| 23 |
from ml_engine.patterns import ChartPatternAnalyzer
|
| 24 |
-
# (V9.1) استيراد "العقل الذكي"
|
| 25 |
from ml_engine.ranker import Layer1Ranker
|
| 26 |
|
| 27 |
logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
@@ -47,10 +48,10 @@ class DataManager:
|
|
| 47 |
self.market_cache = {}
|
| 48 |
self.last_market_load = None
|
| 49 |
|
| 50 |
-
# (
|
| 51 |
self.technical_analyzer = AdvancedTechnicalAnalyzer()
|
| 52 |
-
self.monte_carlo_analyzer = MonteCarloAnalyzer()
|
| 53 |
self.pattern_analyzer = None
|
|
|
|
| 54 |
# (V9.1) تهيئة "العقل الذكي" (النموذج)
|
| 55 |
self.layer1_ranker = None
|
| 56 |
|
|
@@ -66,7 +67,6 @@ class DataManager:
|
|
| 66 |
print(f"❌ [DataManager] فشل تهيئة محرك الأنماط V8: {e}")
|
| 67 |
self.pattern_analyzer = ChartPatternAnalyzer(r2_service=None)
|
| 68 |
|
| 69 |
-
# (تهيئة "العقل الذكي" - نموذج الرانكر V9.8)
|
| 70 |
print(" > [DataManager] تهيئة الكاشف المصغر (Layer1 Ranker V9.8)...")
|
| 71 |
try:
|
| 72 |
# (تأكد من أن النموذج V9.8 موجود ومسمى بهذا الاسم)
|
|
@@ -81,7 +81,7 @@ class DataManager:
|
|
| 81 |
print(f"❌ [DataManager V9.8] فشل تهيئة الرانكر V9.8: {e}")
|
| 82 |
self.layer1_ranker = None
|
| 83 |
|
| 84 |
-
print("✅ DataManager initialized -
|
| 85 |
|
| 86 |
async def _load_markets(self):
|
| 87 |
try:
|
|
@@ -173,6 +173,7 @@ class DataManager:
|
|
| 173 |
def _get_minimal_market_context(self):
|
| 174 |
return { 'timestamp': datetime.now().isoformat(), 'data_available': False, 'market_trend': 'UNKNOWN', 'btc_sentiment': 'UNKNOWN', 'data_quality': 'LOW' }
|
| 175 |
|
|
|
|
| 176 |
def _create_dataframe(self, candles: List) -> pd.DataFrame:
|
| 177 |
"""(V9.1) إنشاء DataFrame (تحتاج 200 شمعة للميزات)"""
|
| 178 |
try:
|
|
@@ -189,25 +190,26 @@ class DataManager:
|
|
| 189 |
|
| 190 |
async def layer1_rapid_screening(self) -> List[Dict[str, Any]]:
|
| 191 |
"""
|
| 192 |
-
الطبقة 1: فحص سريع - (محدث
|
| 193 |
-
-
|
|
|
|
| 194 |
"""
|
| 195 |
-
print("📊 الطبقة 1 (
|
| 196 |
|
| 197 |
if not self.layer1_ranker:
|
| 198 |
-
print("❌ [
|
| 199 |
return []
|
| 200 |
|
| 201 |
# الخطوة 1: جلب أفضل 100 عملة حسب الحجم
|
| 202 |
volume_data = await self._get_volume_data_optimal()
|
| 203 |
if not volume_data: volume_data = await self._get_volume_data_direct_api()
|
| 204 |
if not volume_data:
|
| 205 |
-
print("❌ [
|
| 206 |
return []
|
| 207 |
|
| 208 |
volume_data.sort(key=lambda x: x['dollar_volume'], reverse=True)
|
| 209 |
top_100_by_volume = volume_data[:100]
|
| 210 |
-
print(f"✅ [
|
| 211 |
|
| 212 |
final_candidates_with_scores = []
|
| 213 |
batch_symbols_data = top_100_by_volume
|
|
@@ -225,59 +227,76 @@ class DataManager:
|
|
| 225 |
valid_symbol_data_for_ranking.append(symbol_data)
|
| 226 |
|
| 227 |
if not valid_symbol_data_for_ranking:
|
| 228 |
-
print("❌ [
|
| 229 |
return []
|
| 230 |
|
| 231 |
-
print(f" 🔄 [
|
| 232 |
|
| 233 |
-
# الخطوة 3: حساب "الميزات الذكية V9.8"
|
| 234 |
all_features_list = []
|
| 235 |
symbols_in_order = []
|
| 236 |
for symbol_data in valid_symbol_data_for_ranking:
|
| 237 |
try:
|
| 238 |
df = self._create_dataframe(symbol_data['ohlcv_1h_raw'])
|
| 239 |
if df.empty: continue
|
| 240 |
-
|
|
|
|
| 241 |
smart_features = self.technical_analyzer.calculate_v9_smart_features(df)
|
| 242 |
-
if smart_features:
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 246 |
|
| 247 |
if not all_features_list:
|
| 248 |
-
print("❌ [
|
| 249 |
return []
|
| 250 |
|
| 251 |
# الخطوة 4: التنبؤ (التصنيف)
|
| 252 |
-
print(f" 🧠 [
|
| 253 |
features_dataframe = pd.DataFrame(all_features_list)
|
| 254 |
probabilities = self.layer1_ranker.predict_proba(features_dataframe)
|
| 255 |
|
| 256 |
-
# (الطباعة التشخيصية
|
| 257 |
-
print(f" 🔍 [
|
| 258 |
debug_scores = []
|
| 259 |
for i, (symbol_data) in enumerate(symbols_in_order):
|
| 260 |
debug_scores.append((symbol_data['symbol'], probabilities[i]))
|
| 261 |
debug_scores.sort(key=lambda x: x[1], reverse=True)
|
| 262 |
-
print(" --- 📋 [
|
| 263 |
for i, (symbol, score) in enumerate(debug_scores[:10]):
|
| 264 |
print(f" {i+1}. {symbol}: {score:.4f}")
|
| 265 |
print(" -------------------------------------------------")
|
| 266 |
|
| 267 |
-
# الخطوة 5: تجميع النتائج (مع عتبة
|
| 268 |
for i, (symbol_data) in enumerate(symbols_in_order):
|
| 269 |
score = probabilities[i]
|
| 270 |
|
| 271 |
-
# 🔴 (
|
| 272 |
-
if score >= 0.
|
| 273 |
symbol = symbol_data['symbol']
|
| 274 |
print(f" ✅ {symbol}: نجح (الاحتمالية: {score:.3f})")
|
| 275 |
symbol_data['layer1_score'] = float(score)
|
| 276 |
-
symbol_data['reasons_for_candidacy'] = ["
|
| 277 |
if 'ohlcv_1h_raw' in symbol_data: del symbol_data['ohlcv_1h_raw']
|
| 278 |
final_candidates_with_scores.append(symbol_data)
|
| 279 |
|
| 280 |
-
print(f"🎯 اكتملت الغربلة (
|
| 281 |
|
| 282 |
if final_candidates_with_scores:
|
| 283 |
final_candidates_with_scores.sort(key=lambda x: x['layer1_score'], reverse=True)
|
|
@@ -285,7 +304,7 @@ class DataManager:
|
|
| 285 |
for k, candidate in enumerate(final_candidates_with_scores[:5]):
|
| 286 |
print(f" {k+1}. {candidate['symbol']}: (Score: {candidate.get('layer1_score'):.3f})")
|
| 287 |
else:
|
| 288 |
-
print("⚠️ [
|
| 289 |
|
| 290 |
return final_candidates_with_scores[:20]
|
| 291 |
|
|
@@ -501,4 +520,4 @@ class DataManager:
|
|
| 501 |
except Exception as e:
|
| 502 |
return {'action': 'HOLD', 'confidence': 0.3, 'reason': f'Error: {str(e)}', 'source': 'whale_analysis'}
|
| 503 |
|
| 504 |
-
print("✅ DataManager loaded -
|
|
|
|
| 1 |
+
# data_manager.py (Updated to V10.1 - Balanced 53% + MC Fix)
|
| 2 |
import os
|
| 3 |
import asyncio
|
| 4 |
import httpx
|
|
|
|
| 17 |
print("⚠️ مكتبة pandas_ta غير موجودة. النظام سيفشل.")
|
| 18 |
ta = None
|
| 19 |
|
| 20 |
+
# (V10.0) استيراد العقل الحسابي المطور
|
| 21 |
from ml_engine.indicators import AdvancedTechnicalAnalyzer
|
| 22 |
+
# (V10.0) استيراد مونت كارلو المطور
|
| 23 |
+
from ml_engine.monte_carlo import MonteCarloAnalyzer
|
| 24 |
from ml_engine.patterns import ChartPatternAnalyzer
|
| 25 |
+
# (V9.1) استيراد "العقل الذكي"
|
| 26 |
from ml_engine.ranker import Layer1Ranker
|
| 27 |
|
| 28 |
logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
|
|
| 48 |
self.market_cache = {}
|
| 49 |
self.last_market_load = None
|
| 50 |
|
| 51 |
+
# (V10.0) تهيئة العقول الحسابية
|
| 52 |
self.technical_analyzer = AdvancedTechnicalAnalyzer()
|
|
|
|
| 53 |
self.pattern_analyzer = None
|
| 54 |
+
self.mc_analyzer = MonteCarloAnalyzer()
|
| 55 |
# (V9.1) تهيئة "العقل الذكي" (النموذج)
|
| 56 |
self.layer1_ranker = None
|
| 57 |
|
|
|
|
| 67 |
print(f"❌ [DataManager] فشل تهيئة محرك الأنماط V8: {e}")
|
| 68 |
self.pattern_analyzer = ChartPatternAnalyzer(r2_service=None)
|
| 69 |
|
|
|
|
| 70 |
print(" > [DataManager] تهيئة الكاشف المصغر (Layer1 Ranker V9.8)...")
|
| 71 |
try:
|
| 72 |
# (تأكد من أن النموذج V9.8 موجود ومسمى بهذا الاسم)
|
|
|
|
| 81 |
print(f"❌ [DataManager V9.8] فشل تهيئة الرانكر V9.8: {e}")
|
| 82 |
self.layer1_ranker = None
|
| 83 |
|
| 84 |
+
print("✅ DataManager initialized - V10.1 (Balanced Threshold 53%)")
|
| 85 |
|
| 86 |
async def _load_markets(self):
|
| 87 |
try:
|
|
|
|
| 173 |
def _get_minimal_market_context(self):
|
| 174 |
return { 'timestamp': datetime.now().isoformat(), 'data_available': False, 'market_trend': 'UNKNOWN', 'btc_sentiment': 'UNKNOWN', 'data_quality': 'LOW' }
|
| 175 |
|
| 176 |
+
|
| 177 |
def _create_dataframe(self, candles: List) -> pd.DataFrame:
|
| 178 |
"""(V9.1) إنشاء DataFrame (تحتاج 200 شمعة للميزات)"""
|
| 179 |
try:
|
|
|
|
| 190 |
|
| 191 |
async def layer1_rapid_screening(self) -> List[Dict[str, Any]]:
|
| 192 |
"""
|
| 193 |
+
الطبقة 1: فحص سريع - (محدث V10.1)
|
| 194 |
+
- إصلاح مونت كارلو المفقود.
|
| 195 |
+
- استخدام عتبة التوازن 53% (0.53) التي اخترتها.
|
| 196 |
"""
|
| 197 |
+
print("📊 الطبقة 1 (V10.1 - Balanced 53% + MC Fix): بدء الغربلة...")
|
| 198 |
|
| 199 |
if not self.layer1_ranker:
|
| 200 |
+
print("❌ [V10.1] الرانكر غير مهيأ. إيقاف الغربلة.")
|
| 201 |
return []
|
| 202 |
|
| 203 |
# الخطوة 1: جلب أفضل 100 عملة حسب الحجم
|
| 204 |
volume_data = await self._get_volume_data_optimal()
|
| 205 |
if not volume_data: volume_data = await self._get_volume_data_direct_api()
|
| 206 |
if not volume_data:
|
| 207 |
+
print("❌ [V10.1] فشل جلب بيانات الأحجام.")
|
| 208 |
return []
|
| 209 |
|
| 210 |
volume_data.sort(key=lambda x: x['dollar_volume'], reverse=True)
|
| 211 |
top_100_by_volume = volume_data[:100]
|
| 212 |
+
print(f"✅ [V10.1] تم تحديد أفضل {len(top_100_by_volume)} عملة. بدء حساب الميزات الذكية...")
|
| 213 |
|
| 214 |
final_candidates_with_scores = []
|
| 215 |
batch_symbols_data = top_100_by_volume
|
|
|
|
| 227 |
valid_symbol_data_for_ranking.append(symbol_data)
|
| 228 |
|
| 229 |
if not valid_symbol_data_for_ranking:
|
| 230 |
+
print("❌ [V10.1] لا توجد عملات صالحة (تحتاج 200 شمعة 1H).")
|
| 231 |
return []
|
| 232 |
|
| 233 |
+
print(f" 🔄 [V10.1] حساب الميزات (الذكية + مونت كارلو) لـ {len(valid_symbol_data_for_ranking)} عملة...")
|
| 234 |
|
| 235 |
+
# الخطوة 3: حساب "الميزات الذكية V9.8" (الكاملة)
|
| 236 |
all_features_list = []
|
| 237 |
symbols_in_order = []
|
| 238 |
for symbol_data in valid_symbol_data_for_ranking:
|
| 239 |
try:
|
| 240 |
df = self._create_dataframe(symbol_data['ohlcv_1h_raw'])
|
| 241 |
if df.empty: continue
|
| 242 |
+
|
| 243 |
+
# (أ. حساب الميزات الذكية V9.8 - من indicators.py)
|
| 244 |
smart_features = self.technical_analyzer.calculate_v9_smart_features(df)
|
| 245 |
+
if not smart_features:
|
| 246 |
+
# (فشل حساب الميزات الرئيسية، تجاهل العملة)
|
| 247 |
+
continue
|
| 248 |
+
|
| 249 |
+
# 🔴 --- (V10.0 - الإصلاح) --- 🔴
|
| 250 |
+
# (ب. حساب ميزات مونت كارلو V9.8 - من monte_carlo.py)
|
| 251 |
+
# (نستخدم آخر 100 شمعة فقط للمحاكاة البسيطة كما في التدريب)
|
| 252 |
+
closes_np = df['close'].tail(100).to_numpy()
|
| 253 |
+
mc_features = self.mc_analyzer.generate_1h_price_distribution_simple(closes_np)
|
| 254 |
+
|
| 255 |
+
# (إضافة ميزات مونت كارلو إلى قاموس الميزات)
|
| 256 |
+
smart_features['mc_prob_gain'] = mc_features['mc_prob_gain']
|
| 257 |
+
smart_features['mc_var_95_pct'] = mc_features['mc_var_95_pct']
|
| 258 |
+
# 🔴 --- (نهاية الإصلاح) --- 🔴
|
| 259 |
+
|
| 260 |
+
all_features_list.append(smart_features)
|
| 261 |
+
symbols_in_order.append(symbol_data)
|
| 262 |
+
|
| 263 |
+
except Exception:
|
| 264 |
+
pass # (تجاهل العملة إذا فشل أي جزء)
|
| 265 |
|
| 266 |
if not all_features_list:
|
| 267 |
+
print("❌ [V10.1] فشل حساب الميزات الذكية.")
|
| 268 |
return []
|
| 269 |
|
| 270 |
# الخطوة 4: التنبؤ (التصنيف)
|
| 271 |
+
print(f" 🧠 [V10.1] إرسال {len(all_features_list)} عملة إلى نموذج الرانكر...")
|
| 272 |
features_dataframe = pd.DataFrame(all_features_list)
|
| 273 |
probabilities = self.layer1_ranker.predict_proba(features_dataframe)
|
| 274 |
|
| 275 |
+
# (الطباعة التشخيصية)
|
| 276 |
+
print(f" 🔍 [V10.1 DEBUG] تم استلام {len(probabilities)} نتيجة من الرانكر.")
|
| 277 |
debug_scores = []
|
| 278 |
for i, (symbol_data) in enumerate(symbols_in_order):
|
| 279 |
debug_scores.append((symbol_data['symbol'], probabilities[i]))
|
| 280 |
debug_scores.sort(key=lambda x: x[1], reverse=True)
|
| 281 |
+
print(" --- 📋 [V10.1 DEBUG] أعلى 10 درجات خام (قبل الفلترة) ---")
|
| 282 |
for i, (symbol, score) in enumerate(debug_scores[:10]):
|
| 283 |
print(f" {i+1}. {symbol}: {score:.4f}")
|
| 284 |
print(" -------------------------------------------------")
|
| 285 |
|
| 286 |
+
# الخطوة 5: تجميع النتائج (مع عتبة التوازن 53%)
|
| 287 |
for i, (symbol_data) in enumerate(symbols_in_order):
|
| 288 |
score = probabilities[i]
|
| 289 |
|
| 290 |
+
# 🔴 (V10.1: عتبة التوازن 53% - بناءً على اختيارك) 🔴
|
| 291 |
+
if score >= 0.53:
|
| 292 |
symbol = symbol_data['symbol']
|
| 293 |
print(f" ✅ {symbol}: نجح (الاحتمالية: {score:.3f})")
|
| 294 |
symbol_data['layer1_score'] = float(score)
|
| 295 |
+
symbol_data['reasons_for_candidacy'] = ["V9_SMART_RANKER_BALANCED_53"]
|
| 296 |
if 'ohlcv_1h_raw' in symbol_data: del symbol_data['ohlcv_1h_raw']
|
| 297 |
final_candidates_with_scores.append(symbol_data)
|
| 298 |
|
| 299 |
+
print(f"🎯 اكتملت الغربلة (V10.1). تم تأهيل {len(final_candidates_with_scores)} عملة (ثقة >= 53%).")
|
| 300 |
|
| 301 |
if final_candidates_with_scores:
|
| 302 |
final_candidates_with_scores.sort(key=lambda x: x['layer1_score'], reverse=True)
|
|
|
|
| 304 |
for k, candidate in enumerate(final_candidates_with_scores[:5]):
|
| 305 |
print(f" {k+1}. {candidate['symbol']}: (Score: {candidate.get('layer1_score'):.3f})")
|
| 306 |
else:
|
| 307 |
+
print("⚠️ [V10.1] لم تنجح أي عملة في تجاوز عتبة الثقة 53%.")
|
| 308 |
|
| 309 |
return final_candidates_with_scores[:20]
|
| 310 |
|
|
|
|
| 520 |
except Exception as e:
|
| 521 |
return {'action': 'HOLD', 'confidence': 0.3, 'reason': f'Error: {str(e)}', 'source': 'whale_analysis'}
|
| 522 |
|
| 523 |
+
print("✅ DataManager loaded - V10.1 (Balanced Threshold 53%)")
|