Berke Özyaşar
Blog

Polymarket arbitrage bot: when YES plus NO drops below $1

The architecture and risks of a merge arbitrage bot that buys both sides on Polymarket when the combined price of YES and NO tokens drops below $1, then merges them.

·

Polymarket is a prediction market that runs on the Polygon network. Each market has a question (such as "Will Bitcoin go up in the next 15 minutes?") and two outcome tokens trade on it: YES and NO. I am Berke Özyaşar, and I have built Python bots that scan these markets for small price inconsistencies and trade automatically. In this post I explain the merge arbitrage idea behind the Polymarket bots, the architecture of the bot and the real risks involved.

The core idea: 1 YES + 1 NO = 1 USDC

Polymarket uses the Conditional Token Framework (CTF) smart contracts developed by Gnosis. There are two basic operations in this framework:

  • Split: You deposit 1 USDC of collateral and receive 1 YES and 1 NO token for the same market.
  • Merge: You return 1 YES and 1 NO token to the contract and get your 1 USDC of collateral back.

However the market resolves, one of the tokens will be worth $1 and the other $0. So a full set made of one YES and one NO is always worth $1, and the contract guarantees it. In an efficient market, the best ask for YES plus the best ask for NO should be around $1. But especially in short-term 5- to 15-minute crypto "Up or Down" markets, prices move fast and that sum occasionally drops below $1.

An example: if "Down" is offered at 74 cents and "Up" at 22 cents in a market, buying both sides costs 96 cents. When the two tokens are merged, you get 100 cents back; the 4-cent difference is the gross spread before fees. Which way the price goes does not matter.

Polymarket's hybrid structure

To understand how the bot works, you need to know Polymarket's two layers. Orders are matched off-chain in a central limit order book (CLOB); placing and cancelling orders costs no gas, and orders are signed using the EIP-712 standard. Matched trades settle on Polygon, and operations such as split, merge and redeem happen directly on-chain. USDC.e is used as collateral and POL pays the gas for on-chain transactions.

This structure has an important consequence for arbitrage: buying the two sides happens off-chain, while the merge happens on-chain. In other words, the two buys are not a single atomic transaction. I will come back to why this matters in the risks section.

The bot's architecture

The bot is made up of four main components.

1. Market discovery

Active crypto "up-or-down" markets are pulled from Polymarket's Gamma API. For each market, the conditionId and the YES/NO token IDs are stored. Because short-term markets open and close constantly, this list is refreshed regularly.

2. Scanner

Roughly every two seconds, the scanner reads the order book for both tokens from the CLOB API, adds up the best asks and calculates the gap to $1. What matters here is not the gross spread but the net profit. Polymarket's taker fee on crypto markets depends on price: it is highest around 50 cents and decreases as the price approaches the extremes. The scanner calculates the fee for each side separately at its price and adds the gas cost of the merge. Opportunities below the minimum spread and minimum profit thresholds are skipped. Trade size is also capped at the quantity available at the top level of the order book; a larger order would move the price against itself.

3. Executor

When an opportunity is found, signed orders for both sides are sent as close to simultaneously as possible. On the Python side I use the py-clob-client library for this; order signing and API credentials are managed through it.

4. Merge or hold to resolution

Once both sides are filled, mergePositions() on the CTF contract is called with web3.py and the USDC.e returns to the wallet. Alternatively, the position can be held until the market resolves; this saves the gas for the merge but locks up capital for that period. For a strategy that trades frequently, getting capital back right away usually makes more sense.

A second strategy: Dump & Hedge

In pure merge arbitrage, opportunities close quickly. So the bot also has a second strategy called "Dump & Hedge":

  • When one side's price drops sharply (by 10 cents or more), that side is bought.
  • When the combined cost with the other side falls to 95 cents or less, the other side is bought to complete the set.
  • If this condition is not met within a set time, the other side is bought even at a loss to avoid being left one-sided (a timed stop-loss hedge).

This strategy catches more opportunities, but by definition it carries a one-sided open position for a while, which makes it riskier than pure arbitrage.

Infrastructure

  • Language and libraries: Python, py-clob-client and web3.py. Polymarket also has TypeScript and Rust SDKs, which are worth considering when latency is more critical.
  • RPC: Public Polygon RPC endpoints can be slow and unreliable; using a paid RPC provider has a direct impact on latency.
  • Monitoring: Scan results, submitted orders, fill status and merge transactions are tracked on Grafana dashboards. In my view, running a bot when you cannot see what it is doing is a risk in itself.
  • Emergency stop: A kill switch that halts all trading with a single command if something unexpected happens.

Risks: there is no such thing as "risk-free arbitrage"

On paper, merge arbitrage looks independent of the outcome, but in practice there are serious risks:

  • Legging risk: After the first side fills, the price of the second side may change or the order may never fill. You are then left with a one-sided position that has turned into a directional bet.
  • Fee erosion: If the taker fees plus gas exceed the spread, you make a loss instead of a profit. Because the fee depends on price, the math has to be redone for every opportunity.
  • Slippage and liquidity: The order book can be thin. The price you see and the price when your order arrives may not be the same.
  • Competition: Other bots scan for the same opportunities, and they can close within moments.
  • Rate limits: The APIs sit behind Cloudflare; sending requests too often can get you blocked. Retry logic and request frequency need to be tuned accordingly.
  • No test environment: Polymarket has no testnet; every trade uses real money. That is why every new version has to be tried with very small amounts.
  • Access restrictions: Polymarket restricts access from some countries; you need to check the rules where you are and the platform's terms of use.

This post is not investment advice. An arbitrage bot is designed to capture opportunities under certain conditions; it can also lose money because of fees, slippage and liquidity.

If you are thinking about your own bot

If you have a bot idea for Polymarket or similar markets, the first step is to turn the strategy into clear rules, then move forward with small amounts and good monitoring in place. I describe how I work on projects like this on the trading bots page; you can reach me from there or via the contact page.

More articles

Let's ship your app together.

Describe what you want to build in a few sentences. I reply the same day.

Use ↑ ↓ to navigate, Enter to open, Esc to close