Riy777 commited on
Commit
f5a7217
·
1 Parent(s): 12a2d47

Update learning_engine.py

Browse files
Files changed (1) hide show
  1. learning_engine.py +90 -298
learning_engine.py CHANGED
@@ -1,11 +1,6 @@
1
- import os
2
- import json
3
- import asyncio
4
- import pandas as pd
5
- import numpy as np
6
- from datetime import datetime, timedelta
7
- from typing import Dict, List, Any
8
- import hashlib
9
 
10
  class LearningEngine:
11
  def __init__(self, r2_service, data_manager):
@@ -20,58 +15,42 @@ class LearningEngine:
20
  self.initialization_lock = asyncio.Lock()
21
 
22
  async def initialize(self):
23
- """تهيئة نظام التعلم من R2"""
24
  async with self.initialization_lock:
25
- if self.initialized:
26
- return
27
-
28
- print("🧠 تهيئة نظام التعلم الذاتي...")
29
  try:
30
  await self.load_weights_from_r2()
31
  await self.load_performance_history()
32
  self.initialized = True
33
- print(" نظام التعلم جاهز - الأوزان محملة بنجاح")
34
  except Exception as e:
35
- print(f"⚠️ لم يتم تحميل الأوزان السابقة: {e} - سيتم البدء بأوزان افتراضية")
36
  await self.initialize_default_weights()
37
  self.initialized = True
38
 
39
  async def initialize_enhanced(self):
40
- """تهيئة محسنة لنظام التعلم"""
41
  async with self.initialization_lock:
42
- if self.initialized:
43
- return
44
-
45
- print("🧠 تهيئة نظام التعلم الذاتي المحسّن...")
46
  try:
47
  await self.load_weights_from_r2()
48
  await self.load_performance_history()
49
-
50
- # إصلاح هيكل الأوزان إذا لزم الأمر
51
  await self.fix_weights_structure()
52
-
53
- # إذا لم تكن هناك بيانات كافية، بدء التعلم من الصفر
54
  if not self.performance_history:
55
- print("🔰 بدء التعلم من الصفر - لا توجد بيانات تاريخية")
56
  await self.initialize_default_weights()
57
-
58
  self.initialized = True
59
- print("✅ نظام التعلم المحسّن جاهز")
60
-
61
  except Exception as e:
62
- print(f"⚠️ فشل التهيئة المحسنة: {e}")
63
  await self.initialize_default_weights()
64
  self.initialized = True
65
 
66
  async def fix_weights_structure(self):
67
- """إصلاح هيكل الأوزان ليتوافق مع الكود"""
68
  try:
69
- # تحميل البيانات الحالية
70
  key = "learning_engine_weights.json"
71
  response = self.r2_service.s3_client.get_object(Bucket="trading", Key=key)
72
  current_data = json.loads(response['Body'].read())
73
 
74
- # إذا كان الهيكل قديماً، قم بتحديثه
75
  if 'strategy_weights' in current_data and 'last_updated' not in current_data:
76
  fixed_data = {
77
  "weights": current_data,
@@ -79,89 +58,56 @@ class LearningEngine:
79
  "version": "2.0",
80
  "performance_metrics": await self.calculate_performance_metrics()
81
  }
82
-
83
  data_json = json.dumps(fixed_data, indent=2, ensure_ascii=False).encode('utf-8')
84
  self.r2_service.s3_client.put_object(
85
  Bucket="trading", Key=key, Body=data_json, ContentType="application/json"
86
  )
87
- print(" تم إصلاح هيكل الأوزان بنجاح")
88
-
89
  except Exception as e:
90
- print(f"⚠️ لم يتم إصلاح هيكل الأوزان: {e}")
91
 
92
  async def initialize_default_weights(self):
93
- """تهيئة الأوزان الافتراضية - موزعة بشكل أفضل"""
94
  self.weights = {
95
  "strategy_weights": {
96
- "trend_following": 0.18,
97
- "mean_reversion": 0.15,
98
- "breakout_momentum": 0.22,
99
- "volume_spike": 0.12,
100
- "whale_tracking": 0.15,
101
- "pattern_recognition": 0.10,
102
  "hybrid_ai": 0.08
103
  },
104
  "technical_weights": {
105
- "rsi": 0.15,
106
- "macd": 0.18,
107
- "ema_cross": 0.12,
108
- "bollinger_bands": 0.10,
109
- "volume_analysis": 0.15,
110
- "support_resistance": 0.12,
111
- "market_sentiment": 0.18
112
  },
113
  "risk_parameters": {
114
- "max_position_size": 0.1,
115
- "max_daily_loss": 0.02,
116
- "stop_loss_base": 0.02,
117
- "risk_reward_ratio": 2.0,
118
- "volatility_adjustment": 1.0
119
  },
120
  "market_condition_weights": {
121
- "bull_market": {
122
- "trend_following": 0.25,
123
- "breakout_momentum": 0.20,
124
- "whale_tracking": 0.15
125
- },
126
- "bear_market": {
127
- "mean_reversion": 0.25,
128
- "pattern_recognition": 0.20,
129
- "hybrid_ai": 0.15
130
- },
131
- "sideways_market": {
132
- "mean_reversion": 0.30,
133
- "volume_spike": 0.20,
134
- "pattern_recognition": 0.15
135
- }
136
  }
137
  }
138
 
139
  async def load_weights_from_r2(self):
140
- """تحميل الأوزان من R2"""
141
  try:
142
  key = "learning_engine_weights.json"
143
- response = self.r2_service.s3_client.get_object(
144
- Bucket="trading", Key=key
145
- )
146
  weights_data = json.loads(response['Body'].read())
147
 
148
- # التعامل مع الهيكل الجديد والقديم
149
  if isinstance(weights_data, dict):
150
  if 'weights' in weights_data:
151
  self.weights = weights_data['weights']
152
  else:
153
  self.weights = weights_data
154
- print(f" تم تحميل الأوزان من R2 بنجاح. إصدار الهيكل: {'جديد' if 'weights' in weights_data else 'قديم'}")
155
  else:
156
- raise ValueError("هيكل الأوزان غير صحيح")
157
-
158
  except Exception as e:
