Riy777 commited on
Commit
aef43eb
·
verified ·
1 Parent(s): 6c86b44

Update learning_hub/statistical_analyzer.py

Browse files
Files changed (1) hide show
  1. learning_hub/statistical_analyzer.py +105 -12
learning_hub/statistical_analyzer.py CHANGED
@@ -1,9 +1,6 @@
1
- # learning_hub/statistical_analyzer.py
2
- # (هذا الملف هو النسخة المطورة من learning_engine (39).py القديم)
3
- # وهو يمثل "التعلم البطيء" (الإحصائي)
4
-
5
  import json
6
  import asyncio
 
7
  from datetime import datetime
8
  from typing import Dict, Any, List
9
  import numpy as np
@@ -32,7 +29,10 @@ class StatisticalAnalyzer:
32
  self.strategy_effectiveness = {} # (إحصائيات استراتيجيات الدخول)
33
  self.exit_profile_effectiveness = {} # (إحصائيات مزيج الدخول+الخروج)
34
  self.market_patterns = {}
35
- # --- (نهاية متغيرات الحالة) ---
 
 
 
36
 
37
  self.initialized = False
38
  self.lock = asyncio.Lock()
@@ -49,6 +49,9 @@ class StatisticalAnalyzer:
49
  await self.load_weights_from_r2()
50
  await self.load_performance_history()
51
  await self.load_exit_profile_effectiveness()
 
 
 
52
 
53
  if not self.weights or not self.strategy_effectiveness:
54
  await self.initialize_default_weights()
@@ -106,6 +109,16 @@ class StatisticalAnalyzer:
106
  self.strategy_effectiveness = {}
107
  self.exit_profile_effectiveness = {}
108
  self.market_patterns = {}
 
 
 
 
 
 
 
 
 
 
109
 
110
  async def load_weights_from_r2(self):
111
  key = "learning_statistical_weights.json" # (ملف جديد)
@@ -187,6 +200,49 @@ class StatisticalAnalyzer:
187
  except Exception as e:
188
  print(f"❌ [StatsAnalyzer] فشل حفظ أداء ملف الخروج: {e}")
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  async def update_statistics(self, trade_object: Dict[str, Any], close_reason: str):
191
  """
192
  هذه هي الدالة الرئيسية التي تحدث الإحصائيات (التعلم البطيء).
@@ -210,6 +266,11 @@ class StatisticalAnalyzer:
210
  if not market_context:
211
  market_context = await self.get_current_market_conditions()
212
  market_condition = market_context.get('current_trend', 'sideways_market')
 
 
 
 
 
213
  # 🔴 --- END OF CHANGE --- 🔴
214
 
215
  # --- 1. تحديث تاريخ الأداء (للتتبع العام) ---
@@ -221,7 +282,9 @@ class StatisticalAnalyzer:
221
  "market_conditions": market_context,
222
  "strategy_used": strategy,
223
  "exit_profile_used": exit_profile,
224
- "pnl_percent": pnl_percent
 
 
225
  }
226
  self.performance_history.append(analysis_entry)
227
 
@@ -255,15 +318,28 @@ class StatisticalAnalyzer:
255
  if is_success:
256
  self.market_patterns[market_condition]["successful_trades"] += 1
257
 
258
- # --- 5. تكييف الأوزان والحفظ (إذا لزم الأمر) ---
 
 
 
 
 
 
 
 
 
 
259
  # (ملاحظة: نحتاج إلى إضافة منطق لتعلم أوزان الحارس هنا مستقبلاً)
260
  if should_update_weights(len(self.performance_history)):
261
  await self.adapt_weights_based_on_performance()
262
  await self.save_weights_to_r2()
263
  await self.save_performance_history()
264
  await self.save_exit_profile_effectiveness()
 
 
 
265
 
266
- print(f"✅ [StatsAnalyzer] تم تحديث الإحصائيات لـ {strategy} / {exit_profile}")
267
 
268
  except Exception as e:
269
  print(f"❌ [StatsAnalyzer] فشل تحديث الإحصائيات: {e}")
@@ -328,6 +404,26 @@ class StatisticalAnalyzer:
328
  best_profile = max(relevant_profiles, key=relevant_profiles.get)
329
  return best_profile
330
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  # 🔴 --- START OF CHANGE --- 🔴
332
  async def get_optimized_weights(self, market_condition: str) -> Dict[str, float]:
333
  """
@@ -394,7 +490,4 @@ class StatisticalAnalyzer:
394
  "market_sentiment": market_context.get('btc_sentiment', 'NEUTRAL'),
395
  }
396
  except Exception as e:
