跳到正文

defi-ape

polymarket-kalshi-arbitrage-bot

15-minute prediction market arbitrage bot: poll Kalshi Trade API and Polymarket CLOB, detect YES/UP spreads and late-resolution gaps, expose Express /status, and place Polymarket buys via @polymarket/clob-client.

README 已保存到本站,可直接阅读

Documentation snapshot

README 快照

这篇是英文原文

下面正文是项目自己的英文 README。想读全文就用浏览器自带的整页翻译: Chrome / Edge 点地址栏右侧的翻译图标,或用右键菜单里的「翻译成中文」; 手机浏览器一般在菜单里。

本页保存的是公开项目资料快照,阅读过程不需要连接 GitHub。

Polymarket-Kalshi Arbitrage Bot

Professional TypeScript bot for monitoring short-duration prediction markets across Polymarket and Kalshi, detecting pricing gaps, and placing buy orders on Polymarket when configured arbitrage rules are satisfied.

Canonical repository: github.com/defi-ape/polymarket-kalshi-arbitrage-bot

The bot is designed for 15-minute markets where fast pricing updates, clear execution rules, and transparent runtime status matter. It continuously compares Kalshi YES pricing against Polymarket UP pricing, exposes a simple monitoring API, and can initialize an authenticated Polymarket order client for automated execution.

Important: Prediction market trading involves risk. This project provides configurable automation and monitoring logic; it does not guarantee profit or eliminate execution, liquidity, market, regulatory, or operational risk.

What This Bot Does

  • Monitors a paired Kalshi and Polymarket market on a configurable interval.
  • Pulls Polymarket UP/DOWN token pricing from the Polymarket CLOB.
  • Pulls Kalshi YES/NO pricing and market status from the Kalshi trade API.
  • Waits until a configurable start window has passed before evaluating trades.
  • Emits structured arbitrage signals through /status.
  • Places Polymarket buy orders using @polymarket/clob-client when valid trading credentials are configured.
  • Applies order cooldowns to reduce duplicate execution during repeated signals.
  • Runs as a lightweight Express service that can be deployed on a VPS, container, or cloud instance.

Strategy Overview

The current strategy focuses on buying the Polymarket UP token when Kalshi is pricing the equivalent outcome materially higher.

Rule 1: Spread-Based Entry

After the configured start delay, the bot checks whether Kalshi YES is inside a target confidence band and whether Polymarket UP is meaningfully cheaper.

Default thresholds:

  • Kalshi YES must be between 93 and 96 cents.
  • Polymarket UP must be at least 10 cents cheaper than Kalshi YES.
  • The bot emits buy_polymarket when both conditions are true.

Example:

Kalshi YES:      95 cents
Polymarket UP:   82 cents
Spread:          13 cents
Decision:        BUY Polymarket UP

Resulting signal:

{
  "action": "buy_polymarket",
  "reason": "Kalshi YES 95¢ in [93,96], Polymarket UP 82¢ (spread 13¢ >= 10¢).",
  "kalshiYesCents": 95,
  "polymarketUpCents": 82,
  "spreadCents": 13
}

Rule 2: Late Resolution Opportunity

Some short-duration markets can close or settle on one venue while the other still has an active order book. If Kalshi is finished but Polymarket still has liquidity, the bot emits a late-entry signal.

Example:

Kalshi status:       settled
Polymarket book:     still has liquidity
Decision:            BUY Polymarket UP

Resulting signal:

{
  "action": "buy_polymarket_late",
  "reason": "Kalshi market finished (closed/settled) while Polymarket still has orders.",
  "kalshiStatus": "settled"
}

Demo (Instagram reel — Polymarket vs Kalshi for bots)

Primary source: https://www.instagram.com/reel/DWrBSHxlIZ3/ (permalink on profile: @moondevonyt).

Source metadata (public, as shown on Instagram)

  • Account: @moondevonyt — display name Moon Dev on YT (verified).
  • Post type: Reel / GraphVideo clip (vertical 720×1280 class dimensions in embed data).
  • Published: April 3, 2026 (Instagram “taken at” timestamp in page metadata).
  • Caption (verbatim): Polymarket or kalshi for trading bots?
  • Audio: Original audio credited to the same account (“Moon Dev on YT on Instagram…” in og:title).
  • Approximate length: ~39 seconds (progressive clip; duration from Instagram embed payload when the local video was mirrored).
  • Engagement (snapshot only — changes on Instagram over time): on the order of hundreds of reel plays and a few dozen likes on the public counter at mirror time; use the live post for current numbers.

The spoken rundown is only in the clip (Instagram’s public HTML does not ship a full transcript). In short: the hook is choosing one venue versus wiring both when automation and cross-platform prices matter.

How that question maps to this repository

This repo is not the app from the reel; it is a standalone TypeScript service. It still illustrates one concrete answer for cross-venue work: the bot polls both venues (Kalshi trade API + Polymarket CLOB), runs the spread and late-resolution rules in Strategy Overview, and, when trading is enabled, places Polymarket buy orders. So for “Polymarket or Kalshi?” in the sense of mispricing between books, this code assumes both feeds for signals and Polymarket for the automated buy side wired in polymarketOrders.ts.

Local copy (for README / offline use)

Mirrored under src/img and video/ (shortcode DWrBSHxlIZ3):

  • Video: instagram-DWrBSHxlIZ3-demo.mp4
  • Poster / cover frame: instagram-DWrBSHxlIZ3-poster.jpg

Video

Your browser cannot play this clip inline. Open the file directly: instagram-DWrBSHxlIZ3-demo.mp4.

Still frame (preview)

Poster image from the same reel (local mirror; Instagram: DWrBSHxlIZ3).

Architecture

Kalshi API              Polymarket CLOB
    |                         |
    |                         |
    +------ price polling ----+
              |
              v
      Arbitrage decision engine
              |
      +-------+--------+
      |                |
      v                v
  /status API     Polymarket order client
                   authenticated execution

Core modules:

  • src/index.ts starts the Express API, polling loop, and optional trading client.
  • src/config.ts loads and validates runtime configuration from .env.
  • src/services/kalshi.ts fetches Kalshi market data.
  • src/services/polymarket.ts fetches Polymarket CLOB prices.
  • src/services/arbitrage.ts evaluates buy/no-buy decisions.
  • src/services/polymarketOrders.ts places Polymarket orders when trading is enabled.

Tech Stack

  • Node.js 18+
  • TypeScript
  • Express for the HTTP monitoring/control API
  • Axios for Kalshi and Polymarket HTTP requests
  • @polymarket/clob-client for Polymarket order placement
  • ethers for wallet/client support
  • dotenv for environment-based configuration

Quick Start

Install dependencies:

npm install

Create a local environment file:

cp .env.example .env

Edit .env with your market pair and wallet settings, then run:

npm run build
npm start

For development with auto-reload:

npm run dev

The service starts polling automatically and exposes the API on http://localhost:3000 by default.

Example .env

PORT=3000
POLL_INTERVAL_MS=5000

MARKET_START_TIME=2026-05-11T07:00:00.000Z
START_DELAY_MINS=8

KALSHI_API_BASE=https://api.elections.kalshi.com/trade-api/v2
KALSHI_TICKER=KXHIGHNY-24JAN01-T60

POLYMARKET_CLOB_BASE=https://clob.polymarket.com
POLYMARKET_TOKEN_UP=1234567890123456789012345678901234567890
POLYMARKET_TOKEN_DOWN=9876543210987654321098765432109876543210

KALSHI_MIN_CENTS=93
KALSHI_MAX_CENTS=96
MIN_SPREAD_CENTS=10

POLYMARKET_PRIVATE_KEY=0x<64_HEX_CHARACTER_PRIVATE_KEY>
POLYMARKET_PROXY_WALLET_ADDRESS=0x<40_HEX_CHARACTER_PROXY_WALLET>
POLYMARKET_CHAIN_ID=137
POLYMARKET_TRADE_USD=10
POLYMARKET_BUY_COOLDOWN_SECONDS=60

Keep private keys out of source control. Use a dedicated trading wallet with limited funds.

Configuration Reference

VariableDescriptionDefault / Example
PORTHTTP server port.3000
POLL_INTERVAL_MSPrice polling interval in milliseconds.5000
MARKET_START_TIMEMarket start time in ISO 8601 format.2026-05-11T07:00:00.000Z
START_DELAY_MINSMinutes after market start before evaluating signals.8
KALSHI_API_BASEKalshi trade API base URL.https://api.elections.kalshi.com/trade-api/v2
KALSHI_TICKERKalshi market ticker for the target market.KXHIGHNY-24JAN01-T60
POLYMARKET_CLOB_BASEPolymarket CLOB API base URL.https://clob.polymarket.com
POLYMARKET_TOKEN_UPPolymarket UP/YES token ID.From the Polymarket market
POLYMARKET_TOKEN_DOWNPolymarket DOWN/NO token ID.From the Polymarket market
KALSHI_MIN_CENTSLower Kalshi YES price bound for spread entries.93
KALSHI_MAX_CENTSUpper Kalshi YES price bound for spread entries.96
MIN_SPREAD_CENTSMinimum Kalshi minus Polymarket spread required.10
POLYMARKET_PRIVATE_KEYEOA private key used for trading.0x...
POLYMARKET_PROXY_WALLET_ADDRESSPolymarket proxy wallet / Safe address.0x...
POLYMARKET_CHAIN_IDChain ID for Polymarket CLOB.137
POLYMARKET_TRADE_USDUSD amount per buy order.10
POLYMARKET_BUY_COOLDOWN_SECONDSMinimum seconds between buy orders.60

API Reference

GET /health

Simple health check.

curl http://localhost:3000/health

