Skip to content

WebSocket Market Data

Overview

  • The baseurl for websocket is wss://fstream.asterdex.com
  • Streams can be access either in a single raw stream or a combined stream
  • Raw streams are accessed at /ws/\<streamName>
  • Combined streams are accessed at /stream?streams=\<streamName1>/\<streamName2>/\<streamName3>
  • Combined stream events are wrapped as follows: {"stream":"\<streamName>","data":\<rawPayload>}
  • All symbols for streams are lowercase
  • A single connection is only valid for 24 hours; expect to be disconnected at the 24 hour mark
  • The websocket server will send a ping frame every 5 minutes. If the websocket server does not receive a pong frame back from the connection within a 15 minute period, the connection will be disconnected. Unsolicited pong frames are allowed.
  • WebSocket connections have a limit of 10 incoming messages per second.
  • A connection that goes beyond the limit will be disconnected; IPs that are repeatedly disconnected may be banned.
  • A single connection can listen to a maximum of 200 streams.
  • Considering the possible data latency from RESTful endpoints during an extremely volatile market, it is highly recommended to get the order status, position, etc from the Websocket user data stream.

Live Subscribing/Unsubscribing to streams

  • The following data can be sent through the websocket instance in order to subscribe/unsubscribe from streams. Examples can be seen below.
  • The id used in the JSON payloads is an unsigned INT used as an identifier to uniquely identify the messages going back and forth.

Subscribe to a stream

Response

{
  "result": null,
  "id": 1
}
  • Request

    {
    "method": "SUBSCRIBE",
    "params":
    [
    "btcusdt@aggTrade",
    "btcusdt@depth"
    ],
    "id": 1
    }

Unsubscribe to a stream

Response

{
  "result": null,
  "id": 312
}
  • Request

{
"method": "UNSUBSCRIBE",
"params":
[
"btcusdt@depth"
],
"id": 312
}

Listing Subscriptions

Response

{
  "result": [
    "btcusdt@aggTrade"
  ],
  "id": 3
}
  • Request

{
"method": "LIST_SUBSCRIPTIONS",
"id": 3
}

Setting Properties

Currently, the only property can be set is to set whether combined stream payloads are enabled are not. The combined property is set to false when connecting using /ws/ ("raw streams") and true when connecting using /stream/.

Response

{
  "result": null,
  "id": 5
}
  • Request

{
"method": "SET_PROPERTY",
"params":
[
"combined",
true
],
"id": 5
}

Retrieving Properties

Response

{
  "result": true, // Indicates that combined is set to true.
  "id": 2
}
  • Request

{
"method": "GET_PROPERTY",
"params":
[
"combined"
],
"id": 2
}

Error Messages

Error Message Description
{"code": 0, "msg": "Unknown property"} Parameter used in the SET_PROPERTY or GET_PROPERTY was invalid
{"code": 1, "msg": "Invalid value type: expected Boolean"} Value should only be true or false
{"code": 2, "msg": "Invalid request: property name must be a string"} Property name provided was invalid
{"code": 2, "msg": "Invalid request: request ID must be an unsigned integer"} Parameter id had to be provided or the value provided in the id parameter is an unsupported type
{"code": 2, "msg": "Invalid request: unknown variant %s, expected one of SUBSCRIBE, UNSUBSCRIBE, LIST_SUBSCRIPTIONS, SET_PROPERTY, GET_PROPERTY at line 1 column 28"} Possible typo in the provided method or provided method was neither of the expected values
{"code": 2, "msg": "Invalid request: too many parameters"} Unnecessary parameters provided in the data
{"code": 2, "msg": "Invalid request: property name must be a string"} Property name was not provided
{"code": 2, "msg": "Invalid request: missing field method at line 1 column 73"} method was not provided in the data
{"code":3,"msg":"Invalid JSON: expected value at line %s column %s"} JSON data sent has incorrect syntax.

Aggregate Trade Streams

Payload:

{
  "e": "aggTrade",  // Event type
  "E": 123456789,   // Event time
  "s": "BTCUSDT",    // Symbol
  "a": 5933014,     // Aggregate trade ID
  "p": "0.001",     // Price
  "q": "100",       // Quantity
  "f": 100,         // First trade ID
  "l": 105,         // Last trade ID
  "T": 123456785,   // Trade time
  "m": true,        // Is the buyer the market maker?
}

