vike

Recipe 27 of 30

What does Polymarket liquidity look like in the final seconds before a market closes?

Take each 5-minute BTC market's close from its slug (start plus 300 seconds), join a day of archived top-of-book quotes to it, and bucket spread, size at the touch and quote updates by seconds before the close.

A 5-minute Up/Down market stops trading when its window ends, and its slug says when: the slug ends in the window's start in unix seconds, and the close is 300 seconds later. GET /v1/polymarket/settlements/bulk lists a day's markets with their slugs in one call; the archive's l1_quotes file holds every top-of-book change of their tokens, and DuckDB joins the two and buckets the last minute. The bulk parameters are on Settlements in bulk.

Quick answer

List the day's settled markets of the family, with their slugs.

cURL
# a day of settled 5-minute BTC markets: condition ids and slugs, which carry each market's start time
curl -H "X-API-Key: $VIKE_API_KEY" \
  "https://data.vike.io/v1/polymarket/settlements/bulk?slug_prefix=btc-updown-5m-&from_ms=1792713600000&to_ms=1792800000000&limit=5000"

Example response

Captured from the live API on 2026-10-24 at 17:22 UTC, with limit=3, trimmed to 1 row; at limit=5000 the same row opens the page. btc-updown-5m-1792713300 started at 23:55:00 UTC on 2026-10-22, so it closed at 1792713600 seconds, 00:00:00 UTC; the chain resolved it 81 seconds later. resolved_ts_ms marks the resolution, not the close.

Example response
{
  "settlements": [
    {
      "condition_id": "0xe8eb153c68bb090d0f7378220dda294de0fb903ca7455298e889115bd8db3926",
      "market_known": true,
      "outcomes": ["Up", "Down"],
      "payouts": [1, 0],
      "question": "Bitcoin Up or Down - October 22, 7:55PM-8:00PM ET",
      "resolved_block": 96005540,
      "resolved_ts_ms": 1792713681000,
      "slug": "btc-updown-5m-1792713300",
      "token_ids": ["66807904852803027944717699017367321508323078567048144477724810240924212801296", "31737787044827274982239313079132196514193684856716359909945275491390424775584"],
      "winning_index": 0,
      "winning_outcome": "Up",
      "winning_token_id": "66807904852803027944717699017367321508323078567048144477724810240924212801296"
    }
  ],
  "has_more": true,
  "next_cursor": "1792714280000:0x9bb2ac747df3557a00c1bfe4bc6189daa5289f31eafb7c4f32bae6071a341f2a"
}

Variations

Save the markets for DuckDB.

cURL — markets file
# markets.jsonl: one line per market with its condition id and slug
curl -s -H "X-API-Key: $VIKE_API_KEY" \
  "https://data.vike.io/v1/polymarket/settlements/bulk?slug_prefix=btc-updown-5m-&from_ms=1792713600000&to_ms=1792800000000&limit=5000" \
  | jq -c '.settlements[] | {condition_id, slug}' > markets.jsonl

Download the day's quotes.

cURL — quotes
# the top of book of every 5-minute BTC market on 2026-10-23 (186 MB)
curl -s -L -H "X-API-Key: $VIKE_API_KEY" \
  "https://data.vike.io/v1/polymarket/archive/url?date=2026-10-23&stream=l1_quotes&asset=btc&tenor=5m&redirect=true" \
  -o btc-5m-l1_quotes-2026-10-23.parquet

Bucket the last minute in DuckDB.

DuckDB
WITH m AS (
  SELECT condition_id, (CAST(split_part(slug, '-', 4) AS BIGINT) + 300) * 1000 AS close_ms
  FROM read_json_auto('markets.jsonl')
),
q AS (
  SELECT (m.close_ms - q.local_ts) / 1000.0 AS secs_left,
         CAST(q.ask - q.bid AS DOUBLE) AS spread,
         CAST(q.bid_size + q.ask_size AS DOUBLE) AS touch_shares
  FROM read_parquet('btc-5m-l1_quotes-2026-10-23.parquet') q JOIN m USING (condition_id)
  WHERE q.bid > 0 AND q.ask > 0 AND q.local_ts < m.close_ms AND q.local_ts >= m.close_ms - 60000
)
SELECT CAST(ceil(secs_left / 10) * 10 AS INT) AS last_n_secs,
       count(*) AS updates,
       median(spread) AS median_spread,
       median(touch_shares) AS median_touch_shares
FROM q GROUP BY 1 ORDER BY 1 DESC;

On btc-updown-5m-1792765500 (closing 14:30:00 UTC on 2026-10-23) the spread held at one cent to the end, while the median shares at the touch fell from 820 in the 60 to 50 seconds before the close to 340 in the 30 to 20 seconds before it; the last quote came 0.8 seconds before the close.

Depth beyond the touch. The book_events file of the day has every full-book snapshot and change, for depth past level 1.

cURL — full book
# where the day's full-book file is, with its size
curl -H "X-API-Key: $VIKE_API_KEY" \
  "https://data.vike.io/v1/polymarket/archive/url?date=2026-10-23&stream=book_events&asset=btc&tenor=5m"

Before you rely on it

The close is in the slug, not in resolved_ts_ms

The slug's number is the window's start in UTC seconds: add 300 for a 5-minute market, 900 for 15 minutes, 14,400 for 4 hours. resolved_ts_ms comes later and marks the on-chain resolution. Medians here are over quote changes, not over time, and the busiest seconds weigh most. A market that closes just after midnight UTC has its last quotes in the next day's file.

Ask your agent

Connected to the Vike MCP server (https://vike.io/mcp) in Claude, ChatGPT or Cursor, ask it in plain words. The polymarket_archive tool answers with the link, at 1 credit a call. The bucketing runs in your DuckDB.

Ask your agent
Give me the download link for the Polymarket 5-minute BTC top-of-book file of 2026-10-23
Example response
{  "settlements": [    {      "condition_id": "0xe8eb153c68bb090d0f7378220dda294de0fb903ca7455298e889115bd8db3926",      "market_known": true,      "outcomes": ["Up", "Down"],      "payouts": [1, 0],      "question": "Bitcoin Up or Down - October 22, 7:55PM-8:00PM ET",      "resolved_block": 96005540,      "resolved_ts_ms": 1792713681000,      "slug": "btc-updown-5m-1792713300",      "token_ids": ["66807904852803027944717699017367321508323078567048144477724810240924212801296", "31737787044827274982239313079132196514193684856716359909945275491390424775584"],      "winning_index": 0,      "winning_outcome": "Up",      "winning_token_id": "66807904852803027944717699017367321508323078567048144477724810240924212801296"    }  ],  "has_more": true,  "next_cursor": "1792714280000:0x9bb2ac747df3557a00c1bfe4bc6189daa5289f31eafb7c4f32bae6071a341f2a"}