Example response:

{
  "ok": true,
  "ts": "2026-05-11T07:08:14.122Z"
}

GET /status

Returns the latest market data, trading state, and current arbitrage signal.

curl http://localhost:3000/status

Example response:

{
  "tradingEnabled": true,
  "afterStartWindow": true,
  "lastTickAt": 1778483294122,
  "polymarket": {
    "upCents": 82,
    "downCents": 18,
    "hasLiquidity": true,
    "fetchedAt": 1778483293988
  },
  "kalshi": {
    "yesCents": 95,
    "noCents": 5,
    "status": "open",
    "isFinished": false,
    "fetchedAt": 1778483294041
  },
  "signal": {
    "action": "buy_polymarket",
    "reason": "Kalshi YES 95¢ in [93,96], Polymarket UP 82¢ (spread 13¢ >= 10¢).",
    "kalshiYesCents": 95,
    "polymarketUpCents": 82,
    "spreadCents": 13
  }
}

POST /poll/start

Starts the polling loop. Polling starts automatically when the service boots, but this endpoint is useful after manually stopping it.

curl -X POST http://localhost:3000/poll/start

POST /poll/stop

Stops the polling loop without shutting down the HTTP server.

curl -X POST http://localhost:3000/poll/stop

Operating Notes

Monitoring Signals

The /status endpoint always exposes the latest evaluated signal, including no-buy reasons. This is useful for validating market pairing, reviewing spreads, and demonstrating the strategy logic before increasing capital allocation.

Best for:

  • Strategy validation
  • Client demos
  • Reviewing live signal behavior
  • Collecting signal frequency data

Automated Trading

When POLYMARKET_PRIVATE_KEY and POLYMARKET_PROXY_WALLET_ADDRESS are valid, the bot initializes the Polymarket order client and places buy orders when a buy signal appears. Use a dedicated wallet and conservative trade size while validating behavior.

Execution protections included in the current code:

  • Configurable trade size via POLYMARKET_TRADE_USD
  • Configurable buy cooldown via POLYMARKET_BUY_COOLDOWN_SECONDS
  • Price validation before submitting a buy
  • In-memory latest state for transparent API inspection

Example Client Workflow

  1. Select a 15-minute event that exists on both Kalshi and Polymarket.
  2. Copy the Kalshi ticker into KALSHI_TICKER.
  3. Copy the matching Polymarket UP and DOWN token IDs into .env.
  4. Set MARKET_START_TIME and confirm START_DELAY_MINS.
  5. Run the bot and watch /status to confirm price feeds and signal behavior.
  6. Confirm the signal behavior against live market screens.
  7. Use a limited Polymarket wallet and conservative POLYMARKET_TRADE_USD.
  8. Monitor logs and the /status endpoint during the active market window.

Sample Logs

Polymarket-Kalshi arbitrage bot listening on port 3000
  GET /health  - health check
  GET /status  - last prices and current signal
  POST /poll/start - start price polling
  POST /poll/stop  - stop price polling
[Bot] Polymarket order client ready (trading enabled).
[Bot] Polling every 5000ms
[Bot] BUY SIGNAL: {
  "action": "buy_polymarket",
  "kalshiYesCents": 95,
  "polymarketUpCents": 82,
  "spreadCents": 13
}
[Bot] Polymarket BUY order placed: { "...": "..." }

Deployment Notes

  • Run on a stable machine with reliable network access.
  • Use process supervision such as pm2, Docker, systemd, or your cloud provider’s runtime manager.
  • Store secrets in environment variables or a managed secret store.
  • Use a dedicated wallet with limited capital.
  • Monitor /health, /status, application logs, and wallet balances.
  • Keep polling intervals reasonable to avoid unnecessary API load.

Security Notes

  • Never commit .env or private keys.
  • Rotate keys if they were ever exposed.
  • Use a dedicated proxy wallet for bot execution.
  • Start with small trade sizes until the full workflow is verified.
  • Review venue rules and local regulations before using automated trading.

Commands

npm run dev        # Start development server with auto-reload
npm run build      # Compile TypeScript to dist/
npm start          # Run compiled production build
npm run typecheck  # Type-check without emitting files

Disclaimer

This repository is provided for software engineering and automation purposes. Markets can move quickly, APIs can fail, liquidity can disappear, and automated orders can execute at unfavorable times. Review the code, test carefully, and trade only with capital you can afford to risk.

Official distribution

获取与安装

暂未发现可确认的官方软件包地址

当前 README 快照没有出现 npm、PyPI、Crates.io、pub.dev 等官方包页链接。本站不会根据仓库名称猜测下载地址。

本站不托管项目文件;需要安装时,请以项目维护者发布的官方文档为准。

使用前核验

本站保存公开资料用于阅读,不代表安全审计或功能背书。安装前请核对许可证、依赖来源和发布签名,不要直接运行来源不明的二进制文件或高权限脚本。