The Aggregate Trade Streams push market trade information that is aggregated for a single taker order every 100 milliseconds.

Stream Name:
<symbol>@aggTrade

Update Speed: 100ms

  • Only market trades will be aggregated, which means the insurance fund trades and ADL trades won't be aggregated.

Mark Price Stream

Payload:

  {
    "e": "markPriceUpdate",     // Event type
    "E": 1562305380000,         // Event time
    "s": "BTCUSDT",             // Symbol
    "p": "11794.15000000",      // Mark price
    "i": "11784.62659091",      // Index price
    "P": "11784.25641265",      // Estimated Settle Price, only useful in the last hour before the settlement starts
    "r": "0.00038167",          // Funding rate
    "T": 1562306400000          // Next funding time
  }

Mark price and funding rate for a single symbol pushed every 3 seconds or every second.

Stream Name:
<symbol>@markPrice or <symbol>@markPrice@1s

Update Speed: 3000ms or 1000ms

Mark Price Stream for All market

Payload:

[ 
  {
    "e": "markPriceUpdate",     // Event type
    "E": 1562305380000,         // Event time
    "s": "BTCUSDT",             // Symbol
    "p": "11185.87786614",      // Mark price
    "i": "11784.62659091"       // Index price
    "P": "11784.25641265",      // Estimated Settle Price, only useful in the last hour before the settlement starts
    "r": "0.00030000",          // Funding rate
    "T": 1562306400000          // Next funding time
  }
]

Mark price and funding rate for all symbols pushed every 3 seconds or every second.

Stream Name:
!markPrice@arr or !markPrice@arr@1s

Update Speed: 3000ms or 1000ms

Kline/Candlestick Streams

Payload:

{
  "e": "kline",     // Event type
  "E": 123456789,   // Event time
  "s": "BTCUSDT",    // Symbol
  "k": {
    "t": 123400000, // Kline start time
    "T": 123460000, // Kline close time
    "s": "BTCUSDT",  // Symbol
    "i": "1m",      // Interval
    "f": 100,       // First trade ID
    "L": 200,       // Last trade ID
    "o": "0.0010",  // Open price
    "c": "0.0020",  // Close price
    "h": "0.0025",  // High price
    "l": "0.0015",  // Low price
    "v": "1000",    // Base asset volume
    "n": 100,       // Number of trades
    "x": false,     // Is this kline closed?
    "q": "1.0000",  // Quote asset volume
    "V": "500",     // Taker buy base asset volume
    "Q": "0.500",   // Taker buy quote asset volume
    "B": "123456"   // Ignore
  }
}

The Kline/Candlestick Stream push updates to the current klines/candlestick every 250 milliseconds (if existing).

Kline/Candlestick chart intervals:

m -> minutes; h -> hours; d -> days; w -> weeks; M -> months

  • 1m
  • 3m
  • 5m
  • 15m
  • 30m
  • 1h
  • 2h
  • 4h
  • 6h
  • 8h
  • 12h
  • 1d
  • 3d
  • 1w
  • 1M

Stream Name:
<symbol>@kline_<interval>

Update Speed: 250ms

Individual Symbol Mini Ticker Stream

Payload:

  {
    "e": "24hrMiniTicker",  // Event type
    "E": 123456789,         // Event time
    "s": "BTCUSDT",         // Symbol
    "c": "0.0025",          // Close price
    "o": "0.0010",          // Open price
    "h": "0.0025",          // High price
    "l": "0.0010",          // Low price
    "v": "10000",           // Total traded base asset volume
    "q": "18"               // Total traded quote asset volume
  }

24hr rolling window mini-ticker statistics for a single symbol. These are NOT the statistics of the UTC day, but a 24hr rolling window from requestTime to 24hrs before.

Stream Name:
<symbol>@miniTicker

Update Speed: 500ms

All Market Mini Tickers Stream

Payload:

[  
  {
    "e": "24hrMiniTicker",  // Event type
    "E": 123456789,         // Event time
    "s": "BTCUSDT",         // Symbol
    "c": "0.0025",          // Close price
    "o": "0.0010",          // Open price
    "h": "0.0025",          // High price
    "l": "0.0010",          // Low price
    "v": "10000",           // Total traded base asset volume
    "q": "18"               // Total traded quote asset volume
  }
]

24hr rolling window mini-ticker statistics for all symbols. These are NOT the statistics of the UTC day, but a 24hr rolling window from requestTime to 24hrs before. Note that only tickers that have changed will be present in the array.

Stream Name:
!miniTicker@arr

Update Speed: 1000ms

Individual Symbol Ticker Streams

Payload:

{
  "e": "24hrTicker",  // Event type
  "E": 123456789,     // Event time
  "s": "BTCUSDT",     // Symbol
  "p": "0.0015",      // Price change
  "P": "250.00",      // Price change percent
  "w": "0.0018",      // Weighted average price
  "c": "0.0025",      // Last price
  "Q": "10",          // Last quantity
  "o": "0.0010",      // Open price
  "h": "0.0025",      // High price
  "l": "0.0010",      // Low price
  "v": "10000",       // Total traded base asset volume
  "q": "18",          // Total traded quote asset volume
  "O": 0,             // Statistics open time
  "C": 86400000,      // Statistics close time
  "F": 0,             // First trade ID
  "L": 18150,         // Last trade Id
  "n": 18151          // Total number of trades
}

24hr rollwing window ticker statistics for a single symbol. These are NOT the statistics of the UTC day, but a 24hr rolling window from requestTime to 24hrs before.

Stream Name:
<symbol>@ticker

Update Speed: 500ms

All Market Tickers Streams

Payload:

[
    {
      "e": "24hrTicker",  // Event type
      "E": 123456789,     // Event time
      "s": "BTCUSDT",     // Symbol
      "p": "0.0015",      // Price change
      "P": "250.00",      // Price change percent
      "w": "0.0018",      // Weighted average price
      "c": "0.0025",      // Last price
      "Q": "10",          // Last quantity
      "o": "0.0010",      // Open price
      "h": "0.0025",      // High price
      "l": "0.0010",      // Low price
      "v": "10000",       // Total traded base asset volume
      "q": "18",          // Total traded quote asset volume
      "O": 0,             // Statistics open time
      "C": 86400000,      // Statistics close time
      "F": 0,             // First trade ID
      "L": 18150,         // Last trade Id
      "n": 18151          // Total number of trades
    }
]

24hr rollwing window ticker statistics for all symbols. These are NOT the statistics of the UTC day, but a 24hr rolling window from requestTime to 24hrs before. Note that only tickers that have changed will be present in the array.

Stream Name:
!ticker@arr

Update Speed: 1000ms

Individual Symbol Book Ticker Streams

Payload:

{
  "e":"bookTicker",         // event type
  "u":400900217,            // order book updateId
  "E": 1568014460893,       // event time
  "T": 1568014460891,       // transaction time
  "s":"BNBUSDT",            // symbol
  "b":"25.35190000",        // best bid price
  "B":"31.21000000",        // best bid qty
  "a":"25.36520000",        // best ask price
  "A":"40.66000000"         // best ask qty
}

Pushes any update to the best bid or ask's price or quantity in real-time for a specified symbol.

Stream Name: <symbol>@bookTicker

Update Speed: Real-time

All Book Tickers Stream

Payload:

{
  // Same as <symbol>@bookTicker payload
}

Pushes any update to the best bid or ask's price or quantity in real-time for all symbols.

Stream Name: !bookTicker

Update Speed: Real-time

Liquidation Order Streams

Payload:

{

    "e":"forceOrder",                   // Event Type
    "E":1568014460893,                  // Event Time
    "o":{

        "s":"BTCUSDT",                   // Symbol
        "S":"SELL",                      // Side
        "o":"LIMIT",                     // Order Type
        "f":"IOC",                       // Time in Force
        "q":"0.014",                     // Original Quantity
        "p":"9910",                      // Price
        "ap":"9910",                     // Average Price
        "X":"FILLED",                    // Order Status
        "l":"0.014",                     // Order Last Filled Quantity
        "z":"0.014",                     // Order Filled Accumulated Quantity
        "T":1568014460893,               // Order Trade Time

    }

}

The Liquidation Order Snapshot Streams push force liquidation order information for specific symbol.

For each symbol,only the latest one liquidation order within 1000ms will be pushed as the snapshot. If no liquidation happens in the interval of 1000ms, no stream will be pushed.

Stream Name:  <symbol>@forceOrder

Update Speed: 1000ms

All Market Liquidation Order Streams

Payload:

{

    "e":"forceOrder",                   // Event Type
    "E":1568014460893,                  // Event Time
    "o":{

        "s":"BTCUSDT",                   // Symbol
        "S":"SELL",                      // Side
        "o":"LIMIT",                     // Order Type
        "f":"IOC",                       // Time in Force
        "q":"0.014",                     // Original Quantity
        "p":"9910",                      // Price
        "ap":"9910",                     // Average Price
        "X":"FILLED",                    // Order Status
        "l":"0.014",                     // Order Last Filled Quantity
        "z":"0.014",                     // Order Filled Accumulated Quantity
        "T":1568014460893,               // Order Trade Time

    }

}

The All Liquidation Order Snapshot Streams push force liquidation order information for all symbols in the market.

For each symbol,only the latest one liquidation order within 1000ms will be pushed as the snapshot. If no liquidation happens in the interval of 1000ms, no stream will be pushed.

Stream Name: !forceOrder@arr

Update Speed: 1000ms

Partial Book Depth Streams

Payload:

{
  "e": "depthUpdate", // Event type
  "E": 1571889248277, // Event time
  "T": 1571889248276, // Transaction time
  "s": "BTCUSDT",
  "U": 390497796,
  "u": 390497878,
  "pu": 390497794,
  "b": [          // Bids to be updated
    [
      "7403.89",  // Price Level to be
      "0.002"     // Quantity
    ],
    [
      "7403.90",
      "3.906"
    ],
    [
      "7404.00",
      "1.428"
    ],
    [
      "7404.85",
      "5.239"
    ],
    [
      "7405.43",
      "2.562"
    ]
  ],
  "a": [          // Asks to be updated
    [
      "7405.96",  // Price level to be
      "3.340"     // Quantity
    ],
    [
      "7406.63",
      "4.525"
    ],
    [
      "7407.08",
      "2.475"
    ],
    [
      "7407.15",
      "4.800"
    ],
    [
      "7407.20",
      "0.175"
    ]
  ]
}

Top <levels> bids and asks, Valid <levels> are 5, 10, or 20.

Stream Names: <symbol>@depth<levels> OR <symbol>@depth<levels>@500ms OR <symbol>@depth<levels>@100ms.

Update Speed: 250ms, 500ms or 100ms

Diff. Book Depth Streams

Payload:

{
  "e": "depthUpdate", // Event type
  "E": 123456789,     // Event time
  "T": 123456788,     // Transaction time 
  "s": "BTCUSDT",     // Symbol
  "U": 157,           // First update ID in event
  "u": 160,           // Final update ID in event
  "pu": 149,          // Final update Id in last stream(ie `u` in last stream)
  "b": [              // Bids to be updated
    [
      "0.0024",       // Price level to be updated
      "10"            // Quantity
    ]
  ],
  "a": [              // Asks to be updated
    [
      "0.0026",       // Price level to be updated
      "100"          // Quantity
    ]
  ]
}

Bids and asks, pushed every 250 milliseconds, 500 milliseconds, 100 milliseconds (if existing)

Stream Name:
<symbol>@depth OR <symbol>@depth@500ms OR <symbol>@depth@100ms

Update Speed: 250ms, 500ms, 100ms

How to manage a local order book correctly

  1. Open a stream to wss://fstream.asterdex.com/stream?streams=btcusdt@depth.
  2. Buffer the events you receive from the stream. For same price, latest received update covers the previous one.
  3. Get a depth snapshot from https://fapi.asterdex.com/fapi/v1/depth?symbol=BTCUSDT&limit=1000 .
  4. Drop any event where u is < lastUpdateId in the snapshot.
  5. The first processed event should have U <= lastUpdateId AND u >= lastUpdateId
  6. While listening to the stream, each new event's pu should be equal to the previous event's u, otherwise initialize the process from step 3.
  7. The data in each event is the absolute quantity for a price level.
  8. If the quantity is 0, remove the price level.
  9. Receiving an event that removes a price level that is not in your local order book can happen and is normal.