Riy777 commited on
Commit
c96093c
·
verified ·
1 Parent(s): 9b79c88

Update trade_manager.py

Browse files
Files changed (1) hide show
  1. trade_manager.py +121 -4
trade_manager.py CHANGED
@@ -1,5 +1,5 @@
1
  # ============================================================
2
- # 🛡️ trade_manager.py (V37.2 - GEM-Architect: Context Persistence)
3
  # ============================================================
4
 
5
  import asyncio
@@ -36,7 +36,7 @@ class TradeManager:
36
  self.FEE_RATE = 0.001
37
  self.ORACLE_CHECK_INTERVAL = 900
38
 
39
- # إحصائيات الذكاء الاصطناعي (للعرض في الواجهة)
40
  self.ai_stats = {
41
  "hybrid": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0},
42
  "crash": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0},
@@ -45,13 +45,20 @@ class TradeManager:
45
  }
46
 
47
  self.execution_lock = asyncio.Lock()
48
- print(f"🛡️ [TradeManager V37.2] Full System Online (Context Aware).")
49
 
50
  async def initialize_sentry_exchanges(self):
51
  """تهيئة المحفظة واستعادة الحالة"""
52
  print("🛡️ [TradeManager] Syncing state & Initializing Portfolio...")
53
  await self.smart_portfolio.initialize()
54
  await self.sync_internal_state_with_r2()
 
 
 
 
 
 
 
55
 
56
  async def sync_internal_state_with_r2(self):
57
  """استرجاع الصفقات المفتوحة من R2"""
@@ -112,7 +119,7 @@ class TradeManager:
112
  print(f" -> ⚠️ [Skip] {symbol}: Insufficient 1m data.")
113
  continue
114
 
115
- # ✅ FIX: تمرير سياق الإشارة بالكامل لكي يرى Sniper الحدود الديناميكية
116
  sniper_result = await self.processor.check_sniper_entry(ohlcv_1m, order_book, context_data=signal)
117
 
118
  sniper_signal = sniper_result.get('signal', 'WAIT')
@@ -144,6 +151,103 @@ class TradeManager:
144
  print(f"🚀 [EXECUTING] Attempting entry for best candidate: {best_signal['symbol']}")
145
  await self._execute_entry_from_signal(best_signal['symbol'], best_signal)
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  async def _execute_entry_from_signal(self, symbol, signal_data):
148
  """تنفيذ الدخول الفعلي مع فحص الحوكمة وإدارة المحفظة"""
149
  try:
@@ -241,6 +345,15 @@ class TradeManager:
241
  if symbol in self.sentry_tasks: self.sentry_tasks[symbol].cancel()
242
  self.sentry_tasks[symbol] = asyncio.create_task(self._guardian_loop(symbol))
243
 
 
 
 
 
 
 
 
 
 
244
  print(f"✅ [ENTRY] {symbol} @ {current_price} | Grade: {gov_decision['grade']} | Size: ${approved_size_usd:.2f} | TP: {approved_tp} ({target_label}) | Mood: {market_mood}")
245
 
246
  except Exception as e:
@@ -407,6 +520,10 @@ class TradeManager:
407
 
408
  record = {"symbol": symbol, "exit_price": exit_price, "price_15m": curr, "usd_impact": usd_impact, "verdict": "SUCCESS" if is_good_exit else "MISS"}
409
  await self.r2.append_deep_steward_audit(record)
 
 
 
 
410
  except Exception: pass
411
 
412
  async def _execute_exit(self, symbol, price, reason, ai_scores=None):
 
1
  # ============================================================
2
+ # 🛡️ trade_manager.py (V38.0 - GEM-Architect: Diagnostics Logic)
3
  # ============================================================
4
 
5
  import asyncio
 
36
  self.FEE_RATE = 0.001
37
  self.ORACLE_CHECK_INTERVAL = 900
38
 
39
+ # إحصائيات الذكاء الاصطناعي (سيتم تحميلها من R2)
40
  self.ai_stats = {
41
  "hybrid": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0},
42
  "crash": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0},
 
45
  }
46
 
47
  self.execution_lock = asyncio.Lock()
48
+ print(f"🛡️ [TradeManager V38.0] Full System Online (Diagnostics Ready).")
49
 
50
  async def initialize_sentry_exchanges(self):