159
- print(f" فشل تحميل الأوزان: {e}")
160
  await self.initialize_default_weights()
161
  await self.save_weights_to_r2()
162
 
163
  async def save_weights_to_r2(self):
164
- """حفظ الأوزان إلى R2"""
165
  try:
166
  key = "learning_engine_weights.json"
167
  weights_data = {
@@ -170,64 +116,47 @@ class LearningEngine:
170
  "version": "2.0",
171
  "performance_metrics": await self.calculate_performance_metrics()
172
  }
173
-
174
  data_json = json.dumps(weights_data, indent=2, ensure_ascii=False).encode('utf-8')
175
  self.r2_service.s3_client.put_object(
176
- Bucket="trading",
177
- Key=key,
178
- Body=data_json,
179
- ContentType="application/json"
180
  )
181
- print(" تم حفظ الأوزان إلى R2 بنجاح")
182
  except Exception as e:
183
- print(f" فشل حفظ الأوزان: {e}")
184
 
185
  async def load_performance_history(self):
186
- """تحميل سجل الأداء"""
187
  try:
188
  key = "learning_performance_history.json"
189
- response = self.r2_service.s3_client.get_object(
190
- Bucket="trading", Key=key
191
- )
192
  history_data = json.loads(response['Body'].read())
193
  self.performance_history = history_data.get("history", [])
194
- print(f" تم تحميل سجل الأداء - {len(self.performance_history)} تسجيل")
195
  except Exception as e:
196
- print(f"⚠️ لم يتم تحميل سجل الأداء: {e}")
197
  self.performance_history = []
198
 
199
  async def save_performance_history(self):
200
- """حفظ سجل الأداء"""
201
  try:
202
  key = "learning_performance_history.json"
203
  history_data = {
204
  "history": self.performance_history[-1000:],
205
  "last_updated": datetime.now().isoformat()
206
  }
207
-
208
  data_json = json.dumps(history_data, indent=2, ensure_ascii=False).encode('utf-8')
209
  self.r2_service.s3_client.put_object(
210
- Bucket="trading",
211
- Key=key,
212
- Body=data_json,
213
- ContentType="application/json"
214
  )
215
  except Exception as e:
216
- print(f" فشل حفظ سجل الأداء: {e}")
217
 
218
  async def analyze_trade_outcome(self, trade_data, outcome):
219
- """تحليل نتيجة الصفقة وتحديث الأوزان - الإصدار المحسّن"""
220
- if not self.initialized:
221
- await self.initialize()
222
-
223
  try:
224
- # استخراج الاستراتيجية من بيانات الصفقة
225
  strategy = trade_data.get('strategy', 'unknown')
226
  if strategy == 'unknown':
227
  decision_data = trade_data.get('decision_data', {})
228
  strategy = decision_data.get('strategy', 'unknown')
229
 
230
- # الحصول على سياق السوق الحقيقي
231
  market_context = await self.get_current_market_conditions()
232
 
233
  analysis_entry = {
@@ -242,29 +171,19 @@ class LearningEngine:
242
  }
243
 
244
  self.performance_history.append(analysis_entry)
245
-
246
  await self.update_strategy_effectiveness(analysis_entry)
247
  await self.update_market_patterns(analysis_entry)
248
 
249
- # ✅ التحديث الهام: تحديث الأوزان بعد كل صفقة في البداية
250
- if len(self.performance_history) <= 10: # أول 10 صفقات
251
  await self.adapt_weights_based_on_performance()
252
  await self.save_weights_to_r2()
253
  await self.save_performance_history()
254
- else:
255
- # بعد ذلك، تحديث كل 3 صفقات
256
- if len(self.performance_history) % 3 == 0:
257
- await self.adapt_weights_based_on_performance()
258
- await self.save_weights_to_r2()
259
- await self.save_performance_history()
260
-
261
- print(f"📊 تم تحليل صفقة {trade_data.get('symbol')} - الاستراتيجية: {strategy} - النتيجة: {outcome} - PnL: {trade_data.get('pnl_percent', 0):.2f}%")
262
 
 
263
  except Exception as e:
264
- print(f" فشل تحليل نتيجة الصفقة: {e}")
265
 
266
  async def update_strategy_effectiveness(self, analysis_entry):
267
- """تحديث فعالية الاستراتيجيات"""
268
  strategy = analysis_entry['strategy_used']
269
  outcome = analysis_entry['outcome']
270
  market_condition = analysis_entry['market_conditions']['current_trend']
@@ -272,35 +191,26 @@ class LearningEngine:
272
 
273
  if strategy not in self.strategy_effectiveness:
274
  self.strategy_effectiveness[strategy] = {
275
- "total_trades": 0,
276
- "successful_trades": 0,
277
- "total_profit": 0,
278
- "total_pnl_percent": 0,
279
- "market_conditions": {}
280
  }
281
 
282
  self.strategy_effectiveness[strategy]["total_trades"] += 1
283
  self.strategy_effectiveness[strategy]["total_pnl_percent"] += pnl_percent
284
 
285
- # تحديد النجاح بناءً على النتيجة والأداء
286
  is_success = outcome in ["SUCCESS", "CLOSED_BY_REANALYSIS", "CLOSED_BY_MONITOR"] and pnl_percent > 0
287
- if is_success:
288
- self.strategy_effectiveness[strategy]["successful_trades"] += 1
289
 
290
  if market_condition not in self.strategy_effectiveness[strategy]["market_conditions"]:
291
  self.strategy_effectiveness[strategy]["market_conditions"][market_condition] = {
292
- "trades": 0,
293
- "successes": 0,
294
- "total_pnl": 0
295
  }
296
 
297
  self.strategy_effectiveness[strategy]["market_conditions"][market_condition]["trades"] += 1
298
  self.strategy_effectiveness[strategy]["market_conditions"][market_condition]["total_pnl"] += pnl_percent
299
- if is_success:
300
- self.strategy_effectiveness[strategy]["market_conditions"][market_condition]["successes"] += 1
301
 
302
  async def update_market_patterns(self, analysis_entry):
303
- """تحديث أنماط السوق"""
304
  market_condition = analysis_entry['market_conditions']['current_trend']
