Przeglądaj źródła

Refactor trading command notifications to accommodate new response format - Updated long, short, and exit order success notifications to extract and display order details from the new response structure. Enhanced backward compatibility by creating mock order objects for notifications, ensuring consistent user feedback and improved clarity in order status messages.

Carles Sentis 4 dni temu
rodzic
commit
d0ffa6537a

+ 43 - 5
src/commands/trading_commands.py

@@ -709,8 +709,19 @@ This action cannot be undone.
         result = await self.trading_engine.execute_long_order(token, usdc_amount, price, stop_loss_price)
         
         if result["success"]:
+            # Extract data from new response format
+            order_details = result.get("order_placed_details", {})
+            token_amount = result.get("token_amount", 0)
+            price_used = order_details.get("price_requested") or price
+            
+            # Create a mock order object for backward compatibility with notification method
+            mock_order = {
+                "id": order_details.get("exchange_order_id", "N/A"),
+                "price": price_used
+            }
+            
             await self.notification_manager.send_long_success_notification(
-                query, token, result["token_amount"], result["actual_price"], result["order"], stop_loss_price
+                query, token, token_amount, price_used, mock_order, stop_loss_price
             )
         else:
             await query.edit_message_text(f"❌ Long order failed: {result['error']}")
@@ -732,8 +743,19 @@ This action cannot be undone.
         result = await self.trading_engine.execute_short_order(token, usdc_amount, price, stop_loss_price)
         
         if result["success"]:
+            # Extract data from new response format
+            order_details = result.get("order_placed_details", {})
+            token_amount = result.get("token_amount", 0)
+            price_used = order_details.get("price_requested") or price
+            
+            # Create a mock order object for backward compatibility with notification method
+            mock_order = {
+                "id": order_details.get("exchange_order_id", "N/A"),
+                "price": price_used
+            }
+            
             await self.notification_manager.send_short_success_notification(
-                query, token, result["token_amount"], result["actual_price"], result["order"], stop_loss_price
+                query, token, token_amount, price_used, mock_order, stop_loss_price
             )
         else:
             await query.edit_message_text(f"❌ Short order failed: {result['error']}")
@@ -748,10 +770,26 @@ This action cannot be undone.
         result = await self.trading_engine.execute_exit_order(token)
         
         if result["success"]:
+            # Extract data from new response format
+            order_details = result.get("order_placed_details", {})
+            position_type_closed = result.get("position_type_closed", "UNKNOWN")
+            contracts_intended_to_close = result.get("contracts_intended_to_close", 0)
+            cancelled_stop_losses = result.get("cancelled_stop_losses", 0)
+            
+            # For market orders, we won't have the actual execution price until the fill
+            # We'll use 0 for now since this will be updated by MarketMonitor when the fill occurs
+            estimated_price = 0  # Market order - actual price will be determined by fill
+            estimated_pnl = 0    # PnL will be calculated when fill is processed
+            
+            # Create a mock order object for backward compatibility
+            mock_order = {
+                "id": order_details.get("exchange_order_id", "N/A"),
+                "cancelled_stop_losses": cancelled_stop_losses
+            }
+            
             await self.notification_manager.send_exit_success_notification(
-                query, token, result["position_type_closed"], result["contracts_intended_to_close"], 
-                result.get("actual_price", 0), result.get("pnl", 0), 
-                {**result.get("order_placed_details", {}), "cancelled_stop_losses": result.get("cancelled_stop_losses", 0)}
+                query, token, position_type_closed, contracts_intended_to_close, 
+                estimated_price, estimated_pnl, mock_order
             )
         else:
             await query.edit_message_text(f"❌ Exit order failed: {result['error']}")

+ 106 - 24
src/notifications/notification_manager.py

@@ -27,29 +27,56 @@ class NotificationManager:
         order_id = order.get('id', 'N/A')
         order_type = "Market" if not order.get('price') else "Limit"
         
