Market Push Quotes
Webull provides a real-time quotes push service that supports TCP connection and Websocket, and currently supports real-time pushes of the following data types.
Types of data | Description |
---|---|
QUOTE | Order Book |
SNAPSHOT | Market Snapshot |
TICK | Tick-by-Tick |
It requires 4 steps to get push notifications on real-time quotes:
1. Get client token
2. Connect to Webull Quotes Push Service
3. Send real-time market subscription request
4. Monitor data response
1. Get client token
The authentication of the client's Token user to connect to the Webull market server, and the authentication to subscribe to the real-time quotes pushes. For the method of obtaining the client's Token, refer to Get Token.
2. Connect to Webull push services and send connection request
Webull's market push server is implemented using the MQTT protocol, and the client needs to use the MQTTv3.1.1 standard protocol to connect with the server to receive data.
You can refer to the standard MQTTv3.1.1 protocol to implement a private MQTT client, or you can use open source client libraries that support various programming languages to connect:
MQTTv3.1.1 protocol reference:
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
MQTT open source connection library:
Python: https://github.com/eclipse/paho.mqtt.python
Javascrpit: http://github.com/eclipse/paho.mqtt.javascript
Other more programming languages: https://mqtt.org/software/
After preparing the MQTT client, connect through the following address:
Webull push service related information:
TCP Server Host: quotes-api.webull.hk:8883
Note: Please use TLS connection
When using the MQTT client to connect to the Webull Quotes Server, please use the connection Token obtained in the first step as user_name and password.
After successfully connecting to the Webull Quotes Server, you will receive a successful connection data packet back. If you are using an open source MQTT client, the callback method for successful connection will be called.
3. Send request for subscription/unsubscription
After successfully connecting to the Webull Quotes Server, please use the subscribe/unsubscribe HTTP interface to subscribe and unsubscribe the real-time quotes, instead of subscribe and unsubscribe from the MQTT client.
To subscribe to real-time market push, please refer to Subscribe/ Unsubscribe
4. Monitor data response
After the third step of the subscription request is successful, the data callback method of the MQTT client will be executed, and you will receive two parts of data: one part is the data topic; the other part is the market data of the subscription target. The first part of the data is a string , the second part of the data is the binary data serialized by protobuf.
The string composition of the first part of the data is: instrument_id-data_type_code-interval, such as 913256135-1-1000.
The protobuf data corresponding to the second part of the data corresponds to different protobuf protocols according to data_type.
The protobuf protocol corresponding to data_type is defined as follows:
Types of data | Data Type Code | Proto Protocol | Description |
---|---|---|---|
QUOTE | 0 | Order Book Proto | Order Book |
SNAPSHOT | 1 | Market Snapshot Proto | Market Snapshot |
TICK | 2 | Tick-by-Tick Proto | Tick-by-Tick |
5. Protocol definition of Market Data
Basic Proto
message Basic {
string symbol = 1;
string instrument_id = 2;
string timestamp = 3;
}
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 Proto
message Tick {
Basic basic = 1;
string time = 2;
string price = 3;
string volume = 4;
string side = 5;
}
Request Example
- Python
- Java
from webullsdkmdata.common.category import Category
from webullsdkmdata.common.subscribe_type import SubscribeType
from webullsdkmdata.quotes.subscribe.default_client import DefaultQuotesClient
from webullsdkcore.common.region import Region
your_app_key = "<your_app_key>"
your_app_secret = "<your_app_secret>"
def pt_logs(client, userdata, level, buf):
print("userdata:%s, level:%s, buf:%s" % (userdata, level, buf))
def on_message(client, userdata, message):
print("Received message '" + str(message.payload) + "' on topic '"
+ message.topic + "' with QoS " + str(message.qos))
if __name__ == '__main__':
client = DefaultQuotesClient(your_app_key, your_app_secret, Region.HK.value)
client.init_default_settings('00700', Category.HK_STOCK.name, SubscribeType.SNAPSHOT.name)
client.on_log = pt_logs
client.on_message = on_message
client.connect_and_loop_forever()
import com.webull.openapi.common.Region;
import com.webull.openapi.common.dict.Category;
import com.webull.openapi.example.config.Env;
import com.webull.openapi.logger.Logger;
import com.webull.openapi.logger.LoggerFactory;
import com.webull.openapi.quotes.subsribe.QuotesSubsClient;
import com.webull.openapi.quotes.subsribe.message.MarketData;
import com.webull.openapi.common.dict.SubscribeType;
import com.webull.openapi.serialize.JsonSerializer;
import java.util.HashSet;
import java.util.Set;
public class QuotesSubscribe {
private static final Logger logger = LoggerFactory.getLogger(QuotesSubscribe.class);
public static void main(String[] args) {
Set<String> symbols = new HashSet<>();
symbols.add("00700");
Set<String> subTypes = new HashSet<>();
subTypes.add(SubscribeType.SNAPSHOT.name());
try (QuotesSubsClient client = QuotesSubsClient.builder()
.appKey(Env.APP_KEY)
.appSecret(Env.APP_SECRET)
.regionId(Region.hk.name())
.onMessage(QuotesSubscribe::handleMarketData)
.addSubscription(symbols, Category.HK_STOCK.name(), subTypes)
.build()) {
client.connectBlocking();
client.subscribeBlocking();
} catch (Exception ex) {
logger.error("Subscribe market data error", ex);
}
}
private static void handleMarketData(MarketData marketData) {
logger.info("Received market data: {}", JsonSerializer.toJson(marketData));
}
}