Browse Source

Update stop loss order type from limit to stop-market in trading_commands and TradingEngine

- Changed the order type for stop loss from 'Limit Order' to 'Stop-Market Order' in trading_commands.py to reflect the new functionality.
- Updated TradingEngine to handle stop-market orders, including adjustments to logging and error messages for clarity.
- Enhanced the order placement logic to correctly record and process stop-market orders, ensuring accurate execution and tracking.
Carles Sentis 2 days ago
parent
commit
2b4698fe15
3 changed files with 23 additions and 18 deletions
  1. 2 2
      src/commands/trading_commands.py
  2. 20 15
      src/trading/trading_engine.py
  3. 1 1
      trading_bot.py

+ 2 - 2
src/commands/trading_commands.py

@@ -443,12 +443,12 @@ This will {"place a limit sell order" if limit_price else "execute a market sell
 • Stop Price: {await formatter.format_price_with_symbol(stop_price, token)}
 • Action: {exit_side.upper()} (Close {position_type})
 • Amount: {await formatter.format_amount(contracts, token)} {token}
-• Order Type: Limit Order
+• Order Type: Stop-Market Order
 • {pnl_emoji} Est. P&L: {await formatter.format_price_with_symbol(pnl_at_stop)}
 
 ⚠️ <b>Are you sure you want to set this stop loss?</b>
 
-This will place a limit {exit_side} order at {await formatter.format_price_with_symbol(stop_price, token)} to protect your {position_type} position.
+This will place a stop-market {exit_side} order with a trigger at {await formatter.format_price_with_symbol(stop_price, token)} to protect your {position_type} position.
             """
             
             keyboard = [

+ 20 - 15
src/trading/trading_engine.py

@@ -684,33 +684,38 @@ class TradingEngine:
             elif position_type == "SHORT" and stop_price <= entry_price:
                 return {"success": False, "error": "Stop loss price should be above entry price for short positions"}
             
-            order_type_for_stats = 'limit' # MODIFICATION: SL from /sl command is now a direct limit order
+            order_type_for_stats = 'stop_market' 
 
             # 1. Generate bot_order_ref_id and record order placement intent
             bot_order_ref_id = uuid.uuid4().hex
-            # For a direct limit SL, the 'price' recorded is the limit price.
+            # For a stop-market, the 'price' is the trigger price.
             order_db_id = self.stats.record_order_placed(
                 symbol=symbol, side=exit_side, order_type=order_type_for_stats,
-                amount_requested=contracts, price=stop_price, # price here is the limit price for the SL
+                amount_requested=contracts, price=stop_price, # price here is the trigger price for the SL
                 bot_order_ref_id=bot_order_ref_id, status='pending_submission'
             )
 
             if not order_db_id:
-                logger.error(f"Failed to record SL limit order intent in DB for {symbol} (direct /sl command) with bot_ref {bot_order_ref_id}")
-                return {"success": False, "error": "Failed to record SL limit order intent in database."}
+                logger.error(f"Failed to record SL stop-market order intent in DB for {symbol} (direct /sl command) with bot_ref {bot_order_ref_id}")
+                return {"success": False, "error": "Failed to record SL stop-market order intent in database."}
 
-            # 2. Place a direct LIMIT order for the stop loss
-            logger.info(f"Placing direct LIMIT STOP LOSS ({exit_side.upper()}) order ({bot_order_ref_id}) for {await formatter.format_amount(contracts, token)} {symbol} at limit price {await formatter.format_price_with_symbol(stop_price, token)}")
-            exchange_order_data, error_msg = self.client.place_limit_order(symbol, exit_side, contracts, price=stop_price)
+            # 2. Place a STOP-MARKET order for the stop loss
+            logger.info(f"Placing STOP-MARKET STOP LOSS ({exit_side.upper()}) order ({bot_order_ref_id}) for {await formatter.format_amount(contracts, token)} {symbol} with trigger price {await formatter.format_price_with_symbol(stop_price, token)}")
+            exchange_order_data, error_msg = self.client.place_stop_loss_order(
+                symbol=symbol, 
+                side=exit_side, 
+                amount=contracts, 
+                stop_price_arg=stop_price
+            )
             
             if error_msg:
-                logger.error(f"Direct SL Limit order placement failed for {symbol} ({bot_order_ref_id}): {error_msg}")
+                logger.error(f"Direct SL Stop-Market order placement failed for {symbol} ({bot_order_ref_id}): {error_msg}")
                 self.stats.update_order_status(order_db_id=order_db_id, new_status='failed_submission', bot_order_ref_id=bot_order_ref_id)
-                return {"success": False, "error": f"Direct SL Limit order placement failed: {error_msg}"}
+                return {"success": False, "error": f"Direct SL Stop-Market order placement failed: {error_msg}"}
             if not exchange_order_data:
-                logger.error(f"Direct SL Limit order placement call failed for {symbol} ({bot_order_ref_id}). Client returned no data/error.")
+                logger.error(f"Direct SL Stop-Market order placement call failed for {symbol} ({bot_order_ref_id}). Client returned no data/error.")
                 self.stats.update_order_status(order_db_id=order_db_id, new_status='failed_submission_no_data', bot_order_ref_id=bot_order_ref_id)
-                return {"success": False, "error": "Direct SL Limit order placement failed (no order object or error from client)."}
+                return {"success": False, "error": "Direct SL Stop-Market order placement failed (no order object or error from client)."}
 
             exchange_oid = exchange_order_data.get('id')
             
@@ -718,11 +723,11 @@ class TradingEngine:
             if exchange_oid:
                 self.stats.update_order_status(
                     order_db_id=order_db_id, 
-                    new_status='open', # Limit orders are 'open' until filled
+                    new_status='open', # Stop orders are 'open' until triggered
                     set_exchange_order_id=exchange_oid
                 )
             else:
-                logger.warning(f"No exchange_order_id received for SL limit order {order_db_id} ({bot_order_ref_id}).")
+                logger.warning(f"No exchange_order_id received for SL stop-market order {order_db_id} ({bot_order_ref_id}).")
             
             # NOTE: Stop loss orders are protective orders for existing positions
             # They do not create new trade cycles - they protect existing trade cycles
@@ -739,7 +744,7 @@ class TradingEngine:
                         # it might need to be cancelled first. However, current flow assumes this /sl places a new/updated one.
                         # For simplicity, link_stop_loss_to_trade will update if one already exists or insert.
                         await self.stats.link_stop_loss_to_trade(lifecycle_id, exchange_oid, stop_price)
-                        logger.info(f"🛡️ Linked SL limit order {exchange_oid} to lifecycle {lifecycle_id} for {symbol} (from /sl command)")
+                        logger.info(f"🛡️ Linked SL stop-market order {exchange_oid} to lifecycle {lifecycle_id} for {symbol} (from /sl command)")
             
             return {
                 "success": True,

+ 1 - 1
trading_bot.py

@@ -14,7 +14,7 @@ from datetime import datetime
 from pathlib import Path
 
 # Bot version
-BOT_VERSION = "2.4.270"
+BOT_VERSION = "2.4.271"
 
 # Add src directory to Python path
 sys.path.insert(0, str(Path(__file__).parent / "src"))