Create complex order
Create a conditional or algorithmic order: a stop, trailing stop, iceberg, one-cancels-the-other, bracket, TWAP, peg or smart taker.
Self-hosted. Served by synpath serve on your own machine or host, which must be running; the engine and its order types live there. Nothing on this page runs on Synpath's servers.
Complex orders are held by the engine in your self-hosted server (synpath serve), not by the exchange. Send one to the same route as a plain order with type set to the kind you want and params for its settings. The engine watches the market and places ordinary orders on the venue when the condition is met. Cancel the parent and every child is cancelled with it.
Supported types:
- Stop Market: fires at the stop price, then takes the market
- Stop Limit: fires at the stop price, then rests a limit
- Trailing Stop: a stop that follows the market one way
- Iceberg: shows one slice at a time until the whole size is done
- One Cancels the Other (OCO): two orders, one cancels the other
- Bracket: an entry with a take-profit and a stop-loss attached
- TWAP: slices the order evenly across a time window
- Peg: rests at the touch and follows the book
- Smart Taker: takes liquidity in clips, inside a price bound
Pass the type as stop_market, stop_limit, trailing_stop, iceberg, oco, bracket, twap, peg or smart_taker.
The order comes back with held_by: "engine" and status waiting, then triggered once it fires. Its child orders appear in GET /orders with parent_id set.
Request body
| Name | Type | Description |
|---|---|---|
market_id | string | Synpath id, venue:native. |
side | string | buy (YES) or sell (NO). |
amount | decimal | Total contracts across every child. |
type | string | stop_market, stop_limit, trailing_stop, iceberg, oco, bracket, twap, peg or smart_taker. |
price | decimal | The YES price the children submit at, where the type takes a limit. |
stop_price | decimal | The trigger level, for the stop types. |
time_in_force | stringdefault gtc | Applied to each child. |
expires_at | integer | Milliseconds since epoch. The whole order ends then: the engine cancels it and pulls every live child. Refused if already past. |
reduce_only | booleandefault false | Every child may only reduce your position, never open one. Set it on a protective stop: on Polymarket it makes the stop sell the YES you hold rather than buy NO. OCO and bracket legs inherit it unless a leg sets its own. |
post_only | booleandefault false | Each child rests or is refused, never takes. Only for types that rest on the book: iceberg, peg, and twap in its limit style. Refused with 400 on the others; on oco and bracket, set it on the legs. |
params | object | What the type needs; see the tables below. |
client_order_id, account, book, trader, tags, notes | | As on a plain order. |
Stop orders: stop_market, stop_limit
Fires once when the market reaches stop_price. A sell stop watches the best bid, a buy stop the best ask, because that is the price that would fill it. The child is an immediate limit at the protection price (stop_market) or at price (stop_limit).
| Name | Type | Description |
|---|---|---|
params.trigger_source | stringdefault touch | touch (the side that would fill), mid or last. |
params.protection | decimal | stop_market only: the worst YES price the child may fill at. Defaults to the stop plus max_slippage. |
params.max_slippage | decimal | How far past the stop the protection price sits when protection is not given. |
Trailing stop: trailing_stop
A stop whose level follows the market one way and never back. Give stop_price as the starting level.
| Name | Type | Description |
|---|---|---|
params.trail | decimal | Distance the stop keeps behind the best price, in price. |
params.trail_percent | decimal | The same, as a fraction of the price. One of the two. |
params.trigger_source, params.protection, params.max_slippage | | As for a stop. |
Iceberg: iceberg
Shows one slice of the order at price; when it fills, the next slice is placed at the back of the queue, until amount is done.
| Name | Type | Description |
|---|---|---|
params.display | decimal | Contracts visible at a time. |
params.reload_delay_s | numberdefault 0 | Seconds to wait before the next slice. |
params.jitter_s | numberdefault 0 | Random extra delay, so the reload is not a clock. |
params.follow | booleandefault false | Re-price each slice to the current touch instead of the fixed price. |
One cancels the other: oco
Two legs; when one fills, the other is cancelled, and a partial fill on one resizes the other.
| Name | Type | Description |
|---|---|---|
params.legs | array | Exactly two order specifications, each with side, type, price and optionally market_id, amount, stop_price. A leg inherits the parent's market and size where it says nothing. |
Bracket: bracket
An entry, then a take-profit and a stop-loss that protect whatever the entry fills, sized to the fill as it arrives.
| Name | Type | Description |
|---|---|---|
params.entry | object | The entry order: type, price. |
params.take_profit | object | price for the profit-taking limit on the opposite side. |
params.stop_loss | object | stop_price and optionally price for the protective stop. |
TWAP: twap
Slices amount evenly across a window by the clock, patient or aggressive.
| Name | Type | Description |
|---|---|---|
params.window_s | number | Seconds the whole order is spread over. |
params.slices | integer | How many child orders. |
params.style | stringdefault limit | limit rests each slice at limit; taker crosses with each slice. |
params.limit | decimal | The YES price limit for every slice. Defaults to price. |
params.finish | stringdefault complete | At the end of the window: complete takes what is left, stop gives up on it. |
Peg: peg
Rests one child at the touch and re-pegs it as the book moves, with a minimum stay and a cap on how far it chases.
| Name | Type | Description |
|---|---|---|
params.reference | stringdefault near | near pegs to your own side of the book, far to the other side, mid between them. |
params.offset | decimaldefault 0 | Price added to the reference, in the direction that improves it. |
params.min_stay_s | numberdefault 0 | Seconds a child rests before it may be re-pegged. |
params.level_cap | integer | Never chase more than this many levels from where the peg started. |
params.min_price, params.max_price | decimal | The worst YES price the peg may rest at, on a sell and a buy. |
Smart taker: smart_taker
Takes liquidity in clips over time, inside a price bound, so a large order does not walk the book at once.
| Name | Type | Description |
|---|---|---|
params.clip | decimal | Contracts per clip. Defaults to the whole amount. |
params.interval_s | numberdefault 1 | Seconds between clips. |
params.limit | decimal | The worst YES price any clip may fill at. |
params.max_slippage | decimal | The same, as a distance from the touch when the order starts. |
params.expires_s | number | Give up after this many seconds. |
Response
The parent order, held_by: "engine", status waiting. Status 201.
from synpath import Client, OrderRequest, OrderType
client = Client(server="http://127.0.0.1:8000") # your self-hosted server (synpath serve)
parent = await client.create_order(OrderRequest(
market_id="polymarket:2252244", side="sell", amount=20,
type=OrderType.TRAILING_STOP, stop_price="0.40",
params={"trail": "0.03", "trigger_source": "touch"}, book="alpha",
))
print(parent.status) # waiting{
"id": "mo-3f9a",
"client_order_id": "quickstart-1",
"venue": "kalshi",
"account": {
"venue": "kalshi",
"name": "desk-a",
"subaccount": null
},
"market_id": "kalshi:KXELONMARS-99",
"side": "sell",
"type": "trailing_stop",
"time_in_force": "gtc",
"status": "waiting",
"held_by": "engine",
"price": null,
"stop_price": "0.40",
"amount": "20",
"filled": "0",
"remaining": "5",
"average_price": null,
"cost": null,
"fee": null,
"fee_currency": "USD",
"last_fill_price": null,
"last_fill_amount": null,
"post_only": false,
"reduce_only": false,
"expires_at": null,
"created_at": 1789655008000,
"updated_at": 1789655008000,
"parent_id": null,
"queue_priority_preserved": null,
"book": "alpha",
"trader": "tester",
"tags": {},
"info": {}
}
