Skip to content

Claude/reverse engineer polymarket trades 7wk dr#254

Open
predictx28 wants to merge 27 commits intomsitarzewski:mainfrom
predictx28:claude/reverse-engineer-polymarket-trades-7wkDr
Open

Claude/reverse engineer polymarket trades 7wk dr#254
predictx28 wants to merge 27 commits intomsitarzewski:mainfrom
predictx28:claude/reverse-engineer-polymarket-trades-7wkDr

Conversation

@predictx28
Copy link

@predictx28 predictx28 commented Mar 18, 2026

What does this PR do?

Agent Information (if adding/modifying an agent)

  • Agent Name:
  • Category:
  • Specialty:

Checklist

  • Follows the agent template structure from CONTRIBUTING.md
  • Includes YAML frontmatter with name, description, color
  • Has concrete code/template examples (for new agents)
  • Tested in real scenarios
  • Proofread and formatted correctly

claude added 27 commits March 17, 2026 22:34
Senior quant/HFT agent that reverse-engineers Polymarket user trading
strategies from on-chain data and replicates them as a live trading bot.

Covers 5-phase workflow: data acquisition, behavioral fingerprinting,
signal extraction, quantitative model building, and bot deployment.
Includes Kelly sizing, Bayesian fair value modeling, CLOB integration,
and full risk management framework.

https://claude.ai/code/session_01BuzQm3qUEWju6yFae46sDx
- Add trades_k9Q2mX4L8A7ZP3R.csv (50,201 on-chain trades, 323 markets, 9.3hr window)
- Add reverse_engineer_trades.py: full 5-phase quant analysis pipeline

Findings: target wallet is an automated two-sided LP seeding bot
- 79.7% of inter-trade gaps <1ms (confirmed bot)
- 97.8% of markets have both Up+Down positions (LP not directional)
- Size scales linearly with price (Spearman ρ=0.466, p≈0)
- 68.2% of orders fragmented at same price level (impact minimization)
- $375k deployed across 319 markets at ~$40k USDC/hour
- Primary strategy: Hypothesis C (LP/AMM seeding) — 9/10 confidence
- Replicability score: 8/10

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
Full automated trading bot replicating the reverse-engineered LP strategy
from trades_k9Q2mX4L8A7ZP3R.csv (Hypothesis C: two-sided AMM seeding bot).

Architecture:
- polymarket_bot/config.py      — all settings via env vars / .env file
- polymarket_bot/market_scanner.py — async Gamma API market fetcher with
                                     volume/spread/price filters
- polymarket_bot/sizer.py       — reverse-engineered sizing rule
                                   (size = 26.74×price − 1.59, 2 fragments)
- polymarket_bot/risk.py        — per-market cap (10%), daily loss kill
                                   switch (5%), total exposure cap (80%)
- polymarket_bot/paper_trader.py — simulated fills with slippage model
- polymarket_bot/executor.py    — live CLOB execution via py-clob-client
- polymarket_bot/monitor.py     — CSV trade log + real-time P&L dashboard
- polymarket_bot/bot.py         — async scan→signal→risk→execute loop
- run_bot.py                    — CLI entry point (paper default)
- requirements_bot.txt          — dependencies
- .env.example                  — configuration template

Default mode: paper trading (BOT_MODE=paper)
Live mode requires: py-clob-client + funded Polygon wallet

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
Polymarket no longer has active "5 min / 15 min / 1 hour" price-feed
markets, so the timeframe filter was dropping all 44 otherwise-qualifying
markets to 0. Set MARKET_TIMEFRAMES default to empty (no filter) so the
bot trades any crypto market matching the coin keywords. Also align
MIN_MARKET_VOLUME_USDC default with the 10_000 threshold used in
diagnose_bot.py.

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
Adds a dedicated step that prints all markets mentioning BTC/XRP/SOL
(ignoring all filters) so the user can see whether their target
price-feed markets actually exist on Polymarket right now.

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
… search

Scans up to 500 markets via pagination AND does targeted keyword
searches (bitcoin/BTC/XRP/solana/SOL) using the Gamma API search param,
then merges results. Shows all matching crypto markets sorted by volume
so user can see exactly what titles/formats exist on Polymarket.

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
…tered pages

Adds 4 parallel search strategies:
1. Paginate /markets with NO active filter (includes inactive/upcoming)
2. Search /events endpoint for grouped markets
3. Direct slug lookups for known crypto price-feed URL patterns
4. Tag/category filter params (crypto, bitcoin, price)

This will conclusively find any BTC/XRP/SOL markets regardless of
how they are structured on Polymarket.

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
Polymarket's 5-minute BTC/XRP/SOL up/down markets use slugs like
btc-updown-5m-1773792600 (Unix timestamp rounded to 300s boundary).
These are too short-lived to appear in paginated /markets results and
must be fetched directly by slug each cycle.

Changes:
- market_scanner.py: add fetch_updown_markets() that computes current
  5-min boundary timestamp, constructs slugs for configured assets,
  and fetches them directly; uses relaxed _passes_updown_filter() that
  skips lifetime volume check (brand-new markets have near-zero volume)
- config.py: add UPDOWN_ASSETS env var (default "btc|xrp|sol")
- diagnose_bot.py: add Step 4 that probes current + adjacent 5-min
  window slugs and reports what it finds (active, price, spread, vol)

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
…ashboard

