Skip to content

Market Making

Examples for building a market maker with the 100x SDK.

Setup

typescript
import { HundredX, HundredXApiError } from '100x-sdk';

const sdk = await HundredX.create({
  privateKey: process.env.PRIVATE_KEY!,
  brokerId: Number(process.env.BROKER_ID!),
});

const MARKET_ID = 1;      // ETH-USD
const SIZE = '0.5';
const SPREAD_BPS = 10;    // 10 basis points each side

Basic Spread Quoting

Post a bid and ask around a mid price:

typescript
async function quoteAroundMid(midPrice: number) {
  const halfSpread = midPrice * (SPREAD_BPS / 10000);
  const bidPx = (midPrice - halfSpread).toFixed(2);
  const askPx = (midPrice + halfSpread).toFixed(2);

  // Place bid
  const bid = await sdk.exchange.placeOrder({
    marketId: MARKET_ID,
    isBuy: true,
    amount: SIZE,
    price: bidPx,
    orderType: 'LIMIT',
  });

  // Place ask
  const ask = await sdk.exchange.placeOrder({
    marketId: MARKET_ID,
    isBuy: false,
    amount: SIZE,
    price: askPx,
    orderType: 'LIMIT',
  });

  console.log(`Quoted: ${bidPx} / ${askPx}`);
  return { bid, ask };
}

await quoteAroundMid(2500);

Cancel-and-Replace Loop

A market maker typically refreshes quotes periodically:

typescript
async function marketMakingLoop(getPrice: () => number) {
  while (true) {
    // 1. Cancel all existing orders for this market
    await sdk.exchange.cancelAllOrders(MARKET_ID);

    // 2. Get fresh mid price
    const mid = getPrice();

    // 3. Place new quotes
    await quoteAroundMid(mid);

    // 4. Wait before refreshing
    await sleep(2000);
  }
}

function sleep(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Inventory-Aware Skew

Shift your quotes based on current inventory to manage risk:

typescript
async function skewedQuote(midPrice: number) {
  // Check current position
  const result = await sdk.info.getPositions();
  const position = result.positions.find(p => p.productID === MARKET_ID);

  // Calculate skew: positive inventory -> widen bid, tighten ask
  const inventorySize = position ? parseFloat(position.vBalanceAmount) / 1e18 : 0;
  const maxInventory = 5.0;
  const skewBps = (inventorySize / maxInventory) * 5;

  const halfSpread = midPrice * (SPREAD_BPS / 10000);
  const bidPx = (midPrice - halfSpread - midPrice * (skewBps / 10000)).toFixed(2);
  const askPx = (midPrice + halfSpread - midPrice * (skewBps / 10000)).toFixed(2);

  await sdk.exchange.cancelAllOrders(MARKET_ID);

  await sdk.exchange.placeOrder({
    marketId: MARKET_ID,
    isBuy: true,
    amount: SIZE,
    price: bidPx,
    orderType: 'LIMIT',
  });

  await sdk.exchange.placeOrder({
    marketId: MARKET_ID,
    isBuy: false,
    amount: SIZE,
    price: askPx,
    orderType: 'LIMIT',
  });

  console.log(`Skewed quote: ${bidPx} / ${askPx} (inventory: ${inventorySize.toFixed(4)})`);
}

Full Market Maker Example

typescript
import { HundredX, HundredXApiError } from '100x-sdk';

async function runMarketMaker() {
  const sdk = await HundredX.create({
    privateKey: process.env.PRIVATE_KEY!,
    brokerId: Number(process.env.BROKER_ID!),
  });

  const MARKET_ID = 1;
  const SIZE = '0.5';
  const SPREAD_BPS = 10;
  const REFRESH_MS = 3000;

  let refPrice = 2500;

  console.log(`Starting market maker for market ${MARKET_ID}`);
  console.log(`Size: ${SIZE}, Spread: ${SPREAD_BPS}bps, Refresh: ${REFRESH_MS}ms`);

  while (true) {
    try {
      // Cancel stale quotes
      await sdk.exchange.cancelAllOrders(MARKET_ID);

      // Place fresh quotes
      const halfSpread = refPrice * (SPREAD_BPS / 10000);
      const bid = (refPrice - halfSpread).toFixed(2);
      const ask = (refPrice + halfSpread).toFixed(2);

      await sdk.exchange.placeOrder({
        marketId: MARKET_ID,
        isBuy: true,
        amount: SIZE,
        price: bid,
        orderType: 'LIMIT',
      });

      await sdk.exchange.placeOrder({
        marketId: MARKET_ID,
        isBuy: false,
        amount: SIZE,
        price: ask,
        orderType: 'LIMIT',
      });

      console.log(`[${new Date().toISOString()}] ${bid} / ${ask}`);

      // Check buying power
      const bp = await sdk.info.getBuyingPower();
      console.log(`  Buying power: ${bp.totalBuyingPower}`);

    } catch (error) {
      if (error instanceof HundredXApiError) {
        console.error(`API Error: ${error.message}`);
      } else {
        throw error;
      }
    }

    await new Promise(resolve => setTimeout(resolve, REFRESH_MS));
  }
}

runMarketMaker().catch(console.error);

100x Exchange Market Maker SDK