Riy777 commited on
Commit
56dcc3e
·
verified ·
1 Parent(s): f080b76

Update learning_hub/adaptive_hub.py

Browse files
Files changed (1) hide show
  1. learning_hub/adaptive_hub.py +68 -69
learning_hub/adaptive_hub.py CHANGED
@@ -1,11 +1,10 @@
1
  # ==============================================================================
2
  # 🧠 learning_hub/adaptive_hub.py
3
- # (V36.0 - GEM-Architect: The Cybernetic Strategy Core)
4
  # ==============================================================================
5
- # المسؤوليات:
6
- # 1. إدارة "الحمض النووي" للاستراتيجيات (Strategy DNA).
7
- # 2. التعديل التكتيكي الفوري لأوزان النماذج (Real-time Weight Adjustment).
8
- # 3. حقن الإعدادات في باقي أجزاء النظام.
9
  # ==============================================================================
10
 
11
  import json
@@ -15,7 +14,7 @@ from datetime import datetime
15
  from collections import deque
16
  from typing import Dict, Any, List, Optional
17
 
18
- # استيراد الحدود المركزية لحقن القيم فيها
19
  from ml_engine.processor import SystemLimits
20
 
21
  class StrategyDNA:
@@ -23,11 +22,13 @@ class StrategyDNA:
23
  تعريف هيكلية البيانات لكل استراتيجية.
24
  هذا هو 'الجينوم' الذي سيتم تعديله بواسطة التعلم.
