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.
Install / Use
npx skills add defi-ape/polymarket-kalshi-arbitrage-botInstalls into whichever agent you are using.
README
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.
<p> <a href="https://github.com/defi-ape/polymarket-kalshi-arbitrage-bot"> <img src="https://img.shields.io/badge/Repository-GitHub-181717?style=for-the-badge&logo=github" alt="GitHub repository" /> </a> <a href="https://polymarket.com"> <img src="https://img.shields.io/badge/Polymarket-Platform-6366f1?style=for-the-badge" alt="Polymarket" /> </a> <a href="https://kalshi.com"> <img src="https://img.shields.io/badge/Kalshi-Platform-0ea5e9?style=for-the-badge" alt="Kalshi" /> </a> </p>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-clientwhen 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
93and96cents. - Polymarket UP must be at least
10cents cheaper than Kalshi YES. - The bot emits
buy_polymarketwhen 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 /
GraphVideoclip (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
<video poster="./src/img%20and%20video/instagram-DWrBSHxlIZ3-poster.jpg" src="./src/img%20and%20video/instagram-DWrBSHxlIZ3-demo.mp4" controls playsinline preload="metadata" width="100%"> Your browser cannot play this clip inline. Open the file directly: <a href="./src/img%20and%20video/instagram-DWrBSHxlIZ3-demo.mp4">instagram-DWrBSHxlIZ3-demo.mp4</a>. </video>
Still frame (preview)
<p align="center"> <img src="./src/img%20and%20video/instagram-DWrBSHxlIZ3-poster.jpg" alt="Cover frame from the Instagram reel DWrBSHxlIZ3 (Polymarket or Kalshi for trading bots?)" width="100%" /> <br /> <em>Poster image from the same reel (local mirror; Instagram: <code>DWrBSHxlIZ3</code>).</em> </p>Architecture
Kalshi API Polymarket CLOB
| |
| |
+------ price polling ----+
|
v
Arbitrage decision engine
|
+-------+--------+
| |
v v
/status API Polymarket order client
authenticated execution
Core modules:
src/index.tsstarts the Express API, polling loop, and optional trading client.src/config.tsloads and validates runtime configuration from.env.src/services/kalshi.tsfetches Kalshi market data.src/services/polymarket.tsfetches Polymarket CLOB prices.src/services/arbitrage.tsevaluates buy/no-buy decisions.src/services/polymarketOrders.tsplaces 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
| Variable | Description | Default / Example |
| --- | --- | --- |
| PORT | HTTP server port. | 3000 |
| POLL_INTERVAL_MS | Price polling interval in milliseconds. | 5000 |
| MARKET_START_TIME | Market start time in ISO 8601 format. | 2026-05-11T07:00:00.000Z |
| START_DELAY_MINS | Minutes after market start before evaluating signals. | 8 |
| KALSHI_API_BASE | Kalshi trade API base URL. | https://api.elections.kalshi.com/trade-api/v2 |
| KALSHI_TICKER | Kalshi market ticker for the target market. | KXHIGHNY-24JAN01-T60 |
| POLYMARKET_CLOB_BASE | Polymarket CLOB API base URL. | https://clob.polymarket.com |
| POLYMARKET_TOKEN_UP | Polymarket UP/YES token ID. | From the Polymarket market |
| POLYMARKET_TOKEN_DOWN | Polymarket DOWN/NO token ID. | From the Polymarket market |
| KALSHI_MIN_CENTS | Lower Kalshi YES price bound for spread entries. | 93 |
| KALSHI_MAX_CENTS | Upper Kalshi YES price bound for spread entries. | 96 |
| MIN_SPREAD_CENTS |
Related Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
Writing Hookify Rules
140.7kThis skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
agent-tui
106.4kMain Agents: Do NOT use this skill directly. If you need to test the TUI, invoke the `tui_tester` subagent. Drive terminal UI (TUI) applications programmatically for testing, automation, and inspection
review-duplication
106.4kUse this skill during code reviews to proactively investigate the codebase for duplicated functionality, reinvented wheels, or failure to reuse existing project best practices and shared utilities.
