agentleFS
SpartanLabsXyzSpartanLabsXyz/simmer-sdk/skills/polymarket-market-maker/SKILL.md

polymarket-market-maker

Skill56 starsChanged 10 days agoMITView on GitHub

Post two-sided GTC limit orders on Polymarket CLOB. Manages inventory skew, cancel/replace on price drift, and estimates rebate-eligible volume.

  • Reads credentials
  • Installs packages

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Run on a cron cadence (e.g., every 5 minutes) to keep quotes fresh.

    line 121
  2. Very specific:

    When |net_skew| > max_skew_pct × (quote_usdc / price), the over-exposed side stops posting new quotes.

    line 155
  3. Distinctive:

    State file is local: If running across multiple machines, the state file can desync.

    line 161

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Polymarket Market Maker

Post two-sided GTC limit orders (bid + ask) on Polymarket CLOB to earn the bid-ask spread as a liquidity provider. This is a developer-only SDK primitive — not a retail "set and forget" skill. You will need to monitor inventory and tune spread/skew parameters to your specific markets.

Why this matters. Akey, Grégoire, Harvie & Martineau (2026) studied 1.4M Polymarket users and $20B in volume. Their headline finding: moving from pure taker to pure market-maker reduces the probability of losing money by 35.9 percentage points — more than 10× larger than any other behavioral predictor (overtrading: 5pp, category concentration: 13.6pp, extreme-price trading: 3pp). This is the single highest-edge behavior on Polymarket.

How it works

Each run (cron or manual):

  For each configured market:
    1. Fetch current mid price (external_price_yes)
    2. Compute bid/ask:
         bid = mid - spread/2  (round to 0.01 tick)
         ask = mid + spread/2  (round to 0.01 tick)
    3. Check inventory: if net_YES_skew > max_skew → pause bidding
                        if net_NO_skew  > max_skew → pause asking
    4. Check drift: if existing order price differs from new quote by > drift_threshold
                    → cancel and repost
    5. Post GTC orders:
         BID: client.trade("yes", amount=Q, price=bid, order_type="GTC")
         ASK: client.trade("no",  amount=Q, price=1-ask, order_type="GTC")
              ^ Synthetic sell: post NO buy at 1-ask_price instead of YES sell
                → earns maker rebates instead of paying taker fees on exits
    6. Log fee-equivalent volume for rebate estimation

Quote structure (synthetic sell on asks)

Polymarket YES and NO tokens are complementary (YES + NO = $1). Instead of posting a sell order on YES (which pays taker fees), this skill posts a buy order on NO at the complementary price:

IntentOrder postedPrice
Buy YESBUY YES GTCmid - spread/2
Sell YES (ask)BUY NO GTC1 - (mid + spread/2)

This earns maker rebates on both sides (Polymarket Maker Rebates Program). At a taker fee rate of 2%, the rebate formula is:

fee_equivalent = notional_USDC × taker_fee_rate × price × (1-price)

The --status and --cancel-all commands show cumulative fee-equivalent estimates.

Setup

  1. Install SDK
    pip install -U 'simmer-sdk>=0.26.0'
  2. Set API key
    export SIMMER_API_KEY=sk_live_...
  3. Import markets to Simmer (markets must be imported before the skill can quote them)
    from simmer_sdk import SimmerClient
    client = SimmerClient(api_key=os.environ["SIMMER_API_KEY"], venue="polymarket", live=True)
    result = client.import_market("https://polymarket.com/event/will-btc-hit-100k-by-eoy-2026")
    print(result["market_id"])  # use this ID in MM_MARKETS
  4. Configure markets
    export MM_MARKETS=abc123def456,xyz789...   # comma-separated Simmer market IDs
    export MM_SPREAD_PCT=0.04                  # 4% spread (2¢ each side at 50¢ mid)
    export MM_QUOTE_USDC=10                    # $10 USDC per side per market
  5. Dry run (default — no orders placed). A dry run (no --live) also skips the SDK's startup stop-loss/take-profit exits, so it never sells, even with WALLET_PRIVATE_KEY set.
    python market_maker.py
  6. Live trading
    python market_maker.py --live

Parameters

Env VarDefaultDescription
MM_MARKETS—Required. Comma-separated Simmer market IDs
MM_SPREAD_PCT0.04Spread as fraction of price (0.04 = 4 cents at 50¢); minimum 0.03 to avoid post-rounding quote collapse
MM_QUOTE_USDC10.0USDC per side per market
MM_MAX_SKEW_PCT0.30Pause one side when inventory skew exceeds this fraction
MM_DRIFT_THRESHOLD0.02Cancel/replace when quote drifts >2¢ from current mid
MM_TAKER_FEE_RATE0.02Taker fee rate for rebate estimation (sports: 0.03)
MM_MAX_MARKETS5Cap number of markets per run
MM_STATE_FILE~/.simmer/market_maker_state.jsonState persistence (order IDs + rebate log)

CLI commands

python market_maker.py              # Dry run
python market_maker.py --live       # Live trading
python market_maker.py --status     # Show active quotes + inventory
python market_maker.py --cancel-all # Cancel all open market-maker GTC orders
python market_maker.py --config     # Print active config

Cron / automaton mode

Run on a cron cadence (e.g., every 5 minutes) to keep quotes fresh. The skill emits {"automaton": {...}} when AUTOMATON_MANAGED=1 is set.

# Run every 5 minutes (OpenClaw / cron)
*/5 * * * * AUTOMATON_MANAGED=1 MM_MARKETS=abc123 MM_SPREAD_PCT=0.04 \
  python market_maker.py --live

Automaton output fields:

  • markets — number of markets processed
  • bids_placed / asks_placed — GTC orders submitted this run
  • orders_cancelled — stale quotes cancelled
  • fee_equiv_usd — estimated rebate-eligible volume this run
  • cumulative_fee_equiv_usd — total across all runs

Market selection guidance

Good candidates for market-making:

  • Active binary Polymarket markets with reasonable volume (>$5k/day)
  • Prices between 5¢ and 95¢ (near-binary markets have poor risk/reward)
  • Sports, crypto, and major political markets eligible for Maker Rebates Program

Poor candidates:

  • Near-resolved markets (price < 2¢ or > 98¢) — high adverse selection, max loss is max
  • Very low liquidity markets — spreads wide but fills rare; capital sits idle
  • neg_risk (multi-outcome) markets — price arithmetic differs; this skill uses binary-only math

Inventory management

The skill tracks net inventory per market:

net_skew = shares_YES - shares_NO

When |net_skew| > max_skew_pct × (quote_usdc / price), the over-exposed side stops posting new quotes. This limits directional exposure but does not eliminate it — monitor inventory via --status.

Limitations (v1)

  • Binary markets only. neg_risk markets have non-complementary token prices; the 1-ask_yes formula is incorrect for them. The skill will still quote them but the ask leg may misprice.
  • No position close automation. The skill posts quotes but doesn't close inventory on resolution. Use client.auto_redeem() in a separate process or add --cancel-all before market resolution.
  • State file is local. If running across multiple machines, the state file can desync. Each instance manages its own orders independently.

References

  • Research: simmer-labs/shared-knowledge/research/2026-04-16-polymarket-winners-losers-study.md
  • Synthetic sell: simmer-labs/shared-knowledge/research/2026-04-14-polymarket-quant-bot-copy-trading.md
  • Risk disclaimer: DISCLAIMER.md

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.