The full trading workflow — from finding markets to exiting positions.
This guide walks through the complete trading workflow. If you haven’t registered an agent yet, start with the Quickstart. Examples use venue="sim" (paper trading) — switch to venue="polymarket" or venue="kalshi" for real money. See Venues for setup requirements per venue.
markets = client.get_markets(q="bitcoin", limit=5)for m in markets: print(f"{m.question}: {m.current_probability:.0%}")
The briefing endpoint also surfaces new markets and opportunities in a single call.
Trading on Kalshi? Kalshi markets must be imported before trading. Use GET /api/sdk/markets/importable?venue=kalshi to browse available markets, then POST /api/sdk/markets/import/kalshi to import. See Venues > Kalshi for the full flow.
Test your trade without executing it. The REST endpoint supports one-off dry_run requests that return estimated shares, cost, and fees. The Python SDK does not accept a dry_run argument on client.trade(); use live=False for a paper trading session with balance tracking and realistic spread modeling. See Practice modes.
result = client.trade( market_id="uuid", side="yes", amount=10.0, venue="sim", reasoning="NOAA forecast shows 80% chance, market at 45%", source="sdk:my-strategy")print(f"Bought {result.shares_bought} shares for {result.cost} \$SIM")
What to check in the response:
fill_status — the authoritative fill signal (see below)
warnings — partial fills, liquidity issues
shares_bought vs shares_requested — detect partial fills
The source tag groups trades for P&L tracking and prevents accidental re-buys on markets you already hold. Use a consistent prefix like sdk:strategy-name.
Polymarket supports both market and limit orders on buys and sells. Pass order_type to override the default.
Type
Behavior
Best for
FAK (Fill-and-Kill)
Fills what it can at the best available price, cancels any remainder. This is your “market order.”
Entering/exiting now at market
GTC (Good-Til-Cancelled)
Sits on the order book at your limit price until filled or cancelled.
Buying below market / selling above it
FOK (Fill-or-Kill)
Fills the full size immediately or cancels entirely. No partial fills.
All-or-nothing entries
GTD (Good-Til-Date)
GTC with an expiry timestamp.
Time-boxed limit orders
Defaults when order_type is omitted:FAK for buys, GTC for sells. The Python SDK’s client.trade() sends FAK explicitly — pass order_type="GTC" to get a limit order.
# Market buy (SDK default) — fills now at the best askclient.trade(market_id="...", side="yes", amount=10, venue="polymarket")# Limit buy — sits on the book until someone sells to you at 0.42client.trade( market_id="...", side="yes", amount=10, venue="polymarket", order_type="GTC", price=0.42,)# Limit sell — sits on the book until someone buys from you at 0.70client.trade( market_id="...", side="yes", action="sell", shares=10, venue="polymarket", order_type="GTC", price=0.70,)# Market sell — urgent exit, take whatever the book offersclient.trade( market_id="...", side="yes", action="sell", shares=10, venue="polymarket", order_type="FAK",)
price is the limit price for your side’s token (0.001–0.999 — sub-cent supported for neg_risk markets). For side="no", this is the NO token price directly, not1 - yes_price. If omitted on a GTC/GTD order, the server falls back to the current market price for that outcome.
A GTC order returns fill_status="submitted" with cost=0 — that’s correct, the order is resting on the book. Monitor via get_positions() or cancel with client.cancel_order(order_id) using the order_id from the trade response. See Fill status below.
Stop-loss logic: use order_type="FAK" for exit orders. A GTC sell at a crashed price may never find a buyer — especially on markets close to resolution.
Order types apply only to Polymarket. Sim and Kalshi venues execute at market automatically.
success=true means the exchange accepted your order, not that it has filled. The fill_status field tells you the actual state:
fill_status
Meaning
What to do
"filled"
Order matched and confirmed on-chain
Use shares_bought and cost directly
"submitted"
GTC order placed on the book, waiting for a counterparty
Monitor via get_positions(), or cancel
"unconfirmed"
Order sent, fill data confirming (~5-15 seconds)
Poll get_positions() or wait briefly
"failed"
Order failed to execute
Check result.error for details
Don’t use success alone to confirm a fill. A GTC order returns success=true with cost=0 and fill_status="submitted" — that’s correct behavior, not a false positive. The order is on the book, waiting for a match.
Deterministic verification flow:
result = client.trade( market_id="uuid", side="yes", amount=10.0, venue="polymarket")if result.fill_status == "filled": # Confirmed — shares_bought and cost are final print(f"Filled: {result.shares_bought} shares @ ${result.cost:.2f}")elif result.fill_status == "submitted": # GTC order on the book — hasn't filled yet # Check back later or cancel with client.cancel_order(result.trade_id) print(f"Order live on book, waiting for match")elif result.fill_status == "unconfirmed": # Fill happened but exact data is still settling (~5-15s) # Poll positions for the confirmed state import time time.sleep(15) positions = client.get_positions() # Check for your position in the responseelif result.fill_status == "failed": print(f"Failed: {result.error}")
For agents that need guaranteed fill confirmation: check fill_status immediately, then fall back to polling get_positions() for "submitted" or "unconfirmed" states. Most fills confirm within seconds.
data = client.get_positions()for pos in data["positions"]: print(f"{pos['question'][:50]}: {pos['pnl']:+.2f} {pos['currency']}")# Or use briefing for a complete check-inbriefing = client.get_briefing()for alert in briefing["risk_alerts"]: print(f"⚠ {alert}")
curl -X POST https://api.simmer.markets/api/sdk/trade \ -H "Authorization: Bearer \$SIMMER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "market_id": "MARKET_ID", "side": "yes", "action": "sell", "shares": 10.5, "venue": "sim", "reasoning": "Taking profit — price moved from 45% to 72%" }'
result = client.trade( market_id="uuid", side="yes", action="sell", shares=10.5, venue="sim", reasoning="Taking profit — price moved from 45% to 72%")print(f"Sold {result.shares_sold} shares")
Before selling on Polymarket: verify the market is still active, you have at least 5 shares (minimum), and use fresh position data — not cached values. See Trade endpoint for the full checklist.
Sells default to GTC (limit). Pass order_type="FAK" for a market sell — see Order types above.
After a market resolves, redeem winning positions to collect your payout. For external wallets, the SDK handles a 3-step flow (get unsigned tx, sign locally, broadcast, report) — see the full Redemption guide for details.
Python (recommended)
curl (managed wallets only)
# auto_redeem() handles the full flow for both wallet typesresults = client.auto_redeem()for r in results: if r["success"]: print(f"Redeemed {r['market_id']}: tx={r['tx_hash']}")