PolyClaw Trading includes a copy-trading layer that discovers active Polymarket wallets from public APIs, scores them by historical performance metrics, and generates advisory signals based on their recent trades. The entire pipeline runs without any API key — it uses only Polymarket’s publicDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/deniszidbaev-cmyk/polyclaw-trading/llms.txt
Use this file to discover all available pages before exploring further.
data-api endpoints. Signals are written to runtime/ JSON files and are consumed by the LLM orchestration layer as advisory context.
Copy-trading signals are advisory only. They feed into the LLM orchestration layer for contextual awareness. They are not execution commands and they do not pass through the deterministic execution gate (
validate → execute). A copy signal alone will never place an order.Components
The copy-trading pipeline consists of three scripts that work in sequence:trader_tracker.py — Discover and track wallets
Queries https://data-api.polymarket.com/trades and https://data-api.polymarket.com/positions to discover active wallets and aggregate their activity. No API key is required.
For each discovered wallet it computes:
trade_count— total number of observed tradestotal_notional— sum of|size| × |price|across all tradesdistinct_markets— number of unique condition IDs tradedmarket_concentration— share of total notional in the single largest market (1.0 = fully concentrated)last_seen_age_seconds— seconds since the wallet’s most recent observed trade
TRADER_TRACKER_ENRICH=1), the tracker also fetches the wallet’s open and historical positions from data-api and derives real win-rate, maximum drawdown, and a consistency score from percentPnl per position. Unverified wallets use conservative defaults (win_rate=0.0, max_drawdown_pct=100.0) that keep them below the copy threshold.
runtime/wallet_watchlist.json— scored wallet listruntime/copy_wallet_signals.json— recent trades from tracked wallets
wallet_scoring.py — Score individual wallets
Provides the score_wallet(wallet) function used by trader_tracker.py and copy_trading.py. The score combines five weighted components:
| Component | Max contribution | Formula |
|---|---|---|
| Win rate | 0.40 | min(win_rate / 100, 0.40) |
| Consistency | 0.25 | min(consistency, 0.25) |
| Trade volume | 0.20 | min(trade_count / 1000, 0.20) |
| Low drawdown | 0.10 | min((40 - max_drawdown_pct) / 400, 0.10) |
| Diversification | 0.05 | min((0.8 - market_concentration) * 1.25, 0.05) |
[0.0, 1.0]. Wallets with all-default (unverified) values score 0.0. The copy-trading threshold in copy_trading.py is 0.45 — only wallets that score at or above this value generate actionable signals.
copy_trading.py — Generate copy-trade decisions
A library module (not a CLI script) that exposes generate_fallback_decisions(). It reads the watchlist from runtime/wallet_watchlist.json, scores each wallet with wallet_scoring.score_wallet, filters to those at or above the 0.45 threshold, then reads runtime/copy_wallet_signals.json and normalizes qualifying signals into copy-trade decisions.
Each decision passes through copy_signal_normalizer.normalize_copy_signal, which enforces a liquidity floor, a maximum signal age, and a maximum trade size (max_trade_usd, default 1.0). Signals that fail any of these checks are discarded. This function is called internally by the LLM orchestration layer — it is not invoked directly from the command line.
CoinGecko spot prices
A separate public data adapter fetches spot prices from CoinGecko (no API key required) and writes them toruntime/spot_prices.json. Configure the assets to track with COINGECKO_IDS:
Configuration
All copy-trading behavior is controlled through environment variables. Copy from.env.example and set values in .env.local:
| Variable | Default | Description |
|---|---|---|
TRADER_TRACKER_TRADES_LIMIT | 500 | Number of recent trades to fetch from data-api per refresh |
TRADER_TRACKER_MIN_TRADES | 2 | Minimum observed trades for a wallet to enter the watchlist |
TRADER_TRACKER_ENRICH | 1 | Enable position-based PnL enrichment (0 to disable) |
TRADER_TRACKER_ENRICH_MAX | 20 | Maximum number of wallets to enrich per refresh (budget control) |
TRADER_TRACKER_SIGNAL_USD | 1.0 | Suggested USD amount attached to each copy signal |
TRADER_TRACKER_MAX_SIGNAL_AGE_SEC | 1800 | Discard signals older than this many seconds (default 30 minutes) |
COINGECKO_IDS | bitcoin,ethereum,solana | Comma-separated CoinGecko asset IDs for spot price tracking |
trader_tracker.py:
Running the copy-trading pipeline
trader_tracker.py is the only executable script in the copy-trading pipeline. It calls wallet_scoring.score_wallet and the copy_trading.generate_fallback_decisions helper internally — neither wallet_scoring.py nor copy_trading.py is a standalone CLI script. Run the tracker to refresh both output files:
Output file format
runtime/wallet_watchlist.json
runtime/copy_wallet_signals.json
age_seconds (most recent first). Any signal older than TRADER_TRACKER_MAX_SIGNAL_AGE_SEC seconds is excluded from the output.
Safety properties
The tracker is written to never abort the pipeline on a transient network error — all writes are best-effort. A failure to fetch positions for one wallet does not cancel enrichment for the rest of the batch; the affected wallet receives anenrich_error field in the watchlist and retains its conservative defaults. The entire refresh() call is wrapped in a broad exception handler so a data-source outage never propagates to the main pipeline loop.