
History
- 12 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
history is a Claude Code skill that fetches, syncs and analyzes prediction-market trade history from Polymarket and Kalshi.
About
history is a Claude Code skill that fetches, syncs and analyzes prediction-market trade history from Polymarket and Kalshi. It stores trades in a local SQLite database and reports win rate, total P&L, profit factor, Sharpe ratio and drawdown, plus daily, weekly and monthly P&L. A developer uses it to review trading performance and export trades to CSV or JSON.
- Fetches and syncs trade history from Polymarket and Kalshi into a local SQLite DB
- Computes win rate, P&L, profit factor, Sharpe ratio and max drawdown
- Exports trades to CSV or JSON with daily, weekly and monthly P&L breakdowns
History by the numbers
- 12 all-time installs (skills.sh)
- Ranked #781 of 1,106 Finance & Trading skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
history capabilities & compatibility
Free skill; requires your own Polymarket/Kalshi API keys.
- Capabilities
- trade history · pnl analysis · performance analytics · csv export
- Use cases
- trading · data analysis
- Pricing
- Bring your own API key
What history says it does
Fetch, sync, and analyze trade history from Polymarket and Kalshi with detailed performance metrics.
Get comprehensive statistics
npx skills add https://github.com/alsk1992/cloddsbot --skill historyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 12 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Pull trade history from Polymarket and Kalshi into a local database and analyze win rate, P&L and risk metrics.
Who is it for?
Tracking prediction-market trading performance across Polymarket and Kalshi.
When should I use this skill?
You want to sync your trades and review win rate, P&L or drawdown.
What you get
A local trade database with win rate, P&L, risk metrics and CSV/JSON exports.
- synced trade database
- performance statistics
- CSV/JSON trade export
By the numbers
- 2 supported platforms (Polymarket, Kalshi)
- P&L periods: daily, weekly, monthly
- SQLite trades table schema
Files
Trade History - Complete API Reference
Fetch, sync, and analyze trade history from Polymarket and Kalshi with detailed performance metrics.
---
Chat Commands
Fetch & Sync
/history fetch # Fetch all trades from APIs
/history fetch poly # Fetch Polymarket only
/history fetch --from 2024-01-01 # From specific date
/history sync # Sync to local databaseView History
/history list # Recent trades
/history list --limit 50 # Last 50 trades
/history list --platform poly # Polymarket only
/history list --market <id> # Specific marketStatistics
/history stats # Overall statistics
/history stats --period 30d # Last 30 days
/history stats --platform kalshi # Platform-specificP&L Analysis
/history daily-pnl # Daily P&L
/history weekly-pnl # Weekly P&L
/history monthly-pnl # Monthly P&L
/history by-market # P&L by market categoryExport
/history export # Export to CSV
/history export --format json # Export as JSON
/history export --from 2024-01-01 # Date rangeFiltering
/history filter --side buy # Only buys
/history filter --pnl positive # Only winners
/history filter --pnl negative # Only losers
/history filter --min-size 100 # Min $100 trades---
TypeScript API Reference
Create History Service
import { createTradeHistoryService } from 'clodds/history';
const history = createTradeHistoryService({
polymarket: {
apiKey: process.env.POLY_API_KEY,
address: process.env.POLY_ADDRESS,
},
kalshi: {
apiKey: process.env.KALSHI_API_KEY,
},
// Local storage
dbPath: './trade-history.db',
});Fetch Trades from APIs
// Fetch all trades from exchange APIs
const trades = await history.fetchTrades({
platforms: ['polymarket', 'kalshi'],
from: '2024-01-01',
});
console.log(`Fetched ${trades.length} trades`);
// Fetch from specific platform
const polyTrades = await history.fetchTrades({
platforms: ['polymarket'],
limit: 100,
});Sync to Database
// Sync fetched trades to local database
await history.syncToDatabase();
console.log('Trades synced to database');Get Trades
// Get trades from local storage
const trades = await history.getTrades({
platform: 'polymarket',
from: '2024-01-01',
to: '2024-12-31',
limit: 100,
});
for (const trade of trades) {
console.log(`${trade.timestamp}: ${trade.side} ${trade.market}`);
console.log(` Size: $${trade.size}`);
console.log(` Price: ${trade.price}`);
console.log(` P&L: $${trade.pnl?.toFixed(2) || 'open'}`);
}Statistics
// Get comprehensive statistics
const stats = await history.getStats({
period: '30d',
platform: 'polymarket',
});
console.log(`=== Trading Statistics (30d) ===`);
console.log(`Total trades: ${stats.totalTrades}`);
console.log(`Winning trades: ${stats.winningTrades}`);
console.log(`Losing trades: ${stats.losingTrades}`);
console.log(`Win rate: ${(stats.winRate * 100).toFixed(1)}%`);
console.log(`\nP&L:`);
console.log(` Total: $${stats.totalPnl.toLocaleString()}`);
console.log(` Gross profit: $${stats.grossProfit.toLocaleString()}`);
console.log(` Gross loss: $${stats.grossLoss.toLocaleString()}`);
console.log(` Profit factor: ${stats.profitFactor.toFixed(2)}`);
console.log(`\nTrade sizes:`);
console.log(` Average: $${stats.avgTradeSize.toFixed(2)}`);
console.log(` Largest win: $${stats.largestWin.toFixed(2)}`);
console.log(` Largest loss: $${stats.largestLoss.toFixed(2)}`);
console.log(`\nRisk metrics:`);
console.log(` Sharpe ratio: ${stats.sharpeRatio.toFixed(2)}`);
console.log(` Max drawdown: ${(stats.maxDrawdown * 100).toFixed(1)}%`);Daily P&L
// Get daily P&L breakdown
const dailyPnl = await history.getDailyPnL({
days: 30,
platform: 'polymarket',
});
console.log('=== Daily P&L ===');
for (const day of dailyPnl) {
const sign = day.pnl >= 0 ? '+' : '';
const bar = day.pnl >= 0
? '█'.repeat(Math.min(Math.floor(day.pnl / 10), 20))
: '▓'.repeat(Math.min(Math.floor(Math.abs(day.pnl) / 10), 20));
console.log(`${day.date} | ${sign}$${day.pnl.toFixed(2).padStart(8)} | ${bar}`);
}Performance by Market
// Get performance breakdown by market category
const byMarket = await history.getPerformanceByMarket({
period: '30d',
});
console.log('=== Performance by Market Category ===');
for (const [category, data] of Object.entries(byMarket)) {
console.log(`\n${category}:`);
console.log(` Trades: ${data.trades}`);
console.log(` Win rate: ${(data.winRate * 100).toFixed(1)}%`);
console.log(` P&L: $${data.pnl.toLocaleString()}`);
console.log(` Avg trade: $${data.avgTrade.toFixed(2)}`);
}Export
// Export to CSV
await history.exportCsv({
path: './trades.csv',
from: '2024-01-01',
to: '2024-12-31',
columns: ['timestamp', 'platform', 'market', 'side', 'size', 'price', 'pnl'],
});
// Export to JSON
const json = await history.exportJson({
from: '2024-01-01',
});---
Database Schema
CREATE TABLE trades (
id TEXT PRIMARY KEY,
platform TEXT NOT NULL,
market_id TEXT NOT NULL,
market_question TEXT,
side TEXT NOT NULL, -- 'buy' or 'sell'
outcome TEXT, -- 'YES' or 'NO'
size REAL NOT NULL,
price REAL NOT NULL,
fee REAL DEFAULT 0,
pnl REAL,
timestamp INTEGER NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now'))
);
CREATE INDEX idx_trades_platform ON trades(platform);
CREATE INDEX idx_trades_timestamp ON trades(timestamp);
CREATE INDEX idx_trades_market ON trades(market_id);---
Best Practices
1. Sync regularly - Keep local database up to date 2. Export backups - Periodically export to CSV 3. Review weekly - Analyze performance patterns 4. Track by category - Identify strong/weak areas 5. Monitor drawdown - Set alerts for max drawdown
/**
* History CLI Skill
*
* Commands:
* /history - Recent trades
* /history today - Today's trades
* /history week - This week
* /history pnl - P&L summary
* /history stats - Full trading statistics
* /history search <query> - Search trades by market
* /history export [format] - Export trades
* /history sync - Sync from exchanges
*/
async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const cmd = parts[0]?.toLowerCase() || 'recent';
try {
const historyMod = await import('../../../history/index');
const { createDatabase } = await import('../../../db/index');
const db = createDatabase();
// Build config from env vars if available
const config: any = {};
if (process.env.POLYMARKET_API_KEY) {
config.polymarket = {
apiKey: process.env.POLYMARKET_API_KEY,
apiSecret: process.env.POLYMARKET_API_SECRET || '',
apiPassphrase: process.env.POLYMARKET_API_PASSPHRASE || '',
};
}
if (process.env.KALSHI_API_KEY_ID) {
config.kalshi = {
apiKeyId: process.env.KALSHI_API_KEY_ID,
privateKeyPem: process.env.KALSHI_PRIVATE_KEY_PEM || '',
};
}
const service = historyMod.createTradeHistoryService(config, db);
switch (cmd) {
case 'recent':
case 'list':
case 'ls': {
const limit = parts[1] ? parseInt(parts[1], 10) : 10;
return service.formatRecentTrades(isNaN(limit) ? 10 : limit);
}
case 'today': {
const trades = service.getTrades({
startDate: new Date(new Date().setHours(0, 0, 0, 0)),
endDate: new Date(),
});
if (!trades.length) return '**Today\'s Trades**\n\nNo trades today.';
const todayPnL = service.getTodayPnL();
let output = `**Today's Trades** (${trades.length})\n\n`;
for (const t of trades.slice(0, 20)) {
const side = t.side === 'buy' ? 'BUY' : 'SELL';
output += `${side} ${t.shares.toFixed(2)} ${t.outcome} @ $${t.price.toFixed(3)} = $${t.value.toFixed(2)} [${t.platform}]\n`;
}
output += `\nToday's PnL: $${todayPnL.toFixed(2)}`;
return output;
}
case 'week': {
const stats = service.getStats('week');
const trades = service.getTrades({
startDate: (() => {
const d = new Date();
d.setDate(d.getDate() - d.getDay());
d.setHours(0, 0, 0, 0);
return d;
})(),
endDate: new Date(),
});
let output = `**This Week's Trades** (${trades.length})\n\n`;
output += `PnL: $${stats.totalPnL.toFixed(2)}\n`;
output += `Volume: $${stats.totalVolume.toFixed(2)}\n`;
output += `Win Rate: ${stats.winRate.toFixed(1)}%\n`;
return output;
}
case 'pnl': {
const days = parts[1] ? parseInt(parts[1], 10) : 30;
const dailyPnL = service.getDailyPnL(isNaN(days) ? 30 : days);
const totalPnL = service.getTotalPnL();
const activeDays = dailyPnL.filter(d => d.trades > 0);
if (!activeDays.length) {
return `**P&L Summary**\n\nNo trading activity in the last ${days} days.\nTotal PnL: $${totalPnL.toFixed(2)}`;
}
let output = `**P&L Summary** (${days}d)\n\n`;
output += `Total PnL: $${totalPnL.toFixed(2)}\n`;
output += `Today: $${service.getTodayPnL().toFixed(2)}\n\n`;
output += `| Date | PnL | Trades | Volume |\n|------|-----|--------|--------|\n`;
for (const d of activeDays.slice(-15)) {
output += `| ${d.date} | $${d.pnl.toFixed(2)} | ${d.trades} | $${d.volume.toFixed(2)} |\n`;
}
return output;
}
case 'stats': {
return service.formatStats();
}
case 'search': {
if (parts.length < 2) return 'Usage: /history search <market-id or keyword>';
const query = parts.slice(1).join(' ').toLowerCase();
const allTrades = service.getTrades({});
const matched = allTrades.filter(t =>
t.marketId.toLowerCase().includes(query) ||
(t.marketQuestion && t.marketQuestion.toLowerCase().includes(query))
);
if (!matched.length) return `No trades found matching "${query}".`;
let output = `**Search Results** (${matched.length} trades)\n\n`;
for (const t of matched.slice(0, 15)) {
const label = t.marketQuestion ? t.marketQuestion.slice(0, 40) : t.marketId.slice(0, 20);
output += `${t.side.toUpperCase()} ${t.shares.toFixed(2)} ${t.outcome} @ $${t.price.toFixed(3)} [${t.platform}] - ${label}\n`;
}
return output;
}
case 'export': {
const format = parts[1]?.toLowerCase() || 'csv';
const allTrades = service.getTrades({});
if (!allTrades.length) return 'No trades to export.';
if (format === 'json') {
const json = JSON.stringify(allTrades.slice(0, 100), null, 2);
return `**Export** (${allTrades.length} trades, JSON)\n\n\`\`\`json\n${json.slice(0, 3000)}\n\`\`\``;
}
// Default CSV
let csv = 'id,platform,marketId,outcome,side,shares,price,value,fee,timestamp\n';
for (const t of allTrades.slice(0, 100)) {
csv += `${t.id},${t.platform},${t.marketId},${t.outcome},${t.side},${t.shares},${t.price},${t.value},${t.fee},${t.timestamp.toISOString()}\n`;
}
return `**Export** (${allTrades.length} trades, CSV)\n\n\`\`\`csv\n${csv.slice(0, 3000)}\n\`\`\``;
}
case 'sync': {
const fetched = await service.fetchTrades(100);
const synced = await service.syncToDatabase();
return `**Sync Complete**\n\nFetched ${fetched.length} trades from exchanges.\nSynced ${synced} trades to database.`;
}
default:
return helpText();
}
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
return `Error: ${msg}`;
}
}
function helpText(): string {
return `**History Commands**
/history - Recent trades
/history today - Today's trades
/history week - This week's trades
/history pnl [days] - P&L summary (default 30d)
/history stats - Full trading statistics
/history search <query> - Search trades by market
/history export [csv|json] - Export trades
/history sync - Sync from exchanges`;
}
export default {
name: 'history',
description: 'Trade history tracking, sync, and performance analytics',
commands: ['/history', '/trades'],
handle: execute,
};