Riy777 commited on
Commit
248cb64
·
verified ·
1 Parent(s): 490e43e

Update trade_manager.py

Browse files
Files changed (1) hide show
  1. trade_manager.py +13 -31
trade_manager.py CHANGED
@@ -1,10 +1,5 @@
1
  # ============================================================
2
- # 🛡️ trade_manager.py (V35.0 - GEM-Architect: Portfolio-Driven)
3
- # ============================================================
4
- # التغييرات الجوهرية:
5
- # 1. تم دمج SmartPortfolio كمدير حصري للمخاطر ورأس المال.
6
- # 2. إزالة القيود اليدوية لعدد الصفقات والاعتماد على منطق المحفظة.
7
- # 3. استخدام الثقة المركبة (Consensus) والمزاج العام في اتخاذ القرار.
8
  # ============================================================
9
 
10
  import asyncio
@@ -50,7 +45,7 @@ class TradeManager:
50
  }
51
 
52
  self.execution_lock = asyncio.Lock()
53
- print(f"🛡️ [TradeManager V35.0] Portfolio-Driven Engine Online.")
54
 
55
  async def initialize_sentry_exchanges(self):
56
  print("🛡️ [TradeManager] Syncing state & Initializing Portfolio...")
@@ -65,9 +60,7 @@ class TradeManager:
65
  print(f" -> [Sync] Recovered {len(self.open_positions)} active trades.")
66
 
67
  # 🔄 مزامنة رأس المال المحجوز مع المحفظة بناءً على الصفقات المستعادة
68
- # (خطوة احترازية لضمان دقة allocated_capital في حالة إعادة التشغيل)
69
  total_allocated = sum(float(t.get('entry_capital', 0.0)) for t in self.open_positions.values())
70
- # نحدث الحالة المحلية للمحفظة فقط (دون حفظ لتجنب الكتابة فوق القيمة الدقيقة إذا كانت موجودة)
71
  self.smart_portfolio.state["allocated_capital_usd"] = total_allocated
72
 
73
  except Exception as e:
@@ -108,9 +101,6 @@ class TradeManager:
108
  # 🎯 L4 Sniper Execution Logic
109
  # ==============================================================================
110
  async def select_and_execute_best_signal(self, oracle_approved_signals: List[Dict[str, Any]]):
111
- # ❌ حذفنا القيد اليدوي (if len > 0)
112
- # ✅ الاعتماد الآن كلياً على smart_portfolio.request_entry_approval
113
-
114
  if not self.processor.initialized:
115
  await self.processor.initialize()
116
 
@@ -168,7 +158,6 @@ class TradeManager:
168
  best_signal = sniper_candidates[0]
169
 
170
  async with self.execution_lock:
171
- # لم نعد نتحقق من عدد الصفقات هنا، نترك الأمر للمحفظة عند التنفيذ
172
  print(f"🚀 [EXECUTING] Attempting entry for best candidate: {best_signal['symbol']}")
173
  await self._execute_entry_from_signal(best_signal['symbol'], best_signal)
174
 
@@ -178,7 +167,6 @@ class TradeManager:
178
  async def _execute_entry_from_signal(self, symbol, signal_data):
179
  try:
180
  # 1. 💼 طلب الموافقة من المحفظة الذكية