25
  """
26
- def __init__(self, name, model_weights, ob_settings, filters):
27
  self.name = name
28
  self.model_weights = model_weights # أوزان النماذج (Titan, Sniper, etc.)
29
  self.ob_settings = ob_settings # إعدادات دفتر الطلبات (Wall Ratio, etc.)
30
  self.filters = filters # فلاتر L1 (Thresholds)
 
 
31
  self.stats = {"wins": 0, "losses": 0, "win_rate": 0.0}
32
 
33
  def to_dict(self):
@@ -38,18 +39,18 @@ class AdaptiveHub:
38
  self.r2 = r2_service
39
  self.dna_file_key = "learning/strategic_dna_v2.json"
40
 
41
- # الحالة الحالية للسوق (يتم تحديثها بواسطة DataManager أو تحليل خارجي)
42
  self.current_market_regime = "RANGE"
43
 
44
- # مخزن الحمض النووي (الاستراتيجيات الأربع)
45
  self.strategies: Dict[str, StrategyDNA] = {}
46
 
47
- # معدل التعلم التكتيكي (مدى سرعة تغيير الأوزان)
48
- self.TACTICAL_LEARNING_RATE = 0.05 # 5% تغيير عند كل فوز/خسارة
49
  self.MIN_WEIGHT = 0.10
50
  self.MAX_WEIGHT = 0.90
51
 
52
- print("🧠 [AdaptiveHub V36.0] Cybernetic Strategy Core Initialized.")
53
 
54
  async def initialize(self):
55
  """تحميل الـ DNA من R2 أو إنشاء الافتراضي"""
@@ -67,55 +68,63 @@ class AdaptiveHub:
67
  else:
68
  self._create_default_dna()
69
 
70
- # تطبيق الإعدادات فوراً
71
  self._inject_current_parameters()
72
 
73
  except Exception as e:
74
  print(f"❌ [AdaptiveHub] Init Failed: {e}")
 
75
  self._create_default_dna()
76
 
77
  def _create_default_dna(self):
78
- """إنشاء الإعدادات الافتراضية (الدستور التأسيسي)"""
79
- # 1. BULL MARKET DNA 🐂
 
 
 
 
 
80
  self.strategies["BULL"] = StrategyDNA(
81
  name="BULL",
82
- model_weights={"titan": 0.40, "patterns": 0.30, "sniper": 0.20, "hydra": 0.10},
83
- ob_settings={"wall_ratio_limit": 0.60, "imbalance_thresh": 0.5}, # نتساهل مع جدران البيع
84
- filters={"l1_min_score": 15.0, "l3_conf_thresh": 0.60}
 
85
  )
86
 
87
- # 2. BEAR MARKET DNA 🐻
88
  self.strategies["BEAR"] = StrategyDNA(
89
  name="BEAR",
90
- model_weights={"titan": 0.20, "patterns": 0.10, "sniper": 0.30, "hydra": 0.40}, # Hydra هو الملك هنا
91
- ob_settings={"wall_ratio_limit": 0.30, "imbalance_thresh": 0.7}, # صارم جداً مع جدران البيع
92
- filters={"l1_min_score": 40.0, "l3_conf_thresh": 0.75}
 
93
  )
94
 
95
- # 3. RANGE MARKET DNA ↔️
96
  self.strategies["RANGE"] = StrategyDNA(
97
  name="RANGE",
98
- model_weights={"titan": 0.30, "patterns": 0.40, "sniper": 0.20, "hydra": 0.10}, # الأنماط (Patterns) مهمة في التذبذب
99
  ob_settings={"wall_ratio_limit": 0.40, "imbalance_thresh": 0.6},
100
- filters={"l1_min_score": 25.0, "l3_conf_thresh": 0.65}
 
101
  )
102
-
103
- # 4. DEAD MARKET DNA 💀
104
  self.strategies["DEAD"] = StrategyDNA(
105
  name="DEAD",
106
- model_weights={"titan": 0.25, "patterns": 0.25, "sniper": 0.25, "hydra": 0.25}, # توازن حذر
107
- ob_settings={"wall_ratio_limit": 0.20, "imbalance_thresh": 0.8}, # نطلب سيولة عالية جداً للدخول
108
- filters={"l1_min_score": 50.0, "l3_conf_thresh": 0.80}
 
109
  )
110
 
111
  def _load_from_dict(self, data):
112
- """تحويل JSON إلى كائنات StrategyDNA"""
113
  for key, val in data.get("strategies", {}).items():
114
  self.strategies[key] = StrategyDNA(
115
  name=val["name"],
116
  model_weights=val["model_weights"],
117
  ob_settings=val["ob_settings"],
118
- filters=val["filters"]
 
119
  )
120
  self.strategies[key].stats = val.get("stats", {"wins":0, "losses":0})
121
 
@@ -125,40 +134,26 @@ class AdaptiveHub:
125
  # ⚡ The Tactical Loop: Real-time Weight Adjustment
126
  # ==========================================================================
127
  async def register_trade_outcome(self, trade_data: Dict[str, Any]):
128
- """
129
- يتم استدعاؤها عند إغلاق الصفقة.
130
- تقوم بتعديل أوزان النماذج بناءً على من ساهم في القرار.
131
- """
132
  try:
133
  pnl = trade_data.get('profit_pct', 0.0)
134
  is_win = pnl > 0
135
 
136
- # معرفة الاستراتيجية التي كانت نشطة وقت الدخول (نفترض الحالية للتبسيط الآن)
137
  active_dna = self.strategies[self.current_market_regime]
138
 
139
- # تحديث إحصائيات الاستراتيجية
140
  if is_win: active_dna.stats["wins"] += 1
141
  else: active_dna.stats["losses"] += 1
142
 
143
- # تحليل المساهمين (Decision Components)
144
- # نفترض أن trade_data يحتوي على 'decision_data' بها تفاصيل المساهمة
145
  decision_data = trade_data.get('decision_data', {})
146
- components = decision_data.get('components', {}) # {'titan_score': 0.8, ...}
147
-
148
- # التعديل التكتيكي للأوزان
149
- # إذا ربحت الصفقة، نزيد وزن النماذج التي كانت درجاتها عالية
150
- # إذا خسرت، نعاقب النماذج التي كانت درجاتها عالية (لأنها خدعتنا)
151
 
152
  print(f"⚖️ [Tactical Learning] Adjusting weights for {self.current_market_regime}...")
153
 
154
  changes_log = []
155
 
156
- # قائمة النماذج التي نراقبها
157
  model_keys = {
158
  'titan_score': 'titan',
159
  'patterns_score': 'patterns',
160
- 'sniper_score': 'sniper', # Sniper عادة يأتي من L4
161
- # Hydra usually acts as a veto/exit, but if used for entry logic:
162
  'hydra_score': 'hydra'
163
  }
164
 
@@ -166,15 +161,11 @@ class AdaptiveHub:
166
  score = float(components.get(score_key, 0.5))
167
  current_w = active_dna.model_weights.get(model_name, 0.25)
168
 
169
- # منطق المكافأة والعقاب
170
- # نعدل الوزن فقط إذا كان النموذج "واثقاً" (score > 0.6)
171
  if score > 0.6:
172
  if is_win:
173
- # النموذج كان واثقاً وأصاب -> زيادة الوزن
174
  new_w = min(self.MAX_WEIGHT, current_w + self.TACTICAL_LEARNING_RATE)
175
  change = "⬆️"
176
  else:
177
- # النموذج كان واثقاً وأخطأ -> تقليل الوزن
178
  new_w = max(self.MIN_WEIGHT, current_w - self.TACTICAL_LEARNING_RATE)
179
  change = "⬇️"
180
 
@@ -183,7 +174,6 @@ class AdaptiveHub:
183
 
184
  if changes_log:
185
  print(f" -> Adjustments: {', '.join(changes_log)}")
186
- # إعادة الحقن وحفظ الحالة
187
  self._inject_current_parameters()
188
  await self._save_state_to_r2()
189
  else:
@@ -194,26 +184,29 @@ class AdaptiveHub:
194
  traceback.print_exc()
195
 
196
  # ==========================================================================
197
- # 💉 Parameter Injection (The Control Link)
198
  # ==========================================================================
199
  def _inject_current_parameters(self):
200
  """
