Skip to main content

Overview

Polymarket runs a rolling series of short-dated crypto markets. Every five minutes a new Bitcoin Up or Down market opens a window, and every fifteen minutes a longer one does the same. Each asks one question: at the end of this window, is BTC higher than it was at the start? On 7 August 2026 the way these markets settle changed. They no longer read a single price at the instant the window closes. They read a Chainlink time-weighted average price over the final seconds of the window. That change is the whole reason this guide exists, because it moves the decision point of the market from one instant to a measurable interval, and a bot written against the old behaviour is now systematically wrong at exactly the moment it matters. This guide covers what settles these markets, how to find and price them, what the fees do to your edge, and how to execute through the Bravado Trade API.

Spin up a Trade API key

Create a key with trade.read, trade.execute, and trade.cancel in the Bravado Portal. Every example below runs in dry mode without one, and needs one the moment you go live.
Read time: about 20 minutes. Python and REST experience assumed. Read Build a trading bot first for the state and reconciliation patterns this guide leans on.

TL;DR

  • It is Chainlink, not Pyth. Crypto up/down markets resolve against Chainlink Data Streams TWAP feeds. Pyth is Polymarket’s resolution source for equities, ETFs, and commodities, not for BTC.
  • 5-minute markets use a 30-second TWAP lookback. 15-minute markets use 60 seconds. Read the window from the market’s cryptoMarketConfig rather than hardcoding it.
  • Market slugs are deterministic. btc-updown-5m-<unix window start>. You never need to search for the next market, you can compute it.
  • Taker fees dominate the edge. At 50 cents a taker pays 1.75 cents per share. You need roughly 1.75 points of probability edge just to break even. Rest as a maker whenever you can.
  • Bravado is the execution layer, Polymarket is the data layer. There is no order book endpoint on Bravado, and you do not want one in the hot loop.
  • Advanced order types mostly do not apply here. PEGGED is the one worth testing. TWAP, ICEBERG, and the stop variants are built for hours, not for a 300-second window.
  • Location is a first-class design decision. Polymarket’s primary servers are in eu-west-2.

What you will do

  • Resolve the current and next BTC window without searching
  • Read the TWAP configuration off the market instead of assuming it
  • Stream Chainlink TWAP prices from Polymarket RTDS
  • Compute a fair probability and compare it to a live book
  • Size an order against the fee, not against your conviction
  • Execute through Bravado with retry-safe keys
  • Decide where to run the process

What you will need

Knowledge
  • Python 3.11 or later, comfort with REST and WebSockets
  • A directional view on BTC over a 5 to 15 minute horizon. This guide gives you the harness, not the signal.
Tools and access
  • A Bravado API key with trade.read, trade.execute, and trade.cancel, created in the Bravado Portal
  • pip install requests websockets
  • pUSD collateral for live trading. Dry-run mode needs none.
  • A machine with a clock disciplined by NTP. Window boundaries are absolute times and drift will cost you.

What settles these markets

Each crypto up/down market carries its rules in its own description. This is the current text on a BTC 5-minute market, verbatim:
This market will resolve to “Up” if the time-weighted average price (TWAP) of Bitcoin, generated by Chainlink, of the time range specified in the title is greater than or equal to the price at the beginning of that range. Otherwise, it will resolve to “Down”.
The resolution source is a Chainlink Data Streams feed, published on the market as a URL:
The hourly series is a different animal. It still resolves against a centralised exchange price and carries no cryptoMarketConfig. Do not assume a bot written for 5m and 15m transfers to it.
Worth stating plainly because the assumption is common. Polymarket uses two price oracles for different asset classes: If you are building for BTC, Pyth is not in your path.

Read the window, do not hardcode it

Every crypto up/down market exposes its settlement configuration as a structured field. Read it:
twapLookbackSeconds is the number your bot cares about. It is 30 on 5-minute markets and 60 on 15-minute markets today, and it is the kind of parameter that moved once already this year. A bot that reads it survives the next change. A bot that hardcodes 30 silently mis-prices every market the day it moves.
Chainlink does not publish the sampling boundaries, weighting, or rounding behaviour of these custom feeds. You cannot reproduce the settlement value independently, and you should not try. Consume the published feed and treat it as authoritative.

