polyclaw
# PolyClaw
Trading-enabled Polymarket skill for OpenClaw. Browse markets, manage wallets, execute trades, and track positions.
## Features
- **Market Browsing** - Search and browse Polymarket prediction markets
- **Wallet Management** - Env-var based wallet configuration
- **Trading** - Buy YES/NO positions via split + CLOB execution
- **Position Tracking** - Track entry prices, current prices, and P&L
- **Hedge Discovery** - LLM-powered covering portfolio discovery via logical implications
## Quick Start
First, install dependencies (from skill directory):
```bash
cd {baseDir}
uv sync
```
### First-Time Setup (Required for Trading)
Before your first trade, set Polymarket contract approvals (one-time, costs ~0.01 POL in gas):
```bash
uv run python scripts/polyclaw.py wallet approve
```
This submits 6 approval transactions to Polygon. You only need to do this once per wallet.
### Browse Markets
```bash
# Trending markets by volume
uv run python scripts/polyclaw.py markets trending
# Search markets
uv run python scripts/polyclaw.py markets search "election"
# Market details (returns full JSON with all fields)
uv run python scripts/polyclaw.py market <market_id>
```
**Output options:**
- Default output is a formatted table (good for display)
- Use `--full` flag for full question text without truncation
- Use `--json` flag via `scripts/markets.py --json trending` for structured JSON output
### Wallet Management
```bash
# Check wallet status (address, balances)
uv run python scripts/polyclaw.py wallet status
# Set contract approvals (one-time)
uv run python scripts/polyclaw.py wallet approve
```
The wallet is configured via the `POLYCLAW_PRIVATE_KEY` environment variable.
### Trading
```bash
# Buy YES position for $50
uv run python scripts/polyclaw.py buy <market_id> YES 50
# Buy NO position for $25
uv run python scripts/polyclaw.py buy <market_id> NO 25
```
### Positions
```bash
# List all positions with P&L
uv run python scripts/polyclaw.py positions
```
### Hedge Discovery
Find covering portfolios - pairs of market positions that hedge each other via contrapositive logic.
```bash
# Scan trending markets for hedges
uv run python scripts/polyclaw.py hedge scan
# Scan markets matching a query
uv run python scripts/polyclaw.py hedge scan --query "election"
# Analyze specific markets for hedging relationship
uv run python scripts/polyclaw.py hedge analyze <market_id_1> <market_id_2>
```
**Output options:**
- Default output is a formatted table showing Tier, Coverage, Cost, Target, and Cover
- Use `--json` flag for structured JSON output
- Use `--min-coverage 0.90` to filter by minimum coverage (default 0.85)
- Use `--tier 1` to filter by tier (1=best, default 2)
**Coverage tiers:**
- **Tier 1 (HIGH):** >=95% coverage - near-arbitrage opportunities
- **Tier 2 (GOOD):** 90-95% - strong hedges
- **Tier 3 (MODERATE):** 85-90% - decent but noticeable risk
- **Tier 4 (LOW):** <85% - speculative (filtered by default)
**LLM model:** Uses `nvidia/nemotron-nano-9b-v2:free` via OpenRouter. Model selection matters — some models find spurious correlations while others (like DeepSeek R1) have output format issues. Override with `--model <model_id>` if needed.
## Automation Tools
### Portfolio Live Tracking
Real-time position tracking via Polymarket Data API. Groups positions by `(slug, outcome)` and displays YES/NO side, current value, and P&L with cost basis from `portfolio.json`.
```bash
uv run python portfolio_live.py
```
- Fetches live on-chain positions from `data-api.polymarket.com`
- Shows outcome side (YES/NO), current price, and unrealized P&L
- No web3 dependency — uses REST API only
### Auto Redeem
Automatically detects and redeems settled (resolved) markets. Checks `payoutDenominator` on-chain via the CTF contract. When a market resolves, submits a `redeemPositions` transaction through the NegRiskAdapter.
```bash
# Manual run
cd {baseDir} && source .env && .venv/bin/python3 auto_redeem_check.py
# Cron (every 15 minutes)
*/15 * * * * cd /path/to/polyclaw && source .env && .venv/bin/python3 auto_redeem_check.py >> /var/log/polyclaw-redeem.log 2>&1
```
- Requires `web3` (use `.venv/bin/python3`, not system python)
- Tracks redeemed positions in `redeem_state.json` to avoid duplicates
- Needs `CHAINSTACK_NODE` and `POLYCLAW_PRIVATE_KEY` env vars
### Discipline Scanner
Automated take-profit scanner. Sells positions that are up 20%+ with slippage protection. Configurable via `cfo_params.json` (`DISCIPLINE_TP_PCT` key).
```bash
# Manual run
cd {baseDir} && export $(grep -v "^#" .env | xargs) && .venv/bin/python3 discipline_scanner.py
# Cron (every 30 minutes)
*/30 * * * * cd /path/to/polyclaw && export $(grep -v "^#" .env | xargs) && .venv/bin/python3 discipline_scanner.py >> /var/log/polyclaw-discipline.log 2>&1
```
- Skips positions worth less than $1
- Take-profit threshold defaults to 20% (configurable)
### Enhanced API (polyclaw_api.py)
CLI bridge for external integrations (e.g., Wells TG Bot via SSH). Provides structured JSON output for programmatic use.
```bash
python3 polyclaw_api.py portfolio # All open positions with live prices (JSON)
python3 polyclaw_api.py summary # Text summary of portfolio
python3 polyclaw_api.py balance # CLOB + on-chain wallet balance
python3 polyclaw_api.py risk # Current risk rules
python3 polyclaw_api.py risk_check <usd> <slug> <channel> # Pre-trade risk check
python3 polyclaw_api.py swap auto # Swap all non-USDC.e to USDC.e
python3 polyclaw_api.py swap status # Show token balances
```
- `portfolio` is the **recommended command** for live position data (reads Data API, not local DB)
- `balance` requires `web3` — use `.venv/bin/python3`
- `summary` reads local DB and can be stale — prefer `portfolio` for accuracy
## Security
For the MVP, the private key is stored in an environment variable for simplicity and Claude Code compatibility.
**Security Warning:** Keep only small amounts in this wallet. Withdraw regularly to a secure wallet.
## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| `CHAINSTACK_NODE` | Yes (trading) | Polygon RPC URL |
| `OPENROUTER_API_KEY` | Yes (hedge) | OpenRouter API key for LLM hedge discovery |
| `POLYCLAW_PRIVATE_KEY` | Yes (trading) | EVM private key (hex, with or without 0x prefix) |
| `HTTPS_PROXY` | Recommended | Rotating residential proxy for CLOB (e.g., IPRoyal) |
| `CLOB_MAX_RETRIES` | No | Max CLOB retries with IP rotation (default: 5) |
**Security Warning:** Keep only small amounts in this wallet. Withdraw regularly to a secure wallet. The private key in an env var is convenient for automation but less secure than encrypted storage.
## Trading Flow
1. **Split Position** - USDC.e is split into YES + NO tokens via CTF contract
2. **Sell Unwanted** - The unwanted side is sold via CLOB order book
3. **Result** - You hold the wanted position, recovered partial cost from selling unwanted
Example: Buy YES at $0.70
- Split $100 USDC.e → 100 YES + 100 NO tokens
- Sell 100 NO tokens at ~$0.30 → recover ~$27 USDC.e
- Net cost: ~$73 for 100 YES tokens (entry: $0.73)
## Polymarket Contracts (Polygon Mainnet)
- **USDC.e:** `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`
- **CTF (Conditional Tokens):** `0x4D97DCd97eC945f40cF65F87097ACe5EA0476045`
- **CTF Exchange:** `0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E`
## Dependencies
Install with uv (from skill directory):
```bash
cd {baseDir}
uv sync
```
## Limitations
- Trading requires wallet approval setup (one-time)
- CLOB sells may fail if liquidity is insufficient
### CLOB Cloudflare Blocking
Polymarket's CLOB API uses Cloudflare protection that blocks POST requests from many IPs, including datacenter IPs and some residential ISPs. This affects the "sell unwanted tokens" step.
**Solution: Residential proxy with retry logic**
The recommended setup uses a rotating residential proxy (e.g., IPRoyal, BrightData). The CLOB client automatically retries with new IPs until one works:
```bash
export HTTPS_PROXY="http://user:pass@geo.iproyal.com:12321"
export CLOB_MAX_RETRIES=10 # Default is 5
```
With this setup, CLOB orders typically succeed within 5-10 retries as the proxy rotates through IPs until finding an unblocked one.
**Alternative workarounds:**
1. **Use `--skip-sell`** — Keep both YES and NO tokens, sell manually on polymarket.com
2. **No proxy** — Split still works; only CLOB sell is affected
If CLOB fails after all retries, your split still succeeded. The output tells you how many tokens to sell manually.
## Troubleshooting
### "No wallet available"
Set the `POLYCLAW_PRIVATE_KEY` environment variable:
```bash
export POLYCLAW_PRIVATE_KEY="0x..."
```
### "Insufficient USDC.e"
Check balance with `uv run python scripts/polyclaw.py wallet status`. You need USDC.e (bridged USDC) on Polygon.
### "CLOB order failed"
The CLOB sell may fail due to:
- Insufficient liquidity at the sell price
- IP blocked by Cloudflare (try proxy)
Your split still succeeded - you have the tokens, just couldn't sell unwanted side.
### "Approvals not set"
First trade requires contract approvals. Run:
```bash
uv run python scripts/polyclaw.py wallet approve
```
## License
MIT
标签
skill
ai