201
  نقل الإعدادات من الـ DNA النشط إلى SystemLimits
202
- ليستخدمها Processor و DataManager.
203
  """
 
 
 
 
204
  active_dna = self.strategies[self.current_market_regime]
205
 
206
  print(f"💉 [AdaptiveHub] Injecting DNA for regime: {self.current_market_regime}")
207
 
208
  # 1. حقن أوزان الطبقة الثانية (L2 Weights)
209
- # ملاحظة: نقوم بتطبيع الأوزان (Normalization) لتساوي 1.0 تقريباً
210
  mw = active_dna.model_weights
211
  total_w = sum(mw.values()) if sum(mw.values()) > 0 else 1.0
212
 
213
  SystemLimits.L2_WEIGHT_TITAN = mw.get("titan", 0.4) / total_w
214
  SystemLimits.L2_WEIGHT_PATTERNS = mw.get("patterns", 0.3) / total_w
215
- # Sniper & Hydra weights are handled in their specific engines usually,
216
- # but we can set L4 weights here if SystemLimits supports it.
217
 
218
  # 2. حقن عتبات الفلتر الأولي (L1)
219
  SystemLimits.L1_MIN_AFFINITY_SCORE = active_dna.filters.get("l1_min_score", 20.0)
@@ -221,19 +214,26 @@ class AdaptiveHub:
221
  # 3. حقن عتبات الثقة (L3 Oracle)
222
  SystemLimits.L3_CONFIDENCE_THRESHOLD = active_dna.filters.get("l3_conf_thresh", 0.65)
223
 
224
- # 4. حقن إعدادات دفتر الطلبات (للاستخدام في Sniper/Guard)
225
- # سنحتاج لقراءة هذه القيم من SystemLimits داخل SniperEngine
226
  SystemLimits.L4_OB_WALL_RATIO = active_dna.ob_settings.get("wall_ratio_limit", 0.4)
227
 
 
 
 
 
 
 
 
 
 
228
  # طباعة الملخص
229
- print(f" -> Weights: Titan={SystemLimits.L2_WEIGHT_TITAN:.2f}, Patt={SystemLimits.L2_WEIGHT_PATTERNS:.2f}")
230
- print(f" -> OB Wall Limit: {SystemLimits.L4_OB_WALL_RATIO}")
231
 
232
  # ==========================================================================
233
  # 🎮 External Control & Utilities
234
  # ==========================================================================
235
  def update_market_regime(self, new_regime: str):
236
- """تغيير حالة السوق يدوياً أو آلياً"""
237
  if new_regime in self.strategies:
238
  self.current_market_regime = new_regime
239
  print(f"🔄 [AdaptiveHub] Regime Switched to: {new_regime}")
@@ -242,16 +242,15 @@ class AdaptiveHub:
242
  print(f"⚠️ [AdaptiveHub] Unknown regime: {new_regime}")
243
 
244
  def get_status(self):
245
- dna = self.strategies[self.current_market_regime]
 
246
  mw = dna.model_weights
 
247
  return (f"Regime: {self.current_market_regime} | "
248
- f"W[Ti:{mw.get('titan'):.2f} Sn:{mw.get('sniper'):.2f}] | "
 
249
  f"Wins: {dna.stats['wins']}")
250
 
251
- def get_active_ob_settings(self):
252
- """دالة مساعدة لـ SniperEngine لجلب إعدادات الـ OB الحالية"""
253
- return self.strategies[self.current_market_regime].ob_settings
254
-
255
  async def _save_state_to_r2(self):
256
  if not self.r2: return
257
  try:
 
1
  # ==============================================================================
2
  # 🧠 learning_hub/adaptive_hub.py
3
+ # (V45.0 - GEM-Architect: The Cybernetic Strategy Core & Guardian Link)
4
  # ==============================================================================
5
+ # التحديثات:
6
+ # 1. دعم حقن إعدادات الحراس (Guardians) القادمة من الباكتست.
7
+ # 2. ضمان تحميل وحفظ كافة المتغيرات الجديدة في StrategyDNA.
 
8
  # ==============================================================================
9
 
10
  import json
 
14
  from collections import deque
15
  from typing import Dict, Any, List, Optional
16
 
17
+ # استيراد الحدود المركزية (The Shared Whiteboard)
18
  from ml_engine.processor import SystemLimits
19
 
20
  class StrategyDNA:
 
22
  تعريف هيكلية البيانات لكل استراتيجية.
23
  هذا هو 'الجينوم' الذي سيتم تعديله بواسطة التعلم.
24
  """
