Spaces:
Paused
Paused
Update trade_manager.py
Browse files- trade_manager.py +17 -17
trade_manager.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# ============================================================
|
| 2 |
-
# 🛡️ trade_manager.py (V35.
|
| 3 |
# ============================================================
|
| 4 |
|
| 5 |
import asyncio
|
|
@@ -32,7 +32,7 @@ class TradeManager:
|
|
| 32 |
"stagnation": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0}
|
| 33 |
}
|
| 34 |
self.execution_lock = asyncio.Lock()
|
| 35 |
-
print(f"🛡️ [TradeManager V35.
|
| 36 |
|
| 37 |
async def initialize_sentry_exchanges(self):
|
| 38 |
print("🛡️ [TradeManager] Syncing state & Initializing Portfolio...")
|
|
@@ -316,9 +316,6 @@ class TradeManager:
|
|
| 316 |
await self.learning_hub.register_trade_outcome(trade_obj)
|
| 317 |
except Exception: pass
|
| 318 |
|
| 319 |
-
# ==============================================================================
|
| 320 |
-
# 🔴 Exit Logic (MATH FIXED)
|
| 321 |
-
# ==============================================================================
|
| 322 |
async def _execute_exit(self, symbol, price, reason, ai_scores=None):
|
| 323 |
if symbol not in self.open_positions: return
|
| 324 |
try:
|
|
@@ -326,24 +323,16 @@ class TradeManager:
|
|
| 326 |
entry_price = float(trade['entry_price']); exit_price = float(price)
|
| 327 |
entry_capital = float(trade.get('entry_capital', 100.0)); entry_fee = float(trade.get('entry_fee_usd', 0.0))
|
| 328 |
|
| 329 |
-
#
|
| 330 |
exit_val_gross = (exit_price / entry_price) * entry_capital
|
| 331 |
-
|
| 332 |
-
# 2. Fees
|
| 333 |
exit_fee = exit_val_gross * self.FEE_RATE
|
| 334 |
total_fees = entry_fee + exit_fee
|
| 335 |
|
| 336 |
-
# 3. PnL for Portfolio (Gross PnL so portfolio handles fees correctly)
|
| 337 |
-
# Gross PnL = Difference in Asset Value
|
| 338 |
gross_pnl_usd = exit_val_gross - entry_capital
|
| 339 |
-
|
| 340 |
-
# 4. PnL for Statistics (True Net PnL)
|
| 341 |
-
# True Net = Gross PnL - All Fees
|
| 342 |
true_net_pnl_usd = gross_pnl_usd - total_fees
|
| 343 |
true_net_pct = (true_net_pnl_usd / entry_capital) * 100
|
| 344 |
|
| 345 |
-
#
|
| 346 |
-
# Impact on Wallet = Gross PnL - Total Fees
|
| 347 |
await self.smart_portfolio.register_closed_position(entry_capital, gross_pnl_usd, total_fees)
|
| 348 |
|
| 349 |
trade.update({
|
|
@@ -351,7 +340,6 @@ class TradeManager:
|
|
| 351 |
'profit_pct': true_net_pct, 'net_pnl_usd': true_net_pnl_usd, 'fees_paid_usd': total_fees
|
| 352 |
})
|
| 353 |
|
| 354 |
-
# Update Stats with TRUE NET
|
| 355 |
portfolio = await self.r2.get_portfolio_state_async()
|
| 356 |
portfolio['total_trades'] = portfolio.get('total_trades', 0) + 1
|
| 357 |
if true_net_pnl_usd >= 0:
|
|
@@ -374,4 +362,16 @@ class TradeManager:
|
|
| 374 |
|
| 375 |
except Exception as e:
|
| 376 |
print(f"❌ [Exit Error] {e}"); traceback.print_exc()
|
| 377 |
-
if symbol not in self.open_positions: self.open_positions[symbol] = trade
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
# ============================================================
|
| 2 |
+
# 🛡️ trade_manager.py (V35.4 - GEM-Architect: FATAL FIX & ALL FEATURES)
|
| 3 |
# ============================================================
|
| 4 |
|
| 5 |
import asyncio
|
|
|
|
| 32 |
"stagnation": {"total": 0, "good": 0, "saved": 0.0, "missed": 0.0}
|
| 33 |
}
|
| 34 |
self.execution_lock = asyncio.Lock()
|
| 35 |
+
print(f"🛡️ [TradeManager V35.4] System Restoration Complete.")
|
| 36 |
|
| 37 |
async def initialize_sentry_exchanges(self):
|
| 38 |
print("🛡️ [TradeManager] Syncing state & Initializing Portfolio...")
|
|
|
|
| 316 |
await self.learning_hub.register_trade_outcome(trade_obj)
|
| 317 |
except Exception: pass
|
| 318 |
|
|
|
|
|
|
|
|
|
|
| 319 |
async def _execute_exit(self, symbol, price, reason, ai_scores=None):
|
| 320 |
if symbol not in self.open_positions: return
|
| 321 |
try:
|
|
|
|
| 323 |
entry_price = float(trade['entry_price']); exit_price = float(price)
|
| 324 |
entry_capital = float(trade.get('entry_capital', 100.0)); entry_fee = float(trade.get('entry_fee_usd', 0.0))
|
| 325 |
|
| 326 |
+
# Gross & Net Calculation
|
| 327 |
exit_val_gross = (exit_price / entry_price) * entry_capital
|
|
|
|
|
|
|
| 328 |
exit_fee = exit_val_gross * self.FEE_RATE
|
| 329 |
total_fees = entry_fee + exit_fee
|
| 330 |
|
|
|
|
|
|
|
| 331 |
gross_pnl_usd = exit_val_gross - entry_capital
|
|
|
|
|
|
|
|
|
|
| 332 |
true_net_pnl_usd = gross_pnl_usd - total_fees
|
| 333 |
true_net_pct = (true_net_pnl_usd / entry_capital) * 100
|
| 334 |
|
| 335 |
+
# Update Portfolio with Gross PnL
|
|
|
|
| 336 |
await self.smart_portfolio.register_closed_position(entry_capital, gross_pnl_usd, total_fees)
|
| 337 |
|
| 338 |
trade.update({
|
|
|
|
| 340 |
'profit_pct': true_net_pct, 'net_pnl_usd': true_net_pnl_usd, 'fees_paid_usd': total_fees
|
| 341 |
})
|
| 342 |
|
|
|
|
| 343 |
portfolio = await self.r2.get_portfolio_state_async()
|
| 344 |
portfolio['total_trades'] = portfolio.get('total_trades', 0) + 1
|
| 345 |
if true_net_pnl_usd >= 0:
|
|
|
|
| 362 |
|
| 363 |
except Exception as e:
|
| 364 |
print(f"❌ [Exit Error] {e}"); traceback.print_exc()
|
| 365 |
+
if symbol not in self.open_positions: self.open_positions[symbol] = trade
|
| 366 |
+
|
| 367 |
+
async def force_exit_by_manager(self, symbol, reason):
|
| 368 |
+
p = await self.data_manager.get_latest_price_async(symbol)
|
| 369 |
+
async with self.execution_lock: await self._execute_exit(symbol, p, reason)
|
| 370 |
+
|
| 371 |
+
# ✅ ADDED BACK: Startup/Shutdown hooks
|
| 372 |
+
async def start_sentry_loops(self):
|
| 373 |
+
await self.ensure_active_guardians()
|
| 374 |
+
|
| 375 |
+
async def stop_sentry_loops(self):
|
| 376 |
+
self.running = False
|
| 377 |
+
for task in self.sentry_tasks.values(): task.cancel()
|