+        # For the new system, actual_price is the requested price for limit orders
+        # or estimated price for market orders
+        price_label = "Limit Price" if order_type == "Limit" else "Est. Price"
+        status_message = "ORDER PLACED" if order_type == "Limit" else "ORDER SUBMITTED"
+        
         success_message = f"""
-✅ <b>Long Position Opened Successfully!</b>
+✅ <b>Long Order Placed Successfully!</b>
 
 📊 <b>Order Details:</b>
 • Token: {token}
 • Direction: LONG (Buy)
 • Amount: {token_amount:.6f} {token}
-• Entry Price: ${actual_price:,.2f}
+• {price_label}: ${actual_price:,.2f}
 • Order Type: {order_type}
 • Order ID: <code>{order_id}</code>
 
-💰 <b>Trade Summary:</b>
-• Position Value: ${token_amount * actual_price:,.2f}
-• Status: FILLED ✅
-• Time: {datetime.now().strftime('%H:%M:%S')}
+💰 <b>Order Summary:</b>
+• Order Value: ${token_amount * actual_price:,.2f}
+• Status: {status_message} ✅
+• Time: {datetime.now().strftime('%H:%M:%S')}"""
+
+        if order_type == "Market":
+            success_message += f"""
+
+💡 <b>Note:</b> Market order submitted for execution
+• Actual fill price will be determined by market"""
+        else:
+            success_message += f"""
+
+💡 <b>Note:</b> Limit order placed on exchange
+• Will fill when market price reaches ${actual_price:,.2f}"""
+            
+        if stop_loss_price:
+            success_message += f"""
+
+🛑 <b>Pending Stop Loss:</b> ${stop_loss_price:,.2f}
+• Status: Will activate when main order fills
+• Protection: Automatic position closure"""
+        else:
+            success_message += f"""
 
-{f"🛑 <b>Pending Stop Loss:</b> ${stop_loss_price:,.2f}\n• Status: Will activate when order fills\n• Protection: Automatic position closure" if stop_loss_price else "💡 Consider setting a stop loss with /sl {token} [price]"}
+💡 Consider setting a stop loss with /sl {token} [price] after order fills"""
+
+        success_message += f"""
 
-📊 Use /positions to view your open positions.
+📊 Use /orders to monitor order status | /positions to view positions
         """
         
         await query.edit_message_text(success_message, parse_mode='HTML')
