Skip to content

Latest commit

 

History

History
550 lines (428 loc) · 13.1 KB

File metadata and controls

550 lines (428 loc) · 13.1 KB

Prediction Market API Reference

A unified interface for interacting with multiple prediction market exchanges (Kalshi, Polymarket) identically.

Installation & Usage

npm install pmxtjs

Basic Import (CommonJS)

import pmxt from 'pmxtjs';

const poly = new pmxt.Polymarket();
const kalshi = new pmxt.Kalshi();

Note for ESM Users

pmxt is currently CommonJS-only. If you're using "type": "module" in your package.json, you have two options:

Option 1: Default import (recommended)

import pmxt from 'pmxtjs';
const poly = new pmxt.Polymarket();

Option 2: Dynamic import

const pmxt = await import('pmxtjs');
const poly = new pmxt.default.Polymarket();

Note: Named exports like import { Polymarket } from 'pmxtjs' will not work in ESM projects.


Core Methods

fetchMarkets(params?)

Get active markets from an exchange. This is the unified method for all market fetching operations.

Parameters:

  • limit: Number of results (default: 20)
  • offset: Pagination offset
  • sort: 'volume' | 'liquidity' | 'newest'
  • query: Search text (replaces searchMarkets)
  • slug: Market slug or ticker (replaces getMarketsBySlug)
// 1. Fetch recent markets
const markets = await polymarket.fetchMarkets({ 
  limit: 20, 
  sort: 'volume' 
});

// 2. Search by text (replaces searchMarkets)
const results = await kalshi.fetchMarkets({ 
  query: 'Fed rates',
  limit: 10
});

// 3. Fetch by slug/ticker (replaces getMarketsBySlug)
const market = await polymarket.fetchMarkets({ 
  slug: 'who-will-trump-nominate-as-fed-chair'
});

fetchEvents(params?)

Get events (groups of related markets). Unified method for event fetching.

Parameters:

  • query: Search text
  • limit: Number of results
  • offset: Pagination offset
// Search for events
const events = await polymarket.fetchEvents({ 
  query: 'Fed Chair',
  limit: 5 
});


Deep-Dive Methods

fetchOHLCV(outcomeId, params)

Get historical price candles.

CRITICAL: Use outcome.outcomeId, not market.marketId.

  • Polymarket: outcome.outcomeId is the CLOB Token ID
  • Kalshi: outcome.outcomeId is the Market Ticker
const markets = await polymarket.fetchMarkets({ query: 'Trump' });
const outcomeId = markets[0].outcomes[0].outcomeId; // Get the outcome ID

const candles = await polymarket.fetchOHLCV(outcomeId, {
  resolution: '1h', // '1m' | '5m' | '15m' | '1h' | '6h' | '1d'
  start: new Date('2024-01-01'),
  end: new Date('2024-01-31'),
  limit: 100
});

fetchOrderBook(outcomeId)

Get current bids/asks.

const orderBook = await kalshi.fetchOrderBook('FED-25JAN');
console.log('Best bid:', orderBook.bids[0].price);
console.log('Best ask:', orderBook.asks[0].price);

fetchTrades(outcomeId, params)

Get trade history.

Note: Polymarket requires API key. Use fetchOHLCV for public historical data.

const trades = await kalshi.fetchTrades('FED-25JAN', {
  limit: 100
});

Helper Methods

getExecutionPrice(orderBook, side, amount)

Calculate the volume-weighted average price for a given amount. Returns 0 if there is insufficient liquidity to fully fill the amount.

const orderBook = await polymarket.fetchOrderBook(outcomeId);
const price = await polymarket.getExecutionPrice(orderBook, 'buy', 100);
console.log(`Average price for 100 shares: ${price}`);

getExecutionPriceDetailed(orderBook, side, amount)

Calculate detailed execution price information, including partial fills.

const detailed = await polymarket.getExecutionPriceDetailed(orderBook, 'buy', 100);
console.log(`Average Price: ${detailed.price}`);
console.log(`Filled Amount: ${detailed.filledAmount}`);
console.log(`Fully Filled: ${detailed.fullyFilled}`);

Data Models

UnifiedMarket

{
  marketId: string;        // Market ID (use this for createOrder)
  title: string;
  description: string;
  outcomes: MarketOutcome[]; // All tradeable outcomes

  resolutionDate: Date;
  volume24h: number;       // USD
  volume?: number;         // Total volume (USD)
  liquidity: number;       // USD
  openInterest?: number;   // USD

  url: string;
  image?: string;
  category?: string;
  tags?: string[];
}

MarketOutcome

