Market Data Subscription
Subscribe and Unsubscribe to Quote
Subscribe:
virtual bool subscribe_quote(const std::vector<std::string>& symbols) = 0
Unsubscribe:
virtual bool unsubscribe_quote(const std::vector<std::string>& symbols) = 0;
Description
Stock quote subscription and cancellation interface. The returned data is updated in real time, that is, every time the price or pending order data updates, the data will be pushed to the Callback interface, returning the result type for the basic quote QuoteBasicData object and Best Quote QuoteBBOData object
This interface is returned asynchronously, using push_client->set_quote_changed_callback in response to the basic quote QuoteBasicData object; Use push_client->set_quote_bbo_changed_callback to respond to the best quote QuoteBBOData object
Parameters
| Parameter | Type | Description |
|---|---|---|
| symbols | std::vector std::string | List of securities codes, e.g. ['AAPL', 'BABA'], English codes should be in upper case |
Response
CAUTIONThere are two types of stock quote callback data: trading data and intraday data, and the fields responded to by the two types of data are not the same
Example Call
#include "tigerapi/quote_client.h"
#include "tigerapi/trade_client.h"
#include "tigerapi/contract_util.h
"#include "tigerapi/order_util.h"
#include "tigerapi/push_client.h"
#include <string_view>
#include <csignal>
#include <chrono>
#include <thread>
#include <stdio.h>
#include <functional>
#include <iostream>
#include <memory>
#include <atomic>
using namespace std;
using namespace web;
using namespace web::json;
using namespace TIGER_API;
static std::atomic<bool> keep_running(true);
static void signal_handler(int)
{
keep_running = false;
}
class TestPushClient {
private:
std::shared_ptr<IPushClient> push_client;
std::vector<std::string> symbols;
public:
TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client), symbols({ "AAPL" }) {
// symbols = { "AAPL" };
}
void connected_callback() {
ucout << "Connected to push server" << std::endl;
push_client->subscribe_quote(symbols);
}
void quote_changed_callback(const tigeropen::push::pb::QuoteBasicData& data) {
ucout << "BasicQuote changed: " << std::endl;
ucout << "- symbol: " << utility::conversions::to_string_t(data.symbol()) << std::endl;
ucout << "- latestPrice: " << data.latestprice() << std::endl;
ucout << "- volume: " << data.volume() << std::endl;
}
void quote_bbo_changed_callback(const tigeropen::push::pb::QuoteBBOData& data) {
ucout << "BBOQuote changed: " << std::endl;
ucout << "- symbol: " << utility::conversions::to_string_t(data.symbol()) << std::endl;
ucout << "- bidPrice: " << data.bidprice() << std::endl;
ucout << "- askPrice: " << data.askprice() << std::endl;
}
void start_test(ClientConfig config) {
push_client->set_quote_changed_callback(std::bind(&TestPushClient::quote_changed_callback, this, std::placeholders::_1));
push_client->set_quote_bbo_changed_callback(std::bind(&TestPushClient::quote_bbo_changed_callback, this, std::placeholders::_1));
push_client->connect();
std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Subscribing..." << std::endl;
push_client->subscribe_quote(symbols);
std::cout << "symbols size = " << symbols.size() << std::endl;
std::signal(SIGINT, signal_handler); //Ctrl+C
std::signal(SIGTERM, signal_handler); //killwhile (keep_running)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
push_client->unsubscribe_quote(symbols);
push_client->disconnect();
}
static void test_push_client(std::shared_ptr<IPushClient> push_client, ClientConfig config) {
TestPushClient test(push_client);
test.start_test(config);
}
};
int main(int argc, char* argv[]) {
ClientConfig config(true, U("tiger_openapi_config.properties"));
auto push_client = IPushClient::create_push_client(config);
TestPushClient::test_push_client(push_client, config);
return 0;
}Callback Data Example
symbol: "00700"
type: BASIC
timestamp: 1677742483530
serverTimestamp: 1677742483586
avgPrice: 365.37
latestPrice: 363.8
latestPriceTimestamp: 1677742483369
latestTime: "03-02 15:34:43"
preClose: 368.8
volume: 12674730
amount: 4630947968
open: 368.2
high: 369
low: 362.4
marketStatus: "Trading"
mi {
p: 363.8
a: 365.37
t: 1677742440000
v: 27300
h: 364
l: 363.6
}/include/openapi_pb/pb_source/QuoteBBOData.pb.h Example:
symbol: "01810"
type: BBO
timestamp: 1677741267291
serverTimestamp: 1677741267329
askPrice: 12.54
askSize: 397600
askTimestamp: 1677741266304
bidPrice: 12.52
bidSize: 787400
bidTimestamp: 1677741266916Subscribe and Unsubscribe to Depth Quote
Subscribe:
virtual bool subscribe_quote_depth(const std::vector<std::string>& symbols) = 0;
Unsubscribe:
virtual bool unsubscribe_quote_depth(const std::vector<std::string>& symbols) = 0;
Description
Subscribe to depth quotes. U.S. depth quotes have a push frequency of 300ms; Hong Kong depth quotes have a push frequency of 2s, returning up to 40 files of pending buy and sell orders data. The data returned updates in real-time, pending orders will push data updates. This interface is returned asynchronously, using push_client->set_quote_depth_changed_callback response depth quotes QuoteDepthData (/include/openapi_pb/pb_source/QuoteDepthData.pb.h) object;
Parameters
| Parameter | Type | Description |
|---|---|---|
| symbols | const std::vector std::string | List of securities codes, e.g. ['AAPL', 'BABA'], English codes should be in upper case |
Example Call
#include "tigerapi/quote_client.h"
#include "tigerapi/trade_client.h"
#include "tigerapi/contract_util.h"
#include "tigerapi/order_util.h"
#include "tigerapi/push_client.h"
#include <string_view>
#include <csignal>
#include <chrono>
#include <thread>
#include <atomic>
#include <stdio.h>
#include <functional>
#include <iostream>
#include <memory>
using namespace std;
using namespace web;
using namespace web::json;
using namespace TIGER_API;
std::atomic<bool> keep_running(true);
void signal_handler(int signal)
{
if (signal == SIGINT || signal == SIGTERM)
{
keep_running = false;
}
}
class TestPushClient {
private:
std::shared_ptr<IPushClient> push_client;
std::vector<std::string> symbols;
public:
TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client) {
symbols = { "AAPL" };
}
void connected_callback() {
ucout << "Connected to push server" << std::endl;
push_client->subscribe_quote_depth(symbols);
}
void disconnected_callback() {
ucout << "Disconnected from push server" << std::endl;
}
void error_callback(const tigeropen::push::pb::Response& response) {
ucout << "Push error: code=" << response.code() << " message=" << utility::conversions::to_string_t(response.msg()) << std::endl;
}
void kickout_callback(const tigeropen::push::pb::Response& response) {
ucout << "Kicked out: code=" << response.code() << " message=" << utility::conversions::to_string_t(response.msg()) << std::endl;
}
void quote_depth_changed_callback(const tigeropen::push::pb::QuoteDepthData& data) {
ucout << "QuoteDepth changed: " << std::endl;
ucout << "- symbol: " << utility::conversions::to_string_t(data.symbol()) << std::endl;
ucout << "- ask price size: " << data.ask().price_size() << std::endl;
ucout << "- bid price size: " << data.bid().price_size() << std::endl;
}
void start_test(ClientConfig config) {
push_client->set_connected_callback(std::bind(&TestPushClient::connected_callback, this));
push_client->set_disconnected_callback(std::bind(&TestPushClient::disconnected_callback, this));
push_client->set_error_callback(std::bind(&TestPushClient::error_callback, this, std::placeholders::_1));
push_client->set_kickout_callback(std::bind(&TestPushClient::kickout_callback, this, std::placeholders::_1));
push_client->set_quote_depth_changed_callback(std::bind(&TestPushClient::quote_depth_changed_callback, this, std::placeholders::_1));
push_client->connect();
std::signal(SIGINT, signal_handler); //Ctrl+C
std::signal(SIGTERM, signal_handler); //killwhile (keep_running)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
push_client->unsubscribe_quote_depth(symbols);
push_client->disconnect();
}
static void test_push_client(std::shared_ptr<IPushClient> push_client, ClientConfig config) {
TestPushClient test(push_client);
test.start_test(config);
}
};
int main(int argc, char* argv[]) {
ClientConfig config(true, U("tiger_openapi_config.properties"));
auto push_client = IPushClient::create_push_client(config);
TestPushClient::test_push_client(push_client, config);
return 0;
}Callback Data Example
Data structure:
| Field | Type | Description |
|---|---|---|
| symbol | std::string& | symbol |
| timestamp | uint_64 | depth quote time |
| ask | OrderBook | ask data |
| bid | OrderBook | bid data |
OrderBook structure:
| Field | Type | Description |
|---|---|---|
| price | double | price |
| volume | int64_t | order volume |
| orderCount | uint32_t | order count(HK stock only) |
| exchange | std::string& | exchange |
| time | int64_t | time |
Callback Data Example
Depth quote items example. The price of adjacent slots may be the same, the count is optional
symbol: "00700"
timestamp: 1677742734822
ask {
price: 363.8
price: 364
price: 364.2
price: 364.4
price: 364.6
price: 364.8
price: 365
price: 365.2
price: 365.4
price: 365.6
volume: 26900
volume: 14800
volume: 15200
volume: 31500
volume: 15800
volume: 7700
volume: 29400
volume: 6300
volume: 6000
volume: 5500
orderCount: 27
orderCount: 20
orderCount: 19
orderCount: 22
orderCount: 14
orderCount: 10
orderCount: 20
orderCount: 12
orderCount: 10
orderCount: 11
}
bid {
price: 363.6
price: 363.4
price: 363.2
price: 363
price: 362.8
price: 362.6
price: 362.4
price: 362.2
price: 362
price: 361.8
volume: 9400
volume: 19900
volume: 35300
volume: 74200
volume: 26300
volume: 16700
volume: 22500
volume: 21100
volume: 40500
volume: 5600
orderCount: 16
orderCount: 23
orderCount: 36
orderCount: 79
orderCount: 30
orderCount: 32
orderCount: 31
orderCount: 34
orderCount: 143
orderCount: 26
}Subscribe and Unsubscribe to Tick
tick_changed_callback - function works with modifications (sample in the doc).
subscribes and connects. But only seeing heartbeats. No actual tick data. Looks to be server side issue.
Subscribe:
virtual bool subscribe_tick(const std::vector<std::string>& symbols) = 0;
Unsubscribe:
virtual bool unsubscribe_tick(const std::vector<std::string>& symbols) = 0;
Description
The transaction-by-transaction subscription push interface is an asynchronous interface, and the results of asynchronous requests can be obtained by implementing the push_client->subscribe_tick interface. The callback data type is /include/openapi_pb/pb_source/TradeTickData.pb.h TickData
The full-tick subscription push interface can be enabled by changing the configuration client_config.use_full_tick = true
The push frequency is 200ms, using snapshot push. It will push the last 50 records per tick each time it updates.
Parameters
| Parameter | Type | Description |
|---|---|---|
| symbols | const std::vector std::string | List of securities codes, e.g. ['AAPL', 'BABA'], English codes should be in upper case |
Example Call
#include "tigerapi/quote_client.h"
#include "tigerapi/trade_client.h"
#include "tigerapi/contract_util.h"
#include "tigerapi/order_util.h"
#include "tigerapi/push_client.h"
#include <string_view>
#include <csignal>
#include <chrono>
#include <thread>
#include <stdio.h>
#include <functional>
#include <iostream>
#include <memory>
#include <atomic>
using namespace std;
using namespace web;
using namespace web::json;
using namespace TIGER_API;
static std::atomic<bool> keep_running(true);
static void signal_handler(int)
{
keep_running = false;
}
class TestPushClient {
private:
std::shared_ptr<IPushClient> push_client;
std::vector<std::string> symbols;
public:
TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client), symbols({ "AAPL" }) {
// symbols = { "AAPL" };
}
void connected_callback() {
ucout << "Connected to push server" << std::endl;
std::cout << "symbols.size() = " << symbols.size() << std::endl;
for (const auto& s : symbols)
std::cout << "symbol = " << s << std::endl;
push_client->subscribe_tick(symbols);
std::cout << "subscribe_tick() called" << std::endl;
}
void tick_changed_callback(const TradeTick& data) {
ucout << "TradeTick changed: " << std::endl;
ucout << "- data: " << utility::conversions::to_string_t(data.to_string()) << std::endl;
}
void full_tick_changed_callback(const tigeropen::push::pb::TickData& data) {
ucout << "Full TickData changed: " << std::endl;
ucout << "- symbol: " << utility::conversions::to_string_t(data.symbol()) << std::endl;
ucout << "- tick size: " << data.ticks_size() << std::endl;
}
void start_test(ClientConfig config) {
push_client->set_tick_changed_callback(std::bind(&TestPushClient::tick_changed_callback, this, std::placeholders::_1));
push_client->set_full_tick_changed_callback(std::bind(&TestPushClient::full_tick_changed_callback, this, std::placeholders::_1));
push_client->set_connected_callback(std::bind(&TestPushClient::connected_callback, this));
push_client->connect();
std::signal(SIGINT, signal_handler); //Ctrl+C
std::signal(SIGTERM, signal_handler); //killwhile (keep_running)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
push_client->unsubscribe_tick(symbols);
push_client->disconnect();
}
static void test_push_client(std::shared_ptr<IPushClient> push_client, ClientConfig config) {
TestPushClient test(push_client);
test.start_test(config);
}
};
int main(int argc, char* argv[]) {
ClientConfig config(true, U("tiger_openapi_config.properties"));
config.use_full_tick = true;
//config.use_full_tick = false;auto push_client = IPushClient::create_push_client(config);
TestPushClient::test_push_client(push_client, config);
return 0;
}
}Callback Data
TradeTick data structure:
| Field | Type | Description |
|---|---|---|
| symbol | std::string& | stock |
| type | std::string& | STK |
| cond | std::string& | |
| sn | int64_t | |
| priceBase | int64_t | |
| priceOffset | int32_t | |
| time | int64_t | |
| price | int64_t | |
| volume | int64_t | |
| partCode | std::string& | |
| quoteLevel | std::string& | The level of authority of the ticker from which the data comes (for US stocks, usQuoteBasic has less data per tick than usStockQuote) |
| timestamp | uint64_t | timestamp in millisecond |
| secType | std::string& | |
| mergedVols | TradeTickData.MergedVol |
ticks data structure:
| Field | Type | Description |
|---|---|---|
| sn | int64_t | serial number |
| time | int64_t | transaction time stamp |
| price | float | transaction price |
| volume | int32_t | volume |
| type | std::string& | * means no change, + means up, - means down |
| cond | std::string& | The list of transaction conditions for each data, if the array is empty, it means that each transaction of the current batch is an automatic transaction |
| partCode | std::string& | Exchange code of each transaction (US stocks only) |
Callback Example
symbol: "NVDA"
ticks {
sn: 2381
time: 1712669401076
price: 874.1
volume: 10
type: "*"
partCode: "t"
}
ticks {
sn: 2382
time: 1712669401076
price: 874.1
volume: 11
type: "*"
partCode: "t"
}
ticks {
sn: 2383
time: 1712669401076
price: 874.1
volume: 3
type: "*"
partCode: "t"
}
timestamp: 1712669403808
source: "NLS"Query Subscribed Symbols
virtual void query_subscribed_symbols() = 0;
Description
Query the list of subscribed labels
This interface is asynchronous return, you need to use push_client->set_query_subscribed_symbols_changed_callback response to return the results
Parameters
None
Callback Data
The callback data structure is as follows:
| Field | Type | Description |
|---|---|---|
| limit | Maximum number of subscribed tickers (stocks, options) | |
| used | Number of subscribed tickers (stocks, options) | |
| tradeTickLimit | Maximum number of trade-by-trade stock limits | |
| tradeTickUsed | subscribedAskBidSymbols | |
| askBidLimit | subscribed to the depth of the stock limit maximum number | |
| askBidUsed | Number of subscribed stocks | |
| klineLimit | ||
| klineUsed | ||
| subscribedSymbols | list of subscribed symbols | |
| subscribedTradeTickSymbols | ||
| subscribedAskBidSymbols | ||
| subscribedMarketQuote | ||
| subscribedKlineSymbols |
Example Call
#include "tigerapi/quote_client.h"
#include "tigerapi/trade_client.h"
#include "tigerapi/contract_util.h"
#include "tigerapi/order_util.h"
#include "tigerapi/push_client.h"
#include <string_view>
#include <csignal>
#include <chrono>
#include <thread>
#include <stdio.h>
#include <functional>
#include <iostream>
#include <memory>
#include <atomic>
using namespace std;
using namespace web;
using namespace web::json;
using namespace TIGER_API;
static std::atomic<bool> keep_running(true);
static void signal_handler(int)
{
keep_running = false;
}
class TestPushClient {
private:
std::shared_ptr<IPushClient> push_client;
std::vector<std::string> symbols;
public:
TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client), symbols({ "AAPL" }) {
// symbols = { "AAPL" };
}
void connected_callback() {
ucout << "Connected to push server" << std::endl;
push_client->subscribe_quote(symbols);
}
void query_subscribed_symbols_changed_callback(const tigeropen::push::pb::Response& data) {
ucout << "QuerySubscribedSymbols changed: " << std::endl;
ucout << "- data: " << utility::conversions::to_string_t(data.msg()) << std::endl;
}
void position_changed_callback(const tigeropen::push::pb::PositionData& data){
ucout << "Position changed" << std::endl;
}
void asset_changed_callback(const tigeropen::push::pb::AssetData& data){
ucout << "Asset changed:" << std::endl;
ucout << "- account: "<< utility::conversions::to_string_t(data.account()) << std::endl;
ucout << "- net liquidation: "<< data.netliquidation() << std::endl;
ucout << "- cash: " << data.cashbalance() << std::endl;
}
void start_test(ClientConfig config) {
push_client->set_connected_callback(std::bind(&TestPushClient::connected_callback,this));
push_client->set_query_subscribed_symbols_changed_callback(std::bind(&TestPushClient::query_subscribed_symbols_changed_callback, this, std::placeholders::_1));
push_client->set_position_changed_callback(std::bind(&TestPushClient::position_changed_callback, this, std::placeholders::_1));
push_client->set_asset_changed_callback(std::bind(&TestPushClient::asset_changed_callback, this, std::placeholders::_1));
push_client->connect();
std::signal(SIGINT, signal_handler); //Ctrl+C
std::signal(SIGTERM, signal_handler); //killwhile (keep_running)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
push_client->unsubscribe_quote(symbols);
push_client->disconnect();
}
static void test_push_client(std::shared_ptr<IPushClient> push_client, ClientConfig config) {
TestPushClient test(push_client);
test.start_test(config);
}
};
int main(int argc, char* argv[]) {
ClientConfig config(true, U("tiger_openapi_config.properties"));
// config.use_full_tick = true;
config.use_full_tick = false;
auto push_client = IPushClient::create_push_client(config);
TestPushClient::test_push_client(push_client, config);
return 0;
}Callback Example
{
"limit":2000,
"used":40,
"tradeTickLimit":2000,
"tradeTickUsed":2,
"askBidLimit":500,
"askBidUsed":2,
"klineLimit":2000,
"klineUsed":2,
"subscribedSymbols":
[
"AAPL","09939","09618","01810","TSLA","META","QRTEP","00992","03988","08437","TSM","09888","03022","XOM","A","AVGO",
"CVX","BRK.B","01398","00700","00345","09999","MSFT","03690","09992","TLT","SQ","NFLX","NVDA","00013","AZPN","01024",
"00012","06955","09988","02390","NIO","TQQQ","FFIE","AMZN"
],
"subscribedTradeTickSymbols":
[
"NVDA","TSM"
],
"subscribedAskBidSymbols":
[
"NVDA","TSM"
],
"subscribedMarketQuote":
[
"US_StockTop"
],
"subscribedKlineSymbols":
[
"NVDA","TSM"
]
}Subscribe Option Quote
Subscribe method
virtual bool subscribe_option_quote(const std::vector<std::string>& symbols) = 0;
Parameters
| Parameter | Type | Description |
|---|---|---|
| symbols | const std::vector std::string | List of options codes |
Callback Data
Need to bind the callback method through push_client->quote_changed_callback, the callback method is the same as the stock
Example
push_client->subscribe_option_quote(symbols) or push_client.subscribe_quote(symbols)
Code Example
#include "tigerapi/quote_client.h"
#include "tigerapi/trade_client.h"
#include "tigerapi/contract_util.h"
#include "tigerapi/order_util.h"
#include "tigerapi/push_client.h"
#include <string_view>
#include <csignal>
#include <chrono>
#include <thread>
#include <stdio.h>
#include <functional>
#include <iostream>
#include <memory>
#include <atomic>
using namespace std;
using namespace web;
using namespace web::json;
using namespace TIGER_API;
static std::atomic<bool> keep_running(true);
static void signal_handler(int)
{
keep_running = false;
}
class TestPushClient {
private:
std::shared_ptr<IPushClient> push_client;
std::vector<std::string> symbols;
public:
TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client), symbols({ "AAPL 20260821 315.00 PUT" }) {
}
void connected_callback() {
ucout << "Connected to push server" << std::endl;
push_client->subscribe_option_quote(symbols);
}
void quote_changed_callback(const tigeropen::push::pb::QuoteBasicData& data) {
ucout << "Option quote changed:" << std::endl;
ucout << "- identifier: " << utility::conversions::to_string_t(data.identifier()) << std::endl;
ucout << "- underlying symbol: " << utility::conversions::to_string_t(data.symbol()) << std::endl;
ucout << "- latest price: " << data.latestprice() << std::endl;
ucout << "- open: " << data.open() << std::endl;
ucout << "- high: " << data.high() << std::endl;
ucout << "- low: " << data.low() << std::endl;
ucout << "- prev close: " << data.preclose() << std::endl;
}
void start_test(ClientConfig config) {
push_client->set_connected_callback(std::bind(&TestPushClient::connected_callback, this));
push_client->set_quote_changed_callback(std::bind(&TestPushClient::quote_changed_callback, this, std::placeholders::_1));
push_client->connect();
std::signal(SIGINT, signal_handler); //Ctrl+C
std::signal(SIGTERM, signal_handler); //killwhile (keep_running)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
push_client->unsubscribe_quote(symbols);
push_client->disconnect();
}
static void test_push_client(std::shared_ptr<IPushClient> push_client, ClientConfig config) {
TestPushClient test(push_client);
test.start_test(config);
}
};
int main(int argc, char* argv[]) {
ClientConfig config(true, U("tiger_openapi_config.properties"));
// config.use_full_tick = true;
config.use_full_tick = false;
auto push_client = IPushClient::create_push_client(config);
TestPushClient::test_push_client(push_client, config);
return 0;
}Updated about 2 hours ago