Data Streaming API
Overview
The market data streaming API uses the MQTT protocol for data pushing with Version 3.1.1. The MQTT protocol requires an underlying transport that provides an ordered, lossless, stream of bytes from the client to server and server to client. Webull provides TCP/IP and WebSocket transport protocols currently. By using this API, you can receive the most up to date market information via data streaming, that could help your trading strategy to act upon certain market movements.
Supported markets and categories:
| Market | Data Category |
|---|---|
| United States | Stocks, ETFs |
| Hong Kong | Stocks, ETFs |
| Mainland China | Stocks |
Supported data types:
| Data Type | Description |
|---|---|
| QUOTE | Real-time order book |
| SNAPSHOT | Market snapshot |
| TICK | Transaction details |
The following will introduce how to use the market data streaming API without using Webull SDK.
If you wish to simplify the process of obtaining real-time market data, you can utilize the SDK provided by Webull. Refer to the SDK User Guide and the Example for Retrieving Real-Time Quote Push.
Steps to Use the Market Data Streaming API
Establish Connection
MQTT Open Source Client Libraries:
Connection Endpoint:
-
Production Environment
// TCP/IP protocol:
data-api.webull.hk:1883
// Websocket protocol:
wss://data-api.webull.hk:8883/mqtt -
Sandbox Environment
// TCP/IP protocol:
data-api.sandbox.webull.hk:1883
// Websocket protocol:
wss://data-api.sandbox.webull.hk:8883/mqtt
Since MQTT protocol need a unique Client Identifier(ClientId) for each connection, Please create a session_id
as the ClientId of MQTT CONNECT Packet, and it will also be used in subsequent Market Data Streaming
Subscription/Unsubscription operations.
Please DON'T use the same session_id to
establish multiple connections under a single App Key. If you attempt to connect using same session_id, the
previous connection will be disconnected, and the new connection will replace the previous one.
If an App Key needs to establish multiple connections, please use different session_id for each connection. Also note that a single App Key can establish a maximum of 5 connections. If exceed, the server will return an error
code of 105 when attempting to establish a new connection.
After a connection is closed, the server will retain the connection state information for about 1 minute. If client
disconnect and immediately try to reconnect after having established 5 connections, the client may receive error code
of 105. In this case, please wait for 1 minute before attempting to reconnect.
After a network connection is established by a client to the server, the first packet sent from the client to the server should be a CONNECT packet. The CONNECT packet should contains these fields and values:
If a well formed CONNECT packet is received by the server, but the server is unable to process it for some reason, then the server attempt to send a CONNACK packet containing the non-zero connect return code from this table:
| Return Code | Description |
|---|---|
| 0 | Connection accepted |
| 1 | Connection Refused, unacceptable protocol |
| 2 | Connection Refused, invalid ClientId |
| 3 | App Key is empty |
| 7 | Connection lost |
| 16 | Heartbeat timeout |
| 100 | Unknown error |
| 101 | Internal error |
| 102 | Connection already authenticated |
| 103 | Connection authentication failed |
| 104 | Invalid App Key |
| 105 | Exceeds connections limit |
Subscription/Unsubscription
After successfully establishing an MQTT connection, client should use the HTTP API to subscribe to or unsubscribe the real-time market data. Only after a successful subscription will the server start pushing real-time market data to client.
The connection between the client and server may be passively disconnected due to network issues. After reconnecting, previous market data subscriptions will NOT be automatically restored. Client need to use the subscription API again in order to resume data streaming.
Parse Messages
After a successful subscription request, the data callback method of the MQTT client will be triggered. The data packet pushed from server contains two parts:
- Topic: Identifies which type of the data is pushed.
- Payload: The real-time data that is being pushing.
The data of Payload was serialized using Protocol Buffers protocol or JSON format. Please parse the Payload based on the Topic.
The Payload corresponding to the Topic is as follows:
| Data type | Topic | Protocol | Description |
|---|---|---|---|
| QUOTE | quote | Real-time Order Book Proto | Real-time Order Book |
| SNAPSHOT | snapshot | Quote Snapshot Proto | Quote Snapshot |
| TICK | tick | Tick-by-Tick Detail Proto | Tick-by-Tick Detail |
| NOTICE | notice | Notification JSON | Notification data sent from server to client, used for the server to send notifications to the client |
| ECHO | echo | Null Packet | Null Packet sent from server to client, used to verify if the client is online |
Payload data format definition
Basic Proto
message Basic {
string symbol = 1;
string instrument_id = 2;
string timestamp = 3;
}
Real-time Order Book Proto
message Quote {
Basic basic = 1;
repeated AskBid asks = 2;
repeated AskBid bids = 3;
}
message AskBid {
string price = 1;
string size = 2;
repeated Order order = 3;
repeated Broker broker = 4;
}
message Order {
string mpid = 1;
string size = 2;
}
message Broker {
string bid = 1;
string name = 2;
}
Market Snapshot Proto
message Snapshot {
Basic basic = 1;
string trade_time = 2;
string price = 3;
string open = 4;
string high = 5;
string low = 6;
string pre_close = 7;
string volume = 8;
string change = 9;
string change_ratio = 10;
}
Tick-by-Tick Detail Proto
message Tick {
Basic basic = 1;
string time = 2;
string price = 3;
string volume = 4;
string side = 5;
}
Notification JSON
// Status Notification
{
"type": "status", // Notification type
"rtt": 100, // RTT to server
"drop": 0, // Number of packets dropped by server
"sent": 0, // Number of packets sent by server
}