305
  symbol = analysis_entry['symbol']
306
  outcome = analysis_entry['outcome']
@@ -308,25 +218,20 @@ class LearningEngine:
308
 
309
  if market_condition not in self.market_patterns:
310
  self.market_patterns[market_condition] = {
311
- "total_trades": 0,
312
- "successful_trades": 0,
313
- "total_pnl_percent": 0,
314
- "best_performing_strategies": {},
315
- "best_performing_symbols": {}
316
  }
317
 
318
  self.market_patterns[market_condition]["total_trades"] += 1
319
  self.market_patterns[market_condition]["total_pnl_percent"] += pnl_percent
320
 
321
  is_success = outcome in ["SUCCESS", "CLOSED_BY_REANALYSIS", "CLOSED_BY_MONITOR"] and pnl_percent > 0
322
- if is_success:
323
- self.market_patterns[market_condition]["successful_trades"] += 1
324
 
325
  strategy = analysis_entry['strategy_used']
326
  if strategy not in self.market_patterns[market_condition]["best_performing_strategies"]:
327
  self.market_patterns[market_condition]["best_performing_strategies"][strategy] = {
328
- "count": 0,
329
- "total_pnl": 0
330
  }
331
 
332
  self.market_patterns[market_condition]["best_performing_strategies"][strategy]["count"] += 1
@@ -334,25 +239,20 @@ class LearningEngine:
334
 
335
  if symbol not in self.market_patterns[market_condition]["best_performing_symbols"]:
336
  self.market_patterns[market_condition]["best_performing_symbols"][symbol] = {
337
- "count": 0,
338
- "total_pnl": 0
339
  }
340
 
341
  self.market_patterns[market_condition]["best_performing_symbols"][symbol]["count"] += 1
342
  self.market_patterns[market_condition]["best_performing_symbols"][symbol]["total_pnl"] += pnl_percent
343
 
344
  async def adapt_weights_based_on_performance(self):
345
- """تعديل الأوزان بناءً على الأداء - الإصدار المحسّن"""
346
- print("🔄 تحديث الأوزان بناءً على الأداء...")
347
-
348
  try:
349
- # إذا لم تكن هناك بيانات كافية، استخدم تحديثاً تدريجياً
350
  if not self.strategy_effectiveness:
351
- print("⚠️ لا توجد بيانات أداء كافية، استخدام تحديث تدريجي")
352
  await self.gradual_weights_adjustment()
353
  return
354
 
355
- # تحديث أوزان الاستراتيجيات بناءً على الأداء الحقيقي
356
  total_performance = 0
357
  strategy_performance = {}
358
 
@@ -360,35 +260,26 @@ class LearningEngine:
360
  if data["total_trades"] > 0:
361
  success_rate = data["successful_trades"] / data["total_trades"]
362
  avg_pnl = data["total_pnl_percent"] / data["total_trades"]
363
-
364
- # حساب الأداء المركب
365
  composite_performance = (success_rate * 0.7) + (min(avg_pnl, 10) / 10 * 0.3)
366
  strategy_performance[strategy] = composite_performance
367
  total_performance += composite_performance
368
 
369
- # إذا كان هناك أداء كافٍ، قم بالتحديث
370
  if total_performance > 0 and strategy_performance:
371
  for strategy, performance in strategy_performance.items():
372
  current_weight = self.weights["strategy_weights"].get(strategy, 0.1)
373
- # تحديث تدريجي لتجنب التغيرات المفاجئة
374
  new_weight = current_weight * 0.7 + (performance * 0.3)
375
  self.weights["strategy_weights"][strategy] = new_weight
376
 
377
- # تطبيع الأوزان
378
- self.normalize_weights()
379
- print("✅ تم تحديث الأوزان بناءً على الأداء الحقيقي")
380
  else:
381
  await self.gradual_weights_adjustment()
382
-
383
  except Exception as e:
384
- print(f" فشل تحديث الأوزان: {e}")
385
  await self.gradual_weights_adjustment()
386
 
387
  async def gradual_weights_adjustment(self):
388
- """تعديل تدريجي للأوزان لتحسين الأداء"""
389
- print("📈 إجراء تعديل تدريجي على الأوزان...")
390
-
391
- # زيادة وزن الاستراتيجيات التي تعتمد على البيانات المتاحة
392
  if self.market_patterns:
393
  for market_condition, data in self.market_patterns.items():
394
  if data.get("total_trades", 0) > 0:
@@ -398,87 +289,35 @@ class LearningEngine:
398
  current_weight = self.weights["strategy_weights"].get(best_strategy, 0.1)
399
  self.weights["strategy_weights"][best_strategy] = min(current_weight * 1.1, 0.3)
400
 
401
- self.normalize_weights()
402
- print(" تم التعديل التدريجي للأوزان")
403
-
404
- def normalize_weights(self):
405
- """تطبيع الأوزان للتأكد من أن مجموعها 1"""
406
- total = sum(self.weights["strategy_weights"].values())
407
- if total > 0:
408
- for strategy in self.weights["strategy_weights"]:
409
- self.weights["strategy_weights"][strategy] /= total
410
 
411
  async def get_current_market_conditions(self):
412
- """الحصول على ظروف السوق الحالية - بيانات حقيقية"""
413
  try:
414
- if not self.data_manager:
415
- raise ValueError("DataManager غير متوفر")
416
-
417
  market_context = await self.data_manager.get_market_context_async()
418
- if not market_context:
419
- raise ValueError("فشل جلب سياق السوق")
420
-
421
  return {
422
  "current_trend": market_context.get('market_trend', 'sideways_market'),
423
- "volatility": self._calculate_market_volatility(market_context),
424
  "market_sentiment": market_context.get('btc_sentiment', 'NEUTRAL'),
425
  "whale_activity": market_context.get('general_whale_activity', {}).get('sentiment', 'NEUTRAL'),
426
  "fear_greed_index": market_context.get('fear_and_greed_index', 50)
427
  }
428
  except Exception as e:
429
- print(f"⚠️ فشل الحصول على ظروف السوق: {e}")
430
  return {
431
- "current_trend": "sideways_market",
432
- "volatility": "medium",
433
- "market_sentiment": "neutral",
434
- "whale_activity": "low",
435
- "fear_greed_index": 50
436
  }
