Spaces:
Paused
Paused
Update trade_manager.py
Browse files- trade_manager.py +29 -11
trade_manager.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# trade_manager.py (V25.
|
| 2 |
|
| 3 |
import asyncio
|
| 4 |
import uuid
|
|
@@ -32,7 +32,7 @@ class TradeManager:
|
|
| 32 |
}
|
| 33 |
|
| 34 |
self.execution_lock = asyncio.Lock()
|
| 35 |
-
print(f"🛡️ [TradeManager V25.
|
| 36 |
|
| 37 |
async def initialize_sentry_exchanges(self):
|
| 38 |
print("🛡️ [TradeManager] Syncing state with R2...")
|
|
@@ -48,7 +48,7 @@ class TradeManager:
|
|
| 48 |
self.open_positions = {}
|
| 49 |
|
| 50 |
# ==============================================================================
|
| 51 |
-
# 🎯 L4 Sniper Execution Logic (
|
| 52 |
# ==============================================================================
|
| 53 |
async def select_and_execute_best_signal(self, oracle_approved_signals: List[Dict[str, Any]]):
|
| 54 |
if len(self.open_positions) > 0:
|
|
@@ -60,6 +60,8 @@ class TradeManager:
|
|
| 60 |
|
| 61 |
sniper_candidates = []
|
| 62 |
|
|
|
|
|
|
|
| 63 |
for signal in oracle_approved_signals:
|
| 64 |
symbol = signal['symbol']
|
| 65 |
|
|
@@ -75,25 +77,40 @@ class TradeManager:
|
|
| 75 |
ohlcv_1m, order_book = await asyncio.gather(ohlcv_task, ob_task)
|
| 76 |
|
| 77 |
if not ohlcv_1m or len(ohlcv_1m) < 100:
|
| 78 |
-
print(f" ->
|
| 79 |
continue
|
| 80 |
|
| 81 |
-
# 2. استشارة القناص
|
| 82 |
-
# نمرر له
|
| 83 |
sniper_result = await self.processor.check_sniper_entry(ohlcv_1m, order_book)
|
| 84 |
|
| 85 |
sniper_signal = sniper_result.get('signal', 'WAIT')
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
-
#
|
| 89 |
-
|
| 90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
signal['sniper_entry_price'] = sniper_result.get('entry_price', 0)
|
| 93 |
-
signal['sniper_score'] =
|
| 94 |
sniper_candidates.append(signal)
|
|
|
|
|
|
|
|
|
|
| 95 |
|
| 96 |
if not sniper_candidates:
|
|
|
|
| 97 |
return
|
| 98 |
|
| 99 |
# ترتيب حسب قوة Oracle + قوة القناص
|
|
@@ -106,6 +123,7 @@ class TradeManager:
|
|
| 106 |
|
| 107 |
async with self.execution_lock:
|
| 108 |
if len(self.open_positions) == 0:
|
|
|
|
| 109 |
await self._execute_entry_from_signal(best_signal['symbol'], best_signal)
|
| 110 |
|
| 111 |
# ==============================================================================
|
|
|
|
| 1 |
+
# trade_manager.py (V25.3 - GEM-Architect: Separation of Concerns Edition)
|
| 2 |
|
| 3 |
import asyncio
|
| 4 |
import uuid
|
|
|
|
| 32 |
}
|
| 33 |
|
| 34 |
self.execution_lock = asyncio.Lock()
|
| 35 |
+
print(f"🛡️ [TradeManager V25.3] Full Spot Commander Initialized.")
|
| 36 |
|
| 37 |
async def initialize_sentry_exchanges(self):
|
| 38 |
print("🛡️ [TradeManager] Syncing state with R2...")
|
|
|
|
| 48 |
self.open_positions = {}
|
| 49 |
|
| 50 |
# ==============================================================================
|
| 51 |
+
# 🎯 L4 Sniper Execution Logic (Authority Delegated to Engine)
|
| 52 |
# ==============================================================================
|
| 53 |
async def select_and_execute_best_signal(self, oracle_approved_signals: List[Dict[str, Any]]):
|
| 54 |
if len(self.open_positions) > 0:
|
|
|
|
| 60 |
|
| 61 |
sniper_candidates = []
|
| 62 |
|
| 63 |
+
print(f"\n🔎 [Sniper] Scanning {len(oracle_approved_signals)} candidates...")
|
| 64 |
+
|
| 65 |
for signal in oracle_approved_signals:
|
| 66 |
symbol = signal['symbol']
|
| 67 |
|
|
|
|
| 77 |
ohlcv_1m, order_book = await asyncio.gather(ohlcv_task, ob_task)
|
| 78 |
|
| 79 |
if not ohlcv_1m or len(ohlcv_1m) < 100:
|
| 80 |
+
print(f" -> ⚠️ [Skip] {symbol}: Insufficient 1m data.")
|
| 81 |
continue
|
| 82 |
|
| 83 |
+
# 2. استشارة القناص (هو من يمتلك القرار والعتبة)
|
| 84 |
+
# نمرر له البيانات وننتظر الحكم (BUY/WAIT) + التفاصيل
|
| 85 |
sniper_result = await self.processor.check_sniper_entry(ohlcv_1m, order_book)
|
| 86 |
|
| 87 |
sniper_signal = sniper_result.get('signal', 'WAIT')
|
| 88 |
+
final_conf = sniper_result.get('confidence_prob', 0.0)
|
| 89 |
+
|
| 90 |
+
# استخراج التفاصيل للسجلات (الشفافية الكاملة)
|
| 91 |
+
ml_score = sniper_result.get('ml_score', 0.0)
|
| 92 |
+
ob_score = sniper_result.get('ob_score', 0.0)
|
| 93 |
+
reason = sniper_result.get('reason', 'N/A')
|
| 94 |
|
| 95 |
+
# طباعة السجل المفصل الذي طلبته
|
| 96 |
+
log_msg = (f" -> 🔭 {symbol:<6} | Decision: {sniper_signal} | Score: {final_conf:.2f} "
|
| 97 |
+
f"(ML:{ml_score:.2f} + OB:{ob_score:.2f})")
|
| 98 |
+
print(log_msg)
|
| 99 |
+
|
| 100 |
+
# 3. التحقق من التوافق (طاعة عمياء للمحرك)
|
| 101 |
+
# لم نعد نفحص أي أرقام هنا، المحرك قام بذلك بالفعل
|
| 102 |
+
if sniper_signal == 'BUY':
|
| 103 |
+
print(f" ✅ [ACCEPTED] {symbol} approved by Sniper Engine.")
|
| 104 |
|
| 105 |
signal['sniper_entry_price'] = sniper_result.get('entry_price', 0)
|
| 106 |
+
signal['sniper_score'] = final_conf
|
| 107 |
sniper_candidates.append(signal)
|
| 108 |
+
else:
|
| 109 |
+
# فقط نوضح سبب الرفض في حال أراد المستخدم المراجعة
|
| 110 |
+
pass # الرسالة السابقة تكفي (Decision: WAIT)
|
| 111 |
|
| 112 |
if not sniper_candidates:
|
| 113 |
+
print(" -> 📉 No candidates passed the Sniper L4 check.")
|
| 114 |
return
|
| 115 |
|
| 116 |
# ترتيب حسب قوة Oracle + قوة القناص
|
|
|
|
| 123 |
|
| 124 |
async with self.execution_lock:
|
| 125 |
if len(self.open_positions) == 0:
|
| 126 |
+
print(f"🚀 [EXECUTING] Entering best candidate: {best_signal['symbol']}")
|
| 127 |
await self._execute_entry_from_signal(best_signal['symbol'], best_signal)
|
| 128 |
|
| 129 |
# ==============================================================================
|