181
- # نمرر عدد الصفقات المفتوحة حالياً لتطبيق قيود الـ Slots
182
  is_approved, plan = await self.smart_portfolio.request_entry_approval(
183
  signal_data,
184
  open_positions_count=len(self.open_positions)
@@ -220,7 +208,7 @@ class TradeManager:
220
  'direction': 'LONG',
221
  'entry_time': datetime.now().isoformat(),
222
  'status': 'OPEN',
223
- 'tp_price': approved_tp, # ✅ استخدام الهدف المعتمد من المحفظة
224
  'sl_price': sl_price,
225
  'last_update': datetime.now().isoformat(),
226
  'last_oracle_check': datetime.now().isoformat(),
@@ -230,15 +218,15 @@ class TradeManager:
230
  'initial_oracle_class': oracle_class,
231
  'oracle_tp_map': signal_data.get('tp_map', {}),
232
 
233
- 'entry_capital': approved_size_usd, # ✅ استخدام الحجم المعتمد من المحفظة
234
  'entry_fee_usd': entry_fee_usd,
235
  'l1_score': float(signal_data.get('enhanced_final_score', 0.0)),
236
  'target_class_int': target_class_int,
237
  'decision_data': {
238
  'components': signal_data.get('components', {}),
239
  'oracle_conf': signal_data.get('confidence', 0),
240
- 'system_confidence': system_conf, # ✅ تسجيل الثقة المركبة
241
- 'market_mood': market_mood # ✅ تسجيل حالة السوق
242
  },
243
  'highest_price': current_price
244
  }
@@ -249,7 +237,6 @@ class TradeManager:
249
  # 3. 📝 تسجيل الصفقة ف�� المحفظة (حجز رأس المال)
250
  await self.smart_portfolio.register_new_position(approved_size_usd)
251
 
252
- # تحديث timestamp لأول صفقة إذا لزم الأمر
253
  portfolio_state = await self.r2.get_portfolio_state_async()
254
  if portfolio_state.get('first_trade_timestamp') is None:
255
  portfolio_state['first_trade_timestamp'] = new_trade['entry_time']
@@ -311,12 +298,14 @@ class TradeManager:
311
  t5 = self.data_manager.get_latest_ohlcv(symbol, '5m', 300)
312
  t15 = self.data_manager.get_latest_ohlcv(symbol, '15m', 200)
313
 
 
 
 
314
  try:
315
- d1, d5, d15 = await asyncio.gather(t1, t5, t15)
316
  except:
317
  continue
318
 
319
- # التحقق من كفاية البيانات
320
  if d1 and d5 and d15 and len(d1) >= 200:
321
  context_data = {
322
  'entry_price': trade['entry_price'],
@@ -324,15 +313,15 @@ class TradeManager:
324
  'sl_price': trade['sl_price'],
325
  'entry_time': trade['entry_time'],
326
  'oracle_conf': trade.get('decision_data', {}).get('oracle_conf', 0.8),
327
- 'system_conf': trade.get('decision_data', {}).get('system_confidence', 0.8), # ✅ تمرير الثقة المركبة
328
  'l2_score': trade.get('l1_score', 0.7),
329
  'target_class_int': trade.get('target_class_int', 3),
330
  'highest_price': float(trade['highest_price']),
331
  'time_in_trade_mins': (datetime.now() - datetime.fromisoformat(trade['entry_time'])).total_seconds() / 60
332
  }
333
 
334
- # استشارة الحارس المزدوج
335
- decision = self.processor.consult_dual_guardians(symbol, d1, d5, d15, context_data)
336
 
337
  action = decision.get('action', 'HOLD')
338
  reason = decision.get('reason', '')
@@ -386,7 +375,6 @@ class TradeManager:
386
  await asyncio.sleep(5)
387
 
388
  async def _consult_oracle_strategy_update(self, symbol, trade):
389
- """Oracle V4 Strategy Update"""
390
  try:
391
  tasks = [self.data_manager.get_latest_ohlcv(symbol, tf, limit=100) for tf in ["15m", "1h", "4h"]]
392
  results = await asyncio.gather(*tasks)
@@ -489,7 +477,6 @@ class TradeManager:
489
  total_fees = entry_fee_usd + exit_fee_usd
490
 
491
  # 1. 💼 إبلاغ المحفظة الذكية لتحرير رأس المال وتحديث الرصيد
492
- # (تمرير PnL الصافي والرسوم للمحفظة لتدقيق الحسابات)
493
  await self.smart_portfolio.register_closed_position(entry_capital, net_pnl_usd, total_fees)
494
 