437
 
438
- def _calculate_market_volatility(self, market_context):
439
- """حساب تقلبية السوق بناءً على البيانات الحقيقية"""
440
- try:
441
- btc_price = market_context.get('bitcoin_price_usd', 0)
442
- fear_greed = market_context.get('fear_and_greed_index', 50)
443
- whale_sentiment = market_context.get('general_whale_activity', {}).get('sentiment', 'NEUTRAL')
444
-
445
- volatility_score = 0
446
-
447
- # تحليل سعر البيتكوين (تغيرات كبيرة = تقلبية عالية)
448
- if btc_price > 0:
449
- # هذا مؤشر مبسط - في التطبيق الحقيقي نحتاج بيانات تاريخية
450
- if abs(fear_greed - 50) > 20:
451
- volatility_score += 1
452
-
453
- # تحليل نشاط الحيتان
454
- if whale_sentiment in ['BULLISH', 'BEARISH']:
455
- volatility_score += 1
456
- elif whale_sentiment == 'SLIGHTLY_BULLISH':
457
- volatility_score += 0.5
458
-
459
- if volatility_score >= 1.5:
460
- return "high"
461
- elif volatility_score >= 0.5:
462
- return "medium"
463
- else:
464
- return "low"
465
-
466
- except Exception as e:
467
- print(f"⚠️ خطأ في حساب التقلبية: {e}")
468
- return "medium"
469
-
470
  async def calculate_performance_metrics(self):
471
- """حساب مقاييس الأداء"""
472
- if not self.performance_history:
473
- return {"status": "لا توجد بيانات أداء بعد"}
474
-
475
- recent_trades = self.performance_history[-50:] # آخر 50 صفقة فقط
476
-
477
  total_trades = len(recent_trades)
478
  successful_trades = sum(1 for trade in recent_trades
479
  if trade['outcome'] in ["SUCCESS", "CLOSED_BY_REANALYSIS", "CLOSED_BY_MONITOR"] and trade.get('pnl_percent', 0) > 0)
480
  success_rate = successful_trades / total_trades if total_trades > 0 else 0
481
-
482
  total_pnl = sum(trade.get('pnl_percent', 0) for trade in recent_trades)
483
  avg_pnl = total_pnl / total_trades if total_trades > 0 else 0
484
 
@@ -488,10 +327,8 @@ class LearningEngine:
488
  strategy_success_rate = data["successful_trades"] / data["total_trades"]
489
  strategy_avg_pnl = data["total_pnl_percent"] / data["total_trades"]
490
  strategy_performance[strategy] = {
491
- "success_rate": strategy_success_rate,
492
- "avg_pnl_percent": strategy_avg_pnl,
493
- "total_trades": data["total_trades"],
494
- "successful_trades": data["successful_trades"]
495
  }
496
 
497
  market_performance = {}
@@ -500,111 +337,75 @@ class LearningEngine:
500
  market_success_rate = data["successful_trades"] / data["total_trades"]
501
  market_avg_pnl = data["total_pnl_percent"] / data["total_trades"]
502
  market_performance[condition] = {
503
- "success_rate": market_success_rate,
504
- "avg_pnl_percent": market_avg_pnl,
505
  "total_trades": data["total_trades"]
506
  }
507
 
508
  return {
509
- "overall_success_rate": success_rate,
510
- "overall_avg_pnl_percent": avg_pnl,
511
- "total_analyzed_trades": len(self.performance_history),
512
- "recent_trades_analyzed": total_trades,
513
- "strategy_performance": strategy_performance,
514
- "market_performance": market_performance,
515
  "last_updated": datetime.now().isoformat()
516
  }
517
 
518
  async def get_optimized_strategy_weights(self, market_condition):
519
- """الحصول على أوزان استراتيجية محسنة - الإصدار المصحح"""
520
  try:
521
- if not self.initialized:
522
- print("⚠️ نظام التعلم غير مهيء، استخدام الأوزان الافتراضية")
523
  return await self.get_default_strategy_weights()
524
-
525
- # ✅ التحقق من وجود الأوزان وهيكلتها بشكل صحيح
526
- if (not self.weights or
527
- "strategy_weights" not in self.weights or
528
- not self.weights["strategy_weights"]):
529
- print("⚠️ الأوزان غير متوفرة أو فارغة، استخدام الأوزان الافتراضية")
530
- return await self.get_default_strategy_weights()
531
-
532
  base_weights = self.weights["strategy_weights"].copy()
533
-
534
- # ✅ التحقق من أن الأوزان تحتوي على استراتيجيات فعلية
535
  if not any(weight > 0 for weight in base_weights.values()):
536
- print("⚠️ جميع الأوزان صفر، استخدام الأوزان الافتراضية")
537
  return await self.get_default_strategy_weights()
538
-
539
- print(f"✅ استخدام الأوزان المتعلمة: {base_weights}")
540
  return base_weights
541
-
542
  except Exception as e:
543
- print(f" فشل في حساب الأوزان المحسنة: {e}")
544
  return await self.get_default_strategy_weights()
545
 
546
  async def get_default_strategy_weights(self):
547
- """إرجاع الأوزان الافتراضية"""
548
  return {
549
- "trend_following": 0.18,
550
- "mean_reversion": 0.15,
551
- "breakout_momentum": 0.22,
552
- "volume_spike": 0.12,
553
- "whale_tracking": 0.15,
554
- "pattern_recognition": 0.10,
555
  "hybrid_ai": 0.08
556
  }
557
 
558
  async def get_risk_parameters(self, symbol_volatility):
559
- """الحصول على معايير المخاطرة المحسنة"""
560
- if not self.weights or "risk_parameters" not in self.weights:
561
- await self.initialize_default_weights()
562
-
563
  risk_params = self.weights.get("risk_parameters", {}).copy()
564
-
565
- # تعديل معايير المخاطرة بناءً على تقلبية الرمز
566
  if symbol_volatility == "HIGH":
567
  risk_params["stop_loss_base"] *= 1.5
568
  risk_params["max_position_size"] *= 0.7