397
- return {"current_trend": "sideways_market", "volatility": "medium", "market_sentiment": "NEUTRAL"}
398
- # 🔴 --- START OF CHANGE --- 🔴
399
- # (تم حذف القوس } الزائد من هنا)
400
- # 🔴 --- END OF CHANGE --- 🔴
 
 
 
 
 
1
  import json
2
  import asyncio
3
+ import traceback # (إضافة)
4
  from datetime import datetime
5
  from typing import Dict, Any, List
6
  import numpy as np
 
29
  self.strategy_effectiveness = {} # (إحصائيات استراتيجيات الدخول)
30
  self.exit_profile_effectiveness = {} # (إحصائيات مزيج الدخول+الخروج)
31
  self.market_patterns = {}
32
+
33
+ # 🔴 --- START OF CHANGE (V2 - VADER Learning) --- 🔴
34
+ self.vader_bin_effectiveness = {} # (جديد: لتتبع أداء VADER)
35
+ # 🔴 --- END OF CHANGE --- 🔴
36
 
37
  self.initialized = False
38
  self.lock = asyncio.Lock()
 
49
  await self.load_weights_from_r2()
50
  await self.load_performance_history()
51
  await self.load_exit_profile_effectiveness()
52
+ # 🔴 --- START OF CHANGE (V2 - VADER Learning) --- 🔴
53
+ await self.load_vader_effectiveness()
54
+ # 🔴 --- END OF CHANGE --- 🔴
55
 
56
  if not self.weights or not self.strategy_effectiveness:
57
  await self.initialize_default_weights()
 
109
  self.strategy_effectiveness = {}
110
  self.exit_profile_effectiveness = {}
111
  self.market_patterns = {}
112
+ # 🔴 --- START OF CHANGE (V2 - VADER Learning) --- 🔴
113
+ # (إعادة تعيين إحصائيات VADER أيضاً)
114
+ self.vader_bin_effectiveness = {
115
+ "Strong_Positive": {"total_trades": 0, "total_pnl_percent": 0},
116
+ "Positive": {"total_trades": 0, "total_pnl_percent": 0},
117
+ "Neutral": {"total_trades": 0, "total_pnl_percent": 0},
118
+ "Negative": {"total_trades": 0, "total_pnl_percent": 0},
119
+ "Strong_Negative": {"total_trades": 0, "total_pnl_percent": 0}
120
+ }
121
+ # 🔴 --- END OF CHANGE --- 🔴
122
 
123
  async def load_weights_from_r2(self):
124
  key = "learning_statistical_weights.json" # (ملف جديد)
 
200
  except Exception as e:
201
  print(f"❌ [StatsAnalyzer] فشل حفظ أداء ملف الخروج: {e}")
202
 
203
+ # 🔴 --- START OF CHANGE (V2 - VADER Learning) --- 🔴
204
+ async def load_vader_effectiveness(self):
205
+ """تحميل إحصائيات VADER من R2"""
206
+ key = "learning_vader_effectiveness.json" # (ملف جديد)
207
+ try:
208
+ response = self.r2_service.s3_client.get_object(Bucket="trading", Key=key)
209
+ data = json.loads(response['Body'].read())
210
+ self.vader_bin_effectiveness = data.get("effectiveness", {})
211
+ if not self.vader_bin_effectiveness:
212
+ await self.initialize_default_weights() # (سيقوم بملء القيم الافتراضية)
213
+ except Exception as e:
214
+ # (إذا فشل، ستقوم initialize_default_weights بملء القيم الافتراضية)
215
+ pass
216
+
217
+ async def save_vader_effectiveness(self):
218
+ """حفظ إحصائيات VADER إلى R2"""
219
+ key = "learning_vader_effectiveness.json"
220
+ try:
221
+ data = {
222
+ "effectiveness": self.vader_bin_effectiveness,
223
+ "last_updated": datetime.now().isoformat()
224
+ }
225
+ data_json = json.dumps(data, indent=2, ensure_ascii=False).encode('utf-8')
226
+ self.r2_service.s3_client.put_object(
227
+ Bucket="trading", Key=key, Body=data_json, ContentType="application/json"
228
+ )
229
+ except Exception as e:
230
+ print(f"❌ [StatsAnalyzer] فشل حفظ أداء VADER: {e}")
231
+
232
+ def _get_vader_bin(self, vader_score: float) -> str:
233
+ """تصنيف درجة VADER الخام (-1 إلى +1) إلى سلال"""
234
+ if vader_score > 0.5:
235
+ return "Strong_Positive"
236
+ elif vader_score > 0.05:
237
+ return "Positive"
238
+ elif vader_score < -0.5:
239
+ return "Strong_Negative"
240
+ elif vader_score < -0.05:
241
+ return "Negative"
242
+ else:
243
+ return "Neutral"
244
+ # 🔴 --- END OF CHANGE --- 🔴
245
+
246
  async def update_statistics(self, trade_object: Dict[str, Any], close_reason: str):
