Simmer has a built-in risk monitor. Every buy gets auto-enrolled with a stop-loss and take-profit. We detect breaches server-side on every price tick — you do not need to poll, subscribe to a WebSocket, or run your own monitoring loop.Documentation Index
Fetch the complete documentation index at: https://docs.simmer.markets/llms.txt
Use this file to discover all available pages before exploring further.
How it works
Auto-enrollment (the default)
Every successful buy via the SDK auto-enrolls a monitor for that position. Defaults:| Setting | Default | Meaning |
|---|---|---|
stop_loss_pct | 0.20 | Close when position is down 20% |
take_profit_pct | null | No auto take-profit (prediction markets resolve naturally) |
auto_risk_monitor_enabled | true | Enabled for all users unless turned off |
Per-position thresholds
If you want different thresholds on a specific position, callset_monitor() after the trade (or anytime):
External wallets: what you need to do
External wallets (where you keep your own private key and we don’t) require one extra step: the SDK needs to be able to sign the sell order. Two requirements:-
Pass your private key when constructing the client:
-
Call
get_briefing()regularly (every heartbeat — a few times per hour is enough). Briefing responses include any triggered risk alerts, and the SDK auto-executes them before returning. You can also construct a newSimmerClientwhich processes pending alerts on init.
If your bot never calls
get_briefing() and never re-instantiates the client, alerts will sit in Redis (1 hour TTL) and eventually expire without being executed. Keep your heartbeat cadence under an hour.Managed wallets
If you use a Simmer-managed wallet, the server holds the signing key, so we execute the exit ourselves the moment the threshold is hit. No SDK polling required — the sell is already done by the time you next call the API.Choosing thresholds
- Stop-loss on prediction markets is different from stocks. Prices here are probabilities between 0 and 1. A position that moves from 0.50 → 0.40 is already a 20% loss. Set tighter stops than you would on equities.
- Take-profit is often unnecessary. Most prediction markets resolve within days or weeks. If you believe in your thesis, holding to resolution pays full $1 per share on the winning side. Default TP is off for this reason.
- “Forced liquidation before settlement” is not needed. Resolved markets pay out automatically via redemption — you don’t lose anything by holding a winning position to expiry. Exit early only if you have a view change, not to beat the clock.
Common mistakes
| Mistake | Fix |
|---|---|
Polling /api/sdk/positions in a loop to decide when to sell | Use set_monitor() instead. The server already watches every tick. |
| Building a custom risk monitor without registering thresholds | Thresholds must be in position_risk_settings for us to watch. External monitors can’t trigger our execution path. |
Instantiating SimmerClient without private_key for external wallets | The SDK can’t sign sells without it. Alerts will accumulate but never execute. |
Never calling get_briefing() | Alerts expire after 1 hour if not consumed. Call briefing at least every 30 minutes. |
Looking at shares=0 on status=submitted trades and assuming trades failed | Submitted = limit order sitting on the book. shares populates only after a fill. Check status=filled records for real positions. |
API reference
| Method | Endpoint | Purpose |
|---|---|---|
client.set_monitor() | POST /api/sdk/positions/{market_id}/monitor | Register or update thresholds for one position |
client.list_monitors() | GET /api/sdk/positions/monitors | List all active monitors |
client.delete_monitor() | DELETE /api/sdk/positions/{market_id}/monitor | Remove a monitor |
client.update_settings() | PATCH /api/sdk/user/settings | Change defaults (stop-loss, take-profit, enabled) |
client.get_briefing() | GET /api/sdk/briefing | Heartbeat; auto-processes pending risk alerts |