-        logger.info(f"Long order executed: {token_amount:.6f} {token} @ ${actual_price:,.2f}")
+        logger.info(f"Long order placed: {token_amount:.6f} {token} @ ${actual_price:,.2f} ({order_type})")
     
     async def send_short_success_notification(self, query, token: str, token_amount: float, 
                                             actual_price: float, order: Dict[str, Any], 
@@ -58,29 +85,56 @@ class NotificationManager:
         order_id = order.get('id', 'N/A')
         order_type = "Market" if not order.get('price') else "Limit"
         
+        # For the new system, actual_price is the requested price for limit orders
+        # or estimated price for market orders
+        price_label = "Limit Price" if order_type == "Limit" else "Est. Price"
+        status_message = "ORDER PLACED" if order_type == "Limit" else "ORDER SUBMITTED"
+        
         success_message = f"""
-✅ <b>Short Position Opened Successfully!</b>
+✅ <b>Short Order Placed Successfully!</b>
 
 📊 <b>Order Details:</b>
 • Token: {token}
 • Direction: SHORT (Sell)
 • Amount: {token_amount:.6f} {token}
-• Entry Price: ${actual_price:,.2f}
+• {price_label}: ${actual_price:,.2f}
 • Order Type: {order_type}
 • Order ID: <code>{order_id}</code>
 
-💰 <b>Trade Summary:</b>
-• Position Value: ${token_amount * actual_price:,.2f}
-• Status: FILLED ✅
-• Time: {datetime.now().strftime('%H:%M:%S')}
+💰 <b>Order Summary:</b>
+• Order Value: ${token_amount * actual_price:,.2f}
+• Status: {status_message} ✅
+• Time: {datetime.now().strftime('%H:%M:%S')}"""
+
+        if order_type == "Market":
+            success_message += f"""
+
+💡 <b>Note:</b> Market order submitted for execution
+• Actual fill price will be determined by market"""
+        else:
+            success_message += f"""
 
-{f"🛑 <b>Pending Stop Loss:</b> ${stop_loss_price:,.2f}\n• Status: Will activate when order fills\n• Protection: Automatic position closure" if stop_loss_price else "💡 Consider setting a stop loss with /sl {token} [price]"}
+💡 <b>Note:</b> Limit order placed on exchange
+• Will fill when market price reaches ${actual_price:,.2f}"""
+            
+        if stop_loss_price:
+            success_message += f"""
 
-📊 Use /positions to view your open positions.
+🛑 <b>Pending Stop Loss:</b> ${stop_loss_price:,.2f}
+• Status: Will activate when main order fills
+• Protection: Automatic position closure"""
+        else:
+            success_message += f"""
+
+💡 Consider setting a stop loss with /sl {token} [price] after order fills"""
+
+        success_message += f"""
+
+📊 Use /orders to monitor order status | /positions to view positions
         """
         
         await query.edit_message_text(success_message, parse_mode='HTML')
-        logger.info(f"Short order executed: {token_amount:.6f} {token} @ ${actual_price:,.2f}")
+        logger.info(f"Short order placed: {token_amount:.6f} {token} @ ${actual_price:,.2f} ({order_type})")
     
     async def send_exit_success_notification(self, query, token: str, position_type: str, 
                                            contracts: float, actual_price: float, 
@@ -93,16 +147,32 @@ class NotificationManager:
         # Check if stop losses were cancelled
         cancelled_sls = order.get('cancelled_stop_losses', 0)
         
+        # Check if this is a market order without actual price yet
+        is_market_order_pending = actual_price == 0
+        
         success_message = f"""
-✅ <b>{position_type} Position Closed Successfully!</b>
+✅ <b>{position_type} Position Exit Order Placed!</b>
 
 📊 <b>Exit Details:</b>
 • Token: {token}
 • Position: {position_type}
 • Action: {action} (Close)
 • Amount: {contracts:.6f} {token}
+• Order Type: Market Order
+• Order ID: <code>{order_id}</code>"""
+
+        if is_market_order_pending:
+            success_message += f"""
+
+⏳ <b>Order Status:</b>
+• Status: SUBMITTED ✅
+• Execution: Pending market fill
+• Time: {datetime.now().strftime('%H:%M:%S')}
+
+💡 <b>Note:</b> Actual execution price and P&L will be shown when the order fills."""
+        else:
+            success_message += f"""
 • Exit Price: ${actual_price:,.2f}
-• Order ID: <code>{order_id}</code>
 
 💰 <b>Trade Summary:</b>
 • Exit Value: ${contracts * actual_price:,.2f}
@@ -117,14 +187,26 @@ class NotificationManager:
 • Cancelled {cancelled_sls} pending stop loss order(s)
 • All protective orders removed"""
         
-        success_message += f"""
+        if is_market_order_pending:
+            success_message += f"""
+
+📊 Position exit order submitted successfully
+💡 Use /orders to monitor order status"""
+        else:
+            success_message += f"""
 
 📊 <b>Result:</b> Position fully closed
-💡 Use /stats to view updated performance metrics.
-        """
+💡 Use /stats to view updated performance metrics."""
         
         await query.edit_message_text(success_message, parse_mode='HTML')
-        logger.info(f"Exit order executed: {contracts:.6f} {token} @ ${actual_price:,.2f} (P&L: ${pnl:,.2f}){f' | Cancelled {cancelled_sls} SLs' if cancelled_sls > 0 else ''}")
+        
+        log_message = f"Exit order placed: {contracts:.6f} {token}"
+        if not is_market_order_pending:
+            log_message += f" @ ${actual_price:,.2f} (P&L: ${pnl:,.2f})"
+        if cancelled_sls > 0:
+            log_message += f" | Cancelled {cancelled_sls} SLs"
+        
+        logger.info(log_message)
     
     async def send_sl_success_notification(self, query, token: str, position_type: str, 
                                          contracts: float, stop_price: float,