CCXT-style unified API for prediction markets. Simple, scalable, and easy to extend.
dr-manhattan provides a unified interface to interact with multiple prediction market platforms, similar to how CCXT works for cryptocurrency exchanges.
dr_manhattan/
├── base/ # Core abstractions
│ ├── exchange.py # Abstract base class for exchanges
│ ├── exchange_client.py # High-level trading client
│ ├── exchange_factory.py # Exchange instantiation
│ ├── strategy.py # Strategy base class
│ ├── order_tracker.py # Order event tracking
│ ├── websocket.py # WebSocket base class
│ └── errors.py # Exception hierarchy
├── exchanges/ # Exchange implementations
│ ├── polymarket.py
│ ├── polymarket_ws.py
│ ├── opinion.py
│ ├── limitless.py
│ ├── limitless_ws.py
│ └── predictfun.py
├── models/ # Data models
│ ├── market.py
│ ├── order.py
│ ├── orderbook.py
│ └── position.py
├── strategies/ # Strategy implementations
└── utils/ # Utilities
- Unified Interface: All exchanges implement the same
Exchangebase class - Scalability: Adding new exchanges is straightforward - just implement the abstract methods
- Simplicity: Clean abstractions with minimal dependencies
- Type Safety: Full type hints throughout
- Fetch markets and market data
- Create and cancel orders
- Query positions and balances
- WebSocket support for real-time data
- Strategy base class for building trading strategies
- Order tracking and event logging
- Standardized error handling
- Exchange-agnostic code
- MCP server for Claude Desktop integration
uv venv
uv pip install -e .import dr_manhattan
# Initialize exchange without authentication
polymarket = dr_manhattan.Polymarket({'timeout': 30})
opinion = dr_manhattan.Opinion({'timeout': 30})
limitless = dr_manhattan.Limitless({'timeout': 30})
predictfun = dr_manhattan.PredictFun({'timeout': 30})
# Fetch markets
markets = polymarket.fetch_markets()
for market in markets:
print(f"{market.question}: {market.prices}")import dr_manhattan
# Polymarket
polymarket = dr_manhattan.Polymarket({
'private_key': 'your_private_key',
'funder': 'your_funder_address',
})
# Opinion (BNB Chain)
opinion = dr_manhattan.Opinion({
'api_key': 'your_api_key',
'private_key': 'your_private_key',
'multi_sig_addr': 'your_multi_sig_addr'
})
# Limitless
limitless = dr_manhattan.Limitless({
'private_key': 'your_private_key',
'timeout': 30
})
# Predict.fun (BNB Chain)
predictfun = dr_manhattan.PredictFun({
'api_key': 'your_api_key',
'private_key': 'your_private_key',
'use_smart_wallet': True,
'smart_wallet_owner_private_key': 'your_owner_private_key',
'smart_wallet_address': 'your_smart_wallet_address'
})
# Create order
order = polymarket.create_order(
market_id="market_123",
outcome="Yes",
side=dr_manhattan.OrderSide.BUY,
price=0.65,
size=100,
params={'token_id': 'token_id'}
)
# Fetch balance
balance = polymarket.fetch_balance()
print(f"USDC: {balance['USDC']}")from dr_manhattan import Strategy
class MyStrategy(Strategy):
def on_tick(self):
self.log_status()
self.place_bbo_orders()
strategy = MyStrategy(exchange, market_id="123")
strategy.run()from dr_manhattan import create_exchange, list_exchanges
# List available exchanges
print(list_exchanges()) # ['polymarket', 'limitless', 'opinion', 'predictfun']
# Create exchange by name
exchange = create_exchange('polymarket', {'timeout': 30})Trade prediction markets directly from Claude using the Model Context Protocol (MCP).
# Install with MCP dependencies
uv sync --extra mcp
# Configure credentials
cp .env.example .env
# Edit .env with your POLYMARKET_PRIVATE_KEY and POLYMARKET_FUNDERAdd to ~/.claude/settings.json or project .mcp.json:
{
"mcpServers": {
"dr-manhattan": {
"command": "/path/to/dr-manhattan/.venv/bin/python",
"args": ["-m", "dr_manhattan.mcp.server"],
"cwd": "/path/to/dr-manhattan"
}
}
}Restart Claude Code and verify with /mcp.
Add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"dr-manhattan": {
"command": "/path/to/dr-manhattan/.venv/bin/python",
"args": ["-m", "dr_manhattan.mcp.server"],
"cwd": "/path/to/dr-manhattan"
}
}
}After restarting, you can:
- "Show my Polymarket balance"
- "Find active prediction markets"
- "Buy 10 USDC of Yes on market X at 0.55"
See examples/mcp_usage_example.md for the complete setup guide.
To add a new exchange, create a class that inherits from Exchange:
from dr_manhattan.base import Exchange
class NewExchange(Exchange):
@property
def id(self) -> str:
return "newexchange"
@property
def name(self) -> str:
return "New Exchange"
def fetch_markets(self, params=None):
# Implement API call
pass
# Implement other abstract methods...Register in dr_manhattan/__init__.py:
from .exchanges.newexchange import NewExchange
exchanges = {
"polymarket": Polymarket,
"opinion": Opinion,
"limitless": Limitless,
"predictfun": PredictFun,
"newexchange": NewExchange,
}- Question and outcomes
- Prices and volume
- Close time and status
- Market and outcome
- Side (buy/sell), price, size
- Status tracking
- Current holdings
- PnL calculation
- Average entry price
- Bids and asks
- Best bid/ask prices
All errors inherit from DrManhattanError:
ExchangeError- Exchange-specific errorsNetworkError- Connectivity issuesRateLimitError- Rate limit exceededAuthenticationError- Auth failuresInsufficientFunds- Not enough balanceInvalidOrder- Invalid order parametersMarketNotFound- Market doesn't exist
Check out the examples/ directory for working examples:
- mcp_usage_example.md - Complete MCP server setup and usage guide for Claude Desktop
- list_all_markets.py - List markets from any exchange
- spread_strategy.py - Exchange-agnostic BBO market making strategy
Run examples:
# List markets
uv run python examples/list_all_markets.py polymarket
uv run python examples/list_all_markets.py opinion
uv run python examples/list_all_markets.py limitless
uv run python examples/list_all_markets.py predictfun
# Run spread strategy
uv run python examples/spread_strategy.py --exchange polymarket --slug fed-decision
uv run python examples/spread_strategy.py --exchange opinion --market-id 813See examples/README.md for detailed documentation.
We use Claude Code to implement new features from trading strategy ideas:
- Spot a good strategy on Twitter/X
- Create a GitHub issue describing the strategy
- Add a label:
feature,bug, orchore - Mention
@claudein the issue - Claude creates a PR with the implementation
Branch naming follows the label:
feature->feat/issue-{number}bug->fix/issue-{number}chore->chore/issue-{number}
See .github/workflows/claude.yml for details.
- Python >= 3.11
- requests >= 2.31.0
- websockets >= 15.0.1
- python-socketio >= 5.11.0
- eth-account >= 0.11.0
- py-clob-client >= 0.28.0
- opinion-clob-sdk >= 0.4.3
- pandas >= 2.0.0
Development:
- pytest
- black
- ruff