569
- risk_params["risk_reward_ratio"] = 1.5 # تخفيض نسبة المكافأة/المخاطرة للتقليل العالي
570
  elif symbol_volatility == "LOW":
571
  risk_params["stop_loss_base"] *= 0.7
572
  risk_params["max_position_size"] *= 1.2
573
- risk_params["risk_reward_ratio"] = 2.5 # زيادة النسبة للتقليل المنخفض
574
-
575
  return risk_params
576
 
577
  async def suggest_improvements(self):
578
- """اقتراح تحسينات بناءً على تحليل الأداء"""
579
  improvements = []
580
-
581
  if not self.performance_history:
582
- improvements.append("📊 ابدأ بجمع بيانات الأداء من الصفقات الأولى")
583
  return improvements
584
 
585
- # تحليل أداء الاستراتيجيات
586
  for strategy, data in self.strategy_effectiveness.items():
587
  if data["total_trades"] >= 3:
588
  success_rate = data["successful_trades"] / data["total_trades"]
589
  avg_pnl = data["total_pnl_percent"] / data["total_trades"]
590
-
591
  if success_rate < 0.3 and avg_pnl < 0:
592
- improvements.append(f"🚨 استراتيجية {strategy} ضعيفة الأداء ({success_rate:.1%} نجاح، {avg_pnl:+.1f}% متوسط) - يقترح تقليل استخدامها")
593
  elif success_rate > 0.6 and avg_pnl > 2:
594
- improvements.append(f" استراتيجية {strategy} ممتازة الأداء ({success_rate:.1%} نجاح، {avg_pnl:+.1f}% متوسط) - يقترح زيادة استخدامها")
595
  elif success_rate > 0.7:
596
- improvements.append(f"🎯 استراتيجية {strategy} عالية النجاح ({success_rate:.1%}) - التركيز على جودة الصفقات")
597
 
598
- # تحليل أداء ظروف السوق
599
  for market_condition, data in self.market_patterns.items():
600
  if data["total_trades"] >= 5:
601
  success_rate = data["successful_trades"] / data["total_trades"]
602
  avg_pnl = data["total_pnl_percent"] / data["total_trades"]
603
-
604
  if success_rate < 0.4:
605
- improvements.append(f"⚠️ الأداء ضعيف في سوق {market_condition} ({success_rate:.1%} نجاح) - يحتاج مراجعة الاستراتيجيات")
606
 
607
- # العثور على أفضل استراتيجية لهذا السوق
608
  best_strategy = None
609
  best_performance = -100
610
  for strategy, stats in data["best_performing_strategies"].items():
@@ -615,30 +416,21 @@ class LearningEngine:
615
  best_strategy = strategy
616
 
617
  if best_strategy and best_performance > 1:
618
- improvements.append(f"📈 أفضل استراتيجية في {market_condition}: {best_strategy} ({best_performance:+.1f}% متوسط ربح)")
619
-
620
- if not improvements:
621
- improvements.append("📊 لا توجد تحسينات مقترحة حالياً - استمر في جمع البيانات")
622
 
 
623
  return improvements
624
 
625
  async def force_strategy_learning(self):
626
- """إجبار النظام على التعلم من البيانات الحالية"""
627
- print("🧠 إجبار تحديث الاستراتيجيات من البيانات الحالية...")
628
-
629
  if not self.performance_history:
630
- print("⚠️ لا توجد بيانات أداء للتعلم منها")
631
  return
632
-
633
- # تحديث فعالية الاستراتيجيات من البيانات التاريخية
634
  for entry in self.performance_history:
635
  await self.update_strategy_effectiveness(entry)
636
  await self.update_market_patterns(entry)
637
-
638
- # تحديث الأوزان فوراً
639
  await self.adapt_weights_based_on_performance()
640
  await self.save_weights_to_r2()
641
-
642
- print("✅ تم إجبار تحديث الاستراتيجيات بنجاح")
643
 
644
- print(" نظام التعلم الذاتي المحسن محمل - جاهز للتعلم والتكيف المستمر")
 
1
+ import os, json, asyncio
2
+ from datetime import datetime
3
+ from helpers import normalize_weights, calculate_market_volatility, should_update_weights
 
 
 
 
 
4
 
5
  class LearningEngine:
6
  def __init__(self, r2_service, data_manager):
 
15
  self.initialization_lock = asyncio.Lock()
16
 
17
  async def initialize(self):
 
18
  async with self.initialization_lock:
19
+ if self.initialized: return
20
+ print("Initializing learning system...")
 
 
21
  try:
22
  await self.load_weights_from_r2()
23
  await self.load_performance_history()
24
  self.initialized = True
25
+ print("Learning system ready")
26
  except Exception as e:
27
+ print(f"Weights loading failed: {e}")
28
  await self.initialize_default_weights()
29
  self.initialized = True
30
 
31
  async def initialize_enhanced(self):
 
32
  async with self.initialization_lock:
33
+ if self.initialized: return
34
+ print("Enhanced learning system initialization...")
 
 
35
  try:
36
  await self.load_weights_from_r2()
37
  await self.load_performance_history()
 
 
38
  await self.fix_weights_structure()
 
 
39
  if not self.performance_history:
40
+ print("Starting learning from scratch")
41
  await self.initialize_default_weights()
 
42
  self.initialized = True
 
 
43
  except Exception as e:
44
+ print(f"Enhanced initialization failed: {e}")
45
  await self.initialize_default_weights()
46
  self.initialized = True
47
 
48
  async def fix_weights_structure(self):
 
49
  try:
 
50
  key = "learning_engine_weights.json"
51
  response = self.r2_service.s3_client.get_object(Bucket="trading", Key=key)
52
  current_data = json.loads(response['Body'].read())
53
 
 
54
  if 'strategy_weights' in current_data and 'last_updated' not in current_data:
55
  fixed_data = {
56
  "weights": current_data,
 
58
  "version": "2.0",
59
  "performance_metrics": await self.calculate_performance_metrics()
60
  }
 
61
  data_json = json.dumps(fixed_data, indent=2, ensure_ascii=False).encode('utf-8')
