Skip to main content
Glama
gtorreal
by gtorreal

simulate_order

Simulate a buy or sell order on Buda.com using live ticker data to estimate fill price, fees, total cost, and slippage. No real order is placed.

Instructions

[DEPRECATED: prefer get_real_quotation for server-side accurate quotes] Simulates a buy or sell order on Buda.com using live ticker data — no order is placed. Returns estimated fill price, fee, total cost, and slippage vs mid-price. Omit 'price' for a market order simulation; supply 'price' for a limit order simulation. All outputs are labelled simulation: true — this tool never places a real order. Example: 'How much would it cost to buy 0.01 BTC on BTC-CLP right now?'

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
market_idYesMarket ID (e.g. 'BTC-CLP', 'ETH-BTC').
sideYes'buy' or 'sell'.
amountYesOrder size in base currency (e.g. BTC for BTC-CLP).
priceNoLimit price in quote currency. Omit for a market order simulation.

Implementation Reference

  • Main handler function 'handleSimulateOrder' that executes the order simulation logic. Fetches ticker and market data via cache, computes estimated fill price, fee, total cost, and slippage vs mid-price. Supports both market (no price) and limit (with price) order simulation.
    export async function handleSimulateOrder(
      args: SimulateOrderArgs,
      client: BudaClient,
      cache: MemoryCache,
    ): Promise<{ content: Array<{ type: "text"; text: string }>; isError?: boolean }> {
      const { market_id, side, amount, price } = args;
    
      const validationError = validateMarketId(market_id);
      if (validationError) {
        return {
          content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_MARKET_ID" }) }],
          isError: true,
        };
      }
    
      try {
        const id = market_id.toLowerCase();
    
        const [tickerData, marketData] = await Promise.all([
          cache.getOrFetch<TickerResponse>(
            `ticker:${id}`,
            CACHE_TTL.TICKER,
            () => client.get<TickerResponse>(`/markets/${id}/ticker`),
          ),
          cache.getOrFetch<MarketResponse>(
            `market:${id}`,
            CACHE_TTL.MARKETS,
            () => client.get<MarketResponse>(`/markets/${id}`),
          ),
        ]);
    
        const ticker = tickerData.ticker;
        const market = marketData.market;
    
        const minAsk = parseFloat(ticker.min_ask[0]);
        const maxBid = parseFloat(ticker.max_bid[0]);
        const quoteCurrency = ticker.min_ask[1];
    
        if (isNaN(minAsk) || isNaN(maxBid) || minAsk <= 0 || maxBid <= 0) {
          return {
            content: [
              {
                type: "text",
                text: JSON.stringify({
                  error: "Unable to simulate: invalid or zero bid/ask values in ticker.",
                  code: "INVALID_TICKER",
                }),
              },
            ],
            isError: true,
          };
        }
    
        const mid = (minAsk + maxBid) / 2;
        const takerFeeRate = parseFloat(market.taker_fee) / 100;
        const orderTypeAssumed = price !== undefined ? "limit" : "market";
    
        let estimatedFillPrice: number;
    
        if (orderTypeAssumed === "market") {
          estimatedFillPrice = side === "buy" ? minAsk : maxBid;
        } else {
          // Limit order: fill at provided price if it crosses the spread, otherwise at limit price
          if (side === "buy") {
            estimatedFillPrice = price! >= minAsk ? minAsk : price!;
          } else {
            estimatedFillPrice = price! <= maxBid ? maxBid : price!;
          }
        }
    
        const grossValue = amount * estimatedFillPrice;
        const feeAmount = parseFloat((grossValue * takerFeeRate).toFixed(8));
        const totalCost = side === "buy"
          ? parseFloat((grossValue + feeAmount).toFixed(8))
          : parseFloat((grossValue - feeAmount).toFixed(8));
    
        const slippageVsMidPct = parseFloat(
          (((estimatedFillPrice - mid) / mid) * 100).toFixed(4),
        );
    
        const result = {
          simulation: true,
          market_id: ticker.market_id,
          side,
          amount,
          order_type_assumed: orderTypeAssumed,
          estimated_fill_price: parseFloat(estimatedFillPrice.toFixed(2)),
          price_currency: quoteCurrency,
          fee_amount: feeAmount,
          fee_currency: quoteCurrency,
          fee_rate_pct: parseFloat((takerFeeRate * 100).toFixed(3)),
          total_cost: totalCost,
          slippage_vs_mid_pct: slippageVsMidPct,
          mid_price: parseFloat(mid.toFixed(2)),
        };
    
        return {
          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
        };
      } catch (err) {
        const msg = formatApiError(err);
        return {
          content: [{ type: "text", text: JSON.stringify(msg) }],
          isError: true,
        };
      }
    }
  • TypeScript type 'SimulateOrderArgs' defining the input arguments: market_id, side (buy/sell), amount, and optional price.
    type SimulateOrderArgs = {
      market_id: string;
      side: "buy" | "sell";
      amount: number;
      price?: number;
    };
  • Exported 'toolSchema' object containing the tool name ('simulate_order'), description (marking it deprecated in favor of get_real_quotation), and JSON Schema input definition.
    export const toolSchema = {
      name: "simulate_order",
      description:
        "[DEPRECATED: prefer get_real_quotation for server-side accurate quotes] " +
        "Simulates a buy or sell order on Buda.com using live ticker data — no order is placed. " +
        "Returns estimated fill price, fee, total cost, and slippage vs mid-price. " +
        "Omit 'price' for a market order simulation; supply 'price' for a limit order simulation. " +
        "All outputs are labelled simulation: true — this tool never places a real order. " +
        "Example: 'How much would it cost to buy 0.01 BTC on BTC-CLP right now?'",
      inputSchema: {
        type: "object" as const,
        properties: {
          market_id: {
            type: "string",
            description: "Market ID (e.g. 'BTC-CLP', 'ETH-BTC').",
          },
          side: {
            type: "string",
            description: "'buy' or 'sell'.",
          },
          amount: {
            type: "number",
            description: "Order size in base currency (e.g. BTC for BTC-CLP).",
          },
          price: {
            type: "number",
            description:
              "Limit price in quote currency. Omit for a market order simulation.",
          },
        },
        required: ["market_id", "side", "amount"],
      },
    };
  • Registration function that calls server.tool() with the schema, Zod-validated args, and the handler callback.
    export function register(server: McpServer, client: BudaClient, cache: MemoryCache): void {
      server.tool(
        toolSchema.name,
        toolSchema.description,
        {
          market_id: z
            .string()
            .describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
          side: z
            .enum(["buy", "sell"])
            .describe("'buy' or 'sell'."),
          amount: z
            .number()
            .positive()
            .describe("Order size in base currency (e.g. BTC for BTC-CLP)."),
          price: z
            .number()
            .positive()
            .optional()
            .describe("Limit price in quote currency. Omit for a market order simulation."),
        },
        (args) => handleSimulateOrder(args, client, cache),
      );
    }
  • Helper function 'validateMarketId' used by the handler to validate the market_id format (BASE-QUOTE with 2-10 alphanumeric chars per part).
    export function validateMarketId(id: string): string | null {
      if (!MARKET_ID_RE.test(id)) {
        return (
          `Invalid market ID. ` +
          `Expected format: BASE-QUOTE with 2–10 alphanumeric characters per part ` +
          `(e.g. "BTC-CLP", "ETH-BTC").`
        );
      }
      return null;
    }
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

State that no real order is placed, outputs are labeled simulation:true, and lists returned estimates (fill price, fee, cost, slippage). No annotations exist, so description fully covers behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences plus an example. Very concise: starts with deprecation, then core functionality, usage rules, safety guarantee, and an example. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Completely covers how to use both market and limit order simulations, what outputs to expect, and reaffirms no real order is placed. No output schema, so description adequately explains return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline 3. Description adds value by explaining the role of the 'price' parameter (optional, omitted for market orders) and clarifies that 'amount' is in base currency. Adds context beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it simulates a buy or sell order on Buda.com using live ticker data, and explicitly distinguishes from the preferred sibling get_real_quotation by marking itself as deprecated. The verb 'simulate' and resource 'order on Buda.com' are specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit instructions: omit price for market order simulation, supply price for limit order simulation. Includes an example query. Does not explicitly exclude other tools but the deprecation note guides toward get_real_quotation for accuracy.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/gtorreal/buda-mcp'

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