{
  outcomeId: string;       // Use this for fetchOHLCV/fetchOrderBook/fetchTrades
                           // Polymarket: CLOB Token ID
                           // Kalshi: Market Ticker
  label: string;           // "Trump", "Yes", etc.
  price: number;           // 0.0 to 1.0 (probability)
  priceChange24h?: number;
  metadata?: {
    clobTokenId?: string;  // Polymarket only
  }
}

Other Types

interface PriceCandle {
  timestamp: number;       // Unix ms
  open: number;            // 0.0 to 1.0
  high: number;
  low: number;
  close: number;
  volume?: number;
}

interface OrderBook {
  bids: OrderLevel[];      // Sorted high to low
  asks: OrderLevel[];      // Sorted low to high
  timestamp?: number;
}

interface OrderLevel {
  price: number;           // 0.0 to 1.0
  size: number;            // Contracts
}

interface Trade {
  id: string;
  timestamp: number;       // Unix ms
  price: number;           // 0.0 to 1.0
  amount: number;
  side: 'buy' | 'sell' | 'unknown';
}

interface ExecutionPriceResult {
  price: number;           // Average execution price
  filledAmount: number;    // Amount filled (shares)
  fullyFilled: boolean;    // If the requested amount was met
}

Complete Workflow Example

// 1. Search for markets
const markets = await polymarket.fetchMarkets({ query: 'Fed Chair' });
const market = markets[0];

// 2. Get outcome details
const outcome = market.outcomes[0];
console.log(`${outcome.label}: ${(outcome.price * 100).toFixed(1)}%`);

// 3. Fetch historical data (use outcome.outcomeId!)
const candles = await polymarket.fetchOHLCV(outcome.outcomeId, {
  resolution: '1d',
  limit: 30
});

// 4. Get current order book
const orderBook = await polymarket.fetchOrderBook(outcome.outcomeId);
const spread = orderBook.asks[0].price - orderBook.bids[0].price;
console.log(`Spread: ${(spread * 100).toFixed(2)}%`);

Exchange Differences

Feature Polymarket Kalshi
Sorting Server-side Client-side (slower for large sets)
Market ID UUID Event Ticker (e.g., "PRES-2024")
Outcome ID CLOB Token ID Market Ticker (e.g., "FED-25JAN")
OHLCV Quality Synthetic (O=H=L=C) Native (distinct values)
Auth Required Only for fetchTrades() No (all public)
Slug Format lowercase-with-hyphens UPPERCASE (auto-normalized)

Error Handling

try {
  const markets = await kalshi.getMarketsBySlug('INVALID-TICKER');
} catch (error) {
  // Kalshi: "Event not found: INVALID-TICKER"
  // Polymarket: Returns empty array []
  console.error(error.message);
}

Common Errors:

  • 404: Market/event doesn't exist
  • 401: Missing API key (Polymarket fetchTrades)
  • 429: Rate limited
  • 500: Exchange API issue

Type Exports

import pmxt, { 
  UnifiedMarket,
  MarketOutcome,
  PriceCandle,
  OrderBook,
  Trade,
  CandleInterval,
  MarketFilterParams,
  HistoryFilterParams
} from 'pmxtjs';

Authentication & Trading

Both Polymarket and Kalshi support authenticated trading operations. You must provide credentials when initializing the exchange.

Polymarket Authentication

Requires your Polygon Private Key. See Setup Guide for details.

import pmxt from 'pmxtjs';

const polymarket = new pmxt.Polymarket({
  privateKey: process.env.POLYMARKET_PRIVATE_KEY,
  funderAddress: process.env.POLYMARKET_PROXY_ADDRESS, // Optional: Proxy address
  signatureType: 'gnosis-safe' // 'eoa' | 'poly-proxy' | 'gnosis-safe'
});

Kalshi Authentication

Requires API Key and Private Key.

import pmxt from 'pmxtjs';

const kalshi = new pmxt.Kalshi({
  apiKey: process.env.KALSHI_API_KEY,
  privateKey: process.env.KALSHI_PRIVATE_KEY
});

Account Methods

fetchBalance()

Get your account balance.

const balances = await polymarket.fetchBalance();
console.log(balances);
// [{ currency: 'USDC', total: 1000, available: 950, locked: 50 }]

Returns: Balance[]

interface Balance {
  currency: string;   // e.g., 'USDC'
  total: number;      // Total balance
  available: number;  // Available for trading
  locked: number;     // Locked in open orders
}

fetchPositions()

Get your current positions across all markets.