51
  """تهيئة المحفظة واستعادة الحالة"""
52
  print("🛡️ [TradeManager] Syncing state & Initializing Portfolio...")
53
  await self.smart_portfolio.initialize()
54
  await self.sync_internal_state_with_r2()
55
+
56
+ # ✅ تحميل إحصائيات الحراس من R2
57
+ try:
58
+ saved_stats = await self.r2.get_guardian_stats_async()
59
+ if saved_stats: self.ai_stats = saved_stats
60
+ print(" -> [Stats] Guardian metrics loaded from R2.")
61
+ except Exception: pass
62
 
63
  async def sync_internal_state_with_r2(self):
64
  """استرجاع الصفقات المفتوحة من R2"""
 
119
  print(f" -> ⚠️ [Skip] {symbol}: Insufficient 1m data.")
120
  continue
121
 
122
+ # ✅ تمرير سياق الإشارة بالكامل لكي يرى Sniper الحدود الديناميكية
123
  sniper_result = await self.processor.check_sniper_entry(ohlcv_1m, order_book, context_data=signal)
124
 
125
  sniper_signal = sniper_result.get('signal', 'WAIT')
 
151
  print(f"🚀 [EXECUTING] Attempting entry for best candidate: {best_signal['symbol']}")
152
  await self._execute_entry_from_signal(best_signal['symbol'], best_signal)
153
 
154
+ # ==============================================================================
155
+ # 🕵️ محرك التشخيص (Diagnostic Engine) - تحديد من صوّت للشراء
156
+ # ==============================================================================
157
+ def _snapshot_model_votes(self, signal_data: Dict[str, Any]) -> Dict[str, bool]:
158
+ """
159
+ تحدد أي النماذج صوّتت بـ 'شراء' بناءً على القيم وقت الدخول.
160
+ تستخدم الحدود الديناميكية إن وجدت، أو القيم الافتراضية للنظام.
161
+ """
162
+ votes = {}
163
+ limits = signal_data.get('dynamic_limits', {})
164
+ comps = signal_data.get('components', {}) or {} # مكونات L2 (Titan, Pattern, MC-L)
165
+
166
+ # 1. نموذج تيتان (Titan)
167
+ # إذا تجاوزت النتيجة 0.5 (الحياد) يعتبر موافقاً
168
+ votes['Titan'] = comps.get('titan_score', signal_data.get('titan_score', 0)) > 0.5
169
+
170
+ # 2. نماذج الأنماط (Patterns)
171
+ votes['Patterns'] = comps.get('patterns_score', signal_data.get('patterns_score', 0)) > 0.5
172
+
173
+ # 3. نموذج أوراكل (Oracle)
174
+ # مقارنة الثقة مع الحد الأدنى المطلوب
175
+ oracle_thresh = limits.get('l3_oracle_thresh', SystemLimits.L3_CONFIDENCE_THRESHOLD)
176
+ votes['Oracle'] = signal_data.get('confidence', 0) >= oracle_thresh
177
+
178
+ # 4. نموذج القناص (Sniper)
179
+ sniper_thresh = limits.get('l4_sniper_thresh', SystemLimits.L4_ENTRY_THRESHOLD)
180
+ votes['Sniper'] = signal_data.get('sniper_score', 0) >= sniper_thresh
181
+
182
+ # 5. مونت كارلو L (Light)
183
+ votes['MonteCarlo_L'] = comps.get('mc_score', 0.5) > 0.5
184
+
185
+ # 6. مونت كارلو A (Advanced)
186
+ # عادة النطاق من -0.10 إلى +0.10. أي قيمة موجبة تعني ميلاً إيجابياً.
187
+ votes['MonteCarlo_A'] = signal_data.get('mc_advanced_score', 0) > 0
188
+
189
+ # 7. طبقة الحوكمة (Governance)
190
+ # أي شيء غير REJECT يعتبر قبولاً
191
+ votes['Governance'] = signal_data.get('governance_grade', 'REJECT') != 'REJECT'
192
+
193
+ return votes
194
+
195
+ async def _run_diagnostic_verification(self, symbol: str, entry_price: float, position_size_usd: float, votes: Dict[str, bool]):
196
+ """
197
+ مهمة خلفية للت��قق من أداء النماذج بالتوقيتات المحددة.
198
+ - القناص: بعد دقيقة واحدة.
199
+ - البقية: بعد ساعة واحدة.
200
+ """
201
+ try:
202
+ print(f"🕵️ [Diagnostics] Audit started for {symbol}...")
203
+
204
+ # --- المؤقت 1: فحص القناص (دقيقة واحدة) ---
205
+ await asyncio.sleep(60)
206
+ current_price_1m = await self.data_manager.get_latest_price_async(symbol)
207
+
208
+ if current_price_1m > 0 and votes.get('Sniper'):
209
+ pnl_pct = (current_price_1m - entry_price) / entry_price
210
+ pnl_usd = pnl_pct * position_size_usd
211
+
212
+ # تحديث إحصائيات القناص في R2
213
+ update = {
214
+ "Sniper": {
215
+ "wins": 1 if pnl_pct > 0 else 0,
216
+ "losses": 1 if pnl_pct <= 0 else 0,
217
+ "pnl": pnl_usd
218
+ }
219
+ }
220
+ await self.r2.update_diagnostic_stats_async(update)
221
+ print(f" 🕵️ [Diagnostics] Sniper Result (1m): ${pnl_usd:.2f} ({'WIN' if pnl_pct>0 else 'LOSS'})")
222
+
223
+ # --- المؤقت 2: الفحص العام (ساعة واحدة) ---
224
+ # انتظار 59 دقيقة متبقية (المجموع 60 دقيقة = 3600 ثانية)
225
+ await asyncio.sleep(3540)
226
+ current_price_1h = await self.data_manager.get_latest_price_async(symbol)
227
+
228
+ if current_price_1h > 0:
229
+ pnl_pct = (current_price_1h - entry_price) / entry_price
230
+ pnl_usd = pnl_pct * position_size_usd
231
+
232
+ updates = {}
233
+ # النماذج التي يتم فحصها بعد ساعة
234
+ long_term_models = ["Titan", "Patterns", "Oracle", "MonteCarlo_L", "MonteCarlo_A", "Governance"]
235
+
236
+ for model in long_term_models:
237
+ if votes.get(model): # إذا وافق النموذج على الدخول
238
+ updates[model] = {
239
+ "wins": 1 if pnl_pct > 0 else 0,
240
+ "losses": 1 if pnl_pct <= 0 else 0,
241
+ "pnl": pnl_usd
242
+ }
243
+
244
+ if updates:
245
+ await self.r2.update_diagnostic_stats_async(updates)
246
+ print(f" 🕵️ [Diagnostics] 1H Audit Complete for {symbol}. PnL: ${pnl_usd:.2f}")
247
+
248
+ except Exception as e:
249
+ print(f"❌ [Diagnostics Error] {e}")
250
+
251
  async def _execute_entry_from_signal(self, symbol, signal_data):
