Skip to main content

Agent Infrastructure Overview

Build sophisticated automated trading agents using Matchr’s infrastructure. Our platform provides the building blocks for algorithmic trading on prediction markets.
For Institutional Traders — Agent infrastructure is designed for quantitative teams building automated strategies.

Architecture

┌─────────────────────────────────────────────────────────────┐
│                      Your Trading Agent                      │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐       │
│   │  Strategy   │   │   Signal    │   │   Risk      │       │
│   │   Engine    │──▶│  Generator  │──▶│  Manager    │       │
│   └─────────────┘   └─────────────┘   └─────────────┘       │
│          │                                    │               │
│          ▼                                    ▼               │
│   ┌─────────────────────────────────────────────────┐       │
│   │               Execution Engine                   │       │
│   └─────────────────────────────────────────────────┘       │
│                           │                                   │
└───────────────────────────┼───────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│                     Matchr API Layer                         │
├─────────────────────────────────────────────────────────────┤
│  REST API  │  WebSocket  │  Smart Routing  │  Webhooks      │
└─────────────────────────────────────────────────────────────┘


┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│ Polymarket  │   │   Kalshi    │   │   Future    │
│    CLOB     │   │     API     │   │  Platforms  │
└─────────────┘   └─────────────┘   └─────────────┘

Getting Started

1. API Key with Agent Permissions

Request an API key with elevated rate limits:
curl -X POST "https://api.matchr.xyz/v1/api-keys" \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Trading Agent",
    "type": "agent",
    "permissions": ["read", "trade", "manage_orders"]
  }'
Agent keys have:
  • 10,000 requests/minute (vs 1,000 for standard)
  • Priority WebSocket connections
  • Dedicated support channel

2. Install the SDK

npm install @matchr/agent-sdk

3. Initialize the Client

import { MatchrAgent } from '@matchr/agent-sdk';

const agent = new MatchrAgent({
apiKey: process.env.MATCHR_API_KEY,
environment: 'production', // or 'sandbox'
walletId: 'wallet_abc123'
});

await agent.connect();


Real-Time Data Streams

Subscribe to Price Updates

// Subscribe to multiple markets
agent.subscribe(["mkt_yes123", "mkt_no456"], (update) => {
  console.log(`${update.market_id}: ${update.price}`);

  // React to price changes
  if (update.price < 0.4 && shouldBuy(update.market_id)) {
    agent.submitOrder({
      market_id: update.market_id,
      side: "buy",
      type: "limit",
      price: update.price,
      amount: 100,
    });
  }
});

Subscribe to Orderbook

agent.subscribeOrderbook("mkt_yes123", (orderbook) => {
  const spread = orderbook.asks[0].price - orderbook.bids[0].price;
  const midPrice = (orderbook.asks[0].price + orderbook.bids[0].price) / 2;

  console.log(`Spread: ${spread}, Mid: ${midPrice}`);
});

Subscribe to Trades

agent.subscribeTrades("mkt_yes123", (trade) => {
  console.log(`Trade: ${trade.side} ${trade.size} @ ${trade.price}`);

  // Track flow
  flowTracker.add(trade);
});

Execution Engine

Smart Order Submission

// Market order with slippage protection
const order = await agent.submitOrder({
  market_id: "mkt_yes123",
  side: "buy",
  type: "market",
  amount: 1000,
  max_slippage: 0.02, // 2% max slippage
});

// Limit order
const limitOrder = await agent.submitOrder({
  market_id: "mkt_yes123",
  side: "buy",
  type: "limit",
  price: 0.5,
  amount: 500,
  time_in_force: "GTC",
});

TWAP Execution

Split large orders over time to minimize market impact:
const twapOrder = await agent.executeTWAP({
  market_id: "mkt_yes123",
  side: "buy",
  total_amount: 10000,
  duration_minutes: 60,
  slice_count: 12, // Execute every 5 minutes
  price_limit: 0.55, // Don't buy above this price
});

// Monitor progress
twapOrder.on("slice_executed", (slice) => {
  console.log(`Slice ${slice.index}: ${slice.amount} @ ${slice.price}`);
});

twapOrder.on("completed", (summary) => {
  console.log(`TWAP complete. Avg price: ${summary.average_price}`);
});

Iceberg Orders

Execute large orders in smaller visible pieces:
const icebergOrder = await agent.executeIceberg({
  market_id: "mkt_yes123",
  side: "buy",
  total_amount: 5000,
  visible_amount: 200, // Show only 200 at a time
  price: 0.52,
  variance: 0.001, // Random variance in visible size
});

Strategy Building Blocks

Market Making

class SimpleMarketMaker {
  constructor(agent, config) {
    this.agent = agent;
    this.spread = config.spread || 0.02;
    this.size = config.size || 100;
    this.maxPosition = config.maxPosition || 1000;
  }

  async run(marketId) {
    const position = await this.agent.getPosition(marketId);
    const orderbook = await this.agent.getOrderbook(marketId);

    const midPrice = (orderbook.bids[0].price + orderbook.asks[0].price) / 2;

    // Adjust quotes based on position
    const skew = (position.size / this.maxPosition) * this.spread;

    const bidPrice = midPrice - this.spread / 2 - skew;
    const askPrice = midPrice + this.spread / 2 - skew;

    // Cancel existing orders
    await this.agent.cancelAllOrders(marketId);

    // Place new quotes
    if (position.size < this.maxPosition) {
      await this.agent.submitOrder({
        market_id: marketId,
        side: "buy",
        type: "limit",
        price: bidPrice,
        amount: this.size,
      });
    }

    if (position.size > -this.maxPosition) {
      await this.agent.submitOrder({
        market_id: marketId,
        side: "sell",
        type: "limit",
        price: askPrice,
        amount: this.size,
      });
    }
  }
}

