Skip to main content
Glama

trade_preview

Preview trade details before execution to review estimated fill price, fees, margin impact, and risk checks for perpetual futures trading.

Instructions

Preview a trade WITHOUT executing. Returns estimated fill price, fees, margin impact, and risk checks. ALWAYS call this before trade_execute and show the result to the user for confirmation.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
exchangeYesExchange: pacifica, hyperliquid, or lighter
symbolYesTrading symbol (e.g., BTC, ETH, SOL)
sideYesOrder side
sizeYesOrder size (base currency units, e.g., '0.1' for 0.1 BTC)
orderTypeNoOrder typemarket
priceNoLimit price (required for limit orders)

Implementation Reference

  • The `trade_preview` MCP tool implementation in `src/mcp-server.ts`. It fetches market data, validates the trade, and returns a preview object.
    server.tool(
      "trade_preview",
      "Preview a trade WITHOUT executing. Returns estimated fill price, fees, margin impact, and risk checks. ALWAYS call this before trade_execute and show the result to the user for confirmation.",
      {
        exchange: z.string().describe("Exchange: pacifica, hyperliquid, or lighter"),
        symbol: z.string().describe("Trading symbol (e.g., BTC, ETH, SOL)"),
        side: z.enum(["buy", "sell"]).describe("Order side"),
        size: z.string().describe("Order size (base currency units, e.g., '0.1' for 0.1 BTC)"),
        orderType: z.enum(["market", "limit"]).default("market").describe("Order type"),
        price: z.string().optional().describe("Limit price (required for limit orders)"),
      },
      async ({ exchange, symbol, side, size, orderType, price }) => {
        try {
          const adapter = await getOrCreateAdapter(exchange);
          const [balance, positions, orderbook] = await Promise.all([
            adapter.getBalance(),
            adapter.getPositions(),
            adapter.getOrderbook(symbol),
          ]);
    
          // Estimate fill price from orderbook
          const bestBid = orderbook.bids[0]?.[0];
          const bestAsk = orderbook.asks[0]?.[0];
          const estPrice = orderType === "limit" && price
            ? price
            : side === "buy" ? bestAsk : bestBid;
    
          const notional = estPrice ? Number(estPrice) * Number(size) : 0;
          const existingPos = positions.find(p => p.symbol.toUpperCase().includes(symbol.toUpperCase()));
    
          // Run validation
          let validation;
          try {
            validation = await validateTrade(adapter, { symbol, side, size: Number(size), leverage: existingPos?.leverage ?? 1 });
          } catch {
            validation = { valid: true, checks: [], warnings: ["Validation unavailable — proceed with caution"] };
          }
    
          const preview = {
            order: { exchange, symbol, side, size, orderType, price: price ?? estPrice },
            estimate: {
              fillPrice: estPrice ?? "unknown",
              notionalUsd: notional.toFixed(2),
              spread: bestBid && bestAsk ? ((Number(bestAsk) - Number(bestBid)) / Number(bestBid) * 100).toFixed(4) + "%" : "unknown",
            },
            account: {
              equity: balance.equity,
              available: balance.available,
              marginUsed: balance.marginUsed,
              marginAfter: (Number(balance.marginUsed) + notional / (existingPos?.leverage ?? 1)).toFixed(2),
            },
            existingPosition: existingPos ? {
              side: existingPos.side,
              size: existingPos.size,
              entryPrice: existingPos.entryPrice,
              unrealizedPnl: existingPos.unrealizedPnl,
            } : null,
            validation,
            warning: "This is a PREVIEW only. Call trade_execute to place the order after user confirms.",
          };
    
          return { content: [{ type: "text", text: ok(preview, { exchange, type: "preview" }) }] };
        } catch (e) {
          return { content: [{ type: "text", text: err(e instanceof Error ? e.message : String(e)) }], isError: true };
        }
      },
    );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hypurrquant/perp-cli'

If you have feedback or need assistance with the MCP directory API, please join our Discord server