25
+ def __init__(self, name, model_weights, ob_settings, filters, guard_settings=None):
26
  self.name = name
27
  self.model_weights = model_weights # أوزان النماذج (Titan, Sniper, etc.)
28
  self.ob_settings = ob_settings # إعدادات دفتر الطلبات (Wall Ratio, etc.)
29
  self.filters = filters # فلاتر L1 (Thresholds)
30
+ # ✅ إضافة إعدادات الحراس (جديد)
31
+ self.guard_settings = guard_settings if guard_settings else {}
32
  self.stats = {"wins": 0, "losses": 0, "win_rate": 0.0}
33
 
34
  def to_dict(self):
 
39
  self.r2 = r2_service
40
  self.dna_file_key = "learning/strategic_dna_v2.json"
41
 
42
+ # الحالة الحالية للسوق
43
  self.current_market_regime = "RANGE"
44
 
45
+ # مخزن الحمض النووي
46
  self.strategies: Dict[str, StrategyDNA] = {}
47
 
48
+ # معدل التعلم التكتيكي
49
+ self.TACTICAL_LEARNING_RATE = 0.05
50
  self.MIN_WEIGHT = 0.10
51
  self.MAX_WEIGHT = 0.90
52
 
53
+ print("🧠 [AdaptiveHub V45.0] Cybernetic Strategy Core Initialized.")
54
 
55
  async def initialize(self):
56
  """تحميل الـ DNA من R2 أو إنشاء الافتراضي"""
 
68
  else:
69
  self._create_default_dna()
70
 
71
+ # تطبيق الإعدادات فوراً (Hot Reload)
72
  self._inject_current_parameters()
73
 
74
  except Exception as e:
75
  print(f"❌ [AdaptiveHub] Init Failed: {e}")
76
+ traceback.print_exc()
77
  self._create_default_dna()
78
 
79
  def _create_default_dna(self):
80
+ """إنشاء الإعدادات الافتراضية (في حال عدم وجود ملف)"""
81
+ # قيم افتراضية للحراس
82
+ default_guards = {
83
+ "hydra_crash": 0.60, "hydra_giveback": 0.70,
84
+ "legacy_v2": 0.95, "legacy_v3": 0.95
85
+ }
86
+
87
  self.strategies["BULL"] = StrategyDNA(
88
  name="BULL",
89
+ model_weights={"titan": 0.40, "patterns": 0.30, "sniper": 0.20, "hydra": 0.10, "mc": 0.0},
90
+ ob_settings={"wall_ratio_limit": 0.60, "imbalance_thresh": 0.5},
91
+ filters={"l1_min_score": 15.0, "l3_conf_thresh": 0.60},
92
+ guard_settings=default_guards
93
  )