Arbitrage Detection

class ArbitrageScanner {
  constructor(agent, minSpread = 0.03) {
    this.agent = agent;
    this.minSpread = minSpread;
  }

  async scan() {
    const matches = await this.agent.getMatchedMarkets();
    const opportunities = [];

    for (const match of matches) {
      const spread = Math.abs(
        match.polymarket.yes_price - match.kalshi.yes_price
      );

      if (spread > this.minSpread) {
        opportunities.push({
          match_id: match.id,
          title: match.title,
          spread,
          buy_platform:
            match.polymarket.yes_price < match.kalshi.yes_price
              ? "polymarket"
              : "kalshi",
          sell_platform:
            match.polymarket.yes_price < match.kalshi.yes_price
              ? "kalshi"
              : "polymarket",
          expected_profit: spread - this.estimateFees(match),
        });
      }
    }

    return opportunities.sort((a, b) => b.expected_profit - a.expected_profit);
  }
}

Signal Generation

class MomentumSignal {
  constructor(lookbackPeriod = 24) {
    this.lookbackPeriod = lookbackPeriod; // hours
    this.priceHistory = new Map();
  }

  async generate(marketId, currentPrice) {
    const history = await this.getPriceHistory(marketId);

    if (history.length < this.lookbackPeriod) {
      return { signal: "neutral", confidence: 0 };
    }

    const oldPrice = history[0].price;
    const momentum = (currentPrice - oldPrice) / oldPrice;

    if (momentum > 0.05) {
      return { signal: "bullish", confidence: Math.min(momentum * 10, 1) };
    } else if (momentum < -0.05) {
      return { signal: "bearish", confidence: Math.min(-momentum * 10, 1) };
    }

    return { signal: "neutral", confidence: 0 };
  }
}

Risk Management

Position Limits

const riskManager = agent.createRiskManager({
  maxPositionSize: 10000, // Max $10K per position
  maxTotalExposure: 50000, // Max $50K total
  maxDailyLoss: 2000, // Stop trading if down $2K/day
  maxDrawdown: 0.15, // 15% max drawdown
  categoryLimits: {
    politics: 20000,
    sports: 15000,
    crypto: 10000,
  },
});

// Check before trading
const canTrade = await riskManager.checkOrder({
  market_id: "mkt_yes123",
  side: "buy",
  amount: 500,
});

if (!canTrade.allowed) {
  console.log(`Order blocked: ${canTrade.reason}`);
}

Stop Loss Management

// Set stop loss on position
await agent.setStopLoss({
  position_id: "pos_xyz789",
  type: "trailing",
  trail_percent: 0.1, // 10% trailing stop
  min_price: 0.3, // Never sell below 0.30
});

// Portfolio-level stop
await agent.setPortfolioStop({
  daily_loss_limit: 2000,
  action: "close_all", // Close all positions if hit
});

Backtesting

Test strategies against historical data:
const backtest = await agent.backtest({
  strategy: myStrategy,
  markets: ["mkt_yes123", "mkt_no456"],
  start_date: "2025-01-01",
  end_date: "2025-10-01",
  initial_capital: 10000,
  fees: {
    maker: 0.001,
    taker: 0.002,
  },
});

console.log("Backtest Results:");
console.log(`Total Return: ${backtest.totalReturn}%`);
console.log(`Sharpe Ratio: ${backtest.sharpeRatio}`);
console.log(`Max Drawdown: ${backtest.maxDrawdown}%`);
console.log(`Win Rate: ${backtest.winRate}%`);
console.log(`Total Trades: ${backtest.totalTrades}`);

Monitoring & Alerts

Set Up Alerts

// Price alerts
await agent.createAlert({
  type: "price",
  market_id: "mkt_yes123",
  condition: "crosses_above",
  value: 0.6,
  channel: "webhook",
  webhook_url: "https://your-app.com/alerts",
});

// Position alerts
await agent.createAlert({
  type: "position_pnl",
  position_id: "pos_xyz789",
  condition: "below",
  value: -100, // Alert if down $100
  channel: "email",
});

// System alerts
await agent.createAlert({
  type: "connection",
  condition: "disconnected",
  channel: "sms",
});

Performance Dashboard

const dashboard = await agent.getDashboard();

console.log("Performance Summary:");
console.log(`PnL Today: $${dashboard.pnl.today}`);
console.log(`PnL This Week: $${dashboard.pnl.week}`);
console.log(`Open Positions: ${dashboard.positions.open}`);
console.log(`Open Orders: ${dashboard.orders.open}`);
console.log(`API Calls Today: ${dashboard.api.calls_today}`);
console.log(`Rate Limit Usage: ${dashboard.api.rate_limit_pct}%`);

Sandbox Environment

Test your agent without real money:
const agent = new MatchrAgent({
  apiKey: process.env.MATCHR_SANDBOX_KEY,
  environment: "sandbox",
});

// Sandbox features:
// - Simulated order matching
// - Fake USDC balance
// - Real market data
// - Full API compatibility

Best Practices

Handle Disconnections

Implement reconnection logic with exponential backoff.

Use Idempotency Keys

Prevent duplicate orders with client-side order IDs.

Log Everything

Keep detailed logs for debugging and auditing.

Test in Sandbox

Always test new strategies in sandbox first.

Rate Limits

PlanRequests/minWebSocket ConnectionsMarkets/Subscription
Standard1,000250
Agent10,00010500
EnterpriseCustomCustomCustom

Support