495
  trade.update({
@@ -502,11 +489,7 @@ class TradeManager:
502
  })
503
 
504
  # 2. 📊 تحديث الإحصائيات (Counters Only) في TradeManager
505
- # ملاحظة: نحدث العدادات فقط، ونترك للمحفظة إدارة current_capital_usd في R2
506
- # لتجنب تضارب الكتابة، نقرأ أحدث حالة (التي حدثتها المحفظة للتو)
507
  portfolio = await self.r2.get_portfolio_state_async()
508
-
509
- # نحدث العدادات فقط
510
  portfolio['total_trades'] = portfolio.get('total_trades', 0) + 1
511
  if net_pnl_usd >= 0:
512
  portfolio['winning_trades'] = portfolio.get('winning_trades', 0) + 1
@@ -517,7 +500,6 @@ class TradeManager:
517
  portfolio['total_loss_usd'] = portfolio.get('total_loss_usd', 0) + abs(net_pnl_usd)
518
  trade['result'] = 'LOSS'
519
 
520
- # نحفظ الحالة المحدثة (التي تحتوي على الرصيد الجديد من المحفظة + العدادات الجديدة منا)
521
  await self.r2.save_portfolio_state_async(portfolio)
522
  await self.r2.save_open_trades_async(list(self.open_positions.values()))
523
  await self.r2.append_to_closed_trades_history(trade)
 
1
  # ============================================================
2
+ # 🛡️ trade_manager.py (V35.1 - GEM-Architect: Portfolio-Driven & Muzzled Guardians)
 
 
 
 
 
3
  # ============================================================
4
 
5
  import asyncio
 
45
  }
46
 
47
  self.execution_lock = asyncio.Lock()
48
+ print(f"🛡️ [TradeManager V35.1] Portfolio-Driven Engine Online.")
49
 
50
  async def initialize_sentry_exchanges(self):
51
  print("🛡️ [TradeManager] Syncing state & Initializing Portfolio...")
 
60
  print(f" -> [Sync] Recovered {len(self.open_positions)} active trades.")
61
 
62
  # 🔄 مزامنة رأس المال المحجوز مع المحفظة بناءً على الصفقات المستعادة
 
63
  total_allocated = sum(float(t.get('entry_capital', 0.0)) for t in self.open_positions.values())
 
64
  self.smart_portfolio.state["allocated_capital_usd"] = total_allocated
65
 
66
  except Exception as e:
 
101
  # 🎯 L4 Sniper Execution Logic
102
  # ==============================================================================
103
  async def select_and_execute_best_signal(self, oracle_approved_signals: List[Dict[str, Any]]):
 
 
 
104
  if not self.processor.initialized:
105
  await self.processor.initialize()
106
 
 
158
  best_signal = sniper_candidates[0]
159
 
160
  async with self.execution_lock:
 
161
  print(f"🚀 [EXECUTING] Attempting entry for best candidate: {best_signal['symbol']}")
162
  await self._execute_entry_from_signal(best_signal['symbol'], best_signal)
163
 
 
167
  async def _execute_entry_from_signal(self, symbol, signal_data):
168
  try:
169
  # 1. 💼 طلب الموافقة من المحفظة الذكية
 
170
  is_approved, plan = await self.smart_portfolio.request_entry_approval(
171
  signal_data,
172
  open_positions_count=len(self.open_positions)
 
208
  'direction': 'LONG',
209
  'entry_time': datetime.now().isoformat(),
210
  'status': 'OPEN',
211
+ 'tp_price': approved_tp,
212
  'sl_price': sl_price,
213
  'last_update': datetime.now().isoformat(),
214
  'last_oracle_check': datetime.now().isoformat(),
 
218
  'initial_oracle_class': oracle_class,
219
  'oracle_tp_map': signal_data.get('tp_map', {}),
220
 
221
+ 'entry_capital': approved_size_usd,
222
  'entry_fee_usd': entry_fee_usd,
223
  'l1_score': float(signal_data.get('enhanced_final_score', 0.0)),
224
  'target_class_int': target_class_int,
225
  'decision_data': {
226
  'components': signal_data.get('components', {}),
227
  'oracle_conf': signal_data.get('confidence', 0),
228
+ 'system_confidence': system_conf,
229
+ 'market_mood': market_mood
230
  },
231
  'highest_price': current_price
232
  }
 