252
  """تنفيذ الدخول الفعلي مع فحص الحوكمة وإدارة المحفظة"""
253
  try:
 
345
  if symbol in self.sentry_tasks: self.sentry_tasks[symbol].cancel()
346
  self.sentry_tasks[symbol] = asyncio.create_task(self._guardian_loop(symbol))
347
 
348
+ # 🔥 إطلاق مهمة التدقيق (Diagnostic Matrix)
349
+ model_votes = self._snapshot_model_votes(signal_data)
350
+ asyncio.create_task(self._run_diagnostic_verification(
351
+ symbol,
352
+ current_price,
353
+ approved_size_usd,
354
+ model_votes
355
+ ))
356
+
357
  print(f"✅ [ENTRY] {symbol} @ {current_price} | Grade: {gov_decision['grade']} | Size: ${approved_size_usd:.2f} | TP: {approved_tp} ({target_label}) | Mood: {market_mood}")
358
 
359
  except Exception as e:
 
520
 
521
  record = {"symbol": symbol, "exit_price": exit_price, "price_15m": curr, "usd_impact": usd_impact, "verdict": "SUCCESS" if is_good_exit else "MISS"}
522
  await self.r2.append_deep_steward_audit(record)
523
+
524
+ # 🔥 حفظ إحصائيات الحراس في R2 بعد التحديث
525
+ await self.r2.save_guardian_stats_async(self.ai_stats)
526
+
527
  except Exception: pass
528
 
529
  async def _execute_exit(self, symbol, price, reason, ai_scores=None):