62
  self.r2_service.s3_client.put_object(
63
  Bucket="trading", Key=key, Body=data_json, ContentType="application/json"
64
  )
65
+ print("Weights structure fixed")
 
66
  except Exception as e:
67
+ print(f"Weights structure fix failed: {e}")
68
 
69
  async def initialize_default_weights(self):
 
70
  self.weights = {
71
  "strategy_weights": {
72
+ "trend_following": 0.18, "mean_reversion": 0.15, "breakout_momentum": 0.22,
73
+ "volume_spike": 0.12, "whale_tracking": 0.15, "pattern_recognition": 0.10,
 
 
 
 
74
  "hybrid_ai": 0.08
75
  },
76
  "technical_weights": {
77
+ "rsi": 0.15, "macd": 0.18, "ema_cross": 0.12, "bollinger_bands": 0.10,
78
+ "volume_analysis": 0.15, "support_resistance": 0.12, "market_sentiment": 0.18
 
 
 
 
 
79
  },
80
  "risk_parameters": {
81
+ "max_position_size": 0.1, "max_daily_loss": 0.02, "stop_loss_base": 0.02,
82
+ "risk_reward_ratio": 2.0, "volatility_adjustment": 1.0
 
 
 
83
  },
84
  "market_condition_weights": {
85
+ "bull_market": {"trend_following": 0.25, "breakout_momentum": 0.20, "whale_tracking": 0.15},
86
+ "bear_market": {"mean_reversion": 0.25, "pattern_recognition": 0.20, "hybrid_ai": 0.15},
87
+ "sideways_market": {"mean_reversion": 0.30, "volume_spike": 0.20, "pattern_recognition": 0.15}
 
 
 
 
 
 
 
 
 
 
 
 
88
  }
89
  }
90
 
91
  async def load_weights_from_r2(self):
 
92
  try:
93
  key = "learning_engine_weights.json"
94
+ response = self.r2_service.s3_client.get_object(Bucket="trading", Key=key)
 
 
95
  weights_data = json.loads(response['Body'].read())
96
 
 
97
  if isinstance(weights_data, dict):
98
  if 'weights' in weights_data:
99
  self.weights = weights_data['weights']
100
  else:
101
  self.weights = weights_data
102
+ print(f"Weights loaded from R2")
103
  else:
104
+ raise ValueError("Invalid weights structure")
 
105
  except Exception as e:
106
+ print(f"Weights loading failed: {e}")
107
  await self.initialize_default_weights()
108
  await self.save_weights_to_r2()
109
 
110
  async def save_weights_to_r2(self):
 
111
  try:
112
  key = "learning_engine_weights.json"
113
  weights_data = {
 
116
  "version": "2.0",
117
  "performance_metrics": await self.calculate_performance_metrics()
118
  }
 
119
  data_json = json.dumps(weights_data, indent=2, ensure_ascii=False).encode('utf-8')
120
  self.r2_service.s3_client.put_object(
121
+ Bucket="trading", Key=key, Body=data_json, ContentType="application/json"
 
 
 
122
  )
123
+ print("Weights saved to R2")
124
  except Exception as e:
125
+ print(f"Weights saving failed: {e}")
126
 
127
  async def load_performance_history(self):
 
128
  try:
129
  key = "learning_performance_history.json"
130
+ response = self.r2_service.s3_client.get_object(Bucket="trading", Key=key)
 
 
131
  history_data = json.loads(response['Body'].read())
132
  self.performance_history = history_data.get("history", [])
133
+ print(f"Performance history loaded - {len(self.performance_history)} records")
134
  except Exception as e:
135
+ print(f"Performance history loading failed: {e}")
136
  self.performance_history = []
137
 
138
  async def save_performance_history(self):
 
139
  try:
140
  key = "learning_performance_history.json"
141
  history_data = {
142
  "history": self.performance_history[-1000:],
143
  "last_updated": datetime.now().isoformat()
144
  }
 
145
  data_json = json.dumps(history_data, indent=2, ensure_ascii=False).encode('utf-8')
146
  self.r2_service.s3_client.put_object(
147
+ Bucket="trading", Key=key, Body=data_json, ContentType="application/json"
 
 
 
148
  )
149
  except Exception as e:
150
+ print(f"Performance history saving failed: {e}")
151
 
152
  async def analyze_trade_outcome(self, trade_data, outcome):
153
+ if not self.initialized: await self.initialize()
 
 
 
154
  try:
 
155
  strategy = trade_data.get('strategy', 'unknown')
156
  if strategy == 'unknown':
157
  decision_data = trade_data.get('decision_data', {})
158
  strategy = decision_data.get('strategy', 'unknown')
159
 
 
160
  market_context = await self.get_current_market_conditions()
161
 
162
  analysis_entry = {
 
171
  }
172
 
173
  self.performance_history.append(analysis_entry)
 
174
  await self.update_strategy_effectiveness(analysis_entry)
175
  await self.update_market_patterns(analysis_entry)
176
 
177
+ if should_update_weights(len(self.performance_history)):
 
178
  await self.adapt_weights_based_on_performance()
179
  await self.save_weights_to_r2()
180
  await self.save_performance_history()
 
 
 
 
 
 
 
 
181
 
182
+ print(f"Trade analyzed {trade_data.get('symbol')} - Strategy: {strategy} - Outcome: {outcome}")
183
  except Exception as e:
184
+ print(f"Trade outcome analysis failed: {e}")
185
 
186
  async def update_strategy_effectiveness(self, analysis_entry):
 
187
  strategy = analysis_entry['strategy_used']
188
  outcome = analysis_entry['outcome']
189
  market_condition = analysis_entry['market_conditions']['current_trend']
 
191
 
192
  if strategy not in self.strategy_effectiveness:
193
  self.strategy_effectiveness[strategy] = {
194
+ "total_trades": 0, "successful_trades": 0, "total_profit": 0,
195
+ "total_pnl_percent": 0, "market_conditions": {}
 
 
 
196
  }
197
 
198
  self.strategy_effectiveness[strategy]["total_trades"] += 1
199
  self.strategy_effectiveness[strategy]["total_pnl_percent"] += pnl_percent
