11 KiB
Documentation Index
Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt Use this file to discover all available pages before exploring further.
Trading
Order entry, management, and best practices for market makers
Market makers interact with Polymarket through the CLOB API — posting two-sided quotes, managing inventory across markets, and rebalancing positions. The SDK clients handle order signing and submission, so you can focus on strategy.
This page covers MM-specific workflows and best practices. For full order mechanics, see [Create Orders](/trading/orders/create) and [Cancel Orders](/trading/orders/cancel).Two-Sided Quoting
The core market making workflow is posting a bid and ask around your fair value. Use createAndPostOrder to place each side:
const client = new ClobClient({ host: "https://clob.polymarket.com", chain: 137, signer: wallet, creds: credentials, signatureType, funderAddress: funder, });
// Bid at 0.48 const bid = await client.createAndPostOrder({ tokenID: "3409705850427531082723332342151729...", side: Side.BUY, price: 0.48, size: 1000, });
// Ask at 0.52 const ask = await client.createAndPostOrder({ tokenID: "3409705850427531082723332342151729...", side: Side.SELL, price: 0.52, size: 1000, });
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType
from py_clob_client_v2.order_builder.constants import BUY, SELL
token_id = "3409705850427531082723332342151729..."
# Bid at 0.48
bid = client.create_and_post_order(
OrderArgs(token_id=token_id, side=BUY, price=0.48, size=1000),
order_type=OrderType.GTC,
)
# Ask at 0.52
ask = client.create_and_post_order(
OrderArgs(token_id=token_id, side=SELL, price=0.52, size=1000),
order_type=OrderType.GTC,
)
use polymarket_client_sdk_v2::clob::types::Side;
use polymarket_client_sdk_v2::types::dec;
let token_id = "3409705850427531082723332342151729...".parse()?;
// Bid at 0.48
let bid = client.limit_order()
.token_id(token_id).price(dec!(0.48)).size(dec!(1000)).side(Side::Buy)
.build().await?;
let signed = client.sign(&signer, bid).await?;
client.post_order(signed).await?;
// Ask at 0.52
let ask = client.limit_order()
.token_id(token_id).price(dec!(0.52)).size(dec!(1000)).side(Side::Sell)
.build().await?;
let signed = client.sign(&signer, ask).await?;
client.post_order(signed).await?;
Batch Orders
For tighter spreads across multiple levels, use postOrders to submit up to 15 orders in a single request:
const response = await client.postOrders( orders.map((order) => ({ order, orderType: OrderType.GTC })), );
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType, PostOrdersV2Args
from py_clob_client_v2.order_builder.constants import BUY, SELL
response = client.post_orders([
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.48, size=500, side=BUY, token_id=token_id,
)),
orderType=OrderType.GTC,
),
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.47, size=500, side=BUY, token_id=token_id,
)),
orderType=OrderType.GTC,
),
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.52, size=500, side=SELL, token_id=token_id,
)),
orderType=OrderType.GTC,
),
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.53, size=500, side=SELL, token_id=token_id,
)),
orderType=OrderType.GTC,
),
])
let mut signed_orders = Vec::new();
for (price, side) in [
(dec!(0.48), Side::Buy), (dec!(0.47), Side::Buy),
(dec!(0.52), Side::Sell), (dec!(0.53), Side::Sell),
] {
let order = client.limit_order()
.token_id(token_id).price(price).size(dec!(500)).side(side)
.build().await?;
signed_orders.push(client.sign(&signer, order).await?);
}
let response = client.post_orders(signed_orders).await?;
Choosing Order Types
| Type | Behavior | When to Use |
|---|---|---|
| GTC | Rests on the book until filled or cancelled | Default for passive quoting |
| GTD | Auto-expires at a specified time | Expire quotes before known events |
| FOK | Must fill entirely and immediately, or cancel | Aggressive rebalancing — all or nothing |
| FAK | Fills what's available immediately, cancels rest | Rebalancing where partial fills are OK |
GTC and GTD are your primary tools for passive market making — they rest on the book at your specified price. FOK and FAK are for rebalancing inventory against resting liquidity.
Time-Limited Quotes with GTD
Auto-expire quotes before known events like market close or resolution:
```typescript TypeScript theme={null} // Expire in 1 hour const expiringOrder = await client.createAndPostOrder( { tokenID, side: Side.BUY, price: 0.5, size: 1000, expiration: Math.floor(Date.now() / 1000) + 3600, }, undefined, OrderType.GTD, ); ```import time
from py_clob_client_v2 import OrderArgs, OrderType
from py_clob_client_v2.order_builder.constants import BUY
# Expire in 1 hour
expiring_order = client.create_and_post_order(
OrderArgs(
token_id=token_id,
side=BUY,
price=0.50,
size=1000,
expiration=int(time.time()) + 3600,
),
order_type=OrderType.GTD,
)
use chrono::{TimeDelta, Utc};
use polymarket_client_sdk_v2::clob::types::OrderType;
// Expire in 1 hour
let order = client.limit_order()
.token_id(token_id)
.price(dec!(0.50))
.size(dec!(1000))
.side(Side::Buy)
.order_type(OrderType::GTD)
.expiration(Utc::now() + TimeDelta::hours(1))
.build().await?;
let signed = client.sign(&signer, order).await?;
client.post_order(signed).await?;
Managing Orders
Cancelling
Cancel individual orders, by market, or everything at once:
```typescript TypeScript theme={null} await client.cancelOrder(orderId); // Single order await client.cancelOrders(orderIds); // Multiple orders await client.cancelMarketOrders(conditionId); // All orders in a market await client.cancelAll(); // Everything ```client.cancel(order_id=order_id) # Single order
client.cancel_market_orders(market=condition_id) # All orders in a market
client.cancel_all() # Everything
client.cancel_order(order_id).await?; // Single order
client.cancel_market_orders(&request).await?; // All orders in a market
client.cancel_all_orders().await?; // Everything
See Cancel Orders for full details.
Monitoring Open Orders
```typescript TypeScript theme={null} const order = await client.getOrder(orderId);const orders = await client.getOpenOrders({ market: "0xbd31dc8a...", asset_id: "52114319501245...", });
```python Python theme={null}
from py_clob_client_v2 import OpenOrderParams
order = client.get_order(order_id)
orders = client.get_orders(
OpenOrderParams(market="0xbd31dc8a...")
)
use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;
let order = client.order(order_id).await?;
let request = OrdersRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let orders = client.orders(&request, None).await?;
Tick Sizes
Your order price must conform to the market's tick size, or it will be rejected. Look it up with the SDK before quoting:
```typescript TypeScript theme={null} const tickSize = await client.getTickSize(tokenID); // Returns: "0.1" | "0.01" | "0.001" | "0.0001" ```tick_size = client.get_tick_size(token_id)
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
let resp = client.tick_size(token_id).await?;
// resp.minimum_tick_size: TickSize::Tenth | Hundredth | Thousandth | TenThousandth
Fees
Most markets charge a small taker fee. Makers are never charged fees. Geopolitical and world events markets are fee-free.
Taker fees fund the Maker Rebates Program, which pays daily USDC rebates to liquidity providers.
Fees apply only to markets deployed on or after the activation date. Pre-existing markets are unaffected. Markets with fees enabled have `feesEnabled` set to `true` on the market object.See Fees for the full fee schedule, rates by category, and calculation details.
Best Practices
Quote Management
- Quote both sides — Post bids and asks to earn maximum liquidity rewards
- Skew on inventory — Adjust quote prices based on your current position to manage exposure
- Cancel stale quotes — Pull orders immediately when market conditions change
- Use GTD for events — Auto-expire quotes before known catalysts to avoid stale exposure
Latency
- Batch orders — Use
postOrders()to submit multiple quotes in a single request - WebSocket for data — Subscribe to real-time feeds instead of polling REST endpoints
Risk Controls
- Size limits — Check token balances before quoting and don't exceed your available inventory
- Price guards — Validate prices against the book midpoint and reject outliers
- Kill switch — Call
cancelAll()immediately on errors or position breaches - Monitor fills — Subscribe to the WebSocket user channel for real-time fill notifications