place_order
Execute spot, linear, or inverse trading orders on Bybit. Specify category, symbol, side, order type, and quantity. Supports market, limit, TP/SL, and futures trading with position indexes for long/short positions.
Instructions
Execute order
Args:
category (str): Category
- spot: Spot trading
* Minimum order quantity: 0.000011 BTC (up to 6 decimal places)
* Minimum order amount: 5 USDT
* If buying at market price, qty should be input in USDT units (e.g., "10" = 10 USDT)
* If selling at market price, qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC)
* If placing a limit order, qty should be input in BTC units
* positionIdx is not used
- linear: Futures trading (USDT margin)
* positionIdx is required (1: Long, 2: Short)
- inverse: Futures trading (coin margin)
* positionIdx is required (1: Long, 2: Short)
symbol (str): Symbol (e.g., BTCUSDT)
side (str): Order direction (Buy, Sell)
orderType (str): Order type (Market, Limit)
qty (str): Order quantity
- Market Buy: qty should be input in USDT units (e.g., "10" = 10 USDT)
- Market Sell: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC, up to 6 decimal places)
- Limit: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC, up to 6 decimal places)
price (Optional[str]): Order price (for limit orders)
positionIdx (Optional[str]): Position index
- Required for futures (linear/inverse) trading
- "1": Long position
- "2": Short position
- Not used for spot trading
timeInForce (Optional[str]): Order validity period
- GTC: Good Till Cancel (default, for limit orders)
- IOC: Immediate or Cancel (market order)
- FOK: Fill or Kill
- PostOnly: Post Only
orderLinkId (Optional[str]): Order link ID (unique value)
isLeverage (Optional[int]): Use leverage (0: No, 1: Yes)
orderFilter (Optional[str]): Order filter
- Order: Regular order (default)
- tpslOrder: TP/SL order
- StopOrder: Stop order
triggerPrice (Optional[str]): Trigger price
triggerBy (Optional[str]): Trigger basis
orderIv (Optional[str]): Order volatility
takeProfit (Optional[str]): Take profit price
stopLoss (Optional[str]): Stop loss price
tpTriggerBy (Optional[str]): Take profit trigger basis
slTriggerBy (Optional[str]): Stop loss trigger basis
tpLimitPrice (Optional[str]): Take profit limit price
slLimitPrice (Optional[str]): Stop loss limit price
tpOrderType (Optional[str]): Take profit order type (Market, Limit)
slOrderType (Optional[str]): Stop loss order type (Market, Limit)
Returns:
Dict: Order result
Example:
# Spot trading (SPOT account balance required)
place_order("spot", "BTCUSDT", "Buy", "Market", "10") # Buy market price for 10 USDT
place_order("spot", "BTCUSDT", "Sell", "Market", "0.000100") # Sell market price for 0.0001 BTC
place_order("spot", "BTCUSDT", "Buy", "Limit", "0.000100", price="50000") # Buy limit order for 0.0001 BTC
# Spot trading - limit order + TP/SL
place_order("spot", "BTCUSDT", "Buy", "Limit", "0.000100", price="50000",
takeProfit="55000", stopLoss="45000", # TP/SL setting
tpOrderType="Market", slOrderType="Market") # Execute TP/SL as market order
# Futures trading
place_order("linear", "BTCUSDT", "Buy", "Market", "0.001", positionIdx="1") # Buy market price for long position
place_order("linear", "BTCUSDT", "Sell", "Market", "0.001", positionIdx="2") # Sell market price for short position
Notes:
1. Spot trading order quantity restrictions:
- Minimum order quantity: 0.000011 BTC
- Minimum order amount: 5 USDT
- BTC quantity is only allowed up to 6 decimal places (e.g., 0.000100 O, 0.0001234 X)
2. Pay attention to unit when buying/selling at market price:
- Buying: qty should be input in USDT units (e.g., "10" = 10 USDT)
- Selling: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC)
3. Futures trading requires positionIdx:
- Long position: positionIdx="1"
- Short position: positionIdx="2"
4. positionIdx is not used for spot trading
Reference:
https://bybit-exchange.github.io/docs/v5/order/create-order
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| category | Yes | Category (spot, linear, inverse, etc.) | |
| isLeverage | No | Use leverage (0: No, 1: Yes) | |
| orderFilter | No | Order filter (Order, tpslOrder, StopOrder) | |
| orderIv | No | Order volatility | |
| orderLinkId | No | Order link ID | |
| orderType | Yes | Order type (Market, Limit) | |
| positionIdx | No | Position index (1: Long, 2: Short) | |
| price | No | Order price (for limit orders) | |
| qty | Yes | Order quantity | |
| side | Yes | Order direction (Buy, Sell) | |
| slLimitPrice | No | Stop loss limit price | |
| slOrderType | No | Stop loss order type (Market, Limit) | |
| slTriggerBy | No | Stop loss trigger basis | |
| stopLoss | No | Stop loss price | |
| symbol | Yes | Symbol (e.g., BTCUSDT) | |
| takeProfit | No | Take profit price | |
| timeInForce | No | Time in force (GTC, IOC, FOK, PostOnly) | |
| tpLimitPrice | No | Take profit limit price | |
| tpOrderType | No | Take profit order type (Market, Limit) | |
| tpTriggerBy | No | Take profit trigger basis | |
| triggerBy | No | Trigger basis | |
| triggerPrice | No | Trigger price |
Implementation Reference
- src/server.py:227-352 (handler)The primary MCP tool handler for 'place_order', registered via @mcp.tool(). Defines input schema using Pydantic Field, calls the underlying BybitService.place_order method, handles API responses and errors.@mcp.tool() def place_order( category: str = Field(description="Category (spot, linear, inverse, etc.)"), symbol: str = Field(description="Symbol (e.g., BTCUSDT)"), side: str = Field(description="Order direction (Buy, Sell)"), orderType: str = Field(description="Order type (Market, Limit)"), qty: str = Field(description="Order quantity"), price: Optional[str] = Field(default=None, description="Order price (for limit orders)"), positionIdx: Optional[str] = Field(default=None, description="Position index (1: Long, 2: Short)"), timeInForce: Optional[str] = Field(default=None, description="Time in force (GTC, IOC, FOK, PostOnly)"), orderLinkId: Optional[str] = Field(default=None, description="Order link ID"), isLeverage: Optional[int] = Field(default=None, description="Use leverage (0: No, 1: Yes)"), orderFilter: Optional[str] = Field(default=None, description="Order filter (Order, tpslOrder, StopOrder)"), triggerPrice: Optional[str] = Field(default=None, description="Trigger price"), triggerBy: Optional[str] = Field(default=None, description="Trigger basis"), orderIv: Optional[str] = Field(default=None, description="Order volatility"), takeProfit: Optional[str] = Field(default=None, description="Take profit price"), stopLoss: Optional[str] = Field(default=None, description="Stop loss price"), tpTriggerBy: Optional[str] = Field(default=None, description="Take profit trigger basis"), slTriggerBy: Optional[str] = Field(default=None, description="Stop loss trigger basis"), tpLimitPrice: Optional[str] = Field(default=None, description="Take profit limit price"), slLimitPrice: Optional[str] = Field(default=None, description="Stop loss limit price"), tpOrderType: Optional[str] = Field(default=None, description="Take profit order type (Market, Limit)"), slOrderType: Optional[str] = Field(default=None, description="Stop loss order type (Market, Limit)") ) -> Dict: """ Execute order Args: category (str): Category - spot: Spot trading * Minimum order quantity: 0.000011 BTC (up to 6 decimal places) * Minimum order amount: 5 USDT * If buying at market price, qty should be input in USDT units (e.g., "10" = 10 USDT) * If selling at market price, qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC) * If placing a limit order, qty should be input in BTC units * positionIdx is not used - linear: Futures trading (USDT margin) * positionIdx is required (1: Long, 2: Short) - inverse: Futures trading (coin margin) * positionIdx is required (1: Long, 2: Short) symbol (str): Symbol (e.g., BTCUSDT) side (str): Order direction (Buy, Sell) orderType (str): Order type (Market, Limit) qty (str): Order quantity - Market Buy: qty should be input in USDT units (e.g., "10" = 10 USDT) - Market Sell: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC, up to 6 decimal places) - Limit: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC, up to 6 decimal places) price (Optional[str]): Order price (for limit orders) positionIdx (Optional[str]): Position index - Required for futures (linear/inverse) trading - "1": Long position - "2": Short position - Not used for spot trading timeInForce (Optional[str]): Order validity period - GTC: Good Till Cancel (default, for limit orders) - IOC: Immediate or Cancel (market order) - FOK: Fill or Kill - PostOnly: Post Only orderLinkId (Optional[str]): Order link ID (unique value) isLeverage (Optional[int]): Use leverage (0: No, 1: Yes) orderFilter (Optional[str]): Order filter - Order: Regular order (default) - tpslOrder: TP/SL order - StopOrder: Stop order triggerPrice (Optional[str]): Trigger price triggerBy (Optional[str]): Trigger basis orderIv (Optional[str]): Order volatility takeProfit (Optional[str]): Take profit price stopLoss (Optional[str]): Stop loss price tpTriggerBy (Optional[str]): Take profit trigger basis slTriggerBy (Optional[str]): Stop loss trigger basis tpLimitPrice (Optional[str]): Take profit limit price slLimitPrice (Optional[str]): Stop loss limit price tpOrderType (Optional[str]): Take profit order type (Market, Limit) slOrderType (Optional[str]): Stop loss order type (Market, Limit) Returns: Dict: Order result Example: # Spot trading (SPOT account balance required) place_order("spot", "BTCUSDT", "Buy", "Market", "10") # Buy market price for 10 USDT place_order("spot", "BTCUSDT", "Sell", "Market", "0.000100") # Sell market price for 0.0001 BTC place_order("spot", "BTCUSDT", "Buy", "Limit", "0.000100", price="50000") # Buy limit order for 0.0001 BTC # Spot trading - limit order + TP/SL place_order("spot", "BTCUSDT", "Buy", "Limit", "0.000100", price="50000", takeProfit="55000", stopLoss="45000", # TP/SL setting tpOrderType="Market", slOrderType="Market") # Execute TP/SL as market order # Futures trading place_order("linear", "BTCUSDT", "Buy", "Market", "0.001", positionIdx="1") # Buy market price for long position place_order("linear", "BTCUSDT", "Sell", "Market", "0.001", positionIdx="2") # Sell market price for short position Notes: 1. Spot trading order quantity restrictions: - Minimum order quantity: 0.000011 BTC - Minimum order amount: 5 USDT - BTC quantity is only allowed up to 6 decimal places (e.g., 0.000100 O, 0.0001234 X) 2. Pay attention to unit when buying/selling at market price: - Buying: qty should be input in USDT units (e.g., "10" = 10 USDT) - Selling: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC) 3. Futures trading requires positionIdx: - Long position: positionIdx="1" - Short position: positionIdx="2" 4. positionIdx is not used for spot trading Reference: https://bybit-exchange.github.io/docs/v5/order/create-order """ try: result = bybit_service.place_order( category, symbol, side, orderType, qty, price, positionIdx, timeInForce, orderLinkId, isLeverage, orderFilter, triggerPrice, triggerBy, orderIv, takeProfit, stopLoss, tpTriggerBy, slTriggerBy, tpLimitPrice, slLimitPrice, tpOrderType, slOrderType ) if result.get("retCode") != 0: logger.error(f"Failed to place order: {result.get('retMsg')}") return {"error": result.get("retMsg")} return result except Exception as e: logger.error(f"Failed to place order: {e}", exc_info=True) return {"error": str(e)}
- src/service.py:144-321 (helper)Supporting helper method in BybitService class that implements the core order placement logic: sets defaults, validates parameters (e.g., positionIdx), builds the API request dict, and invokes pybit.unified_trading.HTTP.client.place_order.def place_order(self, category: str, symbol: str, side: str, orderType: str, qty: str, price: Optional[str] = None, timeInForce: Optional[str] = None, orderLinkId: Optional[str] = None, isLeverage: Optional[int] = None, orderFilter: Optional[str] = None, triggerPrice: Optional[str] = None, triggerBy: Optional[str] = None, orderIv: Optional[str] = None, positionIdx: Optional[int] = None, takeProfit: Optional[str] = None, stopLoss: Optional[str] = None, tpTriggerBy: Optional[str] = None, slTriggerBy: Optional[str] = None, tpLimitPrice: Optional[str] = None, slLimitPrice: Optional[str] = None, tpOrderType: Optional[str] = None, slOrderType: Optional[str] = None) -> Dict: """ Execute order Args: category (str): Category - spot: Spot trading * Minimum order quantity: 0.000011 BTC (up to 6 decimal places) * Minimum order amount: 5 USDT * If buying at market price, qty should be input in USDT units (e.g., "10" = 10 USDT) * If selling at market price, qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC) * If placing a limit order, qty should be input in BTC units * positionIdx is not used - linear: Futures trading (USDT margin) * positionIdx is required (1: Long, 2: Short) - inverse: Futures trading (coin margin) * positionIdx is required (1: Long, 2: Short) symbol (str): Symbol (e.g., BTCUSDT) side (str): Order direction (Buy, Sell) orderType (str): Order type (Market, Limit) qty (str): Order quantity - Market Buy: qty should be input in USDT units (e.g., "10" = 10 USDT) - Market Sell: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC, up to 6 decimal places) - Limit: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC, up to 6 decimal places) price (Optional[str]): Order price (for limit order) timeInForce (Optional[str]): Order validity period - GTC: Good Till Cancel (default, for limit order) - IOC: Immediate or Cancel (market order) - FOK: Fill or Kill - PostOnly: Post Only orderLinkId (Optional[str]): Order link ID (unique value) isLeverage (Optional[int]): Use leverage (0: No use, 1: Use) orderFilter (Optional[str]): Order filter - Order: General order (default) - tpslOrder: TP/SL order - StopOrder: Stop order triggerPrice (Optional[str]): Trigger price triggerBy (Optional[str]): Trigger basis orderIv (Optional[str]): Order volatility positionIdx (Optional[int]): Position index - Required for futures (linear/inverse) trading - 1: Long position - 2: Short position - positionIdx is not used for spot trading takeProfit (Optional[str]): Take profit price stopLoss (Optional[str]): Stop loss price tpTriggerBy (Optional[str]): Take profit trigger basis slTriggerBy (Optional[str]): Stop loss trigger basis tpLimitPrice (Optional[str]): Take profit limit price slLimitPrice (Optional[str]): Stop loss limit price tpOrderType (Optional[str]): Take profit order type (Market, Limit) slOrderType (Optional[str]): Stop loss order type (Market, Limit) Returns: Dict: Order result Example: # Spot trading (SPOT account balance required) place_order("spot", "BTCUSDT", "Buy", "Market", "10") # Buy market price for 10 USDT place_order("spot", "BTCUSDT", "Sell", "Market", "0.000100") # Sell market price for 0.0001 BTC place_order("spot", "BTCUSDT", "Buy", "Limit", "0.000100", price="50000") # Buy limit order for 0.0001 BTC # Spot trading - limit order + TP/SL place_order("spot", "BTCUSDT", "Buy", "Limit", "0.000100", price="50000", takeProfit="55000", stopLoss="45000", # TP/SL setting tpOrderType="Market", slOrderType="Market") # Execute TP/SL as market order # Futures trading place_order("linear", "BTCUSDT", "Buy", "Market", "0.001", positionIdx=1) # Buy market price for long position place_order("linear", "BTCUSDT", "Sell", "Market", "0.001", positionIdx=2) # Sell market price for short position Notes: 1. Spot trading order quantity restrictions: - Minimum order quantity: 0.000011 BTC - Minimum order amount: 5 USDT - BTC quantity is only allowed up to 6 decimal places (e.g., 0.000100 O, 0.0001234 X) 2. Pay attention to unit when buying/selling at market price: - Buying: qty should be input in USDT units (e.g., "10" = 10 USDT) - Selling: qty should be input in BTC units (e.g., "0.000100" = 0.0001 BTC) 3. Futures trading requires positionIdx: - Long position: positionIdx=1 - Short position: positionIdx=2 4. positionIdx is not used for spot trading Reference site: https://bybit-exchange.github.io/docs/v5/order/create-order """ try: # Default settings if timeInForce is None: timeInForce = "IOC" if orderType == "Market" else "GTC" if orderFilter is None: orderFilter = "Order" if isLeverage is None: isLeverage = 0 # Check positionIdx for futures trading if category in ["linear", "inverse"]: if not positionIdx or positionIdx not in ["1", "2"]: return {"error": "positionIdx is required for futures trading (1: Long position, 2: Short position)"} # Ignore positionIdx for spot trading if category == "spot": positionIdx = None # Prepare request data request_data = { "category": category, "symbol": symbol, "side": side, "orderType": orderType, "qty": qty, "timeInForce": timeInForce, "orderFilter": orderFilter, "isLeverage": isLeverage } # Add optional parameters if price is not None: request_data["price"] = price if orderLinkId is not None: request_data["orderLinkId"] = orderLinkId if triggerPrice is not None: request_data["triggerPrice"] = triggerPrice if triggerBy is not None: request_data["triggerBy"] = triggerBy if orderIv is not None: request_data["orderIv"] = orderIv if positionIdx is not None: request_data["positionIdx"] = positionIdx if takeProfit is not None: request_data["takeProfit"] = takeProfit if stopLoss is not None: request_data["stopLoss"] = stopLoss if tpTriggerBy is not None: request_data["tpTriggerBy"] = tpTriggerBy if slTriggerBy is not None: request_data["slTriggerBy"] = slTriggerBy if tpLimitPrice is not None: request_data["tpLimitPrice"] = tpLimitPrice if slLimitPrice is not None: request_data["slLimitPrice"] = slLimitPrice if tpOrderType is not None: request_data["tpOrderType"] = tpOrderType if slOrderType is not None: request_data["slOrderType"] = slOrderType # Execute order result = self.client.place_order(**request_data) # Check minimum order quantity/amount if isinstance(result, dict) and "error" in result: if "min_qty" in result and "min_amt" in result: # Minimum order quantity/amount verification failed logger.error(f"Order execution failed: {result['error']}") return { "error": f"{result['error']} (Minimum order quantity: {result['min_qty']} {symbol.replace('USDT', '')}, Minimum order amount: {result['min_amt']} USDT)" } else: logger.error(f"Order execution failed: {result['error']}") return {"error": result['error']} elif result.get("retCode") != 0: logger.error(f"Order execution failed: {result.get('retMsg')}") return {"error": result.get("retMsg")} return result except Exception as e: logger.error(f"Order execution failed: {e}", exc_info=True) return {"error": str(e)}
- src/server.py:227-227 (registration)The @mcp.tool() decorator registers the place_order function as an MCP tool.@mcp.tool()