200
 
 
201
  is_success = outcome in ["SUCCESS", "CLOSED_BY_REANALYSIS", "CLOSED_BY_MONITOR"] and pnl_percent > 0
202
+ if is_success: self.strategy_effectiveness[strategy]["successful_trades"] += 1
 
203
 
204
  if market_condition not in self.strategy_effectiveness[strategy]["market_conditions"]:
205
  self.strategy_effectiveness[strategy]["market_conditions"][market_condition] = {
206
+ "trades": 0, "successes": 0, "total_pnl": 0
 
 
207
  }
208
 
209
  self.strategy_effectiveness[strategy]["market_conditions"][market_condition]["trades"] += 1
210
  self.strategy_effectiveness[strategy]["market_conditions"][market_condition]["total_pnl"] += pnl_percent
211
+ if is_success: self.strategy_effectiveness[strategy]["market_conditions"][market_condition]["successes"] += 1
 
212
 
213
  async def update_market_patterns(self, analysis_entry):
 
214
  market_condition = analysis_entry['market_conditions']['current_trend']
215
  symbol = analysis_entry['symbol']
216
  outcome = analysis_entry['outcome']
 
218
 
219
  if market_condition not in self.market_patterns:
220
  self.market_patterns[market_condition] = {
221
+ "total_trades": 0, "successful_trades": 0, "total_pnl_percent": 0,
222
+ "best_performing_strategies": {}, "best_performing_symbols": {}
 
 
 
223
  }
224
 
225
  self.market_patterns[market_condition]["total_trades"] += 1
226
  self.market_patterns[market_condition]["total_pnl_percent"] += pnl_percent
227
 
228
  is_success = outcome in ["SUCCESS", "CLOSED_BY_REANALYSIS", "CLOSED_BY_MONITOR"] and pnl_percent > 0
229
+ if is_success: self.market_patterns[market_condition]["successful_trades"] += 1
 
230
 
231
  strategy = analysis_entry['strategy_used']
232
  if strategy not in self.market_patterns[market_condition]["best_performing_strategies"]:
233
  self.market_patterns[market_condition]["best_performing_strategies"][strategy] = {
234
+ "count": 0, "total_pnl": 0
 
235
  }
236
 
237
  self.market_patterns[market_condition]["best_performing_strategies"][strategy]["count"] += 1
 
239
 
240
  if symbol not in self.market_patterns[market_condition]["best_performing_symbols"]:
241
  self.market_patterns[market_condition]["best_performing_symbols"][symbol] = {
242
+ "count": 0, "total_pnl": 0
 
243
  }
244
 
245
  self.market_patterns[market_condition]["best_performing_symbols"][symbol]["count"] += 1
246
  self.market_patterns[market_condition]["best_performing_symbols"][symbol]["total_pnl"] += pnl_percent
247
 
248
  async def adapt_weights_based_on_performance(self):
249
+ print("Updating weights based on performance...")
 
 
250
  try:
 
251
  if not self.strategy_effectiveness:
252
+ print("Insufficient performance data, using gradual adjustment")
253
  await self.gradual_weights_adjustment()
254
  return
255
 
 
256
  total_performance = 0
257
  strategy_performance = {}
258
 
 
260
  if data["total_trades"] > 0:
261
  success_rate = data["successful_trades"] / data["total_trades"]
262
  avg_pnl = data["total_pnl_percent"] / data["total_trades"]
 
 
263
  composite_performance = (success_rate * 0.7) + (min(avg_pnl, 10) / 10 * 0.3)
264
  strategy_performance[strategy] = composite_performance
265
  total_performance += composite_performance
266
 
 
267
  if total_performance > 0 and strategy_performance:
268
  for strategy, performance in strategy_performance.items():
269
  current_weight = self.weights["strategy_weights"].get(strategy, 0.1)
 
270
  new_weight = current_weight * 0.7 + (performance * 0.3)
271
  self.weights["strategy_weights"][strategy] = new_weight
272
 
273
+ normalize_weights(self.weights["strategy_weights"])
274
+ print("Weights updated based on real performance")
 
275
  else:
276
  await self.gradual_weights_adjustment()
 
277
  except Exception as e:
278
+ print(f"Weights update failed: {e}")
279
  await self.gradual_weights_adjustment()
280
 
281
  async def gradual_weights_adjustment(self):
282
+ print("Gradual weights adjustment...")
 
 
 
283
  if self.market_patterns:
284
  for market_condition, data in self.market_patterns.items():
285
  if data.get("total_trades", 0) > 0:
 
289
  current_weight = self.weights["strategy_weights"].get(best_strategy, 0.1)
290
  self.weights["strategy_weights"][best_strategy] = min(current_weight * 1.1, 0.3)
291
 
292
+ normalize_weights(self.weights["strategy_weights"])
293
+ print("Gradual weights adjustment completed")
 
 
 
 
 
 
 
294
 
295
  async def get_current_market_conditions(self):
 
296
  try:
297
+ if not self.data_manager: raise ValueError("DataManager unavailable")
 
 
298
  market_context = await self.data_manager.get_market_context_async()
299
+ if not market_context: raise ValueError("Market context fetch failed")
 
 
300
  return {
301
  "current_trend": market_context.get('market_trend', 'sideways_market'),
302
+ "volatility": calculate_market_volatility(market_context),
303
  "market_sentiment": market_context.get('btc_sentiment', 'NEUTRAL'),
304
  "whale_activity": market_context.get('general_whale_activity', {}).get('sentiment', 'NEUTRAL'),
305
  "fear_greed_index": market_context.get('fear_and_greed_index', 50)
306
  }
307
  except Exception as e:
308
+ print(f"Market conditions fetch failed: {e}")
309
  return {
310
+ "current_trend": "sideways_market", "volatility": "medium",
311
+ "market_sentiment": "neutral", "whale_activity": "low", "fear_greed_index": 50
 
 
 
312
  }
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  async def calculate_performance_metrics(self):
315
+ if not self.performance_history: return {"status": "No performance data yet"}
316
+ recent_trades = self.performance_history[-50:]
 
 
 
 
317
  total_trades = len(recent_trades)
