Prediction market strategy research, backtesting, and paper trading toolkit
Project description
agenttrader
agenttrader is a toolkit that lets AI agents autonomously research, write, backtest, and deploy prediction market trading strategies — without human intervention.
Give an agent a goal. It handles everything: discovering markets on Polymarket and Kalshi, analyzing price history, writing strategy code, running the backtesting loop, and starting a live paper trading daemon. Running strategies hot-reload automatically when the strategy file changes — agents can iterate on live deployments without restarting.
All market data flows through the Dome API, unified across Polymarket and Kalshi.
Primary users: AI coding agents (Claude Code, Codex, OpenCode, Cursor).
Secondary users: Developers who want to write and test strategies manually.
How It Works
Agent receives goal
│
▼
agenttrader sync ← pull market data into local cache
│
▼
agenttrader markets list ← discover opportunities
│
▼
[agent writes strategy.py]
│
▼
agenttrader validate ← catch errors before they waste time
│
▼
agenttrader backtest ← test against real historical data
│
├─── metrics look bad? agent edits strategy.py, loops back
│
▼
agenttrader paper start ← deploy as background daemon
│
▼
[agent edits strategy.py] ← daemon hot-reloads, no restart needed
All state lives locally in ~/.agenttrader/. No cloud backend. No app account required. (A Dome API key is still required for market data access.)
Quickstart
Prerequisites
python --version # 3.12+ required
pip --version
Get a free Dome API key at dashboard.domeapi.io.
Install
pip install agenttrader
agenttrader init
agenttrader config set dome_api_key <YOUR_DOME_KEY>
Verify it works
agenttrader sync --platform polymarket --days 2 --limit 5 --json
agenttrader markets list --json
If you see markets in the output, you're ready.
Using agenttrader With Your Agent
There are two ways to connect your agent to agenttrader. MCP is recommended — it's the most natural interface for agents. CLI mode works as a fallback if MCP isn't available.
Option A: MCP (Recommended)
MCP lets your agent call agenttrader tools as native function calls — no shell commands, no output parsing. The agent calls get_markets(), run_backtest(), start_paper_trade() directly inside its reasoning loop.
Setup for Claude Code
Add this to .claude/mcp.json in your project directory:
{
"mcpServers": {
"agenttrader": {
"command": "agenttrader",
"args": ["mcp"]
}
}
}
Restart Claude Code. The MCP server starts automatically — you never run agenttrader mcp manually.
Setup for Cursor
In Cursor settings → MCP → add server:
{
"name": "agenttrader",
"command": "agenttrader",
"args": ["mcp"],
"transport": "stdio"
}
Setup for any other MCP-compatible agent
{
"mcpServers": {
"agenttrader": {
"command": "agenttrader",
"args": ["mcp"]
}
}
}
The transport is stdio. The agent spawns agenttrader mcp as a subprocess and communicates over stdin/stdout. No port, no server to keep running.
Available MCP tools
| Category | Tools |
|---|---|
| Markets | get_markets, get_price, get_history, match_markets |
| Strategy | validate_strategy, run_backtest, get_backtest, list_backtests |
| Paper trading | start_paper_trade, get_portfolio, stop_paper_trade, list_paper_trades |
| Data | sync_data |
Example agent prompts (MCP mode)
Once connected, give your agent natural language goals:
Use agenttrader to find the 10 most liquid Polymarket politics markets.
Build a mean reversion strategy in ./strategy.py. Backtest it from
2024-06-01 to 2024-12-31 with $10,000 starting cash. Iterate until
Sharpe ratio > 1.0 and max drawdown better than -20%. Then start
paper trading and report the portfolio_id.
Check my current paper trading portfolio. If any position has been
open for more than 7 days with negative PnL, update the strategy
to add a stop-loss and let me know what changed.
Find prediction markets on both Polymarket and Kalshi covering the
same event. Write an arbitrage strategy that trades the price
discrepancy when it exceeds 3 cents. Backtest it and paper trade it.
The agent will chain tool calls autonomously — syncing data, writing and editing strategy.py, running backtests, reading metrics, iterating, and deploying — without you touching a terminal.
Option B: CLI Mode
If your agent can run shell commands (most can), it can use agenttrader without any MCP setup. Every command supports --json for clean, parseable output.
Setup
No configuration needed beyond the initial install. Your agent runs commands like:
agenttrader sync --platform polymarket --days 7 --limit 20 --json
agenttrader markets list --platform polymarket --json
agenttrader validate ./strategy.py --json
agenttrader backtest ./strategy.py --from 2024-01-01 --to 2024-06-01 --json
agenttrader paper start ./strategy.py --cash 5000 --json
agenttrader paper status <portfolio_id> --json
Example agent prompts (CLI mode)
For Claude Code without MCP configured:
Use the agenttrader CLI to research Polymarket crypto markets.
Run: agenttrader markets list --platform polymarket --category crypto --json
Then build a strategy in ./strategy.py and iterate using:
agenttrader validate ./strategy.py --json
agenttrader backtest ./strategy.py --from 2024-01-01 --to 2024-06-01 --json
Keep iterating until Sharpe > 1.0, then run:
agenttrader paper start ./strategy.py --json
Report the portfolio_id when done.
The JSON contract
Every --json response follows this shape:
{ "ok": true, "...": "..." }
{ "ok": false, "error": "ErrorType", "message": "Human-readable details" }
Strategy errors include line numbers and tracebacks so agents can self-heal:
{
"ok": false,
"error": "StrategyError",
"message": "name 'undefined_var' is not defined",
"file": "./strategy.py",
"line": 14,
"traceback": "Traceback (most recent call last):\n ..."
}
The Agent Iteration Loop
Whether using MCP or CLI, the core loop looks like this:
1. sync market data
2. inspect markets + history
3. write strategy.py
4. validate --json → fix any errors
5. backtest --json → read Sharpe, drawdown, win rate
6. edit strategy.py → improve based on metrics
7. repeat 4–6 until satisfied
8. paper start → deploy daemon
9. paper status --json → monitor
10. edit strategy.py live → daemon hot-reloads automatically
Steps 3–7 are where agents spend most of their time. A well-prompted agent will iterate 5–10 times before deploying, each time reading the structured backtest metrics and making targeted improvements to the strategy logic.
Strategy Authoring
Strategies are plain Python files that subclass BaseStrategy. Write them in any editor — or let your agent write them.
from agenttrader import BaseStrategy
class MyStrategy(BaseStrategy):
def on_start(self):
# Subscribe to markets — called once at startup
self.subscribe(platform="polymarket", category="politics")
def on_market_data(self, market, price, orderbook):
# Called on every price update for subscribed markets
history = self.get_history(market.id, lookback_hours=48)
if len(history) < 2:
return
avg = sum(h.yes_price for h in history) / len(history)
if price < avg - 0.08 and self.get_position(market.id) is None:
self.buy(market.id, contracts=20)
self.log(f"BUY {market.title[:40]} @ {price:.3f}")
elif price > avg + 0.05 and self.get_position(market.id):
self.sell(market.id)
self.log(f"SELL {market.title[:40]} @ {price:.3f}")
def on_schedule(self, now, market):
# Called every 15 minutes — use for time-based logic
hours_left = (market.close_time - now.timestamp()) / 3600
if hours_left < 3 and self.get_position(market.id):
self.sell(market.id)
self.log(f"Pre-expiry close: {hours_left:.1f}h left")
def on_resolution(self, market, outcome, pnl):
# Called when a market resolves
self.log(f"Resolved: {outcome}, PnL: ${pnl:.2f}")
Available methods inside a strategy:
# Subscribe + discover
self.subscribe(platform, category, tags, market_ids)
self.search_markets(query, platform)
# Price + data (time-bounded in backtesting — no look-ahead bias)
self.get_price(market_id) # current YES price (0.0–1.0)
self.get_orderbook(market_id) # bids, asks, best_bid, best_ask, mid
self.get_history(market_id, lookback_hours) # list of PricePoint objects
# Portfolio
self.get_position(market_id) # open Position or None
self.get_cash() # available cash
self.get_portfolio_value() # cash + mark-to-market positions
# Orders
self.buy(market_id, contracts, side="yes", order_type="market")
self.sell(market_id, contracts=None) # None = sell entire position
# Utilities
self.log(message) # appears in dashboard + paper status
self.set_state(key, value) # persist state across calls
self.get_state(key, default)
Do not call the Dome API directly from a strategy. Do not import requests, httpx, or any networking library. All data access goes through self.* methods.
All Commands
Setup
agenttrader init
agenttrader config set dome_api_key <YOUR_DOME_KEY>
agenttrader config get dome_api_key
agenttrader config show
Data Sync
agenttrader sync # top 100 markets, 90 days
agenttrader sync --platform polymarket --days 7
agenttrader sync --platform kalshi --days 7
agenttrader sync --markets <id1> --markets <id2> # specific markets
agenttrader sync --json
Markets
agenttrader markets list
agenttrader markets list --platform polymarket --limit 20 --json
agenttrader markets list --category politics --min-volume 50000
agenttrader markets price <market_id> --json
agenttrader markets history <market_id> --days 30 --json
agenttrader markets match --polymarket-slug "<slug>"
agenttrader markets match --kalshi-ticker "<ticker>"
Validate
agenttrader validate ./strategy.py
agenttrader validate ./strategy.py --json
Backtest
agenttrader backtest ./strategy.py --from 2024-01-01 --to 2024-06-01
agenttrader backtest ./strategy.py --from 2024-01-01 --to 2024-06-01 --cash 10000
agenttrader backtest ./strategy.py --from 2024-01-01 --to 2024-06-01 --json
agenttrader backtest list --json
agenttrader backtest show <run_id> --json
Backtest results include:
{
"metrics": {
"total_return_pct": 32.4,
"sharpe_ratio": 1.84,
"sortino_ratio": 2.31,
"max_drawdown_pct": -12.3,
"win_rate": 0.61,
"profit_factor": 2.14,
"calmar_ratio": 2.63,
"avg_slippage": 0.008,
"total_trades": 47
},
"equity_curve": [...],
"trades": [...]
}
Paper Trading
agenttrader paper start ./strategy.py --json
agenttrader paper start ./strategy.py --cash 5000 --json
agenttrader paper start ./strategy.py --no-daemon --json # blocking, for testing
agenttrader paper list --json
agenttrader paper status <portfolio_id> --json
agenttrader paper stop <portfolio_id> --json
agenttrader paper stop --all --json
Hot-reload: edit strategy.py while a paper trade is running — the daemon detects the change and reloads automatically. Portfolio state is preserved. No restart needed. paper status shows reload_count to confirm it happened.
Dashboard
agenttrader dashboard # http://localhost:8080
agenttrader dashboard --port 9090
Read-only local dashboard showing active paper trades, positions, trade history, strategy logs, and backtest results with equity curves.
Maintenance
agenttrader prune --older-than 90d --dry-run --json
agenttrader prune --older-than 90d --json
Local Storage
~/.agenttrader/
├── config.yaml # API key and preferences
├── db.sqlite # markets, backtests, positions, trade ledger
└── orderbooks/ # compressed orderbook snapshots by market/day
db.sqlite is a standard SQLite file. Agents can query it directly with SQL for custom analysis — for example, SELECT * FROM markets WHERE volume > 10000 ORDER BY volume DESC.
The Dome API key in config.yaml grants access to market data only — no funds or wallets are involved.
Troubleshooting
| Problem | Fix |
|---|---|
agenttrader: command not found |
Activate your virtual environment: source .venv/bin/activate |
| Not initialized | agenttrader init |
| Missing API key | agenttrader config set dome_api_key <key> |
| Market not in cache | agenttrader sync ... |
| Strategy validation errors | agenttrader validate ./strategy.py --json — read errors array |
| Backtest has no trades | Date range has no price movement — try wider range or sync more markets |
| Dashboard shows blank | Ensure agenttrader dashboard is running and open http://127.0.0.1:8080; check command logs for startup errors |
| MCP not connecting | Verify agenttrader mcp runs without error; check .claude/mcp.json path |
Development
git clone https://github.com/yourname/agenttrader
cd agenttrader
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
ruff check agenttrader tests
python -m compileall agenttrader tests
# Integration tests (requires real API key)
DOME_API_KEY=<key> python tests/integration/test_full_workflow.py
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agenttrader-0.1.1.tar.gz.
File metadata
- Download URL: agenttrader-0.1.1.tar.gz
- Upload date:
- Size: 53.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9dbf2bc0e0c7c72703a3a5fb3f71397dbac0c4496c51d7ba531ce0c27f74218a
|
|
| MD5 |
1b315052cc00832a0140d07a4575551c
|
|
| BLAKE2b-256 |
11d71c3d462aaff03d902ad5848d9ce9ff355bb78cb942ce41095af52b54d6eb
|
File details
Details for the file agenttrader-0.1.1-py3-none-any.whl.
File metadata
- Download URL: agenttrader-0.1.1-py3-none-any.whl
- Upload date:
- Size: 58.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba398b009e3387448d9eeb4576c6dc3f938043d7103d7875b6e54a3f2da536d4
|
|
| MD5 |
e980e2e348530e2a2950a113bfd4d6d2
|
|
| BLAKE2b-256 |
ad5c225067dc2addb9edae6689d430978085c2d64503a7cd27c2c97754240f9c
|