Skip to main content
Glama

start_grid_strategy

Calculate and place grid trading orders around current prices to automate market making strategies on supported cryptocurrency exchanges.

Instructions

Calculate and optionally place grid trading orders around the current price

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
exchangeYesExchange to query. Supported: mexc, gateio, bitget, kraken
symbolYesTrading pair symbol (e.g., BTC/USDT, INDY/USDT)
levelsNoGrid levels per side (default: 5)
spacingNoBase spacing as decimal (default: 0.02 = 2%)
orderSizeNoBase order size in quote currency (default: 50)
spacingModelNoSpacing modellinear
spacingFactorNoFactor for geometric spacing (default: 1.3)
sizeModelNoSize modelflat
dryRunNoPreview grid without placing orders (default: true)

Implementation Reference

  • The main handler function for start_grid_strategy tool. It validates exchange and symbol parameters, fetches the current ticker price, calculates grid levels, optionally places orders based on dryRun flag, and returns a detailed response with grid configuration, calculated levels, and order results.
    async ({
      exchange,
      symbol,
      levels,
      spacing,
      orderSize,
      spacingModel,
      spacingFactor,
      sizeModel,
      dryRun,
    }) => {
      const validExchange = validateExchange(exchange);
      const validSymbol = validateSymbol(symbol);
    
      const connector = await getConnectorSafe(exchange);
      const ticker = await connector.getTicker(validSymbol);
      const centerPrice = ticker.last;
    
      const grid = calculateGridLevels(
        centerPrice,
        levels,
        spacing,
        spacingModel,
        spacingFactor,
        orderSize,
        sizeModel
      );
    
      const placedOrders: any[] = [];
      if (!dryRun) {
        for (const level of grid) {
          const order = await connector.createOrder(
            validSymbol,
            'limit',
            level.side,
            level.orderSize,
            level.price
          );
          placedOrders.push(order);
        }
      }
    
      return {
        content: [
          {
            type: 'text' as const,
            text: JSON.stringify(
              {
                status: dryRun ? 'preview' : 'active',
                centerPrice,
                config: { levels, spacing, spacingModel, spacingFactor, orderSize, sizeModel },
                grid: grid.map((l) => ({
                  side: l.side,
                  price: l.price,
                  amount: l.orderSize,
                  valueQuote: l.price * l.orderSize,
                })),
                totalOrders: grid.length,
                totalBuyValue: grid
                  .filter((l) => l.side === 'buy')
                  .reduce((s, l) => s + l.price * l.orderSize, 0),
                totalSellValue: grid
                  .filter((l) => l.side === 'sell')
                  .reduce((s, l) => s + l.price * l.orderSize, 0),
                ...(dryRun ? {} : { placedOrders }),
                exchange: validExchange,
                symbol: validSymbol,
                timestamp: new Date().toISOString(),
              },
              null,
              2
            ),
          },
        ],
      };
    }
  • Zod schema definition for start_grid_strategy tool parameters. Defines validation rules for exchange, symbol, levels, spacing, orderSize, spacingModel, spacingFactor, sizeModel, and dryRun parameters with appropriate constraints and defaults.
      exchange: ExchangeParam,
      symbol: SymbolParam,
      levels: z.number().min(1).max(10).default(5).describe('Grid levels per side (default: 5)'),
      spacing: z
        .number()
        .min(0.001)
        .max(0.5)
        .default(0.02)
        .describe('Base spacing as decimal (default: 0.02 = 2%)'),
      orderSize: z
        .number()
        .positive()
        .default(50)
        .describe('Base order size in quote currency (default: 50)'),
      spacingModel: z.enum(['linear', 'geometric']).default('linear').describe('Spacing model'),
      spacingFactor: z
        .number()
        .positive()
        .default(1.3)
        .describe('Factor for geometric spacing (default: 1.3)'),
      sizeModel: z.enum(['flat', 'pyramidal']).default('flat').describe('Size model'),
      dryRun: z
        .boolean()
        .default(true)
        .describe('Preview grid without placing orders (default: true)'),
    },
  • Registration of start_grid_strategy tool with the MCP server. The registerStrategyTools function calls server.tool() with the tool name, description, schema, and handler function to register it as an available MCP tool.
    export function registerStrategyTools(server: McpServer): void {
      server.tool(
        'start_grid_strategy',
        'Calculate and optionally place grid trading orders around the current price',
        {
          exchange: ExchangeParam,
          symbol: SymbolParam,
          levels: z.number().min(1).max(10).default(5).describe('Grid levels per side (default: 5)'),
          spacing: z
            .number()
            .min(0.001)
            .max(0.5)
            .default(0.02)
            .describe('Base spacing as decimal (default: 0.02 = 2%)'),
          orderSize: z
            .number()
            .positive()
            .default(50)
            .describe('Base order size in quote currency (default: 50)'),
          spacingModel: z.enum(['linear', 'geometric']).default('linear').describe('Spacing model'),
          spacingFactor: z
            .number()
            .positive()
            .default(1.3)
            .describe('Factor for geometric spacing (default: 1.3)'),
          sizeModel: z.enum(['flat', 'pyramidal']).default('flat').describe('Size model'),
          dryRun: z
            .boolean()
            .default(true)
            .describe('Preview grid without placing orders (default: true)'),
        },
        async ({
          exchange,
          symbol,
          levels,
          spacing,
          orderSize,
          spacingModel,
          spacingFactor,
          sizeModel,
          dryRun,
        }) => {
          const validExchange = validateExchange(exchange);
          const validSymbol = validateSymbol(symbol);
    
          const connector = await getConnectorSafe(exchange);
          const ticker = await connector.getTicker(validSymbol);
          const centerPrice = ticker.last;
    
          const grid = calculateGridLevels(
            centerPrice,
            levels,
            spacing,
            spacingModel,
            spacingFactor,
            orderSize,
            sizeModel
          );
    
          const placedOrders: any[] = [];
          if (!dryRun) {
            for (const level of grid) {
              const order = await connector.createOrder(
                validSymbol,
                'limit',
                level.side,
                level.orderSize,
                level.price
              );
              placedOrders.push(order);
            }
          }
    
          return {
            content: [
              {
                type: 'text' as const,
                text: JSON.stringify(
                  {
                    status: dryRun ? 'preview' : 'active',
                    centerPrice,
                    config: { levels, spacing, spacingModel, spacingFactor, orderSize, sizeModel },
                    grid: grid.map((l) => ({
                      side: l.side,
                      price: l.price,
                      amount: l.orderSize,
                      valueQuote: l.price * l.orderSize,
                    })),
                    totalOrders: grid.length,
                    totalBuyValue: grid
                      .filter((l) => l.side === 'buy')
                      .reduce((s, l) => s + l.price * l.orderSize, 0),
                    totalSellValue: grid
                      .filter((l) => l.side === 'sell')
                      .reduce((s, l) => s + l.price * l.orderSize, 0),
                    ...(dryRun ? {} : { placedOrders }),
                    exchange: validExchange,
                    symbol: validSymbol,
                    timestamp: new Date().toISOString(),
                  },
                  null,
                  2
                ),
              },
            ],
          };
        }
      );
  • Helper function calculateGridLevels that computes buy and sell grid levels around a center price. Supports linear or geometric spacing models and flat or pyramidal size models to determine order distribution.
    function calculateGridLevels(
      centerPrice: number,
      levels: number,
      spacing: number,
      spacingModel: 'linear' | 'geometric',
      spacingFactor: number,
      orderSize: number,
      sizeModel: 'flat' | 'pyramidal'
    ): GridLevel[] {
      const spacings: number[] = [];
      for (let i = 1; i <= levels; i++) {
        if (spacingModel === 'geometric') {
          let cumulative = 0;
          for (let j = 0; j < i; j++) {
            cumulative += spacing * Math.pow(spacingFactor, j);
          }
          spacings.push(cumulative);
        } else {
          spacings.push(spacing * i);
        }
      }
    
      const weights: number[] = [];
      if (sizeModel === 'pyramidal') {
        const raw = Array.from({ length: levels }, (_, i) => levels - i);
        const sum = raw.reduce((a, b) => a + b, 0);
        const norm = levels / sum;
        raw.forEach((w) => weights.push(w * norm));
      } else {
        for (let i = 0; i < levels; i++) weights.push(1.0);
      }
    
      const grid: GridLevel[] = [];
      for (let i = 0; i < spacings.length; i++) {
        const buyPrice = centerPrice * (1 - spacings[i]);
        const sellPrice = centerPrice * (1 + spacings[i]);
        const size = orderSize * weights[i];
    
        grid.push({ price: buyPrice, side: 'buy', orderSize: size / buyPrice });
        grid.push({ price: sellPrice, side: 'sell', orderSize: size / sellPrice });
      }
    
      return grid;
    }
  • Zod schema definitions for ExchangeParam and SymbolParam used by the start_grid_strategy tool for parameter validation.
    export const ExchangeParam = z
      .string()
      .describe('Exchange to query. Supported: mexc, gateio, bitget, kraken');
    
    export const SymbolParam = z.string().describe('Trading pair symbol (e.g., BTC/USDT, INDY/USDT)');

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/QBT-Labs/openmm-mcp'

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