Riy777 commited on
Commit
95d9ce3
·
1 Parent(s): 64e24d8

Update trade_manager.py

Browse files
Files changed (1) hide show
  1. trade_manager.py +77 -35
trade_manager.py CHANGED
@@ -1,4 +1,4 @@
1
- # trade_manager.py (Updated to V7.1 - 4-Factor Trigger & 5m Logger)
2
  import asyncio
3
  import json
4
  import time
@@ -442,7 +442,7 @@ class TradeManager:
442
 
443
 
444
  async def _run_tactical_analysis_loop(self, symbol: str, strategy_hint: str):
445
- """(محدث V7.1) (دماغ الحارس) يشغل التحليل التكتيكي كل ثانية."""
446
  while self.is_running:
447
  await asyncio.sleep(1)
448
  try:
@@ -459,19 +459,21 @@ class TradeManager:
459
 
460
  # 2. إذا لم يتم ضرب SL/TP، تحقق من "مراقب حماية الأرباح" 5m
461
  if not exit_reason and tactical_data.new_5m_data_added:
462
- # 🔴 --- START OF CHANGE (V7.1) --- 🔴
463
- # (تعديل لاستقبال النتيجة والطباعة)
464
  analysis_result = await self._run_5m_profit_saver(trade, list(tactical_data.ohlcv_5m), tactical_data)
465
  tactical_data.new_5m_data_added = False # (إعادة ضبط المؤشر)
466
 
467
  if analysis_result:
 
468
  score = analysis_result.get("score", 0)
469
- threshold = analysis_result.get("threshold", 0.8)
470
- if analysis_result.get("decision") == "EXIT":
471
- exit_reason = f"Tactical 5m Profit Save: Reversal Score {score:.2f} >= {threshold}"
 
472
  else:
473
- # (هذه هي الطباعة المطلوبة للشفافية)
474
- print(f" [Sentry 5m] {symbol} (Profit-Saver): HOLD. Reversal Score: {score:.2f} (Threshold: {threshold})")
475
  # 🔴 --- END OF CHANGE --- 🔴
476
 
477
  if exit_reason:
@@ -617,29 +619,31 @@ class TradeManager:
617
  except Exception:
618
  return pd.DataFrame()
619
 
620
- # 🔴 --- START OF CHANGE (V7.1) --- 🔴
621
  async def _run_5m_profit_saver(self, trade: Dict, ohlcv_5m_list: List, tactical_data: TacticalData) -> Dict:
622
  """
623
- (محدث V7.1) "مراقب الانعكاس" 5m.
624
- يُرجع قاموساً بالنتيجة والقرار.
 
 
625
  """
626
- reversal_threshold = 0.8 # (عتبة الخروج)
627
 
628
  try:
629
- # --- 1. التحقق من الربحية (كما طلبت) ---
630
  best_bid_price = None
631
  if tactical_data.order_book and tactical_data.order_book.get('bids') and len(tactical_data.order_book['bids']) > 0:
632
  best_bid_price = tactical_data.order_book['bids'][0][0]
633
 
634
  if best_bid_price is None:
635
- return None # لا يمكن تحديد السعر
636
 
637
  entry_price = trade.get('entry_price')
638
- if best_bid_price <= entry_price:
639
- return {"decision": "HOLD", "score": 0.0, "threshold": reversal_threshold, "reason": "Trade not profitable"}
640
 
641
- # --- 2. الصفقة رابحة، تشغيل الكاشف 5m ---
642
- if len(ohlcv_5m_list) < 20:
 
643
  return None # بيانات غير كافية للتحليل
644
 
645
  df_5m = self._create_dataframe_5m(ohlcv_5m_list)
@@ -649,32 +653,70 @@ class TradeManager:
649
  indicators_5m = self.sentry_technical_analyzer.calculate_all_indicators(df_5m, '5m')
650
  pattern_analysis_5m = await self.sentry_pattern_analyzer.detect_chart_patterns({'5m': ohlcv_5m_list})
651
 
652
- # --- 3. حساب درجة الانعكاس (Reversal Score) ---
653
- reversal_score = 0.0
 
 
 
 
 
 
654
 
 
 
655
  pattern_name = pattern_analysis_5m.get('pattern_detected', '')
656
  pattern_conf = pattern_analysis_5m.get('pattern_confidence', 0)
657
- if pattern_name in ['Double Top', 'Downtrend', 'Breakout Down', 'Near Resistance'] and pattern_conf > 0.6:
658
- reversal_score += 0.5
659
-
 
 
 
660
  rsi_5m = indicators_5m.get('rsi', 50)
 
 
 
 
 
 
 
