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

ParameterTypeDescription
symbolsstd::vector
std::string
List of securities codes, e.g. ['AAPL', 'BABA'], English codes should be in upper case

Response

⚠️

CAUTION

There 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: 1677741266916

Subscribe 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

ParameterTypeDescription
symbolsconst std::vector
std::string
List of securities codes, e.g. ['AAPL', 'BABA'], English codes should be in upper case
⚠️

Account should be enabled for Level 2

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

⚠️

CAUTION

This interface will only push a maximum of the first 40 ask/bid

Data structure:

FieldTypeDescription
symbolstd::string&symbol
timestampuint_64depth quote time
askOrderBookask data
bidOrderBookbid data

OrderBook structure:

FieldTypeDescription
pricedoubleprice
volumeint64_torder volume
orderCountuint32_torder count(HK stock only)
exchangestd::string&exchange
timeint64_ttime

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

ParameterTypeDescription
symbolsconst 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:

FieldTypeDescription
symbolstd::string&stock
typestd::string&STK
condstd::string&
snint64_t
priceBaseint64_t
priceOffsetint32_t
timeint64_t
priceint64_t
volumeint64_t
partCodestd::string&
quoteLevelstd::string&The level of authority of the ticker from which the data comes (for US stocks, usQuoteBasic has less data per tick than usStockQuote)
timestampuint64_ttimestamp in millisecond
secTypestd::string&
mergedVolsTradeTickData.MergedVol

ticks data structure:

FieldTypeDescription
snint64_tserial number
timeint64_ttransaction time stamp
pricefloattransaction price
volumeint32_tvolume
typestd::string&* means no change, + means up, - means down
condstd::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
partCodestd::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:

FieldTypeDescription
limitMaximum number of subscribed tickers (stocks, options)
usedNumber of subscribed tickers (stocks, options)
tradeTickLimitMaximum number of trade-by-trade stock limits
tradeTickUsedsubscribedAskBidSymbols
askBidLimitsubscribed to the depth of the stock limit maximum number
askBidUsedNumber of subscribed stocks
klineLimit
klineUsed
subscribedSymbolslist 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

ParameterTypeDescription
symbolsconst 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)

⚠️

Notice the symbol format in a code sample below

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;
}

Did this page help you?