237
  # 3. 📝 تسجيل الصفقة ف�� المحفظة (حجز رأس المال)
238
  await self.smart_portfolio.register_new_position(approved_size_usd)
239
 
 
240
  portfolio_state = await self.r2.get_portfolio_state_async()
241
  if portfolio_state.get('first_trade_timestamp') is None:
242
  portfolio_state['first_trade_timestamp'] = new_trade['entry_time']
 
298
  t5 = self.data_manager.get_latest_ohlcv(symbol, '5m', 300)
299
  t15 = self.data_manager.get_latest_ohlcv(symbol, '15m', 200)
300
 
301
+ # ✅ GEM-Architect Update: Fetch Order Book for Validation
302
+ tob = self.data_manager.get_order_book_snapshot(symbol)
303
+
304
  try:
305
+ d1, d5, d15, d_ob = await asyncio.gather(t1, t5, t15, tob)
306
  except:
307
  continue
308
 
 
309
  if d1 and d5 and d15 and len(d1) >= 200:
310
  context_data = {
311
  'entry_price': trade['entry_price'],
 
313
  'sl_price': trade['sl_price'],
314
  'entry_time': trade['entry_time'],
315
  'oracle_conf': trade.get('decision_data', {}).get('oracle_conf', 0.8),
316
+ 'system_conf': trade.get('decision_data', {}).get('system_confidence', 0.8),
317
  'l2_score': trade.get('l1_score', 0.7),
318
  'target_class_int': trade.get('target_class_int', 3),
319
  'highest_price': float(trade['highest_price']),
320
  'time_in_trade_mins': (datetime.now() - datetime.fromisoformat(trade['entry_time'])).total_seconds() / 60
321
  }
322
 
323
+ # Pass order book (d_ob) to Processor
324
+ decision = self.processor.consult_dual_guardians(symbol, d1, d5, d15, context_data, order_book_snapshot=d_ob)
325
 
326
  action = decision.get('action', 'HOLD')
327
  reason = decision.get('reason', '')
 
375
  await asyncio.sleep(5)
376
 
377
  async def _consult_oracle_strategy_update(self, symbol, trade):
 
378
  try:
379
  tasks = [self.data_manager.get_latest_ohlcv(symbol, tf, limit=100) for tf in ["15m", "1h", "4h"]]
380
  results = await asyncio.gather(*tasks)
 
477
  total_fees = entry_fee_usd + exit_fee_usd
478
 
479
  # 1. 💼 إبلاغ المحفظة الذكية لتحرير رأس المال وتحديث الرصيد
 
480
  await self.smart_portfolio.register_closed_position(entry_capital, net_pnl_usd, total_fees)
481
 
482
  trade.update({
 
489
  })
490
 
491
  # 2. 📊 تحديث الإحصائيات (Counters Only) في TradeManager
 
 
492
  portfolio = await self.r2.get_portfolio_state_async()
 
 
493
  portfolio['total_trades'] = portfolio.get('total_trades', 0) + 1
494
  if net_pnl_usd >= 0:
495
  portfolio['winning_trades'] = portfolio.get('winning_trades', 0) + 1
 
500
  portfolio['total_loss_usd'] = portfolio.get('total_loss_usd', 0) + abs(net_pnl_usd)
501
  trade['result'] = 'LOSS'
502
 
 
503
  await self.r2.save_portfolio_state_async(portfolio)
504
  await self.r2.save_open_trades_async(list(self.open_positions.values()))
505
  await self.r2.append_to_closed_trades_history(trade)