Spaces:
Paused
Paused
Update trade_manager.py
Browse files- trade_manager.py +30 -30
trade_manager.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# trade_manager.py (
|
| 2 |
import asyncio
|
| 3 |
import json
|
| 4 |
import uuid
|
|
@@ -13,12 +13,12 @@ class TradeManager:
|
|
| 13 |
self.titan = titan_engine
|
| 14 |
self.pattern_engine = pattern_engine
|
| 15 |
|
| 16 |
-
# ⚠️ GuardEngine (Old
|
| 17 |
self.guard = guard_engine
|
| 18 |
|
| 19 |
self.sniper = sniper_engine
|
| 20 |
|
| 21 |
-
# [
|
| 22 |
self.deep_steward = deep_steward
|
| 23 |
|
| 24 |
self.open_positions = {}
|
|
@@ -26,29 +26,26 @@ class TradeManager:
|
|
| 26 |
self.sentry_tasks = {}
|
| 27 |
self.running = True
|
| 28 |
|
| 29 |
-
# [
|
| 30 |
self.ds_stats = {
|
| 31 |
"total_exits": 0,
|
| 32 |
"good_exits": 0, # السعر هبط بعد الخروج (حمانا)
|
| 33 |
"bad_exits": 0, # السعر صعد بعد الخروج (فوتنا ربح)
|
| 34 |
"saved_loss_cum": 0.0, # مجموع نسبة الخسائر التي تجنبناها
|
| 35 |
"missed_profit_cum": 0.0, # مجموع نسبة الأرباح التي فوتناها
|
| 36 |
-
"saved_loss_usd_cum": 0.0, #
|
| 37 |
-
"missed_profit_usd_cum": 0.0 #
|
| 38 |
}
|
| 39 |
|
| 40 |
self.execution_lock = asyncio.Lock()
|
| 41 |
|
| 42 |
-
print(f"🛡️ [TradeManager
|
| 43 |
|
| 44 |
if self.deep_steward:
|
| 45 |
print(f" -> 🧠 DeepSteward V2 (Multi-Scale) ACTIVE. Taking full control.")
|
| 46 |
else:
|
| 47 |
print(f" -> ⚠️ DeepSteward NOT AVAILABLE. Reverting to basic limits.")
|
| 48 |
|
| 49 |
-
if self.sniper:
|
| 50 |
-
print(f" -> 🎯 Sniper V3 (Entry Sniper) CREATED.")
|
| 51 |
-
|
| 52 |
async def initialize_sentry_exchanges(self):
|
| 53 |
print("🛡️ [TradeManager] Initializing and syncing state with R2...")
|
| 54 |
await self.sync_internal_state_with_r2()
|
|
@@ -138,10 +135,6 @@ class TradeManager:
|
|
| 138 |
|
| 139 |
await self._execute_entry_from_signal(best_signal['symbol'], best_signal)
|
| 140 |
|
| 141 |
-
async def _handle_new_signal(self, symbol, signal_data):
|
| 142 |
-
print(f"⚠️ [TradeManager] _handle_new_signal (Legacy) called for {symbol}. Redirecting to Batch Select Logic...")
|
| 143 |
-
await self.select_and_execute_best_signal([signal_data])
|
| 144 |
-
|
| 145 |
# ==============================================================================
|
| 146 |
# 🎯 تنفيذ الدخول (Entry Execution)
|
| 147 |
# ==============================================================================
|
|
@@ -204,6 +197,16 @@ class TradeManager:
|
|
| 204 |
print(f" -> [Watchlist] مسح {len(self.watchlist)} عنصر من قائمة المراقبة.")
|
| 205 |
self.watchlist.clear()
|
| 206 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
await self.r2.save_open_trades_async(list(self.open_positions.values()))
|
| 208 |
|
| 209 |
if symbol in self.sentry_tasks:
|
|
@@ -266,14 +269,14 @@ class TradeManager:
|
|
| 266 |
await self.select_and_execute_best_signal(signals_from_watchlist)
|
| 267 |
|
| 268 |
# ==============================================================================
|
| 269 |
-
# 🛡️ دوال حارس الخروج (Sentry & Guard) - [
|
| 270 |
# ==============================================================================
|
| 271 |
async def _guardian_loop(self, symbol: str):
|
| 272 |
print(f"🛡️ [Sentry Activated] بدء الحراسة لـ {symbol} (فحص كل 60 ثانية).")
|
| 273 |
|
| 274 |
while self.running and symbol in self.open_positions:
|
| 275 |
try:
|
| 276 |
-
# 🚀 1. الانتظار لمدة 60 ثانية (V2
|
| 277 |
await asyncio.sleep(60)
|
| 278 |
|
| 279 |
trade = self.open_positions.get(symbol)
|
|
@@ -295,12 +298,12 @@ class TradeManager:
|
|
| 295 |
await self._execute_exit(symbol, current_price, "SL_HIT_HARD")
|
| 296 |
break
|
| 297 |
|
| 298 |
-
# 🚀 3. [
|
| 299 |
# النموذج الجديد يحتاج لثلاثة أطر زمنية: 1m, 5m, 15m
|
| 300 |
|
| 301 |
if self.deep_steward and self.deep_steward.initialized:
|
| 302 |
# جلب البيانات بشكل متوازي
|
| 303 |
-
task1 = self.data_manager.get_latest_ohlcv(symbol, '1m', 120) # احتياطي
|
| 304 |
task5 = self.data_manager.get_latest_ohlcv(symbol, '5m', 100)
|
| 305 |
task15 = self.data_manager.get_latest_ohlcv(symbol, '15m', 50)
|
| 306 |
|
|
@@ -310,16 +313,13 @@ class TradeManager:
|
|
| 310 |
if d1 and d5 and d15 and len(d1) >= 60 and len(d5) >= 30 and len(d15) >= 20:
|
| 311 |
decision = self.deep_steward.analyze(d1, d5, d15)
|
| 312 |
|
| 313 |
-
# سجل نبض خفيف
|
| 314 |
-
# print(f"🧠 [DeepSteward V2] {symbol} | Action: {decision['action']} | Conf: {decision['confidence']:.1%}")
|
| 315 |
-
|
| 316 |
if decision['action'] == 'EXIT':
|
| 317 |
print(f"🤖 [DeepSteward V2] 🚨 أمر خروج طارئ لـ {symbol}! ({decision['reason']})")
|
| 318 |
async with self.execution_lock:
|
| 319 |
await self._execute_exit(symbol, current_price, "DEEP_STEWARD_V2_EXIT")
|
| 320 |
break
|
| 321 |
else:
|
| 322 |
-
print(f"⚠️ [Sentry] بيانات V2 غير مكتملة لـ {symbol}.")
|
| 323 |
else:
|
| 324 |
pass # لا يوجد نموذج فعال
|
| 325 |
|
|
@@ -333,10 +333,10 @@ class TradeManager:
|
|
| 333 |
await asyncio.sleep(10)
|
| 334 |
|
| 335 |
# ==============================================================================
|
| 336 |
-
# 👻 المراقب الشبحي (Ghost Monitor) - Post-Exit Analysis
|
| 337 |
# ==============================================================================
|
| 338 |
def _launch_post_exit_analysis(self, symbol, exit_price, exit_time, position_size_usd):
|
| 339 |
-
"""يطلق مهمة خلفية لمراقبة السعر بعد الخروج"""
|
| 340 |
asyncio.create_task(self._analyze_after_exit_task(symbol, exit_price, exit_time, position_size_usd))
|
| 341 |
|
| 342 |
async def _analyze_after_exit_task(self, symbol, exit_price, exit_time, position_size_usd):
|
|
@@ -350,11 +350,10 @@ class TradeManager:
|
|
| 350 |
# حساب الفرق: (السعر الحالي - سعر الخروج) / سعر الخروج
|
| 351 |
change_pct = (current_price - exit_price) / exit_price
|
| 352 |
|
| 353 |
-
# حساب الأثر بالدولار
|
| 354 |
usd_impact = change_pct * position_size_usd
|
| 355 |
|
| 356 |
-
# تصنيف
|
| 357 |
-
# إذا هبط السعر (change_pct < 0) -> قرار جيد (حمانا)
|
| 358 |
is_good_exit = change_pct < 0
|
| 359 |
|
| 360 |
# تحديث الإحصائيات الحية (للوحة التحكم)
|
|
@@ -381,7 +380,7 @@ class TradeManager:
|
|
| 381 |
}
|
| 382 |
|
| 383 |
await self.r2.append_deep_steward_audit(audit_record)
|
| 384 |
-
print(f"👻 [Ghost Monitor] {symbol}: بعد ساعة {change_pct*100:+.2f}% | الحكم: {audit_record['verdict']}")
|
| 385 |
|
| 386 |
except Exception as e:
|
| 387 |
print(f"⚠️ [Ghost Error] فشل تحليل ما بعد الخروج لـ {symbol}: {e}")
|
|
@@ -414,6 +413,7 @@ class TradeManager:
|
|
| 414 |
|
| 415 |
# 4. 💰 [المحاسبة] تحديث المحفظة وحساب PnL بالدولار
|
| 416 |
portfolio = await self.r2.get_portfolio_state_async()
|
|
|
|
| 417 |
current_capital = float(portfolio.get('current_capital_usd', 100.0))
|
| 418 |
|
| 419 |
# حساب الربح بالدولار
|
|
@@ -447,9 +447,9 @@ class TradeManager:
|
|
| 447 |
|
| 448 |
print(f"✅ [EXIT EXECUTED] {symbol} | Reason: {reason} | PnL: {profit_pct_display:.2f}% (${pnl_usd:.2f}) | New Cap: ${new_capital:.2f}")
|
| 449 |
|
| 450 |
-
# 6. [
|
| 451 |
if "DEEP_STEWARD" in reason:
|
| 452 |
-
#
|
| 453 |
self._launch_post_exit_analysis(symbol, exit_price, trade['exit_time'], current_capital)
|
| 454 |
|
| 455 |
# 7. تنظيف مهام الحارس
|
|
|
|
| 1 |
+
# trade_manager.py (V20.0 - GEM-Architect: Final Production - V2/USD/Timers)
|
| 2 |
import asyncio
|
| 3 |
import json
|
| 4 |
import uuid
|
|
|
|
| 13 |
self.titan = titan_engine
|
| 14 |
self.pattern_engine = pattern_engine
|
| 15 |
|
| 16 |
+
# ⚠️ GuardEngine (Old V1) - معطل تماماً وتم استبداله بـ V2
|
| 17 |
self.guard = guard_engine
|
| 18 |
|
| 19 |
self.sniper = sniper_engine
|
| 20 |
|
| 21 |
+
# [ 🧠 ] DeepSteward V2 - The Multi-Scale Boss
|
| 22 |
self.deep_steward = deep_steward
|
| 23 |
|
| 24 |
self.open_positions = {}
|
|
|
|
| 26 |
self.sentry_tasks = {}
|
| 27 |
self.running = True
|
| 28 |
|
| 29 |
+
# [ 🧠 IQ Stats ] إحصائيات الذكاء الاصطناعي (مع الدولار)
|
| 30 |
self.ds_stats = {
|
| 31 |
"total_exits": 0,
|
| 32 |
"good_exits": 0, # السعر هبط بعد الخروج (حمانا)
|
| 33 |
"bad_exits": 0, # السعر صعد بعد الخروج (فوتنا ربح)
|
| 34 |
"saved_loss_cum": 0.0, # مجموع نسبة الخسائر التي تجنبناها
|
| 35 |
"missed_profit_cum": 0.0, # مجموع نسبة الأرباح التي فوتناها
|
| 36 |
+
"saved_loss_usd_cum": 0.0, # مجموع الدولارات التي حمانا منها
|
| 37 |
+
"missed_profit_usd_cum": 0.0 # مجموع الدولارات الضائعة
|
| 38 |
}
|
| 39 |
|
| 40 |
self.execution_lock = asyncio.Lock()
|
| 41 |
|
| 42 |
+
print(f"🛡️ [TradeManager V20.0] Initialized. Guardian Interval: 1 Minute (V2 Speed).")
|
| 43 |
|
| 44 |
if self.deep_steward:
|
| 45 |
print(f" -> 🧠 DeepSteward V2 (Multi-Scale) ACTIVE. Taking full control.")
|
| 46 |
else:
|
| 47 |
print(f" -> ⚠️ DeepSteward NOT AVAILABLE. Reverting to basic limits.")
|
| 48 |
|
|
|
|
|
|
|
|
|
|
| 49 |
async def initialize_sentry_exchanges(self):
|
| 50 |
print("🛡️ [TradeManager] Initializing and syncing state with R2...")
|
| 51 |
await self.sync_internal_state_with_r2()
|
|
|
|
| 135 |
|
| 136 |
await self._execute_entry_from_signal(best_signal['symbol'], best_signal)
|
| 137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
# ==============================================================================
|
| 139 |
# 🎯 تنفيذ الدخول (Entry Execution)
|
| 140 |
# ==============================================================================
|
|
|
|
| 197 |
print(f" -> [Watchlist] مسح {len(self.watchlist)} عنصر من قائمة المراقبة.")
|
| 198 |
self.watchlist.clear()
|
| 199 |
|
| 200 |
+
# ============================================================
|
| 201 |
+
# 🕒 [جديد] تسجيل وقت أول صفقة في تاريخ النظام (للعداد)
|
| 202 |
+
# ============================================================
|
| 203 |
+
portfolio = await self.r2.get_portfolio_state_async()
|
| 204 |
+
if portfolio.get('first_trade_timestamp') is None:
|
| 205 |
+
portfolio['first_trade_timestamp'] = new_trade['entry_time']
|
| 206 |
+
await self.r2.save_portfolio_state_async(portfolio)
|
| 207 |
+
print(f"🕒 [System Info] تم تسجيل توقيت أول صفقة في النظام: {new_trade['entry_time']}")
|
| 208 |
+
# ============================================================
|
| 209 |
+
|
| 210 |
await self.r2.save_open_trades_async(list(self.open_positions.values()))
|
| 211 |
|
| 212 |
if symbol in self.sentry_tasks:
|
|
|
|
| 269 |
await self.select_and_execute_best_signal(signals_from_watchlist)
|
| 270 |
|
| 271 |
# ==============================================================================
|
| 272 |
+
# 🛡️ دوال حارس الخروج (Sentry & Guard) - [V2: كل 1 دقيقة]
|
| 273 |
# ==============================================================================
|
| 274 |
async def _guardian_loop(self, symbol: str):
|
| 275 |
print(f"🛡️ [Sentry Activated] بدء الحراسة لـ {symbol} (فحص كل 60 ثانية).")
|
| 276 |
|
| 277 |
while self.running and symbol in self.open_positions:
|
| 278 |
try:
|
| 279 |
+
# 🚀 1. الانتظار لمدة 60 ثانية (V2 يعمل بدقة دقيقة)
|
| 280 |
await asyncio.sleep(60)
|
| 281 |
|
| 282 |
trade = self.open_positions.get(symbol)
|
|
|
|
| 298 |
await self._execute_exit(symbol, current_price, "SL_HIT_HARD")
|
| 299 |
break
|
| 300 |
|
| 301 |
+
# 🚀 3. [ 🧠 ] DeepSteward V2 (Multi-Scale Logic)
|
| 302 |
# النموذج الجديد يحتاج لثلاثة أطر زمنية: 1m, 5m, 15m
|
| 303 |
|
| 304 |
if self.deep_steward and self.deep_steward.initialized:
|
| 305 |
# جلب البيانات بشكل متوازي
|
| 306 |
+
task1 = self.data_manager.get_latest_ohlcv(symbol, '1m', 120) # احتياطي للـ Lags
|
| 307 |
task5 = self.data_manager.get_latest_ohlcv(symbol, '5m', 100)
|
| 308 |
task15 = self.data_manager.get_latest_ohlcv(symbol, '15m', 50)
|
| 309 |
|
|
|
|
| 313 |
if d1 and d5 and d15 and len(d1) >= 60 and len(d5) >= 30 and len(d15) >= 20:
|
| 314 |
decision = self.deep_steward.analyze(d1, d5, d15)
|
| 315 |
|
|
|
|
|
|
|
|
|
|
| 316 |
if decision['action'] == 'EXIT':
|
| 317 |
print(f"🤖 [DeepSteward V2] 🚨 أمر خروج طارئ لـ {symbol}! ({decision['reason']})")
|
| 318 |
async with self.execution_lock:
|
| 319 |
await self._execute_exit(symbol, current_price, "DEEP_STEWARD_V2_EXIT")
|
| 320 |
break
|
| 321 |
else:
|
| 322 |
+
print(f"⚠️ [Sentry] بيانات V2 غير مكتملة لـ {symbol}. تخطي الدورة.")
|
| 323 |
else:
|
| 324 |
pass # لا يوجد نموذج فعال
|
| 325 |
|
|
|
|
| 333 |
await asyncio.sleep(10)
|
| 334 |
|
| 335 |
# ==============================================================================
|
| 336 |
+
# 👻 المراقب الشبحي (Ghost Monitor) - Post-Exit Analysis (USD Version)
|
| 337 |
# ==============================================================================
|
| 338 |
def _launch_post_exit_analysis(self, symbol, exit_price, exit_time, position_size_usd):
|
| 339 |
+
"""يطلق مهمة خلفية لمراقبة السعر بعد الخروج وحساب الأثر بالدولار"""
|
| 340 |
asyncio.create_task(self._analyze_after_exit_task(symbol, exit_price, exit_time, position_size_usd))
|
| 341 |
|
| 342 |
async def _analyze_after_exit_task(self, symbol, exit_price, exit_time, position_size_usd):
|
|
|
|
| 350 |
# حساب الفرق: (السعر الحالي - سعر الخروج) / سعر الخروج
|
| 351 |
change_pct = (current_price - exit_price) / exit_price
|
| 352 |
|
| 353 |
+
# 💰 حساب الأثر بالدولار
|
| 354 |
usd_impact = change_pct * position_size_usd
|
| 355 |
|
| 356 |
+
# تصنيف القرار: إذا هبط السعر (change_pct < 0) -> قرار جيد (حمانا)
|
|
|
|
| 357 |
is_good_exit = change_pct < 0
|
| 358 |
|
| 359 |
# تحديث الإحصائيات الحية (للوحة التحكم)
|
|
|
|
| 380 |
}
|
| 381 |
|
| 382 |
await self.r2.append_deep_steward_audit(audit_record)
|
| 383 |
+
print(f"👻 [Ghost Monitor] {symbol}: بعد ساعة {change_pct*100:+.2f}% (${usd_impact:+.2f}) | الحكم: {audit_record['verdict']}")
|
| 384 |
|
| 385 |
except Exception as e:
|
| 386 |
print(f"⚠️ [Ghost Error] فشل تحليل ما بعد الخروج لـ {symbol}: {e}")
|
|
|
|
| 413 |
|
| 414 |
# 4. 💰 [المحاسبة] تحديث المحفظة وحساب PnL بالدولار
|
| 415 |
portfolio = await self.r2.get_portfolio_state_async()
|
| 416 |
+
# رأس المال قبل هذه الصفقة هو حجم الصفقة تقريباً
|
| 417 |
current_capital = float(portfolio.get('current_capital_usd', 100.0))
|
| 418 |
|
| 419 |
# حساب الربح بالدولار
|
|
|
|
| 447 |
|
| 448 |
print(f"✅ [EXIT EXECUTED] {symbol} | Reason: {reason} | PnL: {profit_pct_display:.2f}% (${pnl_usd:.2f}) | New Cap: ${new_capital:.2f}")
|
| 449 |
|
| 450 |
+
# 6. [ 🧠 ] إطلاق المراقب الشبحي إذا كان الخروج بسبب الوصي
|
| 451 |
if "DEEP_STEWARD" in reason:
|
| 452 |
+
# نمرر حجم الصفقة (current_capital) لحساب الأثر بالدولار
|
| 453 |
self._launch_post_exit_analysis(symbol, exit_price, trade['exit_time'], current_capital)
|
| 454 |
|
| 455 |
# 7. تنظيف مهام الحارس
|