const positions = await kalshi.fetchPositions();
positions.forEach(pos => {
  console.log(`${pos.outcomeLabel}: ${pos.size} @ $${pos.entryPrice}`);
  console.log(`Unrealized P&L: $${pos.unrealizedPnL}`);
});

Returns: Position[]

interface Position {
  marketId: string;
  outcomeId: string;
  outcomeLabel: string;
  size: number;           // Positive for long, negative for short
  entryPrice: number;
  currentPrice: number;
  unrealizedPnL: number;
  realizedPnL?: number;
}

Trading Methods

createOrder(params)

Place a new order (market or limit).

Limit Order Example:

const order = await polymarket.createOrder({
  marketId: '663583',
  outcomeId: '10991849228756847439673778874175365458450913336396982752046655649803657501964',
  side: 'buy',
  type: 'limit',
  amount: 10,        // Number of contracts
  price: 0.55        // Required for limit orders (0.0-1.0)
});

console.log(`Order ${order.id}: ${order.status}`);

Market Order Example:

const order = await kalshi.createOrder({
  marketId: 'FED-25JAN',
  outcomeId: 'FED-25JAN-YES',
  side: 'sell',
  type: 'market',
  amount: 5          // Price not needed for market orders
});

Parameters: CreateOrderParams

interface CreateOrderParams {
  marketId: string;       // Use market.marketId from market data
  outcomeId: string;      // Use outcome.outcomeId from market data
  side: 'buy' | 'sell';
  type: 'market' | 'limit';
  amount: number;         // Number of contracts/shares
  price?: number;         // Required for limit orders (0.0-1.0)
}

Returns: Order

interface Order {
  id: string;
  marketId: string;
  outcomeId: string;
  side: 'buy' | 'sell';
  type: 'market' | 'limit';
  price?: number;
  amount: number;
  status: 'pending' | 'open' | 'filled' | 'cancelled' | 'rejected';
  filled: number;         // Amount filled so far
  remaining: number;      // Amount remaining
  timestamp: number;
  fee?: number;
}

cancelOrder(orderId)

Cancel an open order.

const cancelledOrder = await polymarket.cancelOrder('order-123');
console.log(cancelledOrder.status); // 'cancelled'

Returns: Order (with updated status)

fetchOrder(orderId)

Get details of a specific order.

const order = await kalshi.fetchOrder('order-456');
console.log(`Filled: ${order.filled}/${order.amount}`);

Returns: Order

fetchOpenOrders(marketId?)

Get all open orders, optionally filtered by market.

// All open orders
const allOrders = await polymarket.fetchOpenOrders();

// Open orders for specific market
const marketOrders = await kalshi.fetchOpenOrders('FED-25JAN');

allOrders.forEach(order => {
  console.log(`${order.side} ${order.amount} @ ${order.price}`);
});

Returns: Order[]


Complete Trading Workflow

import pmxt from 'pmxtjs';

const exchange = new pmxt.Polymarket({
  privateKey: process.env.POLYMARKET_PRIVATE_KEY
});

// 1. Check balance
const [balance] = await exchange.fetchBalance();
console.log(`Available: $${balance.available}`);

// 2. Search for a market
const markets = await exchange.fetchMarkets({ query: 'Trump' });
const market = markets[0];
const outcome = market.outcomes[0];

// 3. Place a limit order
const order = await exchange.createOrder({
  marketId: market.marketId,
  outcomeId: outcome.outcomeId,
  side: 'buy',
  type: 'limit',
  amount: 10,
  price: 0.50
});

console.log(`Order placed: ${order.id}`);

// 4. Check order status
const updatedOrder = await exchange.fetchOrder(order.id);
console.log(`Status: ${updatedOrder.status}`);
console.log(`Filled: ${updatedOrder.filled}/${updatedOrder.amount}`);

// 5. Cancel if needed
if (updatedOrder.status === 'open') {
  await exchange.cancelOrder(order.id);
  console.log('Order cancelled');
}

// 6. Check positions
const positions = await exchange.fetchPositions();
positions.forEach(pos => {
  console.log(`${pos.outcomeLabel}: ${pos.unrealizedPnL > 0 ? '+' : ''}$${pos.unrealizedPnL.toFixed(2)}`);
});

Quick Reference

  • Prices: Always 0.0-1.0 (multiply by 100 for %)
  • Timestamps: Unix milliseconds
  • Volumes: USD
  • IDs: Use outcome.outcomeId for deep-dive methods (fetchOHLCV, fetchOrderBook, fetchTrades), and market.marketId for trading operations
  • Authentication: Required for all trading and account methods

For more examples, see examples/.