{
  "markdown": "# Simmer SDK\n\n[![PyPI version](https://badge.fury.io/py/simmer-sdk.svg)](https://pypi.org/project/simmer-sdk/)\n\nSimmer is the leading prediction market harness for AI agents. Autonomous agents place trades on venues like Polymarket, Kalshi and Hyperliquid through a unified API — with self-custody wallets, safety rails, and smart context.\n\n- **AI-native trading platform** — designed for autonomous agents, with full support for manual trading too. Users install trading skills and let their agents trade autonomously.\n- **$SIM simulated trading** — paper-trade with virtual currency before risking real funds.\n- **Multi-venue** — trade Polymarket, Kalshi and Hyperliquid through one unified API.\n\n## What's in this repo\n\n| | |\n|--|--|\n| [`skills/`](skills/) | 28 skills an agent installs and runs. `skills/simmer/SKILL.md` is the canonical source for [simmer.markets/skill.md](https://simmer.markets/skill.md). |\n| [`mcp/`](mcp/) | MCP server, published to npm as [`simmer-mcp`](https://www.npmjs.com/package/simmer-mcp). |\n| [`simmer_sdk/`](simmer_sdk/) | Python SDK, published to PyPI as [`simmer-sdk`](https://pypi.org/project/simmer-sdk/). |\n\n## Installation\n\n```bash\npip install simmer-sdk\n```\n\nGet your API key from [simmer.markets/dashboard](https://simmer.markets/dashboard).\n\n## Quick Start\n\n### OpenClaw Skill Pattern (recommended)\n\nMost Simmer users run trading skills inside [OpenClaw](https://openclaw.ai). The standard pattern uses a lazy singleton client and reads config from environment variables:\n\n```python\nimport os\nfrom simmer_sdk import SimmerClient\n\nSKILL_SLUG = \"my-skill-slug\"   # Must match your ClawHub slug\nTRADE_SOURCE = f\"sdk:{SKILL_SLUG}\"\n\n_client = None\ndef get_client(live: bool = False):\n    global _client\n    if _client is None:\n        venue = os.environ.get(\"TRADING_VENUE\", \"sim\")\n        # `live` controls paper vs real execution and is a constructor arg, not a\n        # per-trade flag. live=False => paper preview (no real order placed).\n        _client = SimmerClient(api_key=os.environ[\"SIMMER_API_KEY\"], venue=venue, live=live)\n    return _client\n\ndef run(live: bool = False):\n    client = get_client(live)\n\n    # Find markets. Unfiltered browse is windowed to the newest ~1,000 active\n    # markets — filter with sort=\"volume\", q=\"...\", or tags=\"...\" to reach the rest.\n    markets = client.get_markets(status=\"active\", sort=\"volume\", limit=20)\n\n    # Get trading context (safeguards, slippage, conflict detection)\n    ctx = client.get_market_context(markets[0].id)\n\n    # Trade — always tag source and skill_slug\n    if not ctx.conflict and ctx.recommended_action != \"hold\":\n        result = client.trade(\n            market_id=markets[0].id,\n            side=\"yes\",\n            amount=10.0,\n            source=TRADE_SOURCE,\n            skill_slug=SKILL_SLUG,\n            reasoning=\"Signal detected — buying YES\"\n        )\n        print(f\"{'PAPER: ' if not live else ''}Bought {result.shares_bought:.2f} shares\")\n\nif __name__ == \"__main__\":\n    import sys\n    run(live=\"--live\" in sys.argv)\n```\n\nSet environment variables:\n```bash\nexport SIMMER_API_KEY=sk_live_...\nexport TRADING_VENUE=sim            # sim | polymarket | kalshi\nexport WALLET_PRIVATE_KEY=0x...    # Required for Polymarket self-custody\n```\n\n> **Default to dry-run.** Skills should require `--live` to execute real trades. Paper-trade with `$SIM` until your edge is consistent, then graduate to real money.\n\n### Raw SDK\n\nFor developers building custom integrations:\n\n```python\nfrom simmer_sdk import SimmerClient\n\nclient = SimmerClient(api_key=\"sk_live_...\")\n\n# Browse markets (unfiltered browse is windowed to the newest ~1,000 active\n# markets — use sort=\"volume\", q=\"...\", or tags=\"...\" for discovery)\nmarkets = client.get_markets(sort=\"volume\", limit=10)\nfor m in markets:\n    print(f\"{m.question}: {m.current_probability:.1%}\")\n\n# Trade with $SIM (virtual currency)\nresult = client.trade(market_id=markets[0].id, side=\"yes\", amount=10.0)\nprint(f\"Bought {result.shares_bought:.2f} shares for ${result.cost:.2f}\")\n\n# Check P&L\nfor p in client.get_positions():\n    print(f\"{p.question[:50]}: P&L ${p.pnl:.2f}\")\n```\n\n## Trading Venues\n\n| Venue | Currency | Description |\n|-------|----------|-------------|\n| `sim` | $SIM (virtual) | Default. Paper trading on Simmer's LMSR markets. |\n| `polymarket` | USDC.e (real) | Real trades on Polymarket (Polygon). Requires `WALLET_PRIVATE_KEY`. |\n| `kalshi` | USDC (real) | Real trades on Kalshi. Requires Pro plan. |\n\n```python\n# Paper trading (default)\nclient = SimmerClient(api_key=\"sk_live_...\", venue=\"sim\")\n\n# Real trading on Polymarket\nclient = SimmerClient(api_key=\"sk_live_...\", venue=\"polymarket\")\n\n# Read-only validation/status client. Does not process constructor-time risk exits.\nclient = SimmerClient.readonly(api_key=\"sk_live_...\", venue=\"polymarket\")\n\n# Override venue for a single trade\nclient.trade(market_id, side=\"yes\", amount=10.0, venue=\"polymarket\")\n```\n\n`TRADING_VENUE` environment variable is read at client init — OpenClaw skills use this to select venue at startup without code changes.\n\n> **Constructor side effect:** for live Polymarket clients with `WALLET_PRIVATE_KEY` or `OWS_WALLET`, regular `SimmerClient(...)` construction checks pending risk alerts and may submit stop-loss/take-profit exit orders. This is intentional for self-custody safety: Simmer's server cannot sign those exits. Use `SimmerClient.readonly(...)` for API-key validation, preflight/status checks, and other non-trading paths.\n\n> **Spread caveat:** $SIM fills instantly (AMM, no spread). Real venues have orderbook spreads of 2–5%. Target edges >5% in $SIM before graduating to real money.\n\n> **Polymarket order types:** omit `order_type` for the SDK/server smart default: buys use `FAK` (fill what is available immediately), sells use `GTC` (rest on the book to improve fill rate on thin books). For structurally thin markets or maker-style limit entries, pass `order_type=\"GTC\"` and an explicit `price`.\n\n### Paper trading on real venues\n\nPass `live=False` to simulate trades with real market prices — no wallet or USDC required. For Polymarket, fills model the CLOB bid-ask spread for realistic P&L. Resolved markets auto-settle (winning shares pay $1, losers $0).\n\n```python\nclient = SimmerClient(\n    api_key=\"sk_live_...\",\n    venue=\"polymarket\",\n    live=False,                # Simulate fills, no real money\n    starting_balance=10_000.0  # Virtual capital (default: 10,000)\n)\n\nresult = client.trade(market_id=markets[0].id, side=\"yes\", amount=50.0,\n                      reasoning=\"Testing strategy\")\nprint(f\"Filled {result.shares_bought:.2f} shares (simulated)\")\n\n# Portfolio summary\nsummary = client.get_paper_summary()\nprint(f\"Balance: ${summary['balance']:.2f}, P&L: ${summary['total_pnl']:.2f}\")\n```\n\n**Graduation path:** `sim` (instant fills, no spread) → `polymarket` + `live=False` (real prices, spread modeled) → `polymarket` live (real USDC).\n\n## Backtesting\n\nThe three modes above are all *live-forward*. To test a strategy on **historical** data before risking capital, backtest the skill bundle:\n\n```bash\npip install 'simmer-sdk[backtest]'\n\n# Try it offline — bundled 10-market demo slice, no data download:\nsimmer backtest --demo\n\n# Backtest your own skill over a window — the tape is fetched + cached for you:\nsimmer backtest ./my-skill --entrypoint run.py \\\n    --t0 2026-03-01 --t1 2026-03-08 --cadence 12h --out report.json\n\n# ...or by duration, and with your own local slice (BYO):\nsimmer backtest ./my-skill --entrypoint run.py --window 30d\nsimmer backtest ./my-skill --entrypoint run.py --tape ./slice --t0 2026-03-01 --t1 2026-03-08\n```\n\nThe engine replays your **unmodified** skill against a frozen, look-ahead-safe\nreplay server (one subprocess per tick) and reports pnl, hit rate, max drawdown,\ntrades, baselines (buy-and-hold-YES / random), realism gaps, and a reproducible\n`config_hash`. Programmatic equivalent:\n\n```python\nfrom simmer_sdk.backtest import run_backtest\n\n# tape omitted => the window slice is fetched from the tape service and cached.\nreport = run_backtest(\"./my-skill\", entrypoint=\"run.py\",\n                      t0=\"2026-03-01\", t1=\"2026-03-08\", cadence=\"12h\")\nprint(report[\"summary\"][\"pnl\"], report[\"summary\"][\"hit_rate\"])\n```\n\n> Backtests use trade-tape prices (no orderbook), so they model decision quality,\n> not execution realism — every report lists its `realism_gaps`. The window slice\n> is fetched from Simmer's tape service and cached under `~/.simmer/tapes/`; pass\n> `--tape <dir>` to use your own. Data coverage currently ends ~2026-05-05.\n\n## Key Methods\n\n| Method | Description |\n|--------|-------------|\n| `get_markets()` | List markets (filter by status, source, venue, tags, keyword) |\n| `trade()` | Buy or sell shares |\n| `get_positions()` | All positions with P&L |\n| `get_held_markets()` | Map of market_id → source tags for held positions |\n| `check_conflict()` | Check if another skill holds a position on a market |\n| `get_open_orders()` | Open GTC/GTD orders on the CLOB |\n| `maker_rewards_status(market_id)` | Polymarket liquidity-rewards config: max spread, daily pool, eligibility |\n| `get_portfolio(venue=\"all\")` | Portfolio summary with per-venue buckets (sim/polymarket/kalshi/total) |\n| `get_market_context(market_id, venue=\"all\")` | Per-venue positions + trading safeguards |\n| `get_trades(venue=\"all\")` | Trade history merged across venues, each row tagged with venue |\n| `get_price_history()` | Price history for trend detection |\n| `import_market()` | Import a Polymarket market by URL |\n| `import_kalshi_market()` | Import a Kalshi market by URL |\n| `list_importable_markets()` | Discover markets available to import |\n| `check_market_exists()` | Check if a market is already on Simmer (no quota cost) |\n| `set_monitor()` | Set stop-loss / take-profit on a position |\n| `cancel_order()` | Cancel a single open order by ID |\n| `cancel_market_orders()` | Cancel all open orders on a market (optional side filter) |\n| `cancel_all_orders()` | Cancel all open orders across all markets |\n| `create_alert()` | Price alerts with optional webhook |\n| `register_webhook()` | Push notifications for trades, resolutions, price moves |\n| `redeem()` | Redeem a specific winning Polymarket position |\n| `auto_redeem()` | Scan all positions and redeem any winning ones automatically |\n| `get_paper_summary()` | Paper mode portfolio summary (balance, P&L, positions) |\n| `get_settings()` / `update_settings()` | Configure trade limits and notifications |\n| `link_wallet()` | Link external EVM wallet for Polymarket |\n| `set_approvals()` | Set Polymarket token approvals |\n| `activate_polymarket_dw(agent_id=None)` | Set Polymarket Deposit Wallet on-chain CLOB approvals — user-primary (no arg) or per-agent (`agent_id=...`). See note. |\n| `readonly()` | Constructor for validation/status clients that must not process constructor-time risk exits or submit orders |\n| `troubleshoot()` | Look up any error and get a fix (no auth required) |\n\n> **Per-agent wallets (Elite tier):** activating a per-agent (Elite dedicated) wallet takes **two** calls, approvals first: `activate_polymarket_dw(agent_id=...)` sets the deposit wallet's on-chain CLOB approvals, then `update_agent_wallet_creds(...)` caches the CLOB creds. OWS callers use `update_agent_wallet_creds(ows_wallet_name=\"...\")`; raw-key callers with `WALLET_PRIVATE_KEY` use `update_agent_wallet_creds(agent_id=\"...\")`. **Both approvals and cached creds are required before trading** — caching creds alone does not set on-chain allowances, so trades fail at the relayer with \"insufficient allowance\". See the `simmer-wallet-setup` skill for the full flow. (`set_approvals()` is the user-primary EOA path and is a no-op for per-agent deposit wallets.)\n\n**Tip — don't pre-round prices.** simmer-sdk ≥ 0.17.1 automatically rounds the price to each Polymarket market's tick grid. Pass your raw computed price to `client.trade(..., price=p)` and the SDK handles the rest. Pre-rounding with a hardcoded tick (e.g. `round(price, 3)`) will silently produce wrong values for markets at different tick sizes.\n\n**Error handling:** All SDK 4xx responses include a `fix` field with actionable instructions when the error matches a known pattern. You can also call `POST /api/sdk/troubleshoot` with `{\"error_text\": \"...\"}` to look up any error.\n\nFull API reference with parameters, examples, and error codes: **[simmer.markets/docs.md](https://simmer.markets/docs.md)**\n\n## Skill Builder Utilities\n\nThe SDK ships two helper modules for skill authors. Prefer these over rolling your own — they encode patterns from top traders and external research.\n\n### Position sizing — `simmer_sdk.sizing`\n\nKelly Criterion + Expected Value sizing for binary prediction markets. Default is fractional Kelly (0.25x) with an EV gate, so trades below your edge threshold return `0.0` and the skill can simply skip them.\n\n```python\nfrom simmer_sdk import SimmerClient\nfrom simmer_sdk.sizing import size_position\n\nclient = SimmerClient()\nbankroll = client.get_portfolio()[\"available_balance\"]\n\namount = size_position(\n    p_win=0.70,         # your model's probability\n    market_price=0.55,  # current YES price\n    bankroll=bankroll,\n    min_ev=0.03,        # skip trades with edge < 3%\n)\nif amount > 0:\n    client.trade(market_id=..., side=\"yes\",\n                 amount=amount, reasoning=\"Kelly: 70% vs 55%, +15% edge\")\n```\n\n| Function | Purpose |\n|----------|---------|\n| `size_position(p_win, market_price, bankroll, method=, kelly_multiplier=, min_ev=, max_fraction=)` | Returns dollar amount to trade. `0.0` when edge ≤ `min_ev`, Kelly is negative, or inputs are invalid. |\n| `kelly_fraction(p_win, market_price)` | Raw Kelly fraction `(p - c) / (1 - c)`. |\n| `expected_value(p_win, market_price)` | Edge per share (`p_win - market_price`). |\n| `SIZING_CONFIG_SCHEMA` | Drop-in `CONFIG_SCHEMA` fragment exposing `SIMMER_POSITION_SIZING`, `SIMMER_KELLY_MULTIPLIER`, `SIMMER_MIN_EV` env vars. |\n\nMethods: `\"fractional_kelly\"` (default, multiplier 0.25), `\"kelly\"` (full, aggressive), `\"fixed\"` (uses `kelly_multiplier` as a flat fraction). For NO bets pass `p_win=1-p_yes` and `market_price=1-yes_price`.\n\n## Auto-Redeem\n\nWhen a Polymarket market resolves and your side wins, the CTF tokens in your wallet must be redeemed to claim the USDC.e payout. Auto-redeem handles this automatically each cycle.\n\n```python\n# Call at the start of each cycle to claim any pending winnings\nresults = client.auto_redeem()\nfor r in results:\n    if r[\"success\"]:\n        print(f\"Redeemed {r['market_id']} ({r['side']}): {r['tx_hash']}\")\n```\n\n- Fetches positions where `redeemable: true` and `redeemable_side` is set (Polymarket only)\n- For self-custody wallets (`WALLET_PRIVATE_KEY`): signs and broadcasts on-chain\n- For managed wallets: server handles signing, no local key needed\n- Never raises — safe to call every cycle\n\nAuto-redeem can be toggled per-agent from the Simmer dashboard.\n\n## Skills\n\nPre-built trading strategies are published on [ClawHub](https://clawhub.ai) and listed in the Simmer registry. Browse and install at **[simmer.markets/skills](https://simmer.markets/skills)**.\n\n```bash\n# Install a skill via ClawHub CLI\nclawhub install polymarket-weather-trader\n```\n\nSkills in this repo (`skills/`) are the official Simmer-maintained strategies. See [docs.simmer.markets/skills/building](https://docs.simmer.markets/skills/building) for the full guide to building, remixing, and publishing your own.\n\n## Resources\n\n| | |\n|--|--|\n| **Platform** | [simmer.markets](https://simmer.markets) |\n| **API Reference** | [docs.simmer.markets](https://docs.simmer.markets) |\n| **Onboarding Guide** | [simmer.markets/skill.md](https://simmer.markets/skill.md) |\n| **Skills Registry** | [docs.simmer.markets/skills](https://docs.simmer.markets/skills/overview) |\n| **ClawHub** | [clawhub.ai](https://clawhub.ai) |\n| **MCP Server** | `npm install -g simmer-mcp` — docs + error troubleshooting as MCP resources ([npm](https://www.npmjs.com/package/simmer-mcp)) |\n| **Telegram** | [t.me/+m7sN0OLM_780M2Fl](https://t.me/+m7sN0OLM_780M2Fl) |\n\n## Contributing\n\nSDK improvements and bug fixes are welcome. If you've hit an edge case with `SimmerClient` or have a useful addition, open a PR.\n\n- **Skills** belong on [ClawHub](https://clawhub.ai), not this repo — see [docs.simmer.markets/skills/building](https://docs.simmer.markets/skills/building)\n- **API bugs or feature requests** → open an issue first\n- **AI-assisted PRs welcome** — just note it in the PR description\n- Keep PRs focused on one thing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for the full guide.\n\n## License\n\nMIT\n",
  "bytes": 16624,
  "sha": "18de3db9be62d15a2dc6f07c73620c6fed842e69566e216e00caefac06f89da3",
  "repo_slug": "spartanlabsxyz/simmer-sdk",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_adlai88_simmer_mcp_dfd2b170/readme"
}