Skip to main content

Strategy Status Stream

Real-time WebSocket stream of strategy lifecycle events: deployments, pauses, position open/close, order placement and fills, and unrecoverable errors. Use this stream to drive dashboards, audit logs, or downstream automation.

Subscription

After connecting, send a subscribe frame referencing one or more strategy IDs:

{ "op": "subscribe", "channel": "strategy.status", "id": "strat_8f2a1b" }

To receive events for every strategy on the account, subscribe with the wildcard:

{ "op": "subscribe", "channel": "strategy.status", "id": "*" }

Unsubscribe with the symmetric frame:

{ "op": "unsubscribe", "channel": "strategy.status", "id": "strat_8f2a1b" }

The server replies with an ack:

{ "op": "ack", "channel": "strategy.status", "id": "strat_8f2a1b", "ok": true }

Authentication

WebSocket connections must be authenticated using the same HMAC-SHA256 scheme as REST. You may either:

  1. Sign the connection URL — pass api_key, timestamp, and signature as query-string parameters where the canonical string is timestamp + "GET" + path. Example: wss://stream.pipai.example/v1/ws?api_key=...&timestamp=...&signature=....
  2. Send an auth frame as the first message after connecting:
    { "op": "auth", "api_key": "...", "timestamp": 1761739200000, "signature": "..." }

Connections that do not authenticate within 5 seconds are closed. See Authentication for the full signing scheme.

Event types

EventWhen it fires
deployedStrategy transitioned to deployed.
pausedStrategy transitioned to paused.
position_openedA new position was opened by the strategy.
position_closedA position was closed (by exit rule, manual pause-with-close, or stop-loss).
order_placedAn order was submitted to the exchange.
order_filledAn order was fully or partially filled.
order_cancelledAn order was cancelled by the engine or the exchange.
errorThe engine halted with an unrecoverable error. The strategy transitions to error.

Payload schema

Every event uses the same envelope:

{
"channel": "strategy.status",
"event": "position_opened",
"strategy_id": "strat_8f2a1b",
"seq": 12483,
"ts": "2026-04-29T12:00:00.000Z",
"data": { }
}
Envelope fieldTypeDescription
channelstringAlways "strategy.status".
eventstringOne of the event types above.
strategy_idstringStrategy that emitted the event.
seqintegerMonotonically increasing per-channel sequence number. Use to detect gaps and to resume after reconnect.
tsstringISO 8601 UTC timestamp with millisecond precision.
dataobjectEvent-specific payload, schema below.

position_opened

{
"channel": "strategy.status",
"event": "position_opened",
"strategy_id": "strat_8f2a1b",
"seq": 12483,
"ts": "2026-04-29T12:00:00.000Z",
"data": {
"position_id": "pos_4ab9c0",
"symbol": "BTCUSDT",
"side": "long",
"entry_price": "67234.50",
"quantity": "0.0150",
"leverage": 3,
"notional": "1008.52"
}
}

position_closed

{
"channel": "strategy.status",
"event": "position_closed",
"strategy_id": "strat_8f2a1b",
"seq": 12519,
"ts": "2026-04-29T13:42:11.250Z",
"data": {
"position_id": "pos_4ab9c0",
"symbol": "BTCUSDT",
"side": "long",
"entry_price": "67234.50",
"exit_price": "67890.10",
"quantity": "0.0150",
"realized_pnl": "9.83",
"reason": "exit_rule"
}
}

reason is one of exit_rule, stop_loss, take_profit, manual_pause_close, liquidation.

order_filled

{
"channel": "strategy.status",
"event": "order_filled",
"strategy_id": "strat_8f2a1b",
"seq": 12491,
"ts": "2026-04-29T12:00:00.412Z",
"data": {
"order_id": "ord_77e2b1",
"position_id": "pos_4ab9c0",
"symbol": "BTCUSDT",
"side": "buy",
"type": "limit",
"price": "67234.50",
"quantity": "0.0150",
"filled_quantity": "0.0150",
"fee": "0.5039",
"fee_currency": "USDT"
}
}

Partial fills emit one event per fill; filled_quantity is cumulative on the order.

error

{
"channel": "strategy.status",
"event": "error",
"strategy_id": "strat_8f2a1b",
"seq": 12604,
"ts": "2026-04-29T14:05:33.001Z",
"data": {
"code": "EXCHANGE_AUTH_FAILED",
"message": "Exchange API key rejected by Binance",
"fatal": true
}
}

When fatal is true, the strategy has transitioned to error status and will not recover automatically — investigate, fix, and redeploy. Non-fatal errors are emitted for visibility but do not change strategy status.

Reconnection

Connections may drop for a variety of reasons (network, server maintenance, idle timeout). Clients should reconnect with exponential backoff:

  • Start with a 1 s delay.
  • Double on each consecutive failure, jittered by ±25%.
  • Cap at 30 s.
  • Reset to 1 s after a successful connection that stays up for 60 s.

To resume without gaps, include the last received seq in the subscribe frame:

{ "op": "subscribe", "channel": "strategy.status", "id": "strat_8f2a1b", "since_seq": 12483 }

The server replays buffered events with seq > since_seq. Replay is best-effort: events are buffered for up to 5 minutes. If since_seq is older than the buffer, the server responds with { "op": "ack", "ok": false, "code": "REPLAY_UNAVAILABLE" } and you should reconcile state via Get Strategy.