
Execution
- 13 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
Execution is a Claude Code skill that executes and manages trades on Polymarket and Kalshi with slippage protection and order management.
About
Execution is a trading skill that places and manages orders on the Polymarket and Kalshi prediction markets. A developer uses /execute commands or the createExecutionService TypeScript API to submit limit, market, and post-only maker orders, run slippage-protected orders, estimate slippage, and cancel open orders. It is gated on a Polymarket or Kalshi API key.
- Executes buy/sell orders on Polymarket and Kalshi with limit, market, and maker order types
- Slippage-protected orders reject if estimated slippage exceeds a set threshold
- Manages open orders and estimates slippage before a trade; supports maker rebates
Execution by the numbers
- 13 all-time installs (skills.sh)
- Ranked #759 of 1,106 Finance & Trading skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
execution capabilities & compatibility
Requires a Polymarket or Kalshi API key (and Polymarket also API secret/passphrase/private key) plus trading capital; no service fee stated.
- Capabilities
- order execution · slippage protection · order management · slippage estimation
- Use cases
- trading
- Pricing
- Bring your own API key
What execution says it does
Execute trades on Polymarket and Kalshi with slippage protection, maker orders, and order management.
Protected buy - checks slippage before executing
npx skills add https://github.com/alsk1992/cloddsbot --skill executionAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 13 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Execute and manage limit, market, maker, and slippage-protected orders on Polymarket and Kalshi prediction markets.
Who is it for?
Executing prediction-market trades with maker rebates and slippage-protected orders.
Skip if: Users without a Polymarket or Kalshi API key or wanting non-prediction-market brokerages.
When should I use this skill?
You want an agent to place or manage orders on Polymarket or Kalshi with slippage control.
What you get
Orders placed and managed on Polymarket and Kalshi with limit/market/maker types and slippage protection.
By the numbers
- 2 platforms: Polymarket and Kalshi
- Polymarket offers -0.5% maker rebate
Files
Execution Service - Complete API Reference
Execute trades on Polymarket and Kalshi with slippage protection, maker orders, and order management.
Supported Platforms
| Platform | Order Types | Features |
|---|---|---|
| Polymarket | Limit, Market, Maker | -0.5% maker rebate, GTC/FOK |
| Kalshi | Limit, Market | US regulated |
---
Chat Commands
Place Orders
/execute buy poly <market> YES 100 @ 0.52 # Limit buy on Polymarket
/execute sell kalshi <market> NO 50 @ 0.48 # Limit sell on Kalshi
/execute market-buy poly <market> YES 100 # Market buy
/execute market-sell poly <market> NO 50 # Market sellMaker Orders (Rebates)
/execute maker-buy poly <market> YES 100 @ 0.52 # Post-only buy
/execute maker-sell poly <market> NO 50 @ 0.48 # Post-only sellProtected Orders (Slippage Protection)
/execute protected-buy poly <market> YES 100 --max-slippage 1%
/execute protected-sell poly <market> NO 50 --max-slippage 0.5%Order Management
/orders open # View open orders
/orders open poly # Open orders on Polymarket
/orders cancel <order-id> # Cancel specific order
/orders cancel-all # Cancel all open orders
/orders cancel-all poly # Cancel all on PolymarketSlippage Estimation
/estimate-slippage poly <market> buy 1000 # Estimate slippage for $1000 buy
/estimate-slippage kalshi <market> sell 500 # Estimate for $500 sell---
TypeScript API Reference
Create Execution Service
import { createExecutionService } from 'clodds/execution';
const executor = createExecutionService({
polymarket: {
apiKey: process.env.POLY_API_KEY,
apiSecret: process.env.POLY_API_SECRET,
passphrase: process.env.POLY_API_PASSPHRASE,
privateKey: process.env.PRIVATE_KEY,
},
kalshi: {
apiKey: process.env.KALSHI_API_KEY,
privateKey: process.env.KALSHI_PRIVATE_KEY,
},
// Defaults
defaultSlippageTolerance: 0.5, // 0.5%
autoLogTrades: true,
});Limit Orders
// Buy limit order
const order = await executor.buyLimit({
platform: 'polymarket',
marketId: 'market-123',
side: 'YES',
size: 100, // $100
price: 0.52, // 52 cents
timeInForce: 'GTC', // Good-til-cancel
});
console.log(`Order placed: ${order.orderId}`);
console.log(`Status: ${order.status}`);
// Sell limit order
const sellOrder = await executor.sellLimit({
platform: 'polymarket',
marketId: 'market-123',
side: 'YES',
size: 100,
price: 0.55,
});Market Orders
// Market buy - executes immediately at best price
const order = await executor.marketBuy({
platform: 'polymarket',
marketId: 'market-123',
side: 'YES',
size: 100,
});
console.log(`Filled at: ${order.avgFillPrice}`);
console.log(`Filled size: ${order.filledSize}`);
// Market sell
const sellOrder = await executor.marketSell({
platform: 'kalshi',
marketId: 'TRUMP-WIN',
side: 'YES',
size: 50,
});Maker Orders (Post-Only)
// Maker buy - only executes as maker (gets rebate)
const order = await executor.makerBuy({
platform: 'polymarket',
marketId: 'market-123',
side: 'YES',
size: 100,
price: 0.52,
});
// Will be rejected if it would execute immediately as taker
if (order.status === 'rejected') {
console.log('Price too aggressive - would be taker');
}
// Maker sell
const sellOrder = await executor.makerSell({
platform: 'polymarket',
marketId: 'market-123',
side: 'NO',
size: 50,
price: 0.48,
});Protected Orders (Slippage Protection)
// Protected buy - checks slippage before executing
const order = await executor.protectedBuy({
platform: 'polymarket',
marketId: 'market-123',
side: 'YES',
size: 100,
maxSlippage: 0.5, // 0.5% max slippage
});
if (order.status === 'rejected') {
console.log(`Rejected: slippage would be ${order.estimatedSlippage}%`);
} else {
console.log(`Executed with ${order.actualSlippage}% slippage`);
}
// Protected sell
const sellOrder = await executor.protectedSell({
platform: 'kalshi',
marketId: 'TRUMP-WIN',
side: 'YES',
size: 50,
maxSlippage: 1,
});Order Management
// Cancel specific order
await executor.cancelOrder('polymarket', orderId);
// Cancel all orders on platform
await executor.cancelAllOrders('polymarket');
// Cancel all orders for a market
await executor.cancelAllOrders('polymarket', { marketId: 'market-123' });
// Get open orders
const openOrders = await executor.getOpenOrders('polymarket');
for (const order of openOrders) {
console.log(`${order.orderId}: ${order.side} ${order.size} @ ${order.price}`);
console.log(` Status: ${order.status}`);
console.log(` Filled: ${order.filledSize}/${order.size}`);
}Slippage Estimation
// Estimate slippage before executing
const estimate = await executor.estimateSlippage({
platform: 'polymarket',
marketId: 'market-123',
side: 'buy',
size: 1000,
});
console.log(`For $1000 buy:`);
console.log(` Avg fill price: ${estimate.avgFillPrice}`);
console.log(` Expected slippage: ${estimate.slippagePct}%`);
console.log(` Total filled: ${estimate.totalFilled}`);
console.log(` Levels consumed: ${estimate.levelsConsumed}`);---
Order Types
| Type | Description | Best For |
|---|---|---|
| Limit | Execute at specific price or better | Price-sensitive orders |
| Market | Execute immediately at best available | Urgent execution |
| Maker | Post-only, gets rebate | Collecting rebates |
| Protected | Checks slippage before executing | Large orders |
Time In Force
| Value | Description |
|---|---|
| GTC | Good-til-cancel (default) |
| FOK | Fill-or-kill - all or nothing |
| IOC | Immediate-or-cancel - fill what you can |
---
Fee Structure
Polymarket (Verified Jan 2026)
- Most markets: 0% maker, 0% taker (zero fees)
- 15-min crypto markets: Dynamic taker fees up to ~3% at 50/50 odds; makers eligible for rebate program
Kalshi
- Taker: Formula-based ~1.2% average, capped at ~2%
- Maker: ~0.17% (formula-based)
---
Best Practices
1. Use maker orders when possible - Pay no fees on Polymarket (most markets) 2. Check slippage before large orders 3. Use protected orders for size > $500 4. Set appropriate timeInForce - GTC for patient orders, FOK for all-or-nothing 5. Monitor open orders - Cancel stale orders 6. Start small - Test with small sizes first
/**
* Execution CLI Skill
*
* Commands:
* /exec buy <market> <amount> - Buy on market
* /exec sell <market> <amount> - Sell on market
* /exec orders - List open orders
* /exec cancel <id> - Cancel order
* /exec slippage <market> <size> - Estimate slippage
*/
import { formatHelp } from '../../help.js';
import { wrapSkillError } from '../../errors.js';
async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const cmd = parts[0]?.toLowerCase() || 'help';
try {
const { createExecutionService } = await import('../../../execution/index');
// Parse common flags
const platformIdx = parts.indexOf('--platform');
const platform = (platformIdx >= 0 ? parts[platformIdx + 1] : 'polymarket') as 'polymarket' | 'kalshi' | 'opinion' | 'predictfun';
const priceIdx = parts.indexOf('--price');
const rawPrice = priceIdx >= 0 ? parseFloat(parts[priceIdx + 1]) : NaN;
const price = !isNaN(rawPrice) ? rawPrice : undefined;
const slippageIdx = parts.indexOf('--slippage');
const rawSlippage = slippageIdx >= 0 ? parseFloat(parts[slippageIdx + 1]) : NaN;
const maxSlippage = !isNaN(rawSlippage) ? rawSlippage / 100 : 0.02;
const service = createExecutionService({} as any);
// Lazy circuit breaker getter
const getCircuitBreaker = async () => {
const { getGlobalCircuitBreaker } = await import('../../../execution/circuit-breaker');
return getGlobalCircuitBreaker();
};
switch (cmd) {
case 'buy': {
if (parts.length < 3) return 'Usage: /exec buy <market-id> <amount> [--price <p>] [--platform <name>] [--slippage <pct>]';
const marketId = parts[1];
const size = parseFloat(parts[2]);
if (isNaN(size)) return 'Invalid amount.';
const cb = await getCircuitBreaker();
if (!cb.canTrade()) {
const state = cb.getState();
return `**Trade blocked** — Circuit breaker tripped: ${state.tripReason || 'unknown'}\nUse \`/risk reset\` to re-arm.`;
}
const request = { platform, marketId, price: price ?? 0.50, size };
const result = price
? await service.buyLimit(request)
: await service.protectedBuy(request, maxSlippage);
cb.recordTrade({
pnlUsd: 0,
success: result.success,
sizeUsd: size * (price ?? 0.50),
error: result.error,
});
if (result.success) {
try {
const { getGlobalPositionManager } = await import('../../../execution/position-manager');
const pm = getGlobalPositionManager();
pm.updatePosition({
platform: platform as any,
marketId,
tokenId: marketId,
outcomeName: 'Yes',
side: 'long',
size,
entryPrice: result.avgFillPrice ?? (price ?? 0.50),
currentPrice: result.avgFillPrice ?? (price ?? 0.50),
openedAt: new Date(),
});
} catch { /* position tracking non-critical */ }
}
let output = `**Buy Order**\n\nPlatform: ${platform}\nMarket: ${marketId}\n`;
output += `Size: ${size} shares\n`;
if (price) output += `Price: ${price}\n`;
output += `Status: ${result.status || (result.success ? 'submitted' : 'failed')}\n`;
if (result.orderId) output += `Order ID: \`${result.orderId}\`\n`;
if (result.avgFillPrice) output += `Fill price: ${result.avgFillPrice.toFixed(4)}\n`;
if (result.error) output += `Error: ${result.error}\n`;
return output;
}
case 'sell': {
if (parts.length < 3) return 'Usage: /exec sell <market-id> <amount> [--price <p>] [--platform <name>]';
const marketId = parts[1];
const size = parseFloat(parts[2]);
if (isNaN(size)) return 'Invalid amount.';
const cb = await getCircuitBreaker();
if (!cb.canTrade()) {
const state = cb.getState();
return `**Trade blocked** — Circuit breaker tripped: ${state.tripReason || 'unknown'}\nUse \`/risk reset\` to re-arm.`;
}
const request = { platform, marketId, price: price ?? 0.50, size };
const result = price
? await service.sellLimit(request)
: await service.protectedSell(request, maxSlippage);
cb.recordTrade({
pnlUsd: 0,
success: result.success,
sizeUsd: size * (price ?? 0.50),
error: result.error,
});
if (result.success) {
try {
const { getGlobalPositionManager } = await import('../../../execution/position-manager');
const pm = getGlobalPositionManager();
const existing = pm.getPositionsByPlatform(platform as any)
.find(p => p.tokenId === marketId && p.status === 'open');
if (existing) {
pm.closePosition(existing.id, result.avgFillPrice ?? (price ?? 0.50), 'manual');
}
} catch { /* position tracking non-critical */ }
}
let output = `**Sell Order**\n\nPlatform: ${platform}\nMarket: ${marketId}\n`;
output += `Size: ${size} shares\n`;
if (price) output += `Price: ${price}\n`;
output += `Status: ${result.status || (result.success ? 'submitted' : 'failed')}\n`;
if (result.orderId) output += `Order ID: \`${result.orderId}\`\n`;
if (result.avgFillPrice) output += `Fill price: ${result.avgFillPrice.toFixed(4)}\n`;
if (result.error) output += `Error: ${result.error}\n`;
return output;
}
case 'orders':
case 'open': {
const orders = await service.getOpenOrders(platform);
if (!orders.length) return `No open orders on ${platform}.`;
let output = `**Open Orders** (${orders.length} on ${platform})\n\n`;
for (const o of orders) {
output += `[${o.orderId}] ${o.side.toUpperCase()} ${o.originalSize} @ ${o.price.toFixed(4)}`;
output += ` | ${o.status} | ${o.marketId}\n`;
}
return output;
}
case 'cancel': {
if (!parts[1]) return 'Usage: /exec cancel <order-id> [--platform <name>]';
if (parts[1] === 'all') {
const count = await service.cancelAllOrders(platform);
return `Cancelled ${count} orders on ${platform}.`;
}
const success = await service.cancelOrder(platform, parts[1]);
return success ? `Order \`${parts[1]}\` cancelled.` : `Failed to cancel order \`${parts[1]}\`.`;
}
case 'status': {
if (!parts[1]) return 'Usage: /exec status <order-id> [--platform <name>]';
const order = await service.getOrder(platform, parts[1]);
if (!order) return `Order \`${parts[1]}\` not found on ${platform}.`;
let output = `**Order: \`${order.orderId}\`**\n\n`;
output += `Platform: ${platform}\n`;
output += `Market: ${order.marketId}\n`;
output += `Side: ${order.side}\n`;
output += `Size: ${order.originalSize} @ ${order.price.toFixed(4)}\n`;
output += `Status: ${order.status}\n`;
if (order.filledSize) output += `Filled: ${order.filledSize}\n`;
return output;
}
case 'slippage':
case 'estimate': {
if (!parts[1]) return 'Usage: /exec slippage <market-id> <size> [--platform <name>]';
const marketId = parts[1];
const rawSize = parseFloat(parts[2] || '100');
const size = isNaN(rawSize) || rawSize <= 0 ? 100 : rawSize;
const estimate = await service.estimateSlippage({ platform, marketId, side: 'buy', price: 0.50, size });
return `**Slippage Estimate**\n\nMarket: ${marketId}\nSize: ${size}\nEstimated slippage: ${(estimate.slippage * 100).toFixed(2)}%\nExpected price: ${estimate.expectedPrice.toFixed(4)}`;
}
case 'twap': {
// /exec twap <side> <market> <total> <price> <slices> <interval>
const side = parts[1]?.toLowerCase();
if (!side || (side !== 'buy' && side !== 'sell') || !parts[2] || !parts[3] || !parts[4]) {
return 'Usage: /exec twap <buy|sell> <market-id> <total> <price> [slices] [interval-sec] [--platform <name>]';
}
const marketId = parts[2];
const totalSize = parseFloat(parts[3]);
const twapPrice = parseFloat(parts[4]);
const rawSlices = parts[5] ? parseInt(parts[5], 10) : NaN;
const slices = !isNaN(rawSlices) && rawSlices > 0 ? rawSlices : 5;
const rawInterval = parts[6] ? parseInt(parts[6], 10) : NaN;
const intervalSec = !isNaN(rawInterval) && rawInterval > 0 ? rawInterval : 30;
if (isNaN(totalSize) || totalSize <= 0) return 'Invalid total size.';
if (isNaN(twapPrice) || twapPrice < 0.01 || twapPrice > 0.99) return 'Invalid price (0.01-0.99).';
const { createTwapOrder } = await import('../../../execution/twap');
const twap = createTwapOrder(
service,
{ platform, marketId, tokenId: marketId, side: side as 'buy' | 'sell', price: twapPrice },
{ totalSize, sliceSize: totalSize / slices, intervalMs: intervalSec * 1000 }
);
twap.start();
return `**TWAP Started**\n\n${side.toUpperCase()} ${totalSize} shares @ ${twapPrice}\nPlatform: ${platform}\nSlices: ${slices} every ${intervalSec}s`;
}
case 'bracket': {
// /exec bracket <market> <size> <tp> <sl>
if (!parts[1] || !parts[2] || !parts[3] || !parts[4]) {
return 'Usage: /exec bracket <market-id> <size> <tp-price> <sl-price> [--platform <name>]';
}
const marketId = parts[1];
const bracketSize = parseFloat(parts[2]);
const tp = parseFloat(parts[3]);
const sl = parseFloat(parts[4]);
if (isNaN(bracketSize) || bracketSize <= 0) return 'Invalid size.';
if (isNaN(tp) || tp < 0.01 || tp > 0.99) return 'Invalid take-profit price (0.01-0.99).';
if (isNaN(sl) || sl < 0.01 || sl > 0.99) return 'Invalid stop-loss price (0.01-0.99).';
const { createBracketOrder } = await import('../../../execution/bracket-orders');
const bracket = createBracketOrder(service, {
platform: platform as 'polymarket' | 'kalshi',
marketId,
tokenId: marketId,
size: bracketSize,
side: 'long',
takeProfitPrice: tp,
stopLossPrice: sl,
});
await bracket.start();
return `**Bracket Set**\n\nTP @ ${tp} / SL @ ${sl} for ${bracketSize} shares\nPlatform: ${platform}\nMarket: ${marketId}`;
}
case 'trigger':
case 'triggers': {
// /exec trigger <side> <market> <size> <price>
// /exec triggers (list)
const triggerSide = parts[1]?.toLowerCase();
if (cmd === 'triggers' || !triggerSide || triggerSide === 'list') {
return 'Trigger orders require a price feed. Use /poly trigger for Polymarket triggers.';
}
if (triggerSide !== 'buy' && triggerSide !== 'sell') {
return 'Usage: /exec trigger <buy|sell> <market-id> <size> <trigger-price> [--platform <name>]';
}
if (!parts[2] || !parts[3] || !parts[4]) {
return 'Usage: /exec trigger <buy|sell> <market-id> <size> <trigger-price> [--platform <name>]';
}
return `Trigger orders require a price feed subscription. Use /poly trigger for Polymarket triggers with real-time WebSocket feeds.`;
}
case 'circuit': {
const cb = await getCircuitBreaker();
const state = cb.getState();
return `**Circuit Breaker**\n\n` +
`Status: ${state.isTripped ? 'TRIPPED' : 'Armed'}\n` +
`Session PnL: $${state.sessionPnL.toFixed(2)}\n` +
`Daily trades: ${state.dailyTrades}\n` +
`Consecutive losses: ${state.consecutiveLosses}\n` +
`Error rate: ${(state.errorRate * 100).toFixed(0)}%\n` +
(state.tripReason ? `Trip reason: ${state.tripReason}\n` : '') +
`\nUse \`/risk trip\` / \`/risk reset\` to manually control.`;
}
case 'redeem': {
if (platform !== 'polymarket') {
return 'Redeem is currently only supported for Polymarket.';
}
const privateKey = process.env.POLY_PRIVATE_KEY;
const funderAddress = process.env.POLY_FUNDER_ADDRESS;
const apiKey = process.env.POLY_API_KEY;
const apiSecret = process.env.POLY_API_SECRET;
const passphrase = process.env.POLY_API_PASSPHRASE;
if (!privateKey || !funderAddress || !apiKey || !apiSecret || !passphrase) {
return 'Set POLY_PRIVATE_KEY, POLY_FUNDER_ADDRESS, POLY_API_KEY, POLY_API_SECRET, POLY_API_PASSPHRASE to redeem.';
}
const { createAutoRedeemer } = await import('../../../execution/auto-redeem');
const redeemer = createAutoRedeemer({
polymarketAuth: { address: funderAddress, apiKey, apiSecret, apiPassphrase: passphrase },
privateKey,
funderAddress,
dryRun: process.env.DRY_RUN === 'true',
});
const condId = parts[1];
const tokId = parts[2];
if (condId && tokId) {
const result = await redeemer.redeemPosition(condId, tokId);
return result.success
? `Redeemed ${result.shares} shares → $${result.usdcRedeemed.toFixed(2)} USDC${result.txHash ? ` (tx: ${result.txHash})` : ''}`
: `Redeem failed: ${result.error}`;
}
const results = await redeemer.redeemAll();
if (results.length === 0) return 'No resolved positions to redeem.';
const ok = results.filter(r => r.success);
const totalUsdc = ok.reduce((s, r) => s + r.usdcRedeemed, 0);
return `Redeemed ${ok.length}/${results.length} positions → $${totalUsdc.toFixed(2)} USDC`;
}
default:
return formatHelp({
name: 'Execution',
description: 'Execute trades on prediction markets with slippage protection, TWAP, bracket orders, and circuit breakers.',
sections: [
{
title: 'Basic Orders',
commands: [
{ cmd: '/exec buy <market> <amount> [--price <p>]', description: 'Place buy order (market or limit)' },
{ cmd: '/exec sell <market> <amount> [--price <p>]', description: 'Place sell order (market or limit)' },
{ cmd: '/exec orders', description: 'List open orders' },
{ cmd: '/exec cancel <id|all>', description: 'Cancel order(s)' },
{ cmd: '/exec status <id>', description: 'Check order status' },
{ cmd: '/exec slippage <market> <size>', description: 'Estimate slippage' },
],
},
{
title: 'Advanced Orders',
commands: [
{ cmd: '/exec twap <side> <market> <total> <price> [slices] [interval]', description: 'Time-weighted average price order' },
{ cmd: '/exec bracket <market> <size> <tp> <sl>', description: 'Bracket order with take-profit and stop-loss' },
{ cmd: '/exec trigger <side> <market> <size> <price>', description: 'Trigger/conditional order' },
{ cmd: '/exec redeem [cond-id] [token-id]', description: 'Redeem resolved positions (Polymarket)' },
],
},
{
title: 'Risk',
commands: [
{ cmd: '/exec circuit', description: 'View circuit breaker status' },
],
},
],
notes: [
'Shortcuts: `/exec` is an alias for `/execute`.',
'Options: --platform <polymarket|kalshi|opinion|predictfun>, --price <limit>, --slippage <pct>.',
'Omit --price for a market order with slippage protection (default 2%).',
],
seeAlso: [
{ cmd: '/hl', description: 'Hyperliquid perps trading' },
{ cmd: '/lighter', description: 'Lighter DEX trading' },
{ cmd: '/strategy', description: 'Strategy management' },
{ cmd: '/copy', description: 'Copy trading' },
],
});
}
} catch (error) {
return wrapSkillError('Execution', cmd || 'command', error);
}
}
export default {
name: 'execution',
description: 'Execute trades on prediction markets with slippage protection',
commands: ['/exec', '/execute'],
handle: execute,
};