661
  macd_hist_5m = indicators_5m.get('macd_hist', 0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
 
663
- if rsi_5m < 45 and macd_hist_5m < 0:
664
- reversal_score += 0.5
665
- elif rsi_5m < 60 and macd_hist_5m < 0:
666
- reversal_score += 0.3
667
-
668
- # --- 4. القرار ---
669
  if reversal_score >= reversal_threshold:
670
- return {"decision": "EXIT", "score": reversal_score, "threshold": reversal_threshold, "reason": "Reversal signal detected"}
 
 
 
 
 
 
671
  else:
672
- return {"decision": "HOLD", "score": reversal_score, "threshold": reversal_threshold, "reason": "Trend intact"}
 
673
 
674
  except Exception as e:
675
  print(f"❌ [Sentry] خطأ في مراقب حماية الأرباح 5m: {e}")
676
- return None
677
- # 🔴 --- END OF CHANGE --- 🔴
 
678
 
679
 
680
  async def _execute_smart_entry(self, symbol: str, strategy_hint: str, tactical_data: Dict, explorer_context: Dict):
@@ -939,4 +981,4 @@ class TradeManager:
939
  except Exception as e: print(f"❌ Failed to get trade by symbol {symbol}: {e}"); return None
940
 
941
 
942
- print(f"✅ Trade Manager loaded - V7.1 (4-Factor Trigger + 5m Profit-Saver Logger) (ccxt.async_support: {CCXT_ASYNC_AVAILABLE})")
 
1
+ # trade_manager.py (Updated to V7.2 - Fixed 5m Profit-Saver Logic)
2
  import asyncio
3
  import json
4
  import time
 
442
 
443
 
444
  async def _run_tactical_analysis_loop(self, symbol: str, strategy_hint: str):
445
+ """(محدث V7.2) (دماغ الحارس) يشغل التحليل التكتيكي كل ثانية."""
446
  while self.is_running:
447
  await asyncio.sleep(1)
448
  try:
 
459
 
460
  # 2. إذا لم يتم ضرب SL/TP، تحقق من "مراقب حماية الأرباح" 5m
461
  if not exit_reason and tactical_data.new_5m_data_added:
462
+ # 🔴 --- START OF CHANGE (V7.2) --- 🔴
463
+ # (تعديل لاستيعاب المنطق الجديد لحامي الأرباح)
464
  analysis_result = await self._run_5m_profit_saver(trade, list(tactical_data.ohlcv_5m), tactical_data)
465
  tactical_data.new_5m_data_added = False # (إعادة ضبط المؤشر)
466
 
467
  if analysis_result:
468
+ decision = analysis_result.get("decision")
469
  score = analysis_result.get("score", 0)
470
+ reason = analysis_result.get("reason", "N/A")
471
+
472
+ if decision == "EXIT":
473
+ exit_reason = f"Tactical 5m Profit Save: {reason} (Score: {score:.2f})"
474
  else:
475
+ # (طباعة تشخيصية أفضل)
476
+ print(f" [Sentry 5m] {symbol} (Profit-Saver): {decision}. {reason} (Score: {score:.2f})")
477
  # 🔴 --- END OF CHANGE --- 🔴
478
 
479
  if exit_reason:
 
619
  except Exception:
620
  return pd.DataFrame()
621
 
622
+ # 🔴 --- START OF CHANGE (V7.2 - Logic Fix) --- 🔴
623
  async def _run_5m_profit_saver(self, trade: Dict, ohlcv_5m_list: List, tactical_data: TacticalData) -> Dict:
624
  """
625
+ (محدث V7.2) "مراقب الانعكاس" 5m.
626
+ - يحسب درجة الخطر دائماً.
627
+ - يستخدم نظام تسجيل مرن وموزون.
628
+ - لا يخرج إلا إذا كان الخطر مرتفعاً *و* الصفقة رابحة.
629
  """
630
+ reversal_threshold = 0.70 # (عتبة خروج مرنة للنظام الموزون)
631
 
632
  try:
633
+ # --- 1. التحقق من السعر الحالي وحالة الربحية (سنستخدمها في النهاية) ---
634
  best_bid_price = None
635
  if tactical_data.order_book and tactical_data.order_book.get('bids') and len(tactical_data.order_book['bids']) > 0:
636
  best_bid_price = tactical_data.order_book['bids'][0][0]
637
 
638
  if best_bid_price is None:
639
+ return None # لا يمكن تحديد السعر، لا يمكن المتابعة
640
 
641
  entry_price = trade.get('entry_price')
642
+ is_profitable = best_bid_price > entry_price
 
643
 
644
+ # --- 2. تشغيل الكاشف 5m (يجب أن يعمل دائماً لحساب الخطر) ---
645
+ # (يتطلب 26 شمعة على الأقل لـ MACD)
646
+ if len(ohlcv_5m_list) < 26:
647
  return None # بيانات غير كافية للتحليل
648
 
649
  df_5m = self._create_dataframe_5m(ohlcv_5m_list)
 
653
  indicators_5m = self.sentry_technical_analyzer.calculate_all_indicators(df_5m, '5m')
654
  pattern_analysis_5m = await self.sentry_pattern_analyzer.detect_chart_patterns({'5m': ohlcv_5m_list})
655
 
656
+ # --- 3. حساب درجة الانعكاس (Reversal Score) - نظام مرن وموزون ---
657
+
658
+ # الأوزان
659
+ weights = {
660
+ 'pattern': 0.40,
661
+ 'rsi': 0.30,
662
+ 'macd': 0.30
663
+ }
664
 
665
+ # الدرجة 1: الأنماط (Patterns)
666
+ pattern_score = 0.0
667
  pattern_name = pattern_analysis_5m.get('pattern_detected', '')
668
  pattern_conf = pattern_analysis_5m.get('pattern_confidence', 0)
669
+ # (الأنماط السلبية فقط تساهم في خطر الانعكاس)
670
+ if pattern_name in ['Double Top', 'Downtrend', 'Breakout Down', 'Near Resistance'] and pattern_conf > 0.5:
671
+ pattern_score = pattern_conf # (استخدام الثقة مباشرة كدرجة)
672
+
673
+ # الدرجة 2: مؤشر القوة النسبية (RSI) - درجة متدرجة
674
+ rsi_score = 0.0
675
  rsi_5m = indicators_5m.get('rsi', 50)
676
+ if rsi_5m < 50:
677
+ # (كلما انخفض تحت 50، زادت درجة الخطر، تصل إلى 1.0 عند 30 أو أقل)
678
+ # (النطاق: 50 -> 30)
679
+ rsi_score = min(1.0, (50 - rsi_5m) / 20.0)
680
+
681
+ # الدرجة 3: الماكد (MACD) - درجة متدرجة
682
+ macd_score = 0.0
683
  macd_hist_5m = indicators_5m.get('macd_hist', 0)
684
+ if macd_hist_5m < 0:
685
+ # (نحتاج إلى "تطبيع" قيمة الهيستوجرام. سنستخدم نسبة مئوية من السعر)
686
+ current_price = df_5m['close'].iloc[-1]
687
+ if current_price > 0:
688
+ normalized_macd_hist = abs(macd_hist_5m) / current_price
689
+ # (تقدير: إذا كان الهيستوجرام سلبي بنسبة 0.1% من السعر، فهذا خطر 100%)
690
+ # (النطاق: 0 -> 0.001)
691
+ macd_score = min(1.0, normalized_macd_hist / 0.001)
692
+
693
+ # الحساب النهائي للدرجة
694
+ reversal_score = (
695
+ (pattern_score * weights['pattern']) +
696
+ (rsi_score * weights['rsi']) +
697
+ (macd_score * weights['macd'])
698
+ )
699
 
700
+ # --- 4. القرار (المنطق الجديد) ---
701
+
702
+ # (التحقق من زناد الخروج)
 
 
 
703
  if reversal_score >= reversal_threshold:
704
+ # (الخطر مرتفع. هل الصفقة رابحة؟)
705
+ if is_profitable:
706
+ # (نعم، الخطر مرتفع والصفقة رابحة -> اخرج!)
707
+ return {"decision": "EXIT", "score": reversal_score, "threshold": reversal_threshold, "reason": "Reversal signal detected and trade is profitable"}
708
+ else:
709
+ # (الخطر مرتفع، لكن الصفقة خاسرة/متعادلة -> لا تخرج، فقط سجل)
710
+ return {"decision": "HOLD", "score": reversal_score, "threshold": reversal_threshold, "reason": "Reversal signal detected, but trade is not profitable"}
711
  else:
712
+ # (الخطر منخفض -> لا تخرج)
713
+ return {"decision": "HOLD", "score": reversal_score, "threshold": reversal_threshold, "reason": "Trend intact / Reversal score low"}
714
 
715
  except Exception as e:
716
  print(f"❌ [Sentry] خطأ في مراقب حماية الأرباح 5m: {e}")
717
+ # (إرجاع نتيجة آمنة)
718
+ return {"decision": "HOLD", "score": 0.0, "threshold": reversal_threshold, "reason": f"Error in 5m analysis: {e}"}
719
+ # 🔴 --- END OF CHANGE (V7.2) --- 🔴
720
 
721
 
722
  async def _execute_smart_entry(self, symbol: str, strategy_hint: str, tactical_data: Dict, explorer_context: Dict):
 
981
  except Exception as e: print(f"❌ Failed to get trade by symbol {symbol}: {e}"); return None
982
 
983
 
984
+ print(f"✅ Trade Manager loaded - V7.2 (Fixed 5m Profit-Saver Logic) (ccxt.async_support: {CCXT_ASYNC_AVAILABLE})")