11 KiB
Polymarket Prediction Market Agent Module
Quick Start
Prerequisites
# Create virtual environment (Python 3.10+)
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Set up API keys (at least one LLM provider required)
cp .env.example .env
# Edit .env and fill in your API key
Usage
from tradingagents.prediction_market import PMTradingAgentsGraph
from tradingagents.prediction_market.pm_config import PM_DEFAULT_CONFIG
from dotenv import load_dotenv
load_dotenv()
config = PM_DEFAULT_CONFIG.copy()
config["llm_provider"] = "anthropic" # openai, google, anthropic, xai, openrouter, ollama
config["deep_think_llm"] = "claude-sonnet-4-6"
config["quick_think_llm"] = "claude-sonnet-4-6"
pm = PMTradingAgentsGraph(debug=True, config=config)
# market_id from Polymarket website or Gamma API
_, decision = pm.propagate("<market_id>", "2026-03-23", "Market question (optional)")
print(decision)
How to Get a Market ID
The market_id is a numeric ID from the Polymarket Gamma API. You can find it by:
import requests
# Option 1: Browse top markets by volume
resp = requests.get("https://gamma-api.polymarket.com/markets", params={
"active": "true",
"closed": "false",
"order": "volume24hr",
"ascending": "false",
"limit": 10,
})
for m in resp.json():
print(f'{m["id"]} | {m["question"]}')
# Option 2: Look up from a Polymarket web URL slug
# e.g. https://polymarket.com/event/xxx → use the slug to search
CLI Usage
You can also use the CLI, which supports pasting Polymarket URLs directly:
python -m cli.main
# Step 1: Select "Polymarket Market ID (prediction market)"
# Step 2: Paste a Polymarket URL or enter a numeric market ID
Architecture Overview
The system is built as a LangGraph state machine with 4 phases and 10+ LLM agents:
Input: market_id + trade_date + market_question
|
v
+-------------------------------------+
| Phase 1: Analyst Team (4 Analysts) |
| Event -> Odds -> Information -> Sent|
+----------------+--------------------+
v
+-------------------------------------+
| Phase 2: Research Debate |
| YES Researcher <-> NO Researcher |
| -> Research Manager |
+----------------+--------------------+
v
+-------------------------------------+
| Phase 3: Trading Decision |
| PM Trader (Kelly Criterion) |
+----------------+--------------------+
v
+-------------------------------------+
| Phase 4: Risk Management |
| Aggressive <-> Conservative <-> Neut|
| -> Risk Judge |
+----------------+--------------------+
v
Structured JSON Output
Phase 1: Analyst Team
Four analysts run sequentially, each with a tool loop that calls Polymarket APIs until sufficient data is collected. Uses quick_think_llm.
| Analyst | Tools | Responsibility |
|---|---|---|
| Event Analyst | get_market_info, get_resolution_criteria, get_event_context |
Analyze the event: what is being predicted, resolution criteria clarity, timeline |
| Odds Analyst | get_market_info, get_market_price_history, get_order_book |
Market microstructure: current prices, liquidity, bid/ask spread, pricing efficiency |
| Information Analyst | get_news, get_global_news, get_related_markets, search_markets |
Find information not yet priced in, cross-reference related markets |
| Sentiment Analyst | get_news, get_global_news |
Public opinion analysis: news, social sentiment, expert vs crowd divergence |
Each analyst produces a report (event_report, odds_report, information_report, sentiment_report) that feeds into subsequent phases.
Phase 2: Research Debate
| Role | LLM | Responsibility |
|---|---|---|
| YES Researcher | quick_think_llm |
Build the case for the event occurring, citing analyst reports |
| NO Researcher | quick_think_llm |
Build the case against, rebutting YES arguments |
| Research Manager | deep_think_llm |
Synthesize both sides into an investment_plan |
- YES and NO debate for
max_debate_roundsrounds (default 1 round = 2 turns) - Both researchers have a BM25 memory system that recalls lessons from past similar markets
- Research Manager uses the stronger
deep_think_llmfor final synthesis
Phase 3: Trading Decision
The PM Trader (using quick_think_llm) receives all reports and the investment plan, then:
- Estimates the true probability based on all analysis
- Compares against the market price from the Odds report
- Calculates edge = |estimated probability - market price|
- If edge < 5% threshold -> PASS
- If edge >= 5% -> calculate position size using 0.25x Fractional Kelly Criterion:
- Kelly fraction = edge / odds_against
- Position size = 0.25 x Kelly fraction x bankroll
Decision options:
- BUY_YES: Estimated probability > market price + 5% (event more likely than market implies)
- BUY_NO: Estimated probability < market price - 5% (event less likely than market implies)
- PASS: Edge below threshold or uncertainty too high
Phase 4: Risk Management
Three-way debate + final ruling:
| Role | LLM | Stance |
|---|---|---|
| Aggressive Analyst | quick_think_llm |
Advocates for the trade, emphasizes edge and upside |
| Conservative Analyst | quick_think_llm |
Argues against, emphasizes downside risk and uncertainty |
| Neutral Analyst | quick_think_llm |
Balanced perspective, proposes compromise |
| Risk Judge | deep_think_llm |
Final ruling after hearing all sides |
The three analysts debate for max_risk_discuss_rounds rounds (default 1 round = 3 turns, one per analyst).
Output Format
The Risk Judge's natural language output is converted to structured JSON by the Signal Processor:
{
"signal": "BUY_YES | BUY_NO | PASS",
"estimated_probability": 0.65,
"market_price": 0.50,
"edge": 0.15,
"position_size": 0.03,
"confidence": "high | medium | low"
}
Reflection & Learning
After a trade resolves, invoke the reflection mechanism to let agents learn from outcomes:
# After the trade resolves, pass the actual returns
pm.reflect_and_remember(returns_losses=1000)
The system will:
- Review each agent's decisions (YES/NO Researcher, Trader, Research Manager, Risk Judge)
- Analyze which judgments were correct or incorrect, and why
- Store lessons learned in a BM25 memory system
- Automatically reference past experience when encountering similar markets in the future
Configuration
All parameters are in tradingagents/prediction_market/pm_config.py:
PM_DEFAULT_CONFIG = {
# LLM settings
"llm_provider": "openai", # openai, google, anthropic, xai, openrouter, ollama
"deep_think_llm": "gpt-5.2", # For Research Manager, Risk Judge (deep reasoning)
"quick_think_llm": "gpt-5-mini", # For Analysts, Researchers, Trader (speed priority)
# Polymarket API
"polymarket_gamma_url": "https://gamma-api.polymarket.com",
"polymarket_clob_url": "https://clob.polymarket.com",
# Trading parameters
"kelly_fraction": 0.25, # Conservative Kelly multiplier (quarter Kelly)
"min_edge_threshold": 0.05, # Minimum edge threshold (5%)
"max_position_pct": 0.05, # Max single position as % of bankroll (5%)
"max_cluster_exposure_pct": 0.15, # Max exposure to correlated markets (15%)
"bankroll": 10000, # Simulated bankroll
# Debate settings
"max_debate_rounds": 1, # YES/NO debate rounds
"max_risk_discuss_rounds": 1, # Risk management debate rounds
}
Data Sources
| Source | Purpose | API Key Required |
|---|---|---|
| Polymarket Gamma API | Market info, resolution criteria, event context, search | No (public API) |
| Polymarket CLOB API | Price history, order book | No (public API) |
| yfinance News | News search (get_news, get_global_news) |
No |
Note: The news tools are shared with the stock analysis module (yfinance-based), so coverage for political markets may be limited.
Current Limitations
- Analysis only, no order execution: v1 does not place actual trades on Polymarket
- Binary markets only: Supports Yes/No outcomes; multi-outcome and numeric markets are not supported
- REST API only: Uses polling, no WebSocket real-time streaming
- No backtesting: No historical backtesting framework included
- Limited news coverage: Political market news search is limited since the news tools are designed for stocks
File Structure
tradingagents/prediction_market/
├── __init__.py # Exports PMTradingAgentsGraph
├── pm_config.py # Default configuration
├── agents/
│ ├── analysts/
│ │ ├── event_analyst.py # Event analysis
│ │ ├── odds_analyst.py # Odds/pricing analysis
│ │ ├── information_analyst.py # Information gathering
│ │ └── sentiment_analyst.py # Sentiment analysis
│ ├── researchers/
│ │ ├── yes_researcher.py # YES-side researcher
│ │ └── no_researcher.py # NO-side researcher
│ ├── trader/
│ │ └── pm_trader.py # Trading decisions (Kelly Criterion)
│ ├── managers/
│ │ ├── research_manager.py # Research manager (debate synthesis)
│ │ └── risk_manager.py # Risk manager (final ruling)
│ ├── risk_mgmt/
│ │ ├── aggressive_debator.py # Aggressive stance
│ │ ├── conservative_debator.py # Conservative stance
│ │ └── neutral_debator.py # Neutral stance
│ └── utils/
│ ├── pm_agent_states.py # LangGraph state definitions
│ ├── pm_agent_utils.py # Shared utilities
│ └── pm_tools.py # @tool decorator wrappers
├── dataflows/
│ └── polymarket.py # Polymarket API client (Gamma + CLOB)
└── graph/
├── pm_trading_graph.py # Main graph class
├── setup.py # Graph construction logic
├── propagation.py # State initialization & propagation
├── conditional_logic.py # Conditional branching (tool loop, debate control)
├── signal_processing.py # JSON output structuring
└── reflection.py # Reflection & learning mechanism