Spaces:
Paused
Paused
Update trade_manager.py
Browse files- trade_manager.py +58 -9
trade_manager.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# ============================================================
|
| 2 |
-
# 🛡️ trade_manager.py (
|
| 3 |
# ============================================================
|
| 4 |
|
| 5 |
import asyncio
|
|
@@ -43,9 +43,16 @@ class TradeManager:
|
|
| 43 |
"giveback": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0},
|
| 44 |
"stagnation": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0}
|
| 45 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
self.execution_lock = asyncio.Lock()
|
| 48 |
-
print(f"🛡️ [TradeManager
|
| 49 |
|
| 50 |
async def initialize_sentry_exchanges(self):
|
| 51 |
"""تهيئة المحفظة واستعادة الحالة"""
|
|
@@ -60,6 +67,29 @@ class TradeManager:
|
|
| 60 |
print(" -> [Stats] Guardian metrics loaded from R2.")
|
| 61 |
except Exception: pass
|
| 62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
async def sync_internal_state_with_r2(self):
|
| 64 |
"""استرجاع الصفقات المفتوحة من R2"""
|
| 65 |
try:
|
|
@@ -125,7 +155,7 @@ class TradeManager:
|
|
| 125 |
sniper_signal = sniper_result.get('signal', 'WAIT')
|
| 126 |
final_conf = sniper_result.get('confidence_prob', 0.0)
|
| 127 |
|
| 128 |
-
log_msg = (f" -> 🔭 {symbol:<6} | Decision: {sniper_signal} | Score: {final_conf:.2f} |
|
| 129 |
print(log_msg)
|
| 130 |
|
| 131 |
if sniper_signal == 'BUY':
|
|
@@ -262,8 +292,11 @@ class TradeManager:
|
|
| 262 |
|
| 263 |
ohlcv_dict = {'15m': t15, '1h': t1h}
|
| 264 |
|
| 265 |
-
#
|
| 266 |
-
|
|
|
|
|
|
|
|
|
|
| 267 |
|
| 268 |
if gov_decision['grade'] == 'REJECT':
|
| 269 |
print(f"⛔ [Governance VETO] {symbol} Rejected by Senate. Grade: REJECT | Score: {gov_decision['governance_score']:.1f}")
|
|
@@ -324,7 +357,9 @@ class TradeManager:
|
|
| 324 |
'entry_capital': approved_size_usd,
|
| 325 |
'entry_fee_usd': entry_fee_usd,
|
| 326 |
'decision_data': decision_snapshot,
|
| 327 |
-
'highest_price': current_price
|
|
|
|
|
|
|
| 328 |
}
|
| 329 |
|
| 330 |
self.open_positions[symbol] = new_trade
|
|
@@ -354,7 +389,7 @@ class TradeManager:
|
|
| 354 |
model_votes
|
| 355 |
))
|
| 356 |
|
| 357 |
-
print(f"✅ [ENTRY] {symbol} @ {current_price} | Grade: {gov_decision['grade']} | Size: ${approved_size_usd:.2f}
|
| 358 |
|
| 359 |
except Exception as e:
|
| 360 |
print(f"❌ [Entry Error] {symbol}: {e}")
|
|
@@ -564,11 +599,24 @@ class TradeManager:
|
|
| 564 |
portfolio['total_loss_usd'] = portfolio.get('total_loss_usd', 0) + abs(true_net_pnl_usd)
|
| 565 |
trade['result'] = 'LOSS'
|
| 566 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 567 |
await self.r2.save_portfolio_state_async(portfolio)
|
| 568 |
await self.r2.save_open_trades_async(list(self.open_positions.values()))
|
| 569 |
await self.r2.append_to_closed_trades_history(trade)
|
| 570 |
|
| 571 |
-
print(f"✅ [EXIT] {symbol} |
|
| 572 |
|
| 573 |
# ==========================================================
|
| 574 |
# 🏛️ إرسال البيانات لملف تدريب الحوكمة (Governance Training Data)
|
|
@@ -586,7 +634,8 @@ class TradeManager:
|
|
| 586 |
"entry_price": trade['entry_price'],
|
| 587 |
"exit_price": trade['exit_price'],
|
| 588 |
"profit_pct": true_net_pct,
|
| 589 |
-
"result": trade['result']
|
|
|
|
| 590 |
}
|
| 591 |
# إرسال إلى R2 في الخلفية
|
| 592 |
asyncio.create_task(self.r2.append_governance_training_data(training_record))
|
|
|
|
| 1 |
# ============================================================
|
| 2 |
+
# 🛡️ trade_manager.py (V61.1 - GEM-Architect: Full Integrity)
|
| 3 |
# ============================================================
|
| 4 |
|
| 5 |
import asyncio
|
|
|
|
| 43 |
"giveback": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0},
|
| 44 |
"stagnation": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0}
|
| 45 |
}
|
| 46 |
+
|
| 47 |
+
# 📊 [NEW] إحصائيات أنواع العملات (الجديدة)
|
| 48 |
+
# الهيكل: الاسم، الفوز، الخسارة، الربح (USD)، الخسارة (USD)
|
| 49 |
+
self.type_stats = {
|
| 50 |
+
"SAFE_BOTTOM": {"wins": 0, "losses": 0, "profit_usd": 0.0, "loss_usd": 0.0},
|
| 51 |
+
"MOMENTUM_LAUNCH": {"wins": 0, "losses": 0, "profit_usd": 0.0, "loss_usd": 0.0}
|
| 52 |
+
}
|
| 53 |
|
| 54 |
self.execution_lock = asyncio.Lock()
|
| 55 |
+
print(f"🛡️ [TradeManager V61.1] Full System Online (Diagnostics + Type Stats).")
|
| 56 |
|
| 57 |
async def initialize_sentry_exchanges(self):
|
| 58 |
"""تهيئة المحفظة واستعادة الحالة"""
|
|
|
|
| 67 |
print(" -> [Stats] Guardian metrics loaded from R2.")
|
| 68 |
except Exception: pass
|
| 69 |
|
| 70 |
+
# ✅ تحميل إحصائيات الأنواع (Persistent Type Stats)
|
| 71 |
+
await self._load_type_stats_from_r2()
|
| 72 |
+
|
| 73 |
+
async def _load_type_stats_from_r2(self):
|
| 74 |
+
"""تحميل إحصائيات أنواع العملات من R2"""
|
| 75 |
+
try:
|
| 76 |
+
# ملف منفصل لضمان عدم تصفيره مع السجلات الأخرى بالخطأ
|
| 77 |
+
saved_stats = await self.r2.get_file_json_async("stats/coin_type_performance_v1.json")
|
| 78 |
+
if saved_stats:
|
| 79 |
+
self.type_stats = saved_stats
|
| 80 |
+
print(" 📊 [Stats] Coin Type performance loaded from R2.")
|
| 81 |
+
else:
|
| 82 |
+
print(" ℹ️ [Stats] No existing type stats found. Starting fresh.")
|
| 83 |
+
except Exception:
|
| 84 |
+
print(" ⚠️ [Stats] Error loading type stats.")
|
| 85 |
+
|
| 86 |
+
async def _save_type_stats_to_r2(self):
|
| 87 |
+
"""حفظ إحصائيات الأنواع إلى R2"""
|
| 88 |
+
try:
|
| 89 |
+
await self.r2.upload_json_async(self.type_stats, "stats/coin_type_performance_v1.json")
|
| 90 |
+
except Exception as e:
|
| 91 |
+
print(f"❌ Failed to save type stats: {e}")
|
| 92 |
+
|
| 93 |
async def sync_internal_state_with_r2(self):
|
| 94 |
"""استرجاع الصفقات المفتوحة من R2"""
|
| 95 |
try:
|
|
|
|
| 155 |
sniper_signal = sniper_result.get('signal', 'WAIT')
|
| 156 |
final_conf = sniper_result.get('confidence_prob', 0.0)
|
| 157 |
|
| 158 |
+
log_msg = (f" -> 🔭 {symbol:<6} | Decision: {sniper_signal} | Score: {final_conf:.2f} | Type: {signal.get('strategy_type', 'N/A')}")
|
| 159 |
print(log_msg)
|
| 160 |
|
| 161 |
if sniper_signal == 'BUY':
|
|
|
|
| 292 |
|
| 293 |
ohlcv_dict = {'15m': t15, '1h': t1h}
|
| 294 |
|
| 295 |
+
# ✅ تمرير نوع الاستراتيجية للحوكمة (لتعديل الأوزان داخلياً إن لزم الأمر)
|
| 296 |
+
strategy_type = signal_data.get('strategy_type', 'NORMAL')
|
| 297 |
+
|
| 298 |
+
# تقييم الحوكمة مع تمرير نوع الاستراتيجية
|
| 299 |
+
gov_decision = await self.governance.evaluate_trade(symbol, ohlcv_dict, ob, strategy_type=strategy_type)
|
| 300 |
|
| 301 |
if gov_decision['grade'] == 'REJECT':
|
| 302 |
print(f"⛔ [Governance VETO] {symbol} Rejected by Senate. Grade: REJECT | Score: {gov_decision['governance_score']:.1f}")
|
|
|
|
| 357 |
'entry_capital': approved_size_usd,
|
| 358 |
'entry_fee_usd': entry_fee_usd,
|
| 359 |
'decision_data': decision_snapshot,
|
| 360 |
+
'highest_price': current_price,
|
| 361 |
+
# ✅ حفظ نوع الاستراتيجية في الصفقة
|
| 362 |
+
'strategy_type': strategy_type
|
| 363 |
}
|
| 364 |
|
| 365 |
self.open_positions[symbol] = new_trade
|
|
|
|
| 389 |
model_votes
|
| 390 |
))
|
| 391 |
|
| 392 |
+
print(f"✅ [ENTRY] {symbol} @ {current_price} | Type: {strategy_type} | Grade: {gov_decision['grade']} | Size: ${approved_size_usd:.2f}")
|
| 393 |
|
| 394 |
except Exception as e:
|
| 395 |
print(f"❌ [Entry Error] {symbol}: {e}")
|
|
|
|
| 599 |
portfolio['total_loss_usd'] = portfolio.get('total_loss_usd', 0) + abs(true_net_pnl_usd)
|
| 600 |
trade['result'] = 'LOSS'
|
| 601 |
|
| 602 |
+
# ✅ 2. تحديث إحصائيات الأنواع (Persistent Type Stats)
|
| 603 |
+
strat_type = trade.get('strategy_type', 'UNKNOWN')
|
| 604 |
+
if strat_type in self.type_stats:
|
| 605 |
+
if true_net_pnl_usd >= 0:
|
| 606 |
+
self.type_stats[strat_type]['wins'] += 1
|
| 607 |
+
self.type_stats[strat_type]['profit_usd'] += true_net_pnl_usd
|
| 608 |
+
else:
|
| 609 |
+
self.type_stats[strat_type]['losses'] += 1
|
| 610 |
+
self.type_stats[strat_type]['loss_usd'] += true_net_pnl_usd
|
| 611 |
+
|
| 612 |
+
# حفظ فوري لضمان عدم الضياع
|
| 613 |
+
asyncio.create_task(self._save_type_stats_to_r2())
|
| 614 |
+
|
| 615 |
await self.r2.save_portfolio_state_async(portfolio)
|
| 616 |
await self.r2.save_open_trades_async(list(self.open_positions.values()))
|
| 617 |
await self.r2.append_to_closed_trades_history(trade)
|
| 618 |
|
| 619 |
+
print(f"✅ [EXIT] {symbol} | Type: {strat_type} | PnL: {true_net_pct:.2f}% (${true_net_pnl_usd:.2f}) | {reason}")
|
| 620 |
|
| 621 |
# ==========================================================
|
| 622 |
# 🏛️ إرسال البيانات لملف تدريب الحوكمة (Governance Training Data)
|
|
|
|
| 634 |
"entry_price": trade['entry_price'],
|
| 635 |
"exit_price": trade['exit_price'],
|
| 636 |
"profit_pct": true_net_pct,
|
| 637 |
+
"result": trade['result'],
|
| 638 |
+
"strategy_type": strat_type # Added for context
|
| 639 |
}
|
| 640 |
# إرسال إلى R2 في الخلفية
|
| 641 |
asyncio.create_task(self.r2.append_governance_training_data(training_record))
|