247
  """
248
  هذه هي الدالة الرئيسية التي تحدث الإحصائيات (التعلم البطيء).
 
266
  if not market_context:
267
  market_context = await self.get_current_market_conditions()
268
  market_condition = market_context.get('current_trend', 'sideways_market')
269
+
270
+ # (V2 - VADER Learning) جلب درجة VADER وقت القرار
271
+ # (نفترض أن TradeManager حفظها هنا)
272
+ vader_score_at_decision = decision_data.get('news_score', 0.0)
273
+ vader_bin = self._get_vader_bin(vader_score_at_decision)
274
  # 🔴 --- END OF CHANGE --- 🔴
275
 
276
  # --- 1. تحديث تاريخ الأداء (للتتبع العام) ---
 
282
  "market_conditions": market_context,
283
  "strategy_used": strategy,
284
  "exit_profile_used": exit_profile,
285
+ "pnl_percent": pnl_percent,
286
+ "vader_score": vader_score_at_decision, # (إضافة)
287
+ "vader_bin": vader_bin # (إضافة)
288
  }
289
  self.performance_history.append(analysis_entry)
290
 
 
318
  if is_success:
319
  self.market_patterns[market_condition]["successful_trades"] += 1
320
 
321
+ # 🔴 --- START OF CHANGE (V2 - VADER Learning) --- 🔴
322
+ # --- 5. تحديث إحصائيات VADER ---
323
+ if vader_bin not in self.vader_bin_effectiveness:
324
+ # (لضمان عدم حدوث خطأ إذا كانت السلة غير موجودة)
325
+ self.vader_bin_effectiveness[vader_bin] = {"total_trades": 0, "total_pnl_percent": 0}
326
+
327
+ self.vader_bin_effectiveness[vader_bin]["total_trades"] += 1
328
+ self.vader_bin_effectiveness[vader_bin]["total_pnl_percent"] += pnl_percent
329
+ # 🔴 --- END OF CHANGE --- 🔴
330
+
331
+ # --- 6. تكييف الأوزان والحفظ (إذا لزم الأمر) ---
332
  # (ملاحظة: نحتاج إلى إضافة منطق لتعلم أوزان الحارس هنا مستقبلاً)
333
  if should_update_weights(len(self.performance_history)):
334
  await self.adapt_weights_based_on_performance()
335
  await self.save_weights_to_r2()
336
  await self.save_performance_history()
337
  await self.save_exit_profile_effectiveness()
338
+ # 🔴 --- START OF CHANGE (V2 - VADER Learning) --- 🔴
339
+ await self.save_vader_effectiveness() # (حفظ إحصائيات VADER)
340
+ # 🔴 --- END OF CHANGE --- 🔴
341
 
342
+ print(f"✅ [StatsAnalyzer] تم تحديث الإحصائيات لـ {strategy} (News Bin: {vader_bin})")
343
 
344
  except Exception as e:
345
  print(f"❌ [StatsAnalyzer] فشل تحديث الإحصائيات: {e}")
 
404
  best_profile = max(relevant_profiles, key=relevant_profiles.get)
405
  return best_profile
406
 
407
+ # 🔴 --- START OF CHANGE (V2 - VADER Learning) --- 🔴
408
+ async def get_statistical_vader_pnl(self, vader_score: float) -> float:
409
+ """
410
+ جلب متوسط الربح/الخسارة التاريخي لدرجة VADER
411
+ """
412
+ if not self.initialized:
413
+ return 0.0 # (العودة بقيمة محايدة)
414
+
415
+ vader_bin = self._get_vader_bin(vader_score)
416
+ bin_data = self.vader_bin_effectiveness.get(vader_bin)
417
+
418
+ if not bin_data or bin_data.get("total_trades", 0) < 3:
419
+ # (لا توجد بيانات كافية، العودة بقيمة محايدة)
420
+ return 0.0
421
+
422
+ # (إرجاع متوسط الربح/الخسارة الفعلي لهذه السلة)
423
+ avg_pnl = bin_data["total_pnl_percent"] / bin_data["total_trades"]
424
+ return avg_pnl
425
+ # 🔴 --- END OF CHANGE --- 🔴
426
+
427
  # 🔴 --- START OF CHANGE --- 🔴
428
  async def get_optimized_weights(self, market_condition: str) -> Dict[str, float]:
429
  """
 
490
  "market_sentiment": market_context.get('btc_sentiment', 'NEUTRAL'),
491
  }
492
  except Exception as e:
493
+ return {"current_trend": "sideways_market", "volatility": "medium", "market_sentiment": "NEUTRAL"}