GuidesTrading

Market making

Quote both sides of a market with post-only orders, stay in sync with the book, and handle the market states that limit trading.

A market maker keeps resting limit orders on both sides of a market's order book. This page covers what is specific to that: quoting both outcomes, keeping orders from taking liquidity, staying in sync, and the limits that apply. It assumes you can already place orders.

Quote both sides

Each market has one order book, priced in the Yes outcome. A bid for No at price p sits in the book as an ask for Yes at 1 − p. So a two-sided quote can use either outcome:

You want toEquivalent order
Bid for Yes at 0.48Buy Yes at 0.48
Offer Yes at 0.52Sell Yes at 0.52, or buy No at 0.48

Selling Yes needs Yes shares in your wallet. Buying No only needs USDT. That makes buying No the way to quote the ask side without holding inventory. See Prices and order book for how the two outcomes map onto one book.

Keep orders from taking liquidity

Set isPostOnly: true on a LIMIT order to make sure it only ever rests on the book. If the order would match a resting order at the moment it arrives, it is not accepted at all. You get an orderNotAccepted wallet event with the reason rejectedPostOnly, and the order ends as CANCELLED.

Post-only orders have two more advantages on markets with a speed bump, such as the up/down markets:

  • Other orders wait a short delay before they reach the book. Post-only orders skip it.
  • Other orders cannot be removed until their removalLockedUntil time. Post-only orders can be removed right away.

Avoid trading with yourself

By default, your own orders can match each other. Set selfTradePrevention on an order to stop that. With any of the three modes, the order never matches orders from the same wallet. The mode decides what happens when it would have:

selfTradePreventionEffect when the order would match your own resting orders
CANCEL_TAKERThe incoming order is cancelled. Your resting orders stay.
CANCEL_MAKERYour crossing resting orders are cancelled. The incoming order still matches anyone else's orders.
CANCEL_BOTHBoth the incoming order and your crossing resting orders are cancelled.

Cancelled orders arrive as orderCancelled wallet events with the reason selfTradePrevention.

Update quotes by replacing them

Orders cannot be edited. To move a quote, remove the old order and place a new one. Removal is off-chain and free, and you can remove up to 100 orders per request. See Cancel orders.

Stay in sync

Two WebSocket topics give you everything you need to track your quotes. Subscribe to both on one connection.

TopicWhat it tells you
predictOrderbook/{marketId}The full book each time it changes, including what is waiting to settle.
predictWalletEvents/{jwt}Your own orders: accepted, not accepted, matched, cancelled, expired, and each settlement transaction.

To follow prices in markets you watch but don't quote, you don't need their whole books. Subscribe to their top of book topic, or poll Get quotes for multiple markets, which covers up to 500 markets per request.

Answer every heartbeat, or the server closes the connection (see Stay connected). Before a planned restart, the server sends a reconnect notice. Reconnect when you get it, subscribe again, and then fetch your open orders with Get orders to catch anything you missed.

Pending settlements

A match is final only once its transaction settles on-chain. Until then, the matched amounts are reserved and cannot match again. The order book shows them in settlementsPending:

FieldMeaning
settlementsPending.asks[price, amount] pairs on the ask side, with prices on the Yes axis.
settlementsPending.bidsThe same for the bid side.

Each amount is the USDT value at that price that has matched and is waiting to settle. lastOrderSettled is the most recent order whose settlement confirmed.

Market states

The market's tradingStatus tells you what the market accepts right now. The predictTradingStatus/{marketId} topic pushes each change. tradingStatus doesn't show a pause. A market whose status is PAUSED can still show OPEN, but it rejects new orders with create_order_market_not_trading. So watch the market's status too.

tradingStatusWhat you can do
OPENEverything.
MATCHING_NOT_ENABLEDOnly post-only LIMIT orders are accepted, and they rest without matching. Other LIMIT orders are rejected with create_order_trading_disabled, and MARKET orders with create_order_market_orders_disabled. Matching starts when the status turns OPEN.
CANCEL_ONLYNew orders are rejected, but you can still remove your open orders.
CLOSEDThe market is resolved or removed. It accepts no new orders.

Rewards fields

Some markets reward resting liquidity. How to earn Predict Points and Maker rebates in the product docs explain the programs. These market fields describe a market's rewards:

FieldMeaning
rewards.currentThe reward period active now, or null when the market is not accruing rewards.
rewards.scheduleEvery past and future reward period, each with hourlyRate (reward points per hour), startsAt and endsAt.
spreadThresholdHow far apart, in USDT, the best bid and best ask can be before the market stops counting towards rewards.
shareThresholdHow many shares an order needs before it counts towards rewards.

Get markets can filter by hasActiveRewards.

Rate limits

Order placement and removal count against the trading limit, which is higher than the limit for other routes. Keys from the developer console also have a per-second cap on order operations. See Rate limits for the numbers and headers.

Checklist

  • Use post-only orders for quotes, so a stale price cannot take liquidity.
  • Set selfTradePrevention if you quote both sides from the same wallet.
  • Remove and replace orders to move quotes. Track each order's hash so you can remove it later.
  • Subscribe to the order book and your wallet events, and answer heartbeats.
  • After a reconnect, subscribe again and reconcile your open orders through the REST API.
  • Watch tradingStatus and status, and stop quoting a market that leaves OPEN or is PAUSED.
  • Keep enough USDT and allowance for all your open bids. The API checks a new order only against your open orders on the same outcome and side in that market. It doesn't stop you from committing more than you hold across outcomes or markets, and an order your funds can't cover fails when it settles.

On this page