place_order
Execute cryptocurrency trades on Bybit exchange by submitting buy or sell orders with configurable parameters for market, limit, and conditional orders.
Instructions
Execute order
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| category | Yes | Category (spot, linear, inverse, etc.) | |
| symbol | Yes | Symbol (e.g., BTCUSDT) | |
| side | Yes | Order direction (Buy, Sell) | |
| orderType | Yes | Order type (Market, Limit) | |
| qty | Yes | Order quantity | |
| price | No | Order price (for limit orders) | |
| positionIdx | No | Position index (1: Long, 2: Short) | |
| timeInForce | No | Time in force (GTC, IOC, FOK, PostOnly) | |
| orderLinkId | No | Order link ID | |
| isLeverage | No | Use leverage (0: No, 1: Yes) | |
| orderFilter | No | Order filter (Order, tpslOrder, StopOrder) | |
| triggerPrice | No | Trigger price | |
| triggerBy | No | Trigger basis | |
| orderIv | No | Order volatility | |
| takeProfit | No | Take profit price | |
| stopLoss | No | Stop loss price | |
| tpTriggerBy | No | Take profit trigger basis | |
| slTriggerBy | No | Stop loss trigger basis | |
| tpLimitPrice | No | Take profit limit price | |
| slLimitPrice | No | Stop loss limit price | |
| tpOrderType | No | Take profit order type (Market, Limit) | |
| slOrderType | No | Stop loss order type (Market, Limit) |
Implementation Reference
- src/bybit-service.ts:276-328 (handler)Core handler function that implements the place_order tool logic: auto-detects position mode for futures, validates parameters, sets defaults, and calls Bybit V5 order create API.async placeOrder(orderRequest: OrderRequest): Promise<BybitResponse<OrderResponse> | { error: string }> { // Auto-detect position mode for futures trading if positionIdx not provided if (['linear', 'inverse'].includes(orderRequest.category) && !orderRequest.positionIdx) { console.log('Auto-detecting position mode for futures trading...'); // Check current positions to determine position mode const currentPositions = await this.getPositions(orderRequest.category, orderRequest.symbol); let detectedPositionIdx = '0'; // Default to one-way mode if ('result' in currentPositions && currentPositions.result.list.length > 0) { // Check if we have separate long/short positions (hedge mode) const positions = currentPositions.result.list; const hasLongPosition = positions.some(p => p.side === 'Buy'); const hasShortPosition = positions.some(p => p.side === 'Sell'); if (hasLongPosition || hasShortPosition) { // Hedge mode detected - use appropriate position index detectedPositionIdx = orderRequest.side === 'Buy' ? '1' : '2'; console.log(`Hedge mode detected, using positionIdx: ${detectedPositionIdx}`); } else { console.log('One-way mode detected, using positionIdx: 0'); } } else { console.log('No existing positions, defaulting to one-way mode (positionIdx: 0)'); } // Set the detected position index orderRequest.positionIdx = detectedPositionIdx; } // Validate positionIdx for futures trading (after auto-detection) if (['linear', 'inverse'].includes(orderRequest.category)) { if (!orderRequest.positionIdx || !['0', '1', '2'].includes(orderRequest.positionIdx)) { return { error: 'Invalid positionIdx. Use 0 for one-way mode, 1 for long position, or 2 for short position in hedge mode' }; } } // Set defaults const requestData = { ...orderRequest, timeInForce: orderRequest.timeInForce || (orderRequest.orderType === 'Market' ? 'IOC' : 'GTC'), orderFilter: orderRequest.orderFilter || 'Order', isLeverage: orderRequest.isLeverage || 0 }; // Remove positionIdx for spot trading if (orderRequest.category === 'spot') { delete requestData.positionIdx; } return this.makeBybitRequest('/v5/order/create', 'POST', requestData); }
- src/index.ts:175-272 (registration)MCP tool registration for 'place_order' including name, description, and detailed input schema.{ name: 'place_order', description: 'Execute order', inputSchema: { type: 'object', properties: { category: { type: 'string', description: 'Category (spot, linear, inverse, etc.)', }, symbol: { type: 'string', description: 'Symbol (e.g., BTCUSDT)', }, side: { type: 'string', description: 'Order direction (Buy, Sell)', }, orderType: { type: 'string', description: 'Order type (Market, Limit)', }, qty: { type: 'string', description: 'Order quantity', }, price: { type: 'string', description: 'Order price (for limit orders)', }, positionIdx: { type: 'string', description: 'Position index (1: Long, 2: Short)', }, timeInForce: { type: 'string', description: 'Time in force (GTC, IOC, FOK, PostOnly)', }, orderLinkId: { type: 'string', description: 'Order link ID', }, isLeverage: { type: 'number', description: 'Use leverage (0: No, 1: Yes)', }, orderFilter: { type: 'string', description: 'Order filter (Order, tpslOrder, StopOrder)', }, triggerPrice: { type: 'string', description: 'Trigger price', }, triggerBy: { type: 'string', description: 'Trigger basis', }, orderIv: { type: 'string', description: 'Order volatility', }, takeProfit: { type: 'string', description: 'Take profit price', }, stopLoss: { type: 'string', description: 'Stop loss price', }, tpTriggerBy: { type: 'string', description: 'Take profit trigger basis', }, slTriggerBy: { type: 'string', description: 'Stop loss trigger basis', }, tpLimitPrice: { type: 'string', description: 'Take profit limit price', }, slLimitPrice: { type: 'string', description: 'Stop loss limit price', }, tpOrderType: { type: 'string', description: 'Take profit order type (Market, Limit)', }, slOrderType: { type: 'string', description: 'Stop loss order type (Market, Limit)', }, }, required: ['category', 'symbol', 'side', 'orderType', 'qty'], }, },
- src/index.ts:793-828 (handler)MCP server request handler switch case that maps input arguments to OrderRequest and delegates to BybitService.placeOrder.case 'place_order': { const orderRequest: OrderRequest = { category: typedArgs.category, symbol: typedArgs.symbol, side: typedArgs.side, orderType: typedArgs.orderType, qty: typedArgs.qty, price: typedArgs.price, timeInForce: typedArgs.timeInForce, orderLinkId: typedArgs.orderLinkId, isLeverage: typedArgs.isLeverage, orderFilter: typedArgs.orderFilter, triggerPrice: typedArgs.triggerPrice, triggerBy: typedArgs.triggerBy, orderIv: typedArgs.orderIv, positionIdx: typedArgs.positionIdx, takeProfit: typedArgs.takeProfit, stopLoss: typedArgs.stopLoss, tpTriggerBy: typedArgs.tpTriggerBy, slTriggerBy: typedArgs.slTriggerBy, tpLimitPrice: typedArgs.tpLimitPrice, slLimitPrice: typedArgs.slLimitPrice, tpOrderType: typedArgs.tpOrderType, slOrderType: typedArgs.slOrderType, }; const result = await this.bybitService.placeOrder(orderRequest); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; }
- src/types.ts:108-131 (schema)TypeScript interface definition for OrderRequest used in place_order implementation for type safety and validation.export interface OrderRequest { category: string; symbol: string; side: 'Buy' | 'Sell'; orderType: 'Market' | 'Limit'; qty: string; price?: string; timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'PostOnly'; orderLinkId?: string; isLeverage?: number; orderFilter?: 'Order' | 'tpslOrder' | 'StopOrder'; triggerPrice?: string; triggerBy?: string; orderIv?: string; positionIdx?: string; takeProfit?: string; stopLoss?: string; tpTriggerBy?: string; slTriggerBy?: string; tpLimitPrice?: string; slLimitPrice?: string; tpOrderType?: 'Market' | 'Limit'; slOrderType?: 'Market' | 'Limit'; }
- src/bybit-service.ts:278-305 (helper)Helper logic within placeOrder for automatic positionIdx detection using current positions to support hedge/one-way modes.if (['linear', 'inverse'].includes(orderRequest.category) && !orderRequest.positionIdx) { console.log('Auto-detecting position mode for futures trading...'); // Check current positions to determine position mode const currentPositions = await this.getPositions(orderRequest.category, orderRequest.symbol); let detectedPositionIdx = '0'; // Default to one-way mode if ('result' in currentPositions && currentPositions.result.list.length > 0) { // Check if we have separate long/short positions (hedge mode) const positions = currentPositions.result.list; const hasLongPosition = positions.some(p => p.side === 'Buy'); const hasShortPosition = positions.some(p => p.side === 'Sell'); if (hasLongPosition || hasShortPosition) { // Hedge mode detected - use appropriate position index detectedPositionIdx = orderRequest.side === 'Buy' ? '1' : '2'; console.log(`Hedge mode detected, using positionIdx: ${detectedPositionIdx}`); } else { console.log('One-way mode detected, using positionIdx: 0'); } } else { console.log('No existing positions, defaulting to one-way mode (positionIdx: 0)'); } // Set the detected position index orderRequest.positionIdx = detectedPositionIdx; }