318
  successful_trades = sum(1 for trade in recent_trades
319
  if trade['outcome'] in ["SUCCESS", "CLOSED_BY_REANALYSIS", "CLOSED_BY_MONITOR"] and trade.get('pnl_percent', 0) > 0)
320
  success_rate = successful_trades / total_trades if total_trades > 0 else 0
 
321
  total_pnl = sum(trade.get('pnl_percent', 0) for trade in recent_trades)
322
  avg_pnl = total_pnl / total_trades if total_trades > 0 else 0
323
 
 
327
  strategy_success_rate = data["successful_trades"] / data["total_trades"]
328
  strategy_avg_pnl = data["total_pnl_percent"] / data["total_trades"]
329
  strategy_performance[strategy] = {
330
+ "success_rate": strategy_success_rate, "avg_pnl_percent": strategy_avg_pnl,
331
+ "total_trades": data["total_trades"], "successful_trades": data["successful_trades"]
 
 
332
  }
333
 
334
  market_performance = {}
 
337
  market_success_rate = data["successful_trades"] / data["total_trades"]
338
  market_avg_pnl = data["total_pnl_percent"] / data["total_trades"]
339
  market_performance[condition] = {
340
+ "success_rate": market_success_rate, "avg_pnl_percent": market_avg_pnl,
 
341
  "total_trades": data["total_trades"]
342
  }
343
 
344
  return {
345
+ "overall_success_rate": success_rate, "overall_avg_pnl_percent": avg_pnl,
346
+ "total_analyzed_trades": len(self.performance_history), "recent_trades_analyzed": total_trades,
347
+ "strategy_performance": strategy_performance, "market_performance": market_performance,
 
 
 
348
  "last_updated": datetime.now().isoformat()
349
  }
350
 
351
  async def get_optimized_strategy_weights(self, market_condition):
 
352
  try:
353
+ if not self.initialized: return await self.get_default_strategy_weights()
354
+ if (not self.weights or "strategy_weights" not in self.weights or not self.weights["strategy_weights"]):
355
  return await self.get_default_strategy_weights()
 
 
 
 
 
 
 
 
356
  base_weights = self.weights["strategy_weights"].copy()
 
 
357
  if not any(weight > 0 for weight in base_weights.values()):
 
358
  return await self.get_default_strategy_weights()
359
+ print(f"Using learned weights: {base_weights}")
 
360
  return base_weights
 
361
  except Exception as e:
362
+ print(f"Optimized weights calculation failed: {e}")
363
  return await self.get_default_strategy_weights()
364
 
365
  async def get_default_strategy_weights(self):
 
366
  return {
367
+ "trend_following": 0.18, "mean_reversion": 0.15, "breakout_momentum": 0.22,
368
+ "volume_spike": 0.12, "whale_tracking": 0.15, "pattern_recognition": 0.10,
 
 
 
 
369
  "hybrid_ai": 0.08
370
  }
371
 
372
  async def get_risk_parameters(self, symbol_volatility):
373
+ if not self.weights or "risk_parameters" not in self.weights: await self.initialize_default_weights()
 
 
 
374
  risk_params = self.weights.get("risk_parameters", {}).copy()
 
 
375
  if symbol_volatility == "HIGH":
376
  risk_params["stop_loss_base"] *= 1.5
377
  risk_params["max_position_size"] *= 0.7
378
+ risk_params["risk_reward_ratio"] = 1.5
379
  elif symbol_volatility == "LOW":
380
  risk_params["stop_loss_base"] *= 0.7
381
  risk_params["max_position_size"] *= 1.2
382
+ risk_params["risk_reward_ratio"] = 2.5
 
383
  return risk_params
384
 
385
  async def suggest_improvements(self):
 
386
  improvements = []
 
387
  if not self.performance_history:
388
+ improvements.append("Start collecting performance data from first trades")
389
  return improvements
390
 
 
391
  for strategy, data in self.strategy_effectiveness.items():
392
  if data["total_trades"] >= 3:
393
  success_rate = data["successful_trades"] / data["total_trades"]
394
  avg_pnl = data["total_pnl_percent"] / data["total_trades"]
 
395
  if success_rate < 0.3 and avg_pnl < 0:
396
+ improvements.append(f"Strategy {strategy} poor performance ({success_rate:.1%} success, {avg_pnl:+.1f}% average) - suggest reducing usage")
397
  elif success_rate > 0.6 and avg_pnl > 2:
398
+ improvements.append(f"Strategy {strategy} excellent performance ({success_rate:.1%} success, {avg_pnl:+.1f}% average) - suggest increasing usage")
399
  elif success_rate > 0.7:
400
+ improvements.append(f"Strategy {strategy} high success ({success_rate:.1%}) - focus on trade quality")
401
 
 
402
  for market_condition, data in self.market_patterns.items():
403
  if data["total_trades"] >= 5:
404
  success_rate = data["successful_trades"] / data["total_trades"]
405
  avg_pnl = data["total_pnl_percent"] / data["total_trades"]
 
406
  if success_rate < 0.4:
407
+ improvements.append(f"Poor performance in {market_condition} market ({success_rate:.1%} success) - needs strategy review")
408
 
 
409
  best_strategy = None
410
  best_performance = -100
411
  for strategy, stats in data["best_performing_strategies"].items():
 
416
  best_strategy = strategy
417
 
418
  if best_strategy and best_performance > 1:
419
+ improvements.append(f"Best strategy in {market_condition}: {best_strategy} ({best_performance:+.1f}% average profit)")
 
 
 
420
 
421
+ if not improvements: improvements.append("No suggested improvements currently - continue data collection")
422
  return improvements
423
 
424
  async def force_strategy_learning(self):
425
+ print("Forcing strategy update from current data...")
 
 
426
  if not self.performance_history:
427
+ print("No performance data to learn from")
428
  return
 
 
429
  for entry in self.performance_history:
430
  await self.update_strategy_effectiveness(entry)
431
  await self.update_market_patterns(entry)
 
 
432
  await self.adapt_weights_based_on_performance()
433
  await self.save_weights_to_r2()
434
+ print("Strategy update forced successfully")
 
435
 
436
+ print("Enhanced self-learning system loaded - ready for continuous learning and adaptation")