94
 
 
95
  self.strategies["BEAR"] = StrategyDNA(
96
  name="BEAR",
97
+ model_weights={"titan": 0.20, "patterns": 0.10, "sniper": 0.30, "hydra": 0.40, "mc": 0.0},
98
+ ob_settings={"wall_ratio_limit": 0.30, "imbalance_thresh": 0.7},
99
+ filters={"l1_min_score": 40.0, "l3_conf_thresh": 0.75},
100
+ guard_settings=default_guards
101
  )
102
 
 
103
  self.strategies["RANGE"] = StrategyDNA(
104
  name="RANGE",
105
+ model_weights={"titan": 0.30, "patterns": 0.40, "sniper": 0.20, "hydra": 0.10, "mc": 0.0},
106
  ob_settings={"wall_ratio_limit": 0.40, "imbalance_thresh": 0.6},
107
+ filters={"l1_min_score": 25.0, "l3_conf_thresh": 0.65},
108
+ guard_settings=default_guards
109
  )
110
+
 
111
  self.strategies["DEAD"] = StrategyDNA(
112
  name="DEAD",
113
+ model_weights={"titan": 0.25, "patterns": 0.25, "sniper": 0.25, "hydra": 0.25, "mc": 0.0},
114
+ ob_settings={"wall_ratio_limit": 0.20, "imbalance_thresh": 0.8},
115
+ filters={"l1_min_score": 50.0, "l3_conf_thresh": 0.80},
116
+ guard_settings=default_guards
117
  )
118
 
119
  def _load_from_dict(self, data):
120
+ """تحويل JSON إلى كائنات StrategyDNA مع دعم الحقول الجديدة"""
121
  for key, val in data.get("strategies", {}).items():
122
  self.strategies[key] = StrategyDNA(
123
  name=val["name"],
124
  model_weights=val["model_weights"],
125
  ob_settings=val["ob_settings"],
126
+ filters=val["filters"],
127
+ guard_settings=val.get("guard_settings", {}) # ✅ تحميل إعدادات الحراس
128
  )
129
  self.strategies[key].stats = val.get("stats", {"wins":0, "losses":0})
130
 
 
134
  # ⚡ The Tactical Loop: Real-time Weight Adjustment
135
  # ==========================================================================
136
  async def register_trade_outcome(self, trade_data: Dict[str, Any]):
 
 
 
 
137
  try:
138
  pnl = trade_data.get('profit_pct', 0.0)
139
  is_win = pnl > 0
140
 
 
141
  active_dna = self.strategies[self.current_market_regime]
142
 
 
143
  if is_win: active_dna.stats["wins"] += 1
144
  else: active_dna.stats["losses"] += 1
145
 
 
 
146
  decision_data = trade_data.get('decision_data', {})
147
+ components = decision_data.get('components', {})
 
 
 
 
148
 
149
  print(f"⚖️ [Tactical Learning] Adjusting weights for {self.current_market_regime}...")
150
 
151
  changes_log = []
152
 
 
153
  model_keys = {
154
  'titan_score': 'titan',
155
  'patterns_score': 'patterns',
156
+ 'sniper_score': 'sniper',
 
157
  'hydra_score': 'hydra'
158
  }
159
 
 
161
  score = float(components.get(score_key, 0.5))
162
  current_w = active_dna.model_weights.get(model_name, 0.25)
163
 
 
 
164
  if score > 0.6:
165
  if is_win:
 
166
  new_w = min(self.MAX_WEIGHT, current_w + self.TACTICAL_LEARNING_RATE)
167
  change = "⬆️"
168
  else:
 
169
  new_w = max(self.MIN_WEIGHT, current_w - self.TACTICAL_LEARNING_RATE)
170
  change = "⬇️"
171
 
 
174
 
175
  if changes_log:
176
  print(f" -> Adjustments: {', '.join(changes_log)}")
 
177
  self._inject_current_parameters()
178
  await self._save_state_to_r2()
179
  else:
 
184
  traceback.print_exc()
185
 
186
  # ==========================================================================
187
+ # 💉 Parameter Injection (The Vital Link)
188
  # ==========================================================================
