Skip to main content

polymarket-openclaw-ai-trading-bot

AI-enhanced Polymarket CLOB trading bot for BTC 5m/15m prediction markets with arbitrage strategies and risk management

インストールへ移動

ソース情報

リポジトリ
reason-machines/hermes-skills
ソースの最終更新活動
2026年5月29日 13:38
検出された SKILL.md の言語
英語
スター
5
フォーク
0

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
polymarket-openclaw-ai-trading-bot
description
AI-enhanced Polymarket CLOB trading bot for BTC 5m/15m prediction markets with arbitrage strategies and risk management
triggers
["set up polymarket trading bot","configure openclaw ai trading","trade polymarket btc 5 minute markets","implement polymarket clob arbitrage","run polymarket automated trading","configure polymarket trading strategies","debug polymarket trading bot","set up polymarket wallet authentication"]
# Polymarket OpenClaw AI Trading Bot > Skill by [ara.so](https://ara.so) — Hermes Skills collection. ## Overview An OpenClaw-enhanced Polymarket AI trading bot designed for BTC 5m/15m Up/Down prediction markets on the Polymarket CLOB. This TypeScript/Node.js system automates short-horizon prediction market trading using deterministic rule-based logic with optional HTTP/LLM OpenClaw decision engine for signal experimentation. Includes strict risk management gates (cooldowns, retries, safety locks), continuous market polling, and structured decision flow. **Key capabilities:** - Trades Polymarket BTC 5-minute and 15-minute Up/Down markets - CLOB-based market orders with Gamma API integration - Two built-in strategies (`trade_1`, `trade_2`) with configurable thresholds - Optional OpenClaw AI decision layer (deterministic or HTTP mode) - L1 wallet signing with L2 authenticated CLOB client - Automatic retry logic for transient errors - Entry cooldown and position management ## Installation ### Prerequisites - Node.js ≥ 20.6 - Polygon wallet with Polymarket-compatible setup - Small USDC balance for trading experiments ### Setup ```bash git clone https://github.com/Predictly-MCP-Labs/polymarket-openclaw-ai-btc-arbitrage-trading-bot cd polymarket-openclaw-ai-btc-arbitrage-trading-bot npm install ``` ### Environment Configuration Create `.env` file from template: ```bash cp .env.example .env ``` Required environment variables: ```bash # Wallet configuration POLYMARKET_PRIVATE_KEY=your_private_key_here POLYMARKET_FUNDER_ADDRESS=your_funder_address_here # Optional: signature type (defaults to proxy-friendly) # Options: EOA, POLY_PROXY, POLY_GNOSIS_SAFE, POLY_1271 POLYMARKET_SIGNATURE_TYPE=POLY_PROXY # Alternative to POLYMARKET_FUNDER_ADDRESS PROXY_WALLET_ADDRESS=your_proxy_address_here ``` **Never commit `.env` to version control.** ## Configuration ### trade.toml Structure The `trade.toml` file controls all trading behavior: ```toml # Strategy selection: trade_1 or trade_2 strategy = "trade_1" # Trading parameters trade_usd = 1.0 # USD per trade max_retries = 3 # Retry attempts for transient errors entry_buy_cooldown_sec = 30 # Cooldown after failed entry # Market selection [market] market_coin = "btc" # Options: btc, eth, sol, xrp market_period = "5" # Options: 5, 15, 60, 240, 1440 (minutes) # OpenClaw AI decision layer (optional) [openclaw] enabled = false # Set true to enable mode = "deterministic" # Options: deterministic, http min_edge_bps = 50 # Minimum edge in basis points max_spread_bps = 200 # Maximum spread in basis points lookback_points = 12 # Historical data points for decisions # Optional HTTP/LLM integration # [openclaw.http] # url = "https://your-openclaw-service.example.com/decide" # bearer_token = "your_bearer_token" # timeout_ms = 2500 # Trade_1 strategy parameters [trade_1] sell_hold_sec = 120 sell_profit_target = 0.15 sell_stop_loss = -0.10 buy_last_sec = 30 range_up_min = 0.45 range_up_max = 0.55 range_down_min = 0.45 range_down_max = 0.55 # Trade_2 strategy parameters [trade_2] sell_hold_sec = 180 sell_profit_target = 0.20 sell_stop_loss = -0.08 emergency_swap_ratio = 0.85 range_up_min = 0.40 range_up_max = 0.60 range_down_min = 0.40 range_down_max = 0.60 ``` ## Running the Bot ### Development Mode ```bash npm run dev ``` ### Production Mode ```bash npm run build npm start ``` ### Key Startup Sequence 1. Banner displays configuration 2. Environment validation (private key, funder address) 3. CLOB L1 authentication → API key derivation/creation 4. CLOB L2 client initialization 5. Market slug resolution (e.g., `btc-5m-up-down`) 6. Continuous market polling begins ## Code Examples ### Basic Trade Execution Flow ```typescript import { ClobClient } from '@polymarket/clob-client'; import { loadConfig } from './config/toml'; import { Trade } from './trade/trade'; // Initialize CLOB client with wallet const clobClient = new ClobClient( process.env.CLOB_HOST, process.env.CHAIN_ID, wallet, process.env.POLYMARKET_SIGNATURE_TYPE ); // Load trading configuration const config = loadConfig(); // Create trade instance const trade = new Trade(clobClient, config); // Main trading loop async function runTradingLoop() { while (true) { // Fetch current market prices const upPrice = await fetchPrice(marketId, 'UP'); const downPrice = await fetchPrice(marketId, 'DOWN'); // Update prices and make decision trade.updatePrices(upPrice, downPrice, timeToExpiry); await sleep(config.poll_interval_ms); } } ``` ### Custom Strategy Implementation ```typescript // src/trade/decision.ts export async function make_trading_decision( trade: Trade, upPrice: number, downPrice: number, timeToExpiry: number ): Promise<void> { const { strategy } = trade.config; if (strategy === 'trade_1') { return trade_1_decision(trade, upPrice, downPrice, timeToExpiry); } else if (strategy === 'trade_2') { return trade_2_decision(trade, upPrice, downPrice, timeToExpiry); } } async function trade_1_decision( trade: Trade, upPrice: number, downPrice: number, timeToExpiry: number ): Promise<void> { const cfg = trade.config.trade_1; // Entry logic: check if in buy range if (!trade.hasBought) { const inUpRange = upPrice >= cfg.range_up_min && upPrice <= cfg.range_up_max; const inDownRange = downPrice >= cfg.range_down_min && downPrice <= cfg.range_down_max; if (inUpRange) { await trade.buyUp(); } else if (inDownRange) { await trade.buyDown(); } return; } // Exit logic: time, profit, or stop-loss const holdTime = (Date.now() - trade.buyTimestamp) / 1000; const profitPct = trade.calculateProfitPct(); if ( holdTime >= cfg.sell_hold_sec || profitPct >= cfg.sell_profit_target || profitPct <= cfg.sell_stop_loss || timeToExpiry <= cfg.buy_last_sec ) { await trade.sell(); } } ``` ### Market Order Execution ```typescript // src/trade/trade.ts async buyUp(): Promise<void> { if (this.hasBought || this.isInCooldown()) { return; } try { const order = await this.createAndPostMarketOrder( this.upTokenId, 'BUY', this.config.trade_usd ); this.hasBought = true; this.side = 'UP'; this.buyTimestamp = Date.now(); this.boughtPrice = this.upPrice; log.success(`✅ Bought UP @ ${this.upPrice.toFixed(4)}`); } catch (error) { this.lastFailedBuyTime = Date.now(); log.error(`Buy failed: ${getFriendlyTradingError(error)}`); } } async createAndPostMarketOrder( tokenId: string, side: 'BUY' | 'SELL', amountUSD: number ): Promise<any> { const order = { tokenID: tokenId, price: side === 'BUY' ? 0.99 : 0.01, // Market order limits size: amountUSD.toString(), side, feeRateBps: '0', nonce: Date.now(), expiration: Math.floor(Date.now() / 1000) + 300, }; return await retryWithPolicy( () => this.clobClient.postOrder(order), this.config.max_retries ); } ``` ### OpenClaw Decision Integration ```typescript // src/trade/openclaw/deterministic.ts export function makeDeterministicDecision( upPrice: number, downPrice: number, timeToExpiry: number, lookbackWindow: Array<{ up: number; down: number; timestamp: number }>, config: OpenClawConfig, positionState: { hasBought: boolean; side?: 'UP' | 'DOWN' } ): OpenClawDecision { // Calculate spread const spread = Math.abs(upPrice - downPrice); const spreadBps = spread * 10000; if (spreadBps > config.max_spread_bps) { return { action: 'HOLD', reason: `Spread too wide: ${spreadBps.toFixed(0)}bps` }; } // Calculate edge const upEdge = (0.5 - upPrice) * 10000; const downEdge = (0.5 - downPrice) * 10000; // Entry signals if (!positionState.hasBought) { if (upEdge > config.min_edge_bps) { return { action: 'BUY_UP', reason: `UP edge ${upEdge.toFixed(0)}bps` }; } if (downEdge > config.min_edge_bps) { return { action: 'BUY_DOWN', reason: `DOWN edge ${downEdge.toFixed(0)}bps` }; } return { action: 'HOLD', reason: 'No edge found' }; } // Exit signals if (timeToExpiry < 60) { return { action: 'CLOSE_POSITION', reason: 'Near expiry' }; } return { action: 'HOLD', reason: 'Monitoring position' }; } ``` ### Market Slug Generation ```typescript // src/config/slug.ts export function buildSlug(coin: string, period: string): string { const coinMap: Record<string, string> = { 'btc': 'bitcoin', 'eth': 'ethereum', 'sol': 'solana', 'xrp': 'ripple', }; const periodMap: Record<string, string> = { '5': '5-minute', '15': '15-minute', '60': '1-hour', '240': '4-hour', '1440': '1-day', }; const coinName = coinMap[coin.toLowerCase()] || coin; const periodName = periodMap[period] || `${period}-minute`; return `${coinName}-${periodName}-up-down`; } // Usage const slug = buildSlug('btc', '5'); // "bitcoin-5-minute-up-down" ``` ### Error Handling with Retry Logic ```typescript // src/utils/retry.ts export async function retryWithPolicy<T>( fn: () => Promise<T>, maxRetries: number, delayMs: number = 1000 ): Promise<T> { let lastError: any; for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await fn(); } catch (error: any) { lastError = error; // Only retry transient errors if (isTransientError(error) && attempt < maxRetries) { await sleep(delayMs * Math.pow(2, attempt)); // Exponential backoff continue; } throw error; } } throw lastError; } function isTransientError(error: any): boolean { const transientCodes = [429, 500, 502, 503, 504]; const transientMessages = ['ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND']; return ( transientCodes.includes(error.status) || transientMessages.some(msg => error.message?.includes(msg)) ); } ``` ## Common Patterns ### Running Multiple Time Windows Run separate processes for 5m and 15m markets: ```bash # Terminal 1 - 5 minute markets cp trade.toml trade-5m.toml # Edit trade-5m.toml: market_period = "5" npm run build CONFIG_PATH=./trade-5m.toml npm start # Terminal 2 - 15 minute markets cp trade.toml trade-15m.toml # Edit trade-15m.toml: market_period = "15" CONFIG_PATH=./trade-15m.toml npm start ``` ### Monitoring Position State ```typescript // Add to main loop for logging function logPositionState(trade: Trade) { if (trade.hasBought) { const holdTime = (Date.now() - trade.buyTimestamp) / 1000; const profitPct = trade.calculateProfitPct(); console.log(`📊 Position: ${trade.side} | Hold: ${holdTime.toFixed(0)}s | P&L: ${(profitPct * 100).toFixed(2)}%`); } else { console.log(`💤 No position | Watching market`); } } ``` ### Safe Shutdown Handler ```typescript // src/index.ts let isShuttingDown = false; process.on('SIGINT', async () => { if (isShuttingDown) return; isShuttingDown = true; log.warn('🛑 Shutdown signal received'); // Close any open positions if (trade.hasBought) { log.info('Closing open position...'); await trade.sell(); } log.info('Shutdown complete');
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る