The reference price is the part to verify yourself

The rule compares the TWAP at the end of the window against “the price at the beginning of that range”. Polymarket does not publish a separate reference-price endpoint, and the TWAP stream has no history or replay after a disconnect. The practical consequence: your bot has to snapshot the reference itself, at the window open, and keep it. Before you risk capital, run the harness in dry mode for a few hundred windows, log your snapshot and the settled outcome side by side, and confirm your reference reconstruction agrees with how the market actually resolved. This is not optional diligence. It is the one part of the model you cannot verify from documentation alone.

Find the market without searching

The single most useful property of these series: the slug is a pure function of the window start time.
So the market whose window opens at the next five-minute boundary is:
Resolve it in one call:
Do not discover these markets by listing and sorting. Polymarket creates each window roughly 24 hours ahead of time, so a query ordered by startDate descending returns markets whose windows open tomorrow, not the one about to run. That is the most expensive discovery bug in this series: everything looks correct, the book is liquid, and you are trading a window a day away.

What a real window looks like

Three consecutive BTC 5-minute books, sampled two seconds before the top of a window: That progression is the shape of the entire strategy space. A window is a coin flip when it opens, becomes tradeable as the underlying moves, and is fully priced before it closes. Your bot lives in the middle.
The bestBid and bestAsk fields on the Gamma market object are cached and were stale in every sample above. For anything you trade on, read https://clob.polymarket.com/book?token_id=....

Venue parameters

A one cent tick on a market that lives for 300 seconds is coarse. It means the smallest expressible edge is one full percentage point of probability, which matters a great deal once you see the fee.

The fee decides the strategy

Polymarket charges a taker fee on crypto markets, and it is not small:
Where p is the share price. Makers pay nothing and receive a share of collected fees as a rebate. Bravado charges 10 bips of notional per side on top. The fee peaks exactly where these markets live: Read the last column carefully. To cross the spread at 50 cents and break even, your estimate of the true probability has to beat the offered price by 1.75 percentage points. The tick is one cent. So a taker strategy at the money needs close to two ticks of genuine edge on every trade, before slippage, before any error in your reference price, and before the 10 bips Bravado adds.
This is the number that kills naive bots in this series. A signal that is right 52% of the time is a losing strategy as a taker at 50 cents, and a comfortably profitable one as a maker. Design for the book, not against it.
The consequence for design: rest limit orders and get paid the spread. Take only when the underlying has moved far enough that your fair value has left the current price by more than the fee. In practice that means late in the window, in the direction the TWAP is already going.

Architecture: Polymarket for data, Bravado for execution

Bravado has no order book, midpoint, or market discovery endpoint, and that is the correct split for this workload. Price data belongs on a WebSocket you own; execution belongs behind an API that handles signing, idempotency, and strategy supervision.
1

Stream the TWAP

Polymarket RTDS pushes Chainlink TWAP updates about once a second, with no credentials. This is your signal input.
2

Resolve the window

Compute the slug, fetch the market once per window, cache the token ids and twapLookbackSeconds.
3

Price it

Reference price plus current TWAP plus time remaining gives a fair probability.
4

Execute through Bravado

POST /v2/trade/order with an idempotency key. Rest as a maker by default.
5

Flatten or let it settle

Cancel anything unfilled before the window closes. Redeem the winners.

Streaming the TWAP

RTDS is live and is the recommended path. No API key, no Chainlink credentials, no report decoding.
Three things in there are load-bearing:
  • full_accuracy_value is the price. It is a signed E18 fixed-point integer. The value field beside it is a float provided for display, and it is not what settles the market. Divide the integer with Decimal.
  • payload.timestamp is the Chainlink observation time. The outer timestamp is when Polymarket relayed it. In sampling, the gap between them ran about 1 to 2 seconds. Use the inner one for freshness checks, and budget for the relay lag in your model.
  • PING every 5 seconds, as a text frame. RTDS uses an application-level heartbeat and will drop you without it.
Subscriptions start with the next update. There is no snapshot, no history, and no replay after a disconnect. If your process restarts mid-window, you have lost the reference price for that window. Treat that as a hard skip, not a guess.

Resolving the window

Note the twapEnabled guard. It is the cheapest possible protection against pointing a TWAP-aware bot at a series that does not settle on TWAP.