189
  def _inject_current_parameters(self):
190
  """
191
  نقل الإعدادات من الـ DNA النشط إلى SystemLimits
192
+ ليستخدمها Processor و DataManager والحراس.
193
  """
194
+ if self.current_market_regime not in self.strategies:
195
+ print(f"⚠️ [AdaptiveHub] Regime {self.current_market_regime} not found in strategies.")
196
+ return
197
+
198
  active_dna = self.strategies[self.current_market_regime]
199
 
200
  print(f"💉 [AdaptiveHub] Injecting DNA for regime: {self.current_market_regime}")
201
 
202
  # 1. حقن أوزان الطبقة الثانية (L2 Weights)
 
203
  mw = active_dna.model_weights
204
  total_w = sum(mw.values()) if sum(mw.values()) > 0 else 1.0
205
 
206
  SystemLimits.L2_WEIGHT_TITAN = mw.get("titan", 0.4) / total_w
207
  SystemLimits.L2_WEIGHT_PATTERNS = mw.get("patterns", 0.3) / total_w
208
+ SystemLimits.L2_WEIGHT_MC = mw.get("mc", 0.1) / total_w
209
+ # Sniper/Hydra weights can be used here or in their respective logic
210
 
211
  # 2. حقن عتبات الفلتر الأولي (L1)
212
  SystemLimits.L1_MIN_AFFINITY_SCORE = active_dna.filters.get("l1_min_score", 20.0)
 
214
  # 3. حقن عتبات الثقة (L3 Oracle)
215
  SystemLimits.L3_CONFIDENCE_THRESHOLD = active_dna.filters.get("l3_conf_thresh", 0.65)
216
 
217
+ # 4. حقن إعدادات دفتر الطلبات (Sniper)
 
218
  SystemLimits.L4_OB_WALL_RATIO = active_dna.ob_settings.get("wall_ratio_limit", 0.4)
219
 
220
+ # 5. 🔥 حقن إعدادات الحراس (الجديد)
221
+ gs = active_dna.guard_settings
222
+ if gs:
223
+ SystemLimits.HYDRA_CRASH_THRESH = gs.get('hydra_crash', 0.60)
224
+ SystemLimits.HYDRA_GIVEBACK_THRESH = gs.get('hydra_giveback', 0.70)
225
+ SystemLimits.LEGACY_V2_PANIC_THRESH = gs.get('legacy_v2', 0.95)
226
+ SystemLimits.LEGACY_V3_HARD_THRESH = gs.get('legacy_v3', 0.95)
227
+ print(f" 🛡️ Guards Updated: Hydra(C:{SystemLimits.HYDRA_CRASH_THRESH}/G:{SystemLimits.HYDRA_GIVEBACK_THRESH}) | Legacy(V2:{SystemLimits.LEGACY_V2_PANIC_THRESH})")
228
+
229
  # طباعة الملخص
230
+ print(f" -> Weights: Ti={SystemLimits.L2_WEIGHT_TITAN:.2f}, Pat={SystemLimits.L2_WEIGHT_PATTERNS:.2f}")
231
+ print(f" -> L1 Thresh: {SystemLimits.L1_MIN_AFFINITY_SCORE}")
232
 
233
  # ==========================================================================
234
  # 🎮 External Control & Utilities
235
  # ==========================================================================
236
  def update_market_regime(self, new_regime: str):
 
237
  if new_regime in self.strategies:
238
  self.current_market_regime = new_regime
239
  print(f"🔄 [AdaptiveHub] Regime Switched to: {new_regime}")
 
242
  print(f"⚠️ [AdaptiveHub] Unknown regime: {new_regime}")
243
 
244
  def get_status(self):
245
+ dna = self.strategies.get(self.current_market_regime)
246
+ if not dna: return "System Initializing..."
247
  mw = dna.model_weights
248
+ gs = dna.guard_settings
249
  return (f"Regime: {self.current_market_regime} | "
250
+ f"W[Ti:{mw.get('titan'):.2f}] | "
251
+ f"G[Hyd:{gs.get('hydra_crash',0.6):.2f}] | "
252
  f"Wins: {dna.stats['wins']}")
253
 
 
 
 
 
254
  async def _save_state_to_r2(self):
255
  if not self.r2: return
256
  try: