1. Connection

๐Ÿ”Œ Endpoint
ws://[host]:18181 โ€” The ttTrader core runs a built-in WebSocket server on port 18181. In production, proxy through your web server (nginx) or connect directly when on the same machine. The server sends JSON messages only. No binary frames.
๐Ÿ”—

Transport

Standard WebSocket (RFC 6455). No Socket.IO, no custom framing. Native browser WebSocket works directly.

๐Ÿ“ฆ

Message Format

Every message is a JSON object with a single-key envelope. The key is the message section; the value is the payload object. Multiple sections are sent as separate messages.

๐Ÿ”„

Reconnection

Implement exponential backoff. On reconnect, the server sends a fresh full snapshot. Disconnects under 60s: positions/orders preserved. Over 60s: full state reset.

// Minimal WebSocket connection const ws = new WebSocket("ws://localhost:18181"); ws.onopen = () => console.log("Connected to ttTrader"); ws.onmessage = (event) => { const msg = JSON.parse(event.data); // msg is a single-key envelope: {"snap": {...}} or {"order": {...}} etc. const [section, payload] = Object.entries(msg)[0]; switch (section) { case "snap": handleSnapshot(payload); break; case "order": handleOrder(payload); break; case "fills": handleFill(payload); break; case "exchg": handleExchange(payload); break; case "instr": handleInstrument(payload);break; case "pb": handlePlayback(payload); break; } };

2. Snapshot (On Connect)

Immediately after the WebSocket handshake, the server sends a complete state snapshot as {"snap": {...}}. This contains every piece of state the frontend needs.

Key Type Content
nextSeq uint64 Sequence number of the next real-time message
states object Execution mode (production/simulation/playback), uptime
algos array All loaded algos: id, name, status (RUNNING/STOPPED/HALTED)
exchanges array All connected exchanges: name, status, stream health
acct array Account balances: currency, spot, margin, equity, PnL
instruments array All subscribed instruments: symbol, exchange, price/size precision, fees, leverage limits
trades array Recent trades per instrument: price, size, CVD, taker direction
quotes array Latest BBO per instrument: bid/ask price and size, spread
orders array All active orders with full state
fills array Recent execution reports (fills)
positions array All open positions with long/short leg details
playbackFiles array Available .ttpb files: id, name, size, date range, instruments
playback object Current playback state (only if active)
recording object Current recording state (only if active)
โš ๏ธ Sequence Tracking
Every message after the snapshot carries a seq field. Track the expected sequence. If a gap is detected (received seq > expected seq + 1), trigger a reconnect to get a fresh snapshot. This ensures no market data or order updates are missed.

3. Real-Time Streams

After the snapshot, the server pushes incremental updates on a 200ms flush interval. Each message is a single-key envelope: {"section": payload}.

๐Ÿ“Š

Quote Updates

Section: "snap" (same key as snapshot, with delta payload)

Sub-key Content
quotes Array of BBO updates: symbol, exchg, bid, bidSize, ask, askSize, timestamp, receiveTimestamp
trades Array of trades: symbol, exchg, last (price), lastSize, isSell, timestamp
instruments New or updated instrument definitions
exchanges Exchange state changes (connected/disconnected)
algos Algo status transitions
acct Account balance changes
recUpdate Recording progress (every ~1s during recording)
pbUpdate Playback progress (every ~1s during playback)
๐Ÿ“

Order & Fill Events

Sent immediately โ€” not batched on the 200ms timer.

Section Trigger
"order" Order created, modified, cancelled, or state changed
"fills" Execution (fill) occurred โ€” includes execution, parent order, and position
โšก 200ms Flush Cadence
Market data updates (quotes, trades, instruments, exchanges, account) are batched and sent every 200ms. This balances real-time responsiveness with message efficiency. Order and fill events are sent immediately โ€” they skip the batch timer.

4. Data Schemas (v3)

Order Object

Field Key Type Req Description
ID id uint32 โœ” Unique order identifier
Revision rev uint32 Revision counter for modification tracking
Instrument iid string โœ” Instrument ID (resolves to symbol+exchange via instrument map)
Side sd enum โœ” 1=BUY, 2=BUY_OPEN_LONG, 3=BUY_CLOSE_SHORT, 4=SELL, 5=SELL_OPEN_SHORT, 6=SELL_CLOSE_LONG
State st enum โœ” 1=IDLE, 2=ACTIVE, 3=FILLED, 4=FAILED, 5=DELETED, 6=CANCELED
Type tp enum 1=MARKET, 2=LIMIT, 3=STOP_MARKET, 4=STOP_LIMIT
Size sz string โœ” Total order size (string for decimal precision)
Size Left sl string Remaining unfilled size
Limit Price lm string Limit price (for limit/stop-limit orders)
Trigger tr string Stop trigger price
Triggered trig bool Whether the stop has been triggered
Location loc enum 1=LOCAL, 2=BROKER, 3=EXCHANGE
Notes nt string Human-readable order description
Algo ID aid string Algorithm that created this order
Created tcr uint64 โœ” Creation timestamp (epoch ms)
Updated tup uint64 โœ” Last update timestamp (epoch ms)

Position Object

Field Key Type Req Description
ID id uint64 โœ” Unique position identifier
Instrument iid string โœ” Instrument ID reference
Direction sd enum โœ” 1=LONG, 2=SHORT
Long Leg long object โœ” {sz, val, px, fee, cnt} โ€” size, value, avg price, fee, execution count
Short Leg short object โœ” {sz, val, px, fee, cnt} โ€” same structure
Realized PnL rpnl string โœ” Realized profit/loss
Fees fees string Total fees
Currency ccy string Settlement currency
Algo ID aid number Algorithm that owns this position
Notes nt string Position description
Opened top uint64 Position open timestamp (epoch ms)
Updated tup uint64 โœ” Last update timestamp (epoch ms)
Closed tcl uint64 Close timestamp โ€” MUST be sent when size reaches 0

Execution Report (Fill)

Field Key Type Req Description
Execution ID id string โœ” Unique execution identifier
Instrument iid string โœ” Instrument ID
Side sd enum โœ” Order direction
Size sz string โœ” Filled size
Price px string โœ” Fill price
Value val string โœ” Notional value (size ร— price)
Fee fee string โœ” Fee amount
Fee Currency feeCcy string โœ” Fee currency
Timestamp ts uint64 โœ” Fill timestamp (epoch ms)
Parent Order order object Full order object (partial update)
Position pos object Full position object after fill

Instrument Object

Field Key Type Req Description
ID id string โœ” Canonical instrument identifier
Symbol sym string โœ” Trading symbol (e.g., "BTCF0:USTF0")
Exchange ID eid string โœ” Exchange module identifier
Base base string Base currency
Quote quote string Quote currency
Type type enum Instrument type (spot, perpetual, future, option)
Price Delta pxDelta string Minimum price increment
Size Delta szDelta string Minimum size increment
Min Size szMin string Minimum order size
Max Size szMax string Maximum order size
Contract Size szCtr string Contract multiplier
Maker Fee feeMaker string Maker fee rate
Taker Fee feeTaker string Taker fee rate
Min Leverage levMin string Minimum leverage (derivatives only)
Max Leverage levMax string Maximum leverage
Lev Step levDelta string Leverage step increment
Active active bool Whether the instrument is currently trading

5. Client Commands

The WebSocket connection is bidirectional. Send JSON commands to control playback and recording. All commands follow the format {"t": "section", "action": "verb", ...params}.

Playback Controls

Command Params Description
{"t":"pb","action":"load","id":123} id: file ID from playbackFiles Load a .ttpb file for playback
{"t":"pb","action":"play"} โ€” Start or resume playback
{"t":"pb","action":"pause"} โ€” Pause playback
{"t":"pb","action":"stop"} โ€” Stop playback and unload file
{"t":"pb","action":"seek","position":5000} position: target position in file Jump to a specific position
{"t":"pb","action":"setSpeed","speed":10} speed: 1, 10, 100, 1000, or 0 (MAX) Change replay speed multiplier

Recording Controls

Command Params Description
{"t":"rec","action":"start"} file (optional): custom filename Start recording market data to .ttpb
{"t":"rec","action":"stop"} โ€” Stop recording

Risk Actions (v3 Extension)

Command Params Description
{"t":"risk","action":"reduce-only"} โ€” Set all algos to reduce-only mode
{"t":"risk","action":"cancel-all"} โ€” Cancel all open orders across all algos
{"t":"risk","action":"flatten-all"} โ€” Close all positions (market orders)

6. Implementation Guide

1
Connect to ws://host:18181
โ†’
2
Parse snapshot โ€” build local state from all sections
โ†’
3
Track sequence โ€” detect gaps, reconnect if needed
โ†’
4
Merge deltas โ€” apply incremental updates to local state
โ†’
5
Send commands โ€” playback, recording, risk actions
๐Ÿ“

Design Principles

1
Single source of truth
Build one canonical data structure per entity. Never derive values from multiple sources.
2
Strict parsing
Every field has exactly one canonical key. Reject unknown keys. Throw on missing mandatory fields.
3
Immutable terminal states
FILLED/CANCELED/FAILED orders are frozen. Subsequent updates for terminal orders are dropped.
4
Defined-fields-only merge
When updating an existing entity, only apply keys with !== undefined. Snapshot-only fields are preserved.
โš ๏ธ

Common Pitfalls

โœ—
Don't fabricate data
Never default missing PnL to 0. Never invent exchange names from instrument data. If the BE doesn't send it, throw.
โœ—
Don't alias keys
Never chain exchg || exchange. Each field has one canonical key. Alternative keys are contract violations.
โœ—
Don't derive positions from executions
The BE sends atomic execution reports with embedded position state. Use that โ€” don't compute positions from fills.
โœ—
Don't skip sequence checks
Sequence gaps mean lost messages. A quiet reconnect is always safer than silently corrupt state.
๐Ÿ”— Reference Implementation
The official ttTrader Dashboard (ttTraderDash) is a React + TypeScript implementation of this protocol. It serves as the reference frontend. Key modules: src/services/websocket.ts (connection + normalizers), src/types/trading.ts (TypeScript type definitions mirroring the v3 schema), src/utils/strictRecord.ts (strict single-key parser).