TradingAgents/POLYMARKET.md

295 lines
11 KiB
Markdown

# Polymarket Prediction Market Agent Module
## Quick Start
### Prerequisites
```bash
# 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
```python
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:
```python
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:
```bash
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_rounds` rounds (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_llm` for final synthesis
---
## Phase 3: Trading Decision
The **PM Trader** (using `quick_think_llm`) receives all reports and the investment plan, then:
1. Estimates the **true probability** based on all analysis
2. Compares against the **market price** from the Odds report
3. Calculates **edge** = |estimated probability - market price|
4. If edge < **5% threshold** -> **PASS**
5. 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**:
```json
{
"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:
```python
# After the trade resolves, pass the actual returns
pm.reflect_and_remember(returns_losses=1000)
```
The system will:
1. Review each agent's decisions (YES/NO Researcher, Trader, Research Manager, Risk Judge)
2. Analyze which judgments were correct or incorrect, and why
3. Store lessons learned in a BM25 memory system
4. Automatically reference past experience when encountering similar markets in the future
---
## Configuration
All parameters are in `tradingagents/prediction_market/pm_config.py`:
```python
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
```