File size: 10,539 Bytes
b14782e 2b74733 629cd1d cc5540e 2b74733 370e8b2 629cd1d b14782e 2b74733 b14782e 2b74733 370e8b2 2b74733 370e8b2 b14782e 2b74733 b14782e 2b74733 b14782e 2b74733 b14782e 2b74733 b14782e 2b74733 b14782e 2b74733 b14782e 2b74733 b14782e 2b74733 370e8b2 2b74733 cc5540e 2b74733 cc5540e 2b74733 b14782e 2b74733 370e8b2 2b74733 b14782e 2b74733 3f14a6c b14782e 2b74733 3f14a6c 2b74733 3f14a6c 2b74733 3f14a6c 2b74733 3f14a6c b14782e 3f14a6c 2b74733 629cd1d 2b74733 cc5540e 2b74733 629cd1d 2b74733 629cd1d 2b74733 b14782e 2b74733 b14782e 2b74733 b14782e 629cd1d 2b74733 b14782e 2b74733 b14782e 2b74733 629cd1d b14782e 2b74733 b14782e 2b74733 b14782e 6c86b44 2b74733 cc5540e 2b74733 370e8b2 2b74733 370e8b2 2b74733 370e8b2 629cd1d 370e8b2 629cd1d 370e8b2 629cd1d 2b74733 629cd1d 2b74733 370e8b2 2b74733 629cd1d 2b74733 629cd1d 370e8b2 2b74733 370e8b2 2b74733 370e8b2 2b74733 629cd1d 2b74733 629cd1d 370e8b2 629cd1d 370e8b2 629cd1d 2b74733 629cd1d 370e8b2 2b74733 629cd1d 2b74733 629cd1d 2b74733 629cd1d 2b74733 370e8b2 2b74733 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# learning_hub/hub_manager.py
# (محدث بالكامل - V4 - Adaptive Hybrid Weights Support)
import asyncio
import traceback
from typing import Any, Dict, List
from datetime import datetime, timezone
from collections import defaultdict
# (استيراد جميع المكونات الداخلية للمركز)
from .schemas import *
from .policy_engine import PolicyEngine
from .memory_store import MemoryStore
from .statistical_analyzer import StatisticalAnalyzer
from .reflector import Reflector
from .curator import Curator
# استيراد لتحليل الارتباط (Whale Learning)
try:
import numpy as np
from scipy.stats import pearsonr
NUMPY_AVAILABLE = True
except ImportError:
print("❌ [HubManager] مكتبة numpy أو scipy غير مثبتة! لن يعمل تعلم الحيتان.")
NUMPY_AVAILABLE = False
class LearningHubManager:
def __init__(self, r2_service: Any, llm_service: Any, data_manager: Any):
print("🚀 Initializing Learning Hub Manager (V4 - Adaptive)...")
# 1. الخدمات الأساسية
self.r2_service = r2_service
self.llm_service = llm_service
self.data_manager = data_manager
# 2. تهيئة المكونات
self.policy_engine = PolicyEngine()
self.memory_store = MemoryStore(
r2_service=self.r2_service,
policy_engine=self.policy_engine,
llm_service=self.llm_service
)
self.reflector = Reflector(
llm_service=self.llm_service,
memory_store=self.memory_store
)
self.curator = Curator(
llm_service=self.llm_service,
memory_store=self.memory_store
)
self.statistical_analyzer = StatisticalAnalyzer(
r2_service=self.r2_service,
data_manager=self.data_manager
)
# متغيرات حالة لتعلم الحيتان
self.whale_learning_lock = asyncio.Lock()
self.optimal_whale_config = {}
self.initialized = False
print("✅ Learning Hub Manager constructed. Ready for initialization.")
async def initialize(self):
"""تهيئة جميع الأنظمة الفرعية"""
if self.initialized: return
print("🔄 [HubManager] Initializing all sub-modules...")
# تهيئة المحلل الإحصائي (المسؤول عن الأوزان المتكيفة)
await self.statistical_analyzer.initialize()
# تحميل إعدادات تعلم الحيتان
if hasattr(self.r2_service, 'load_whale_learning_config_async'):
self.optimal_whale_config = await self.r2_service.load_whale_learning_config_async()
if self.optimal_whale_config:
print(f"✅ [HubManager] Loaded optimal whale config: {self.optimal_whale_config.get('best_metric', 'N/A')}")
self.initialized = True
print("✅ [HubManager] All sub-modules initialized. Learning Hub is LIVE.")
async def analyze_trade_and_learn(self, trade_object: Dict[str, Any], close_reason: str):
"""الدالة الرئيسية للتعلم من الصفقات المغلقة"""
if not self.initialized: return
print(f"🧠 [HubManager] Learning from trade {trade_object.get('symbol')}...")
# 1. التعلم السريع (Reflector)
try:
await self.reflector.analyze_trade_outcome(trade_object, close_reason)
except Exception as e:
print(f"❌ [HubManager] Reflector failed: {e}")
# 2. التعلم البطيء وتكييف الأوزان (StatisticalAnalyzer)
try:
await self.statistical_analyzer.update_statistics(trade_object, close_reason)
except Exception as e:
print(f"❌ [HubManager] StatisticalAnalyzer failed: {e}")
print(f"✅ [HubManager] Learning complete for {trade_object.get('symbol')}.")
async def get_optimized_weights(self, market_condition: str = None) -> Dict[str, Any]:
"""
جلب الأوزان المحسنة (بما في ذلك الأوزان الهجينة المتكيفة).
يستخدمها MLProcessor لتحديث معادلته الهجينة.
"""
if not self.initialized:
return await self.statistical_analyzer.get_default_strategy_weights()
# إرجاع قاموس الأوزان الكامل من المحلل الإحصائي
return self.statistical_analyzer.weights
# --- دوال مساعدة أخرى (للـ LLM وغيرها) ---
async def get_active_context_for_llm(self, domain: str, query: str) -> str:
if not self.initialized: return "Learning Hub not initialized."
return await self.memory_store.get_active_context(domain, query)
async def get_statistical_feedback_for_llm(self, entry_strategy: str) -> str:
if not self.initialized: return "Learning Hub not initialized."
best_profile = await self.statistical_analyzer.get_best_exit_profile(entry_strategy)
if best_profile != "unknown":
return f"Statistical Feedback: For '{entry_strategy}', '{best_profile}' exit profile performed best."
return "No statistical feedback available yet."
async def get_statistical_news_score(self, raw_vader_score: float) -> float:
if not self.initialized: return 0.0
return await self.statistical_analyzer.get_statistical_vader_pnl(raw_vader_score)
async def run_distillation_check(self):
"""تشغيل دوري للتقطير (Curator)"""
if not self.initialized: return
# print("ℹ️ [HubManager] Running distillation check...")
for domain in self.memory_store.domain_files.keys():
await self.curator.check_and_distill_domain(domain)
async def shutdown(self):
"""حفظ كل البيانات عند الإغلاق"""
if not self.initialized: return
print("🔄 [HubManager] Shutting down... Saving learning data.")
try:
# المحلل الإحصائي يحفظ الأوزان المتكيفة وسجل الأداء
await self.statistical_analyzer.save_weights_to_r2()
await self.statistical_analyzer.save_performance_history()
await self.statistical_analyzer.save_exit_profile_effectiveness()
await self.statistical_analyzer.save_vader_effectiveness()
print("✅ [HubManager] Data saved successfully.")
except Exception as e:
print(f"❌ [HubManager] Save failed: {e}")
# --- Whale Learning Loop (كما هي من V3) ---
async def run_whale_learning_check(self):
if not self.initialized: await asyncio.sleep(60)
print(f"🧠 [Whale-Logger] Starting background learning loop...")
await asyncio.sleep(600)
while True:
try:
pending = await self.r2_service.get_pending_whale_learning_records_async()
if not pending:
await asyncio.sleep(600)
continue
now_utc = datetime.now(timezone.utc)
for record in pending:
try:
target_time = datetime.fromisoformat(record['target_time_utc'])
if now_utc >= target_time:
symbol = record['symbol']
target_price = await self.data_manager.get_latest_price_async(symbol)
if target_price and target_price > 0 and record['start_price_usd'] > 0:
pct_change = ((target_price - record['start_price_usd']) / record['start_price_usd']) * 100
record.update({'target_price_usd': target_price, 'price_change_percentage': pct_change, 'status': "COMPLETED"})
await self.r2_service.update_completed_whale_learning_record_async(record)
except Exception: pass
await self.update_optimal_whale_window()
await asyncio.sleep(300)
except Exception as e:
print(f"❌ [Whale-Logger] Error: {e}")
await asyncio.sleep(600)
async def update_optimal_whale_window(self):
if not NUMPY_AVAILABLE: return
async with self.whale_learning_lock:
try:
all_completed = await self.r2_service.get_all_completed_whale_records_async()
if len(all_completed) < 20: return
price_changes = []
metrics_data = defaultdict(lambda: defaultdict(list))
windows = ['30m', '1h', '2h', '4h', '24h']
metric_keys = ['relative_net_flow_percent', 'transaction_density', 'net_flow_usd']
for r in all_completed:
if r.get('price_change_percentage') is None: continue
price_changes.append(r['price_change_percentage'])
analysis = r.get('window_analysis', {})
for w in windows:
for k in metric_keys:
metrics_data[w][k].append(analysis.get(w, {}).get(k, 0.0))
price_np = np.array(price_changes)
best_corr = 0
best_key = None
for w in windows:
for k in metric_keys:
metric_np = np.array(metrics_data[w][k])
if len(metric_np) == len(price_np):
corr, p_val = pearsonr(metric_np, price_np)
if not np.isnan(corr) and p_val < 0.1 and abs(corr) > best_corr:
best_corr = abs(corr)
best_key = f"{w}_{k}"
if best_key:
w, m = best_key.split('_', 1)
new_config = {"best_window": w, "best_metric": m, "correlation_score": best_corr, "total_samples": len(price_np), "last_updated_utc": datetime.now(timezone.utc).isoformat()}
self.optimal_whale_config = new_config
await self.r2_service.save_whale_learning_config_async(new_config)
print(f"🏆 [Whale-Teacher] New best signal: {m} on {w} (Corr: {best_corr:.2f})")
except Exception as e:
print(f"❌ [Whale-Teacher] Error: {e}") |