Pricing the window

The fair probability of Up is the probability that the closing TWAP finishes at or above your reference. Everything you know reduces to three quantities: how far the TWAP has already moved, how much time is left, and how volatile BTC is over that horizon.
This is a placeholder and it is deliberately naive. It assumes no drift, constant volatility, and that the settlement value equals the last TWAP print. Two effects it ignores are worth naming, because they are where the real work is:
  • The lookback window flattens the endgame. With 30 seconds of lookback on a 5-minute market, roughly the final 10% of the window is already being averaged in. A move in the last 5 seconds moves the settlement value by about a sixth of its magnitude. Under the old snapshot rule that same move counted in full. Any model carried over from before 7 August 2026 systematically overestimates how much late price action matters.
  • Your view is delayed. The relay adds 1 to 2 seconds and the feed prints about once a second. With 8 seconds left on the clock, you are pricing off information that is a meaningful fraction of the remaining window old.

Executing through Bravado

One endpoint, one idempotency key per intended order. If you have not created an API key yet, do it now in the Bravado Portal and grant trade.read, trade.execute, and trade.cancel, since the flatten step below needs all three.
Generate the idempotency key outside any retry loop. Inside it, every attempt carries a fresh key and every one that lands creates its own position. In a series that opens a new market every five minutes, a duplicate is not a one-off, it compounds 288 times a day. See Safe retries.

Closing out the window

Two calls, and they are not interchangeable:
Cancel-all clears CLOB orders only. A PEGGED order left running past the close belongs to a market that no longer exists in any useful sense. After settlement, winning shares are redeemable but not redeemed automatically. Call POST /v2/trade/positions/redeem once position.redeemable is true. Running 288 windows a day, unredeemed winners are the most common form of capital sitting idle in this strategy.

Confirming what you do not need

You were right to be suspicious of both.

Advanced order types

The general rule: Bravado’s advanced types exist to work size into thin books over time. These markets are the opposite problem, small size and no time.

The Data API

Not in the hot loop. It reads on-chain Polygon settlement records, so it is the wrong latency class for a decision you make every second. It is the right tool the moment the window closes. Run 288 windows a day and the only question that matters is whether the strategy is profitable after fees, which is precisely what a cashflow-model PnL over your own wallet tells you. Pull GET /traders/{address}/pnl and GET /traders/{address}/trades on a daily cadence and check the answer against your own logs. See Build a PnL leaderboard.

Latency and location

Where the venue is

Polymarket publishes this, and it changes how you should think about hosting: Typical inter-region round trips, as orders of magnitude. Measure your own rather than trusting the table:

What that actually costs you

Be honest about the mechanism, because latency matters here for a narrower reason than people assume. The TWAP feed prints about once a second and the relay adds 1 to 2 seconds. So 50 milliseconds of network time does not change what you know. What it changes is what you can do about it:
  • Queue position. A one cent tick means many participants want the same price level. On a book with a few hundred shares at the touch, arriving first at a level is most of the game.
  • Cancel races. When the TWAP prints and the fair value moves, your resting order is now mispriced and someone else’s taker is on the way to hit it. The gap between your cancel and their take is measured in exactly the milliseconds this table describes.
  • The final window. In the last 30 or 60 seconds the outcome is being averaged into existence. The book repriced from 0.54 / 0.55 to 0.99 bid, no ask inside a single window in the sample above. Being 150 milliseconds late into that transition is the difference between a fill and a chase.

Why execute through Bravado

Two concrete reasons, plus one thing to check for yourself. You skip order construction entirely. A native CLOB order requires building and EIP-712 signing the order locally before it can be sent. Through Bravado it is one authenticated JSON POST. That removes local signing work from the path between your decision and the venue, on every order, in a loop that runs 288 times a day. Managed strategies run server-side. If you use PEGGED, its chase logic lives on Bravado’s infrastructure, adjacent to the venue, rather than in a loop on your box that has to observe a move, decide, and send. Your process restarting does not abandon it mid-window. Then measure the hop. Routing through Bravado inserts a network hop between you and Polymarket. That is a clear win when Bravado sits closer to eu-west-2 than your process does, which is the common case for anyone not already co-located, and it is worth confirming against your own numbers before you scale size. Time a round trip through POST /v2/trade/order in dry conditions and compare it against your own path to the CLOB. Optimise the leg that is actually costing you.
The single largest latency lever available to most people is not the API they use. It is moving the process out of a home connection or a US region and into Europe. Do that first, then tune.

