import asyncio import sys import os from pathlib import Path # Add project root to path project_root = Path(__file__).parent sys.path.insert(0, str(project_root)) sys.path.insert(0, str(project_root / 'backend')) from database.connection import db from database.models import Trade from trading_system import config from trading_system.risk_manager import RiskManager async def fix_missing_sltp(): print("Checking for open trades with missing SL/TP across all accounts...") all_open_trades = [] # Iterate through potential account IDs for account_id in [1, 2, 3, 4]: print(f"\nChecking Account {account_id}...") try: # Check if Trade.get_all supports account_id argument trades = Trade.get_all(status='open', account_id=account_id) except TypeError: print(f"Warning: Trade.get_all might not support account_id. Checking default.") trades = Trade.get_all(status='open') if account_id > 1: break if trades: print(f"Found {len(trades)} open trades for Account {account_id}.") all_open_trades.extend(trades) else: print(f"No open trades found for Account {account_id}.") open_trades = all_open_trades if not open_trades: print("No open trades found.") return print(f"Found {len(open_trades)} open trades total.") # Initialize RiskManager (lightweight) # We don't need a real client if we just use basic calculation rm = RiskManager(None) updates = 0 for trade in open_trades: t_id = trade['id'] symbol = trade['symbol'] entry_price = float(trade['entry_price'] or 0) quantity = float(trade['quantity'] or 0) side = trade['side'] leverage = int(trade['leverage'] or 10) sl = trade.get('stop_loss_price') tp = trade.get('take_profit_price') if entry_price <= 0: print(f"Skipping trade {t_id} ({symbol}): Invalid entry price {entry_price}") continue needs_update = False # Calculate defaults # Config defaults: SL 3%, TP 10% (or 30%?) # Logic from position_manager: stop_loss_pct = config.TRADING_CONFIG.get('STOP_LOSS_PERCENT', 0.03) if stop_loss_pct > 1: stop_loss_pct /= 100.0 take_profit_pct = config.TRADING_CONFIG.get('TAKE_PROFIT_PERCENT', 0.10) if take_profit_pct > 1: take_profit_pct /= 100.0 # Calculate SL if sl is None or float(sl) <= 0: print(f"Trade {t_id} ({symbol}) missing SL. Calculating...") # Use RiskManager logic manually or call it # We'll use the basic margin-based logic position_value = entry_price * quantity margin = position_value / leverage if leverage > 0 else position_value stop_loss_amount = margin * stop_loss_pct if side == 'BUY': new_sl = entry_price - (stop_loss_amount / quantity) else: new_sl = entry_price + (stop_loss_amount / quantity) sl = new_sl needs_update = True print(f" -> Calculated SL: {sl:.4f} (Margin: {margin:.2f}, SL Amount: {stop_loss_amount:.2f})") # Calculate TP if tp is None or float(tp) <= 0: print(f"Trade {t_id} ({symbol}) missing TP. Calculating...") # Use basic logic # Default TP is usually SL distance * 3 or fixed pct # Position manager uses config TAKE_PROFIT_PERCENT if take_profit_pct is None or take_profit_pct == 0: take_profit_pct = stop_loss_pct * 3.0 tp_price = rm.get_take_profit_price( entry_price, side, quantity, leverage, take_profit_pct=take_profit_pct, atr=None, stop_distance=abs(entry_price - float(sl)) ) tp = tp_price needs_update = True print(f" -> Calculated TP: {tp:.4f}") if needs_update: try: db.execute_update( "UPDATE trades SET stop_loss_price = %s, take_profit_price = %s WHERE id = %s", (sl, tp, t_id) ) print(f"✓ Updated trade {t_id} ({symbol})") updates += 1 except Exception as e: print(f"❌ Failed to update trade {t_id}: {e}") else: print(f"Trade {t_id} ({symbol}) OK.") print(f"Fixed {updates} trades.") if __name__ == "__main__": asyncio.run(fix_missing_sltp())