Digital Oracle
komako-workshop/digital-oracle
Answer prediction questions using market trading data, not opinions.
Execute trades on Polymarket using pyclobclient - full API access for market data, orders, positions
$ npx skills add alsk1992/CloddsBot --skill trading-polymarket -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install alsk1992/CloddsBot trading-polymarket --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/alsk1992/CloddsBot.git skills-src && mkdir -p .claude/skills && cp -r skills-src/src/skills/bundled/trading-polymarket .claude/skills/trading-polymarket && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "trading-polymarket" agent skill from https://github.com/alsk1992/CloddsBot/tree/main/src/skills/bundled/trading-polymarket into .claude/skills/trading-polymarket/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "trading-polymarket", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/alsk1992/CloddsBot/tree/main/src/skills/bundled/trading-polymarketType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add alsk1992/CloddsBot --skill trading-polymarket -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install alsk1992/CloddsBot trading-polymarket --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/alsk1992/CloddsBot.git skills-src && mkdir -p .agents/skills && cp -r skills-src/src/skills/bundled/trading-polymarket .agents/skills/trading-polymarket && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "trading-polymarket" agent skill from https://github.com/alsk1992/CloddsBot/tree/main/src/skills/bundled/trading-polymarket into .agents/skills/trading-polymarket/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "trading-polymarket", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add alsk1992/CloddsBot --skill trading-polymarket -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install alsk1992/CloddsBot trading-polymarket --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/alsk1992/CloddsBot.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/src/skills/bundled/trading-polymarket .cursor/skills/trading-polymarket && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "trading-polymarket" agent skill from https://github.com/alsk1992/CloddsBot/tree/main/src/skills/bundled/trading-polymarket into .cursor/skills/trading-polymarket/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "trading-polymarket", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/alsk1992/CloddsBot.git --path src/skills/bundled/trading-polymarket--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add alsk1992/CloddsBot --skill trading-polymarket -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install alsk1992/CloddsBot trading-polymarket --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/alsk1992/CloddsBot.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/src/skills/bundled/trading-polymarket .gemini/skills/trading-polymarket && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "trading-polymarket" agent skill from https://github.com/alsk1992/CloddsBot/tree/main/src/skills/bundled/trading-polymarket into .gemini/skills/trading-polymarket/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "trading-polymarket", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install alsk1992/CloddsBot trading-polymarketInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add alsk1992/CloddsBot --skill trading-polymarket -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/alsk1992/CloddsBot.git skills-src && mkdir -p .github/skills && cp -r skills-src/src/skills/bundled/trading-polymarket .github/skills/trading-polymarket && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "trading-polymarket" agent skill from https://github.com/alsk1992/CloddsBot/tree/main/src/skills/bundled/trading-polymarket into .github/skills/trading-polymarket/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "trading-polymarket", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add alsk1992/CloddsBot --skill trading-polymarket -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install alsk1992/CloddsBot trading-polymarket --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/alsk1992/CloddsBot.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/src/skills/bundled/trading-polymarket .opencode/skills/trading-polymarket && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "trading-polymarket" agent skill from https://github.com/alsk1992/CloddsBot/tree/main/src/skills/bundled/trading-polymarket into .opencode/skills/trading-polymarket/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "trading-polymarket", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
trading-polymarketExecute trades on Polymarket using pyclobclient - full API access for market data, orders, positions
Trading Polymarket is an agent skill from alsk1992/CloddsBot. Execute trades on Polymarket using pyclobclient - full API access for market data, orders, positions
Its SKILL.md is about 8.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `index.ts`).
It sits in Business, Finance & HR, covering Trading and backtesting and Stock and market analysis. It works with Polymarket. The repository describes itself as: Open Source AI trading agent that operates autonomously across 1000+ markets - Polymarket, Kalshi, Binance, Hyperliquid, Solana DEXs, 5 EVM chains. Scans for edge, executes… The licence is MIT.
Read from SKILL.md and the folder at commit c930628. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (TypeScript), which the agent can run.
Shell commands in SKILL.md call:
pipFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
clob.polymarket.compolygon-rpc.comgamma-api.polymarket.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
POLY_API_KEYPOLY_API_SECRETPRIVATE_KEYAPI_KEYAPI_SECRETFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Trading Polymarket loads about 8.3k tokens when it runs. Until then it costs about 30 tokens; SKILL.md has 1,023 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from alsk1992/CloddsBot at commit c930628, republished under its MIT licence (© alsk1992). 1,023 words, ~8,276 tokens.
.claude/skills/trading-polymarket/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Full access to Polymarket's CLOB (Central Limit Order Book) via the official py_clob_client library.
60+ methods documented. This is the complete reference.
PRIVATE_KEY=0x... # Ethereum private key for signing
POLY_FUNDER_ADDRESS=0x... # Your wallet address on Polygon
POLY_API_KEY=... # From Polymarket API
POLY_API_SECRET=... # Base64 encoded secret
POLY_API_PASSPHRASE=... # API passphrasepip install py-clob-client requests| Level | Requirements | Capabilities |
|---|---|---|
| L0 | None | Read-only: orderbooks, prices, markets |
| L1 | Private key | Create & sign orders (not post) |
| L2 | Private key + API creds | Full trading: post orders, cancel, query |
| Type | Use Case |
|---|---|
0 | Standard EOA (MetaMask, hardware wallets) |
1 | Magic/email wallets (delegated signing) |
2 | Proxy wallets (Gnosis Safe, browser proxy) |
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import (
OrderArgs, MarketOrderArgs, ApiCreds, OrderType,
BookParams, TradeParams, OpenOrderParams, BalanceAllowanceParams,
AssetType, OrderScoringParams, OrdersScoringParams, DropNotificationParams
)
from py_clob_client.order_builder.constants import BUY, SELL
from py_clob_client.constants import POLYGON # 137
# Level 2 Auth (full trading access)
client = ClobClient(
host="https://clob.polymarket.com",
key=os.getenv("PRIVATE_KEY"), # Private key for signing
chain_id=POLYGON, # 137 for mainnet, 80002 for Amoy testnet
funder=os.getenv("POLY_FUNDER_ADDRESS"), # Wallet address (for proxy wallets)
signature_type=2 # 0=EOA, 1=MagicLink, 2=Proxy
)
# Set API credentials for authenticated endpoints
client.set_api_creds(ApiCreds(
api_key=os.getenv("POLY_API_KEY"),
api_secret=os.getenv("POLY_API_SECRET"),
api_passphrase=os.getenv("POLY_API_PASSPHRASE")
))client.get_ok() # Check if server is up
client.get_server_time() # Get server timestamp
client.get_address() # Your signer's public address
client.get_collateral_address() # USDC contract address
client.get_conditional_address() # CTF contract address
client.get_exchange_address() # Exchange contract (neg_risk=False default)# Get prices and spreads
client.get_midpoint(token_id) # Mid market price
client.get_price(token_id, side="BUY") # Best price for side
client.get_spread(token_id) # Current spread
client.get_last_trade_price(token_id) # Last executed trade price
# Get full orderbook
orderbook = client.get_order_book(token_id)
# Returns: OrderBookSummary with bids, asks, tick_size, neg_risk, timestamp, hashparams = [
BookParams(token_id="TOKEN1", side="BUY"),
BookParams(token_id="TOKEN2", side="SELL")
]
client.get_midpoints(params) # Multiple midpoints
client.get_prices(params) # Multiple prices
client.get_spreads(params) # Multiple spreads
client.get_order_books(params) # Multiple orderbooks
client.get_last_trades_prices(params) # Multiple last pricesclient.get_tick_size(token_id) # Returns: "0.1", "0.01", "0.001", or "0.0001"
client.get_neg_risk(token_id) # Returns: True/False (negative risk market)
client.get_fee_rate_bps(token_id) # Returns: fee rate in basis points (0 or 1000)from py_clob_client.clob_types import OrderType
OrderType.GTC # Good Till Cancelled - stays open until filled/cancelled
OrderType.FOK # Fill Or Kill - fill entirely immediately or cancel
OrderType.GTD # Good Till Date - expires at timestamp (min 60 seconds)
OrderType.FAK # Fill And Kill - fill what's possible, cancel rest| Type | Use Case | Example |
|---|---|---|
| GTC | Entries - wait for fill | Place buy at 0.45, wait for dip |
| FOK | Exits - need immediate fill | Market sell entire position NOW |
| GTD | Time-limited orders | Offer expires in 5 minutes |
| FAK | Partial fills OK | Get as much as possible now |
OrderArgs(
token_id: str, # Token ID (outcome to trade)
price: float, # Price 0.01-0.99
size: float, # Number of shares
side: str, # "BUY" or "SELL" (or use BUY/SELL constants)
fee_rate_bps: int = 0, # Optional: fee rate in bps (0 or check market)
nonce: int = 0, # Optional: unique nonce for cancellation
expiration: int = 0, # Optional: expiry timestamp (0 = GTC, use timestamp for GTD)
taker: str = ZERO_ADDRESS # Optional: specific taker (ZERO_ADDRESS = anyone)
)MarketOrderArgs(
token_id: str, # Token ID
amount: float, # Total USDC amount to spend (BUY) or shares (SELL)
side: str, # "BUY" or "SELL"
price: float = 0, # Optional: worst acceptable price (slippage protection)
fee_rate_bps: int = 0, # Optional: fee rate
nonce: int = 0, # Optional: nonce
taker: str = ZERO_ADDRESS, # Optional: taker address
order_type: OrderType = FOK # Optional: FOK (default) or FAK
)from py_clob_client.order_builder.constants import BUY, SELL
# 1. LIMIT BUY (GTC) - sits on book until filled
order = client.create_and_post_order(
OrderArgs(token_id=TOKEN_ID, price=0.45, size=100.0, side=BUY)
)
# 2. LIMIT SELL (GTC)
order = client.create_and_post_order(
OrderArgs(token_id=TOKEN_ID, price=0.55, size=50.0, side=SELL)
)
# 3. MARKET BUY - spend $100 USDC at current prices (FOK)
signed = client.create_market_order(
MarketOrderArgs(token_id=TOKEN_ID, amount=100.0, side=BUY)
)
result = client.post_order(signed, orderType=OrderType.FOK)
# 4. MARKET SELL - sell all shares immediately (FOK)
signed = client.create_market_order(
MarketOrderArgs(token_id=TOKEN_ID, amount=my_shares, side=SELL)
)
result = client.post_order(signed, orderType=OrderType.FOK)
# 5. POST-ONLY MAKER ORDER (avoid taker fees, earn rebates)
signed = client.create_order(
OrderArgs(token_id=TOKEN_ID, price=0.44, size=100.0, side=BUY)
)
result = client.post_order(signed, orderType=OrderType.GTC, post_only=True)
# If order would cross spread, it gets REJECTED instead of taking
# 6. GOOD TIL DATE (GTD) - expires after timestamp
import time
expiry = int(time.time()) + 300 # 5 minutes from now
signed = client.create_order(
OrderArgs(token_id=TOKEN_ID, price=0.50, size=100.0, side=BUY, expiration=expiry)
)
result = client.post_order(signed, orderType=OrderType.GTD)
# 7. FILL AND KILL (FAK) - fill what you can, cancel rest
signed = client.create_market_order(
MarketOrderArgs(token_id=TOKEN_ID, amount=1000.0, side=BUY)
)
result = client.post_order(signed, orderType=OrderType.FAK)# SIMPLE: Create and post in one call (recommended)
result = client.create_and_post_order(
OrderArgs(
token_id="123456789012345678901234567890",
price=0.45,
size=10.0,
side="BUY"
)
)
# Returns: {"orderID": "...", "status": "...", ...}
# ADVANCED: Separate create and post
order = client.create_order(OrderArgs(...)) # Returns SignedOrder
result = client.post_order(order, orderType=OrderType.GTC, post_only=False)
# Market order (calculates price automatically)
result = client.create_market_order(
MarketOrderArgs(
token_id="...",
amount=100.0, # Spend $100 USDC
side="BUY"
)
)
# Calculate expected fill price before market order
price = client.calculate_market_price(
token_id="...",
side="BUY",
amount=100.0,
order_type=OrderType.FOK
)client.cancel(order_id="ORDER_ID") # Cancel specific order
client.cancel_orders(["ID1", "ID2", "ID3"]) # Cancel multiple
client.cancel_all() # Cancel ALL open orders
client.cancel_market_orders( # Cancel by market/asset
market="CONDITION_ID",
asset_id="TOKEN_ID"
)# Get all open orders
orders = client.get_orders(
params=OpenOrderParams(
id="ORDER_ID", # Optional: specific order
market="COND_ID", # Optional: filter by market
asset_id="TOKEN" # Optional: filter by token
),
next_cursor="MA==" # For pagination
)
# Get specific order
order = client.get_order(order_id="ORDER_ID")trades = client.get_trades(
params=TradeParams(
id="TRADE_ID", # Optional: specific trade
maker_address="0x...", # Optional: filter by maker
market="CONDITION_ID", # Optional: filter by market
asset_id="TOKEN_ID", # Optional: filter by token
before="2024-01-01", # Optional: before date
after="2023-01-01" # Optional: after date
),
next_cursor="MA=="
)# Check balance and allowances
balance = client.get_balance_allowance(
params=BalanceAllowanceParams(
asset_type=AssetType.COLLATERAL, # USDC balance
# or AssetType.CONDITIONAL # Token balance
token_id="TOKEN_ID" # For conditional tokens
)
)
# Update/refresh allowance cache
client.update_balance_allowance(params=...)# All active markets
markets = client.get_markets(next_cursor="MA==")
simplified = client.get_simplified_markets()
# Specific market
market = client.get_market(condition_id="CONDITION_ID")
# Market trade events
events = client.get_market_trades_events(condition_id="CONDITION_ID")
# Sampling/featured markets
client.get_sampling_markets()
client.get_sampling_simplified_markets()import requests
def search_markets(query: str, limit: int = 10):
"""Search Polymarket markets by keyword"""
url = "https://gamma-api.polymarket.com/markets"
params = {
"_q": query,
"active": "true",
"closed": "false",
"_limit": limit
}
r = requests.get(url, params=params)
return r.json()
# Get market details
markets = search_markets("bitcoin")
for m in markets:
print(f"Question: {m['question']}")
print(f"Condition ID: {m['condition_id']}")
print(f"Volume: ${m.get('volume', 0):,.2f}")
for token in m.get('tokens', []):
print(f" {token['outcome']}: {token['token_id']}")
print(f" Price: {float(token['price']):.2f}")import requests
CTF_CONTRACT = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
RPC_URL = "https://polygon-rpc.com/"
def get_token_balance(wallet: str, token_id: str) -> float:
"""Get balance of a specific outcome token in shares"""
token_int = int(token_id)
# ERC-1155 balanceOf(address,uint256)
data = f"0x00fdd58e000000000000000000000000{wallet[2:].lower()}{token_int:064x}"
r = requests.post(RPC_URL, json={
"jsonrpc": "2.0",
"method": "eth_call",
"params": [{"to": CTF_CONTRACT, "data": data}, "latest"],
"id": 1
})
result = r.json().get("result", "0x0")
balance = int(result, 16) / 1e6 # Convert from raw to shares
return balance
# Usage
balance = get_token_balance(
wallet="0x7c2211103e7Fbb257Ac6fa59f972cfd8bc9D4795",
token_id="12345678901234567890"
)
print(f"Position: {balance} shares")USDC_CONTRACT = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
def get_usdc_balance(wallet: str) -> float:
"""Get USDC balance on Polygon"""
# ERC-20 balanceOf(address)
data = f"0x70a08231000000000000000000000000{wallet[2:].lower()}"
r = requests.post(RPC_URL, json={
"jsonrpc": "2.0",
"method": "eth_call",
"params": [{"to": USDC_CONTRACT, "data": data}, "latest"],
"id": 1
})
result = r.json().get("result", "0x0")
return int(result, 16) / 1e6 # USDC has 6 decimals# Create new API key
creds = client.create_api_key(nonce=0)
# Derive existing API key (if you lost creds but have private key)
creds = client.derive_api_key(nonce=0)
# Create or derive (tries both)
creds = client.create_or_derive_api_creds(nonce=0)
# Get all your API keys
keys = client.get_api_keys()
# Delete current API key
client.delete_api_key()
# Readonly API keys (for monitoring only)
readonly = client.create_readonly_api_key()
client.get_readonly_api_keys()
client.delete_readonly_api_key(key="...")
client.validate_readonly_api_key(address="0x...", key="...")# Start heartbeat - if not sent within 10s, all orders cancelled
heartbeat_id = client.post_heartbeat(heartbeat_id=None)
# Continue sending heartbeats
while trading:
client.post_heartbeat(heartbeat_id=heartbeat_id)
time.sleep(5)# Check if order is scoring (earning rewards)
is_scoring = client.is_order_scoring(
params=OrderScoringParams(order_id="...")
)
# Check multiple orders
scores = client.are_orders_scoring(
params=OrdersScoringParams(order_ids=["ID1", "ID2"])
)notifications = client.get_notifications()
client.drop_notifications(params=DropNotificationParams(...))IMPORTANT: Most Polymarket markets have ZERO fees (0% maker, 0% taker).
Only 15-minute BTC/ETH/SOL/XRP price prediction markets have fees:
fee = shares × 0.25 × (price × (1 - price))²| Entry Price | Fee % (per side) |
|---|---|
| 0.50 | ~1.56% |
| 0.60 or 0.40 | ~1.44% |
| 0.70 or 0.30 | ~1.10% |
| 0.80 or 0.20 | ~0.64% |
| 0.90 or 0.10 | ~0.20% |
TAKER = crosses spread = PAYS fee MAKER = adds liquidity = NO fee + earns rebates
To be a maker: Post orders that don't immediately fill (inside the spread).
| Order Side | Price Decimals | Size Decimals |
|---|---|---|
| BUY | 2 | 4 |
| SELL | 2 | 2 |
Min order size: $1 per side
#!/usr/bin/env python3
"""
Production-ready Polymarket trading script
"""
import os
import time
import requests
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs, ApiCreds, OrderType
# Initialize
client = ClobClient(
"https://clob.polymarket.com",
key=os.getenv("PRIVATE_KEY"),
chain_id=137,
funder=os.getenv("POLY_FUNDER_ADDRESS"),
signature_type=2
)
client.set_api_creds(ApiCreds(
api_key=os.getenv("POLY_API_KEY"),
api_secret=os.getenv("POLY_API_SECRET"),
api_passphrase=os.getenv("POLY_API_PASSPHRASE")
))
TOKEN_ID = "YOUR_TOKEN_ID"
WALLET = os.getenv("POLY_FUNDER_ADDRESS")
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
def get_balance(token_id):
"""Get position size"""
token_int = int(token_id)
data = f"0x00fdd58e000000000000000000000000{WALLET[2:].lower()}{token_int:064x}"
r = requests.post("https://polygon-rpc.com/", json={
"jsonrpc": "2.0", "method": "eth_call",
"params": [{"to": CTF, "data": data}, "latest"], "id": 1
})
return int(r.json().get("result", "0x0"), 16) / 1e6
def get_orderbook(token_id):
"""Get current bid/ask"""
book = client.get_order_book(token_id)
return {
"best_bid": float(book.bids[0].price) if book.bids else 0,
"best_ask": float(book.asks[0].price) if book.asks else 1
}
# Check position
position = get_balance(TOKEN_ID)
print(f"Current position: {position} shares")
# Get market
book = get_orderbook(TOKEN_ID)
print(f"Bid: {book['best_bid']:.2f}, Ask: {book['best_ask']:.2f}")
# Place a buy order (maker - inside spread)
buy_price = book['best_bid'] + 0.01 # 1 cent above bid
if buy_price < book['best_ask']: # Ensure we're maker
result = client.create_and_post_order(OrderArgs(
token_id=TOKEN_ID,
price=buy_price,
size=10.0,
side="BUY"
))
print(f"Buy order placed: {result}")
# Place a sell order (market sell via FOK)
if position > 0:
result = client.create_and_post_order(OrderArgs(
token_id=TOKEN_ID,
price=0.01, # Lowest price = immediate fill
size=position,
side="SELL"
))
print(f"Sold position: {result}")from py_clob_client.exceptions import PolyApiException
try:
result = client.create_and_post_order(OrderArgs(...))
except PolyApiException as e:
print(f"API Error: {e}")
except Exception as e:
print(f"Error: {e}")Common errors:
"insufficient balance" - Not enough USDC/tokens"invalid price" - Price outside 0.01-0.99 or wrong decimals"order too small" - Below minimum order size"market closed" - Market not accepting orders/poly)Access Polymarket trading directly from Claude Code:
/poly search <query> # Search markets
/poly market <condition-id> # Market details
/poly book <token-id> # View orderbook/poly buy <token-id> <size> <price> # Buy shares (limit)
/poly sell <token-id> <size> <price> # Sell shares (limit)
/poly orders # Open orders
/poly cancel <order-id> # Cancel order
/poly cancel all # Cancel all orders
/poly trades [limit] # Recent trade history
/poly balance # USDC + positions/poly twap <buy|sell> <token> <total> <price> [slices] [interval-sec]
/poly bracket <token> <size> <tp> <sl> # TP + SL bracket
/poly trigger buy <token> <size> <price> # Buy when price dropsNote: TWAP and bracket orders are persisted to the database and will automatically resume after restarts.
/poly redeem # One-time redeem all resolved positions
/poly redeem start # Start auto-polling (default: every 60s)
/poly redeem stop # Stop auto-polling
/poly redeem status # Check auto-redeemer status
/poly redeem pending # List positions pending redemption
/poly redeem <conditionId> <tokenId> # Redeem specific positionEnv vars:
POLY_REDEEM_INTERVAL_MS - Polling interval in ms (default: 60000 = 1 minute)/poly fills # Connect fills WebSocket
/poly fills status # Show connection + recent fills
/poly fills stop # Disconnect fills WebSocket
/poly fills clear # Clear tracked fills/poly heartbeat # Start heartbeat (keeps orders alive)
/poly heartbeat status # Check heartbeat status
/poly heartbeat stop # Stop heartbeat (orders cancelled in 10s)/poly settlements # View pending settlements from resolved markets
/poly allowance # Check USDC approval status
/poly orderbooks <token1> [token2] ... # Batch fetch orderbooks| Method | Parameters | Returns | Description |
|---|---|---|---|
get_ok() | - | dict | Health check |
get_server_time() | - | dict | Server timestamp |
get_address() | - | str | Your signer address |
get_collateral_address() | - | str | USDC contract |
get_conditional_address() | - | str | CTF contract |
get_exchange_address(neg_risk) | bool | str | Exchange contract |
| Method | Parameters | Returns | Description |
|---|---|---|---|
get_midpoint(token_id) | str | dict | Mid price |
get_midpoints(params) | list[BookParams] | dict | Multiple mid prices |
get_price(token_id, side) | str, str | dict | Best price for side |
get_prices(params) | list[BookParams] | dict | Multiple prices |
get_spread(token_id) | str | dict | Bid-ask spread |
get_spreads(params) | list[BookParams] | dict | Multiple spreads |
get_order_book(token_id) | str | OrderBookSummary | Full orderbook |
get_order_books(params) | list[BookParams] | list | Multiple orderbooks |
get_last_trade_price(token_id) | str | dict | Last trade |
get_last_trades_prices(params) | list[BookParams] | dict | Multiple last trades |
get_tick_size(token_id) | str | TickSize | "0.1"/"0.01"/"0.001"/"0.0001" |
get_neg_risk(token_id) | str | bool | Is neg_risk market |
get_fee_rate_bps(token_id) | str | int | Fee in basis points |
| Method | Parameters | Returns | Description |
|---|---|---|---|
get_markets(next_cursor) | str | dict | Paginated markets |
get_simplified_markets(next_cursor) | str | dict | Simplified markets |
get_sampling_markets(next_cursor) | str | dict | Featured markets |
get_market(condition_id) | str | dict | Single market |
get_market_trades_events(condition_id) | str | dict | Trade events |
| Method | Parameters | Returns | Description |
|---|---|---|---|
create_order(order_args, options) | OrderArgs, CreateOrderOptions | dict | Sign limit order |
create_market_order(order_args, options) | MarketOrderArgs, CreateOrderOptions | dict | Sign market order |
calculate_market_price(token_id, side, amount, order_type) | str, str, float, OrderType | float | Expected fill price |
| Method | Parameters | Returns | Description |
|---|---|---|---|
post_order(order, orderType, post_only) | SignedOrder, OrderType, bool | dict | Post single order |
post_orders(args) | list[PostOrdersArgs] | dict | Post batch orders |
create_and_post_order(order_args, options) | OrderArgs, PartialCreateOrderOptions | dict | Create + post (recommended) |
| Method | Parameters | Returns | Description |
|---|---|---|---|
cancel(order_id) | str | dict | Cancel one order |
cancel_orders(order_ids) | list[str] | dict | Cancel multiple |
cancel_all() | - | dict | Cancel ALL orders |
cancel_market_orders(market, asset_id) | str, str | dict | Cancel by market |
| Method | Parameters | Returns | Description |
|---|---|---|---|
get_orders(params, next_cursor) | OpenOrderParams, str | list | Get open orders |
get_order(order_id) | str | dict | Get specific order |
get_trades(params, next_cursor) | TradeParams, str | list | Trade history |
| Method | Parameters | Returns | Description |
|---|---|---|---|
create_api_key(nonce) | int | ApiCreds | Create new key |
derive_api_key(nonce) | int | ApiCreds | Derive existing key |
create_or_derive_api_creds(nonce) | int | ApiCreds | Create or derive |
set_api_creds(creds) | ApiCreds | - | Set credentials |
get_api_keys() | - | dict | List your keys |
delete_api_key() | - | dict | Delete current key |
create_readonly_api_key() | - | ReadonlyApiKeyResponse | Readonly key |
get_readonly_api_keys() | - | list[str] | List readonly keys |
delete_readonly_api_key(key) | str | bool | Delete readonly key |
| Method | Parameters | Returns | Description |
|---|---|---|---|
get_balance_allowance(params) | BalanceAllowanceParams | dict | Check balance |
update_balance_allowance(params) | BalanceAllowanceParams | dict | Refresh allowance |
| Method | Parameters | Returns | Description |
|---|---|---|---|
post_heartbeat(heartbeat_id) | str | dict | Keep orders alive (10s timeout) |
is_order_scoring(params) | OrderScoringParams | dict | Check if earning rewards |
are_orders_scoring(params) | OrdersScoringParams | dict | Check multiple orders |
get_notifications() | - | dict | Get notifications |
drop_notifications(params) | DropNotificationParams | dict | Delete notifications |
get_closed_only_mode() | - | dict | Check closed-only status |
USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" # Collateral token
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" # Conditional tokens (ERC-1155)
EXCHANGE = "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E" # Regular exchange
NEG_RISK = "0xC5d563A36AE78145C45a50134d48A1215220f80a" # Neg risk exchange (crypto)balance = get_token_balance(wallet, token_id)
if balance > 0:
client.create_and_post_order(OrderArgs(
token_id=token_id, price=0.01, size=balance, side="SELL"
))book = client.get_order_book(token_id)
best_bid = float(book.bids[0].price) if book.bids else 0
maker_price = best_bid + 0.01 # 1 cent above bid
signed = client.create_order(OrderArgs(token_id=token_id, price=maker_price, size=100, side="BUY"))
client.post_order(signed, orderType=OrderType.GTC, post_only=True)signed = client.create_market_order(MarketOrderArgs(token_id=token_id, amount=50.0, side="BUY"))
client.post_order(signed, orderType=OrderType.FOK)client.cancel_all()Polymarket provides WebSocket channels for real-time updates. No RPC needed - everything goes through CLOB.
MARKET_WS = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
USER_WS = "wss://ws-subscriptions-clob.polymarket.com/ws/user"Subscribe to orderbook updates, price changes, trades for any market.
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
event_type = data.get("event_type")
if event_type == "book":
# Full orderbook snapshot (on subscribe + after trades)
print(f"Book update: {data['bids']}, {data['asks']}")
elif event_type == "price_change":
# Order placed/cancelled affecting price level
print(f"Price change: {data}")
elif event_type == "last_trade_price":
# Trade executed
print(f"Trade: {data['price']} x {data['size']}")
elif event_type == "tick_size_change":
# Tick size changed (price went extreme)
print(f"Tick size: {data['old_tick_size']} -> {data['new_tick_size']}")
def on_open(ws):
# Subscribe to specific token
ws.send(json.dumps({
"type": "subscribe",
"channel": "market",
"assets_ids": [TOKEN_ID] # List of token IDs
}))
ws = websocket.WebSocketApp(
"wss://ws-subscriptions-clob.polymarket.com/ws/market",
on_message=on_message,
on_open=on_open
)
ws.run_forever()Subscribe to YOUR order updates, fills, trades. This is how you get fill notifications.
import websocket
import json
import hmac
import hashlib
import time
import base64
API_KEY = os.getenv("POLY_API_KEY")
API_SECRET = os.getenv("POLY_API_SECRET")
API_PASSPHRASE = os.getenv("POLY_API_PASSPHRASE")
def get_auth_headers():
"""Generate HMAC auth for WebSocket"""
timestamp = str(int(time.time()))
message = f"GET\n{timestamp}\n/ws/user"
signature = hmac.new(
base64.b64decode(API_SECRET),
message.encode(),
hashlib.sha256
).digest()
return {
"POLY-ADDRESS": WALLET_ADDRESS,
"POLY-SIGNATURE": base64.b64encode(signature).decode(),
"POLY-TIMESTAMP": timestamp,
"POLY-API-KEY": API_KEY,
"POLY-PASSPHRASE": API_PASSPHRASE
}
def on_message(ws, message):
data = json.loads(message)
event_type = data.get("event_type")
if event_type == "trade":
# YOUR FILL - order matched!
status = data.get("status") # MATCHED, MINED, CONFIRMED, FAILED
print(f"FILL: {data['side']} {data['size']} @ {data['price']}")
print(f" Status: {status}")
print(f" Trade ID: {data['id']}")
print(f" Market: {data['market']}")
if status == "CONFIRMED":
print(" ✓ Trade confirmed on-chain!")
elif status == "FAILED":
print(" ✗ Trade failed - check logs")
elif event_type == "order":
order_type = data.get("type") # PLACEMENT, UPDATE, CANCELLATION
print(f"ORDER {order_type}: {data['side']} {data['original_size']} @ {data['price']}")
print(f" Filled: {data.get('size_matched', 0)}")
if order_type == "CANCELLATION":
print(" Order cancelled")
def on_open(ws):
# Subscribe with auth
ws.send(json.dumps({
"type": "subscribe",
"channel": "user",
"auth": get_auth_headers(),
# Optional: filter to specific market
# "markets": [CONDITION_ID]
}))
ws = websocket.WebSocketApp(
"wss://ws-subscriptions-clob.polymarket.com/ws/user",
on_message=on_message,
on_open=on_open
)
ws.run_forever()Market Channel:
| Event | Trigger | Key Fields |
|---|---|---|
book | Subscribe, trades affect book | bids, asks, timestamp |
price_change | Order placed/cancelled | price, size, side |
last_trade_price | Trade executed | price, size, side |
tick_size_change | Price extreme (>0.96 or <0.04) | old_tick_size, new_tick_size |
User Channel:
| Event | Trigger | Key Fields |
|---|---|---|
trade | Your order filled | status, side, size, price, market |
order | Order placed/updated/cancelled | type (PLACEMENT/UPDATE/CANCELLATION), size_matched |
MATCHED → MINED → CONFIRMED (success)
→ RETRYING → CONFIRMED/FAILEDSend PING every 10 seconds to keep connection alive:
import threading
def send_ping():
while True:
ws.send(json.dumps({"type": "ping"}))
time.sleep(10)
threading.Thread(target=send_ping, daemon=True).start()Polymarket also provides @polymarket/real-time-data-client for TypeScript:
import { RealTimeDataClient } from "@polymarket/real-time-data-client";
const client = new RealTimeDataClient({
onMessage: (msg) => console.log(msg),
onConnect: (c) => {
// Subscribe to user fills with auth
c.subscribe({
subscriptions: [{
topic: "clob_user",
type: "*",
clob_auth: {
key: API_KEY,
secret: API_SECRET,
passphrase: API_PASSPHRASE
}
}]
});
}
});
client.connect();| Operation | Method |
|---|---|
| Get positions | GET /data/positions?user={address} via Gamma API |
| Get balance | client.get_balance_allowance() |
| Place orders | client.create_and_post_order() |
| Get fills | User WebSocket channel |
| Get prices | client.get_order_book() or Market WebSocket |
| Cancel orders | client.cancel() |
The only time you might use RPC is to check on-chain token balances independently, but even that's available via Gamma API positions endpoint.
© alsk1992, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in src/skills/bundled/trading-polymarket of alsk1992/CloddsBot.
Open the folder on GitHubat commit c930628
Trading Polymarket next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Trading Polymarket this skillalsk1992/CloddsBot | 3k | — | ~8.3k | Automated safety check: Pass | MIT | |
| Digital Oraclekomako-workshop/digital-oracle | 878 | — | ~5.9k | Automated safety check: Pass | MIT | |
| Polymarket Tennislivetennisapi/livetennisapi-mcp | 152 | — | ~3k | Automated safety check: Pass | MIT | |
| Catalyst ConfirmationSuperior-Trade/superior-skills | 215 | — | ~667 | Automated safety check: Pass | MIT | |
| PolymarketAnil-matcha/awesome-muse-connectors | 1.3k | — | ~790 | Automated safety check: Pass | MIT | |
| Heytraders APILeoYeAI/openclaw-master-skills | 2.2k | — | ~4.2k | Automated safety check: Pass | MIT |
komako-workshop/digital-oracle
Answer prediction questions using market trading data, not opinions.
livetennisapi/livetennisapi-mcp
Build observe-only Polymarket and Kalshi tennis market tooling on the polymarket-tennis Python package (MIT) plus the Live Tennis API free tier.
Superior-Trade/superior-skills
A skill your agent uses when a Polymarket prediction-market thesis rests on an external event — CPI, Fed, elections, court rulings, ETF decisions — and needs market confirmation before committing.
Anil-matcha/awesome-muse-connectors
Read-only Polymarket market data: events, markets, prices, order books.
LeoYeAI/openclaw-master-skills
Trade crypto (Binance, Upbit, Hyperliquid, Lighter) and prediction markets (Polymarket).
aAAaqwq/AGI-Super-Team
Build and test Polymarket prediction market trading strategies for YES/NO token trading.
alsk1992/CloddsBot
Local hybrid search for markdown notes and docs. An agent skill from alsk1992/CloddsBot.
alsk1992/CloddsBot
AI Strategy - natural language to trades. An agent skill from alsk1992/CloddsBot.
alsk1992/CloddsBot
Create and manage price alerts for prediction markets. An agent skill from alsk1992/CloddsBot.
alsk1992/CloddsBot
Performance attribution, trade analytics, and strategy optimization
alsk1992/CloddsBot
Automated cross-platform arbitrage detection and monitoring. An agent skill from alsk1992/CloddsBot.
alsk1992/CloddsBot
Automatic response rules, patterns, and scheduled messages. An agent skill from alsk1992/CloddsBot.
Works with
Categories
Execute trades on Polymarket using pyclobclient - full API access for market data, orders, positions. Trading Polymarket is an agent skill from alsk1992/CloddsBot.
Trading Polymarket fits situations like: tasks that involve Trading and backtesting; tasks that involve Stock and market analysis.
Run `npx skills add alsk1992/CloddsBot --skill trading-polymarket -a claude-code`. Or copy the skill folder (src/skills/bundled/trading-polymarket in alsk1992/CloddsBot) into .claude/skills/trading-polymarket in your project. Claude Code loads it when a task matches its description.
Run `npx skills add alsk1992/CloddsBot --skill trading-polymarket -a codex`. Or copy the skill folder (src/skills/bundled/trading-polymarket in alsk1992/CloddsBot) into .agents/skills/trading-polymarket in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add alsk1992/CloddsBot --skill trading-polymarket -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/trading-polymarket, .gemini/skills/trading-polymarket, .github/skills/trading-polymarket and .opencode/skills/trading-polymarket in your project.
Going by SKILL.md and its folder, Trading Polymarket needs TypeScript for the scripts in its folder, the command-line tools its instructions call (pip) and credentials named POLY_API_KEY, POLY_API_SECRET, PRIVATE_KEY and API_KEY. Our summary lists: Python 3; Node.js; A credential in POLY_API_KEY; A credential in POLY_API_SECRET.
SKILL.md names 3 domains. In commands or code: clob.polymarket.com, polygon-rpc.com and gamma-api.polymarket.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Trading Polymarket is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 8.3k tokens (SKILL.md is roughly 33k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Trading Polymarket: Digital Oracle (komako-workshop/digital-oracle, 878 stars), Polymarket Tennis (livetennisapi/livetennisapi-mcp, 152 stars), Catalyst Confirmation (Superior-Trade/superior-skills, 215 stars) and Polymarket (Anil-matcha/awesome-muse-connectors, 1.3k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
alsk1992 (a GitHub user) maintains it in alsk1992/CloddsBot, which has 2,951 GitHub stars. The repository holds 116 skills in this directory. The repository was last updated on October 2, 2026.
Source: alsk1992/CloddsBot on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.