Eligibility, before you write any of this

Polymarket restricts order placement by jurisdiction, and the restrictions apply to the API, not just the website.
  • Blocked entirely: Iran, Syria, Cuba, North Korea, and the Crimea, Donetsk, and Luhansk regions of Ukraine. No new orders, no closing existing positions.
  • Close-only on frontend and API: a longer list that includes the United States, the United Kingdom, Canada, Australia, France, Germany, Belgium, Brazil, and Russia. Existing positions can be closed. New positions cannot be opened.
  • Close-only on frontend, API unrestricted: Ireland, Japan, Malta, the Netherlands.
Hosting a process in eu-west-2 is a latency decision. It is not a compliance decision and does not change your eligibility. Confirm your own status against the geoblock endpoint and against your Bravado account terms before you build. Do not design around these restrictions.

Going live

1

Run dry for 200 windows

DRY_RUN = True. Log your reference snapshot, your fair value, the book, and the settled outcome for every window. This is how you validate the reference-price reconstruction, which is the one thing documentation cannot confirm for you.
2

Check the calibration, not the hit rate

Bucket your fair values and compare each bucket against realised outcomes. A model that says 60% should be right about 60% of the time. A high hit rate with poor calibration will not survive the fee.
3

Trade one series, maker only

Turn off the taker branch entirely. Run 15-minute windows first: the same mechanics with four times the decision time and less exposure to relay lag.
4

Reconcile against the Data API

After a week, compare your logged PnL against GET /traders/{address}/pnl. If they disagree, your fee accounting is wrong, and fee accounting is the whole margin here.
5

Then add 5-minute windows, then add taking

In that order. Each step adds a distinct failure mode and you want to know which one broke.

Wrapping up

The TWAP change made these markets harder to manipulate and easier to model. Settlement is now an average over a defined interval published on a public feed you can subscribe to for free, rather than a single number read at an instant you had to race. What is left is an execution problem with an unusually explicit cost. You know the fee formula, you know the tick, you know the feed cadence, and you know where the venue is. The 1.75 cents per share at the money is the number the strategy lives or dies on, and almost everything in this guide is downstream of the decision to rest rather than cross.

Frequently asked questions

No. Crypto up/down markets resolve against Chainlink Data Streams TWAP feeds. Pyth is Polymarket’s resolution source for equities, ETFs, forex, and commodities, and it surfaces on the equity_prices RTDS topic. If your market is a BTC window, Pyth is not in the path.
Because Polymarket creates each window roughly 24 hours ahead of time. If you discovered the market by listing events sorted by startDate descending, you found tomorrow’s window rather than the current one. Compute the slug from the window start timestamp instead.
No. Chainlink does not publish the sampling boundaries, weighting, rounding, or missing-input behaviour of these custom feeds, so an independently computed value will not reliably match. Consume the published feed.
Not from the feed. RTDS subscriptions start with the next update and there is no snapshot, history, or replay. Persist your reference snapshot as soon as you take it, and if it is missing for a window, skip that window rather than estimating it.
Almost certainly the taker fee. At 50 cents a taker pays 1.75 cents per share, which is 3.5% of notional and about 1.75 points of probability. A 52% signal has 2 points of edge before costs and close to nothing after them. Rest as a maker and the same signal has a very different economics.
No, and the name collision is a coincidence worth naming out loud. Bravado’s TWAP order type spreads your execution over time to reduce market impact. The market’s TWAP settlement is how the outcome is computed. In a 300-second window with a minimum interval_sec of 10, a TWAP order gives you a slowly-accumulated position in a market that will have resolved before it finishes.
Yes. Redemption is not automatic. Check position.redeemable and call POST /v2/trade/positions/redeem. At 288 windows a day this adds up quickly if you skip it.
Same mechanics, different constants. The lookback is 60 seconds rather than 30, so the final minute is averaged rather than the final half-minute, and you have four times as long to act on the same information. Start there.

Resources