Documentation Index
Fetch the complete documentation index at: https://docs.ekiden.fi/llms.txt
Use this file to discover all available pages before exploring further.
Overview
- Bracket (TP/SL): Attach Take Profit and/or Stop Loss to an entry or position. The legs form an OCO group (one-cancels-the-other).
- Modes:
- FULL: Bracket attaches at the position level for the full absolute position size; legs are reduce-only and typically execute IOC.
- PARTIAL: Bracket attaches per fill of an entry order. Each taker/maker fill creates its own OCO legs sized to that fill; any resting remainder can later create legs when filled as maker.
- Trigger: Each leg specifies a
trigger_price and a direction is derived from the side and price relation. Activation occurs on boundary equality.
- Reduce-only: Triggered legs never increase exposure. Size is clamped to the current position size; if no exposure to reduce, the leg is acknowledged and OCO is cancelled or re-armed.
- Slippage guard: MARKET-type legs are converted to LIMIT IOC with a guard band (
SLIPPAGE_GUARD_BPS, default 200 bps = 2%) anchored to the trigger or current mark.
Request shape (order_create)
{
"payload": {
"type": "order_create",
"orders": [
{
"market_addr": "0x...",
"side": "buy",
"price": 100000000000,
"size": 100000000, // base units (scaled)
"leverage": 10,
"type": "limit",
"is_cross": false,
"time_in_force": "GTC",
"bracket": {
"mode": "FULL", // or "PARTIAL"
"take_profit": { // optional
"trigger_price": 105000000000,
"order_type": "MARKET" // or "LIMIT"
// "limit_price": 105000000000 // required when order_type == LIMIT
},
"stop_loss": { // optional
"trigger_price": 98000000000,
"order_type": "LIMIT",
"limit_price": 98000000000
}
},
// Optional conditional entry (independent of bracket):
// "trigger_price": 100000000000,
// Optional reduce-only entry:
// "reduce_only": true
}
]
},
"nonce": 1,
"signature": "0x..."
}
Behavior details
- OCO lifecycle
- When one leg executes, its sibling is cancelled by the trigger service upon acknowledgement.
- Equality activates: Up-leg triggers when mark crosses up to
trigger_price; Down-leg triggers when mark crosses down to trigger_price.
- FULL mode
- Bracket legs resize as the position size changes; cancelling/closing the position cancels the OCO group.
- Legs are executed as reduce-only IOC. MARKET legs are converted to LIMIT IOC with guard:
guard_price = trigger_price ± (trigger_price * GUARD_BPS / 10_000).
- PARTIAL mode
- Each fill (taker or maker) creates a distinct OCO group sized to that fill. All trigger IDs are unique across fills.
- Reduce-only clamping
- If current position size is smaller than the leg size, execution clamps to the closable amount. If zero, the service cancels the group (or re-arms based on exposure).
Environment and guard configuration
- Env var:
SLIPPAGE_GUARD_BPS (default 200 = 2%).
Examples
- Attach FULL bracket to a BUY entry:
{
"mode": "FULL",
"take_profit": { "trigger_price": 105000000000, "order_type": "MARKET" },
"stop_loss": { "trigger_price": 98000000000, "order_type": "LIMIT", "limit_price": 98000000000 }
}
- Attach PARTIAL bracket to a BUY LIMIT entry:
{
"mode": "PARTIAL",
"take_profit": { "trigger_price": 110000000000, "order_type": "LIMIT", "limit_price": 110000000000 },
"stop_loss": { "trigger_price": 95000000000, "order_type": "MARKET" }
}
Notes and constraints
- For LIMIT legs,
limit_price is required; invalid legs are ignored.
- Triggered orders use
time_in_force: IOC.
- All prices and sizes are scaled integers; see market
base_decimals and quote_decimals.
WebSocket examples
- When a TP/SL leg executes, you will receive standard
fill and order events on the private stream.
Order update (reduce-only IOC leg placed/cancelled/filled):
{
"op": "event",
"topic": "order",
"data": [
{
"sid": "0xordLeg...",
"side": "sell",
"size": 100000000,
"price": 105000000000,
"leverage": 10,
"initial_margin": null,
"type": "limit",
"status": "filled",
"user_addr": "0xuser...",
"market_addr": "0xmarket...",
"is_cross": false,
"seq": 1234,
"timestamp": 1718000000,
"timestamp_ms": 1718000000000
}
]
}
Fill event generated by the leg execution:
{
"op": "event",
"topic": "fill",
"data": [
{
"sid": "0xfill...",
"side": "sell",
"size": 100000000,
"price": 105000000000,
"maker_fee": 0,
"taker_fee": 0,
"taker_order_sid": "0xordLeg...",
"taker_addr": "0xuser...",
"maker_order_sid": "0xordMaker...",
"maker_addr": "0xother...",
"market_addr": "0xmarket...",
"seq": 1234,
"maker_leverage": 10,
"taker_leverage": 10,
"maker_is_cross": false,
"taker_is_cross": false,
"timestamp": 1718000000,
"timestamp_ms": 1718000000000
}
]
}
Position update reflecting reduced size:
{
"op": "event",
"topic": "position",
"data": [
{
"sid": "0xpos...",
"market_addr": "0xmarket...",
"user_addr": "0xuser...",
"size": 0,
"price": 100000000000,
"entry_price": 100000000000,
"margin": 5000000000,
"funding_index": 0,
"epoch": 42,
"is_cross": false,
"initial_margin": 0,
"initial_margin_mark": 0,
"maintenance_margin": 0,
"leverage": null,
"mark_price": 105000000000,
"seq": 1234,
"timestamp": 1718000000,
"timestamp_ms": 1718000000000,
"side": "buy",
"unrealized_pnl": 0,
"liq_price": null
}
]
}