place_order
Submit market or limit orders to Alpaca paper trading for testing trading strategies with specified symbols, quantities, and order types.
Instructions
Submits a market or limit order to Alpaca paper trading.
Args:
symbol: Ticker symbol.
side: 'buy' or 'sell'.
qty: Quantity to trade.
order_type: 'market' or 'limit'.
limit_price: Required if order_type is 'limit'.
Returns:
Confirmation message or error
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | ||
| side | Yes | ||
| qty | Yes | ||
| order_type | No | market | |
| limit_price | No |
Implementation Reference
- tools/execution.py:57-138 (handler)Core handler function for placing market or limit orders via Alpaca broker. Includes pre-trade risk validation, price fetching, and detailed order confirmation responses.def place_order( symbol: str, side: Literal["buy", "sell"], qty: float, order_type: Literal["market", "limit"] = "market", limit_price: Optional[float] = None ) -> str: """ Submits a market or limit order to Alpaca paper trading. Args: symbol: Ticker symbol. side: 'buy' or 'sell'. qty: Quantity to trade. order_type: 'market' or 'limit'. limit_price: Required if order_type is 'limit'. Returns: Confirmation message or error """ if broker is None: return "ERROR: Alpaca broker not initialized. Check your API credentials in .env file." # Import here to avoid circular dependency from tools.risk_engine import validate_trade try: # Get current price for risk validation ticker = yf.Ticker(symbol) try: current_price = ticker.fast_info.last_price except: return f"Failed to get price for {symbol}" if current_price is None: return f"Failed to get price for {symbol}" # Pre-Trade Risk Check risk_error = validate_trade(symbol, side, qty, current_price) if risk_error: logger.warning(f"Trade rejected by risk engine: {risk_error}") return risk_error # Submit order to Alpaca if order_type == "market": logger.info(f"Submitting MARKET order: {side.upper()} {qty} {symbol}") order_result = broker.submit_market_order(symbol, side, qty) logger.info(f"Order submitted successfully: ID={order_result['order_id']}") return ( f"✅ Market Order Submitted: {side.upper()} {qty} {symbol}\n" f"Order ID: {order_result['order_id']}\n" f"Status: {order_result['status']}\n" f"Submitted at: {order_result['submitted_at']}" ) elif order_type == "limit": if not limit_price: return "ERROR: Limit price required for limit orders." # Validate limit price direction if side == "buy" and limit_price > current_price: logger.warning(f"Buy limit {limit_price} is above market {current_price}") if side == "sell" and limit_price < current_price: logger.warning(f"Sell limit {limit_price} is below market {current_price}") logger.info(f"Submitting LIMIT order: {side.upper()} {qty} {symbol} @ ${limit_price}") order_result = broker.submit_limit_order(symbol, side, qty, limit_price) logger.info(f"Order submitted successfully: ID={order_result['order_id']}") return ( f"✅ Limit Order Submitted: {side.upper()} {qty} {symbol} @ ${limit_price:.2f}\n" f"Order ID: {order_result['order_id']}\n" f"Status: {order_result['status']}\n" f"Submitted at: {order_result['submitted_at']}" ) else: logger.error(f"Unknown order type requested: {order_type}") return f"ERROR: Unknown order type: {order_type}" except Exception as e: logger.error(f"Order failed: {e}", exc_info=True) return f"ERROR: Order failed - {str(e)}"
- server.py:375-378 (registration)Registration of the place_order tool (along with other execution tools) using the register_tools helper, which applies the @mcp.tool() decorator for MCP integration.register_tools( [place_order, cancel_order, get_positions, flatten, get_order_history], "Execution" )
- server.py:355-364 (helper)Helper function that dynamically registers tools by applying the FastMCP @mcp.tool() decorator and logging the process.def register_tools(tools: List[Callable], category: str): """Helper to register multiple tools with logging.""" for tool in tools: try: mcp.tool()(tool) logger.info(f"Registered {category} tool: {tool.__name__}") except Exception as e: logger.error(f"Failed to register {tool.__name__}: {e}") raise