- Scan interval reduced to 5s (was 60s) for near-continuous market coverage
- Bot now detects when 5m/15m/1h markets close and queries Gamma API for the
  outcome; winning positions are redeemed at $1.00/token, losing at $0.00
- bot_trades.csv is reset (header-only) on every bot startup so each run is clean
- Market.end_time and OrderIntent.end_time flow through the full stack so the
  settlement checker knows when each position expires
- New CSV columns: question, market_end_ts, pnl_usdc (replaces empty question field)
- Dashboard completely rewritten as a dark terminal UI with:
    * Stats bar: trades, open, won, lost, win-rate, realised P&L, exposure
    * Open positions table with live countdown timer (colour-coded urgency)
    * Won / Lost side-by-side tables with P&L per trade
    * Rolling trade log (last 80) with BUY / SETTLE / WIN / LOSS colour coding

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
Adds an EXPORT TRADES section at the bottom of the terminal dashboard:
- Download button generates a CSV matching the original trade file format
- Columns: timestamp, market, outcome, entry_price, size_usdc, tokens,
  market_end_ts, payout_price, pnl_usdc, settled_at, result (WIN/LOSS/OPEN)
- 10-row preview inline with win/loss/open counts shown
- Filename includes timestamp for easy versioning

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
…pytrader.py)

Dashboard (dashboard.py):
- Replaced Streamlit with FastAPI + WebSocket — serves http://localhost:8001
- Design matches copytrader.py exactly: dark glassmorphism, DM Mono + Outfit fonts,
  radial gradient background, macOS traffic lights in topbar
- Tab navigation: Overview / Trades / Analytics / Log
- Overview: 6-stat grid, last trade card, open positions list, Chart.js P&L curve,
  win-rate-by-price bar chart, open-exposure doughnut chart
- Trades: filterable table (All/Open/Win/Loss) with live expiry countdown + Export CSV
- Analytics: win rate by side (UP/DOWN) and by entry price bucket with bar charts
- Log: auto-rendered from trade history with colour-coded WIN/LOSS/BUY tags
- WebSocket push every 3 s; reconnects automatically on drop
- /export endpoint serves comparison CSV (same columns as original account trades)

Settlement / Claiming (ported from copytrader.py):
- market_scanner.py: parse end_time from endDateIso/end_date_iso for all markets
- sizer.py + OrderIntent: carry token_id (ERC-1155) through from market.clob_token_ids
- risk.py: track token_id per PositionRecord + market_token_ids lookup dict
- paper_trader.py: pass token_id to risk.record_buy
- config.py: add FUNDER_ADDRESS field for on-chain sweep step
- executor.py: replace NotImplementedError stub with real _resolve_token_id from
  risk state; add 3-step redeem_position() (transfer EOA→Safe, redeem, sweep USDC)
- bot.py: check ALL open positions every 60 s (not just those with known end_times);
  CLOB price ≥ 0.95 fast path + Gamma API fallback; redeem_queue with 3-min delay
  and 5-min retry (identical to copytrader.py); process queue in live mode only

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
When a position's token price reaches TAKE_PROFIT_PRICE (default 0.98),
the bot automatically sells the full position each cycle. The exit is
logged to CSV with side="TP" and pnl_usdc populated so win/loss is
visible in the trade log. Configurable via TAKE_PROFIT_PRICE env var.

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
record_sell() computed tokens_sold = payout_usdc / price. For losses,
payout_usdc=0, so tokens_sold=0 and tokens_held was never decremented.
The position stayed open, getting re-settled every 60s and hammering
daily PnL repeatedly.

Fix: add tokens_override param to record_sell() so settle_position()
can pass the actual token count directly, bypassing the division math.

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
…le to 5s

Two bugs causing positions to show as OPEN:
1. dashboard.py only looked for side="SETTLE" rows to mark positions closed.
   Take-profit exits (side="TP") were invisible to the export and build_state,
   so every TP-exited position appeared permanently OPEN. Fixed by treating
   both "SETTLE" and "TP" sides as exit events throughout build_state() and
   the /export endpoint. Win/loss for TP rows uses pnl_usdc > 0.

2. The 60s settle throttle was too slow for 5-minute markets — if Gamma
   hadn't resolved by the first check, the window could be missed. Reduced
   to 5s so each market gets multiple resolution attempts within its window.

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
…adence

- bot.py: add _refresh_market_cache() + _cached_markets; market list
  refreshed every market_rescan_sec (default 30s) instead of every cycle.
  run_once() now trades against the cache (no Gamma API call per burst).
  run() calls initial cache load at startup, then re-scans on schedule.
  Removed 0.1s asyncio.sleep between markets in run_once().

- paper_trader.py: removed asyncio.sleep(order_delay_sec) from execute_buy
  and execute_sell — paper fills are instant, matching original wallet's
  sub-ms within-burst timing. Live mode delay unchanged.

- config.py: scan_interval_sec default 2s (matches original wallet cadence),
  order_delay_sec default 0.1s, added market_rescan_sec=30 and
  take_profit_price=0.98.

- .env.example: updated SCAN_INTERVAL_SEC=2, ORDER_DELAY_SEC=0.1,
  added MARKET_RESCAN_SEC=30.

https://claude.ai/code/session_01GVCktVy3tZRf6CoVMAaFrY
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants