Market Data Subscription

About 10 min

Subscribe and Unsubscribe to Quote

Subscribe method

virtual bool subscribe_quote(const std::vector<std::string>& symbols) = 0

Unsubscribe method

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 update will have data pushed Callback interface returns the result type for the basic quote QuoteBasicData object 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::vectorstd::stringList of securities codes, e.g. ['AAPL', 'BABA'], English codes should be in upper case

Return

CAUTION

There are two types of stock quote callback data: trading data and intraday data, and the fields returned by the two types of data are not the same

Example

class TestPushClient {
private:
    std::shared_ptr<IPushClient> push_client;
    std::vector<std::string> symbols;

public:
    TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client) {
        std::vector<std::string> hk_option_symbols = {"TCH.HK 20241230 410.00 CALL"};
        std::vector<std::string> future_symbols = {"CL2412"};
        symbols = future_symbols;
    }

    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::signal(SIGINT, signal_handler);  //Ctrl+C
        std::signal(SIGTERM, signal_handler); //kill
        while (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 *args[]) {
    cout << "Tiger Api main" << endl;
    /************************** set config **********************/
    ClientConfig config = ClientConfig(true);

    config.private_key = "-----BEGIN RSA PRIVATE KEY-----\n"
                         "xxxxxx private key xxxxxxxx"
                         "-----END RSA PRIVATE KEY-----";
    config.tiger_id = "Tiger ID";
    config.account = "Account ID";
    
    auto push_client = IPushClient::create_push_client(config);
    TestPushClient::test_push_client(push_client, config);

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 methodvirtual bool subscribe_quote_depth(const std::vector<std::string>& symbols) = 0;

Unsubscribe method

virtual bool unsubscribe_quote_depth(const std::vector<std::string>& symbols) = 0;

Description

Subscribe to depth quotes, ** U.S. depth quotes push frequency of 300ms, Hong Kong depth quotes push frequency of 2s, return up to 40 files of pending buy and sell orders data **, the data returned for real-time updates, that is, pending orders data updates will have data pushed. This interface is asynchronous return, 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::vectorstd::stringList of securities codes, e.g. ['AAPL', 'BABA'], English codes should be in upper case

Example

class TestPushClient {
private:
    std::shared_ptr<IPushClient> push_client;
    std::vector<std::string> symbols;

public:
    TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client) {
        std::vector<std::string> hk_option_symbols = {"TCH.HK 20241230 410.00 CALL"};
        std::vector<std::string> future_symbols = {"CL2412"};
        symbols = future_symbols;
    }

    void connected_callback() {
        ucout << "Connected to push server" << std::endl;
        push_client->subscribe_quote_depth(symbols);
    }
    
    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_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); //kill
        while (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 *args[]) {
    cout << "Tiger Api main" << endl;
    /************************** set config **********************/
    ClientConfig config = ClientConfig(true);

    config.private_key = "-----BEGIN RSA PRIVATE KEY-----\n"
                         "xxxxxx private key xxxxxxxx"
                         "-----END RSA PRIVATE KEY-----";
    config.tiger_id = "Tiger ID";
    config.account = "Account ID";
    
    auto push_client = IPushClient::create_push_client(config);
    TestPushClient::test_push_client(push_client, config);

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, where 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

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 This method is used for both stocks and futures.

The full-tick subscription push interface can be enabled by changing the configuration client_config.use_full_tick = true

Push frequency is 200ms, using snapshot push, each time pushing the latest 50 records per tick.

Parameters

ParameterTypeDescription
symbolsconst std::vectorstd::stringList of securities codes, e.g. ['AAPL', 'BABA'], English codes should be in upper case

Example

class TestPushClient {
private:
    std::shared_ptr<IPushClient> push_client;
    std::vector<std::string> symbols;

public:
    TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client) {
        std::vector<std::string> hk_option_symbols = {"TCH.HK 20241230 410.00 CALL"};
        std::vector<std::string> future_symbols = {"CL2412"};
        symbols = future_symbols;
    }

    void connected_callback() {
        ucout << "Connected to push server" << std::endl;
        push_client->subscribe_tick(symbols);
    }
    
    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->connect();

        std::signal(SIGINT, signal_handler);  //Ctrl+C
        std::signal(SIGTERM, signal_handler); //kill
        while (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 *args[]) {
    cout << "Tiger Api main" << endl;
    /************************** set config **********************/
    ClientConfig config = ClientConfig(true);

    config.private_key = "-----BEGIN RSA PRIVATE KEY-----\n"
                         "xxxxxx private key xxxxxxxx"
                         "-----END RSA PRIVATE KEY-----";
    config.tiger_id = "Tiger ID";
    config.account = "Account ID";
    
    //enable full tick
    config.use_full_tick = true;
    
    auto push_client = IPushClient::create_push_client(config);
    TestPushClient::test_push_client(push_client, config);

Callback data TradeTick data structure:

FieldTypeDescription
symbolstd::string&stock or future code
typestd::string&STK/FUT
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); there is no level distinction for futures
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 (not available for futures)
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 (futures are not available on a per-transaction basis)
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, futures)
usedNumber of subscribed tickers (stocks, options, futures)
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

class TestPushClient {
private:
    std::shared_ptr<IPushClient> push_client;
    std::vector<std::string> symbols;

public:
    TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client) {
        std::vector<std::string> hk_option_symbols = {"TCH.HK 20241230 410.00 CALL"};
        std::vector<std::string> future_symbols = {"CL2412"};
        symbols = future_symbols;
    }

    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 start_test(ClientConfig config) {
        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); //kill
        while (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 *args[]) {
    cout << "Tiger Api main" << endl;
    /************************** set config **********************/
    ClientConfig config = ClientConfig(true);

    config.private_key = "-----BEGIN RSA PRIVATE KEY-----\n"
                         "xxxxxx private key xxxxxxxx"
                         "-----END RSA PRIVATE KEY-----";
    config.tiger_id = "Tiger ID";
    config.account = "Account ID";
    
    //enable full tick
    config.use_full_tick = true;
    
    auto push_client = IPushClient::create_push_client(config);
    TestPushClient::test_push_client(push_client, config);

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 methodvirtual bool subscribe_option_quote(const std::vector<std::string>& symbols) = 0;

Parameters

ParameterTypeDescription
symbolsconst std::vectorstd::stringList 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

Examplepush_client->subscribe_option_quote(symbols) or push_client.subscribe_quote(symbols)

Subscribe Future Quote

Parameters

ParameterTypeDescription
symbolsstd::vectorstd::stringList of futures 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_future_quote(symbols) or push_client->subscribe_quote(symbols)


Subscribe to stock top data

Subscribe methodvirtual bool subscribe_stock_top(const std::string& market) = 0;Unsubscribe methodvirtual bool unsubscribe_stock_top(const std::string& market) = 0;

Description

Subscribe to stock top data, no push during non-trading hours, push interval is 30s, each push subscribes to indicators Top30 underlying data. The push interface is an asynchronous callback, and the result of asynchronous request can be obtained by implementing the ApiComposeCallback interface. The callback interface returns the result type as StockTopData object. The data of each indicator is sorted in reverse order by indicator value.

Support the subscription of stock indicators in the US and Hong Kong markets. The top of intraday data has all indicators of StockRankingIndicator, and the top data of only two indicators of US stocks before and after the market is up (changeRate) and up in 5 minutes (changeRate5Min)

Parameters

Parameter NameTypeRequiredDescription
marketstd::string&YesMarket

Callback data

Need to bind the callback method via push_client->set_stock_top_changed_callback

The data structure of StockTopData is as follows:

FieldTypeDescription
marketstd::string&market:US/HK
timestampint64_ttimestamp
topDatatopDataList of data for each indicator list

The data structure of TopData is as follows:

fieldtypedescription
targetNamestd::string&indicatorName(changeRate, changeRate5Min, turnoverRate, amount, volume, amplitude)
itemStockItemA list of the list data under this indicator dimension

The data structure of StockItem is as follows:

fieldtypedescription
symbolstd::string&marked
latestPricedoubleThe latest price
targetValuedoubleCorresponding indicator value

Example

class TestPushClient {
private:
    std::shared_ptr<IPushClient> push_client;
    std::vector<std::string> symbols;

public:
    TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client) {
        std::vector<std::string> hk_option_symbols = {"TCH.HK 20241230 410.00 CALL"};
        std::vector<std::string> future_symbols = {"CL2412"};
        symbols = future_symbols;
    }

    void connected_callback() {
        ucout << "Connected to push server" << std::endl;
        push_client->subscribe_stock_top("US");
    }

    void stock_top_changed_callback(const tigeropen::push::pb::StockTopData& data) {
        ucout << "StockTopData: " << std::endl;
        ucout << "- market: " << data.market() << std::endl;
        ucout << "- timestamp: " << data.timestamp() << std::endl;
    }
    
    void start_test(ClientConfig config) {
        push_client->set_stock_top_changed_callback(std::bind(&TestPushClient::stock_top_changed_callback, this, std::placeholders::_1));
        
        push_client->connect();

        std::signal(SIGINT, signal_handler);  //Ctrl+C
        std::signal(SIGTERM, signal_handler); //kill
        while (keep_running)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }

        push_client->unsubscribe_stock_top("US");
        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 *args[]) {
    cout << "Tiger Api main" << endl;
    /************************** set config **********************/
    ClientConfig config = ClientConfig(true);

    config.private_key = "-----BEGIN RSA PRIVATE KEY-----\n"
                         "xxxxxx private key xxxxxxxx"
                         "-----END RSA PRIVATE KEY-----";
    config.tiger_id = "Tiger ID";
    config.account = "Account ID";
    
    //enable full tick
    config.use_full_tick = true;
    
    auto push_client = IPushClient::create_push_client(config);
    TestPushClient::test_push_client(push_client, config);

Subscribe to option top data

Subscribe methodvirtual bool subscribe_option_top(const std::string& market) = 0;Unsubscribe methodvirtual bool unsubscribe_option_top(const std::string& market) = 0

Description

Subscribe to the option's market top data,** no push during non-trading hours, push interval is 30s, each push subscribes to the data of the indicator Top50 underlying**. The push interface is an asynchronous callback, and the result of asynchronous request can be obtained by implementing the ApiComposeCallback interface. The return result type of the callback interface is OptionTopData object. Among them, the variation of large orders is the data of single transaction volume greater than 1000, sorted in reverse order by transaction time, and the other indicator data is the data of cumulative indicator value in reverse order on trading days.

Support for subscription to the U.S. market options indicators, the intraday data list has OptionRankingIndicator all indicators.

Parameters

Parameter NameTypeRequiredDescription
marketstd::string&YesMarket

Callback data

The callback method should be bound by push_client->set_option_top_changed_callback.

The OptionTopData data structure is as follows:

FieldTypeDescription
marketstd::string&market:US
timestampint64_ttimestamp
topDatatopDataList of data for each indicator list

The data structure of TopData is as follows:

fieldtypedescription
targetNamestd::string&Indicator name(bigOrder, volume, amount, openInt)
bigOrderstd:vector<bigOrder>The list of variance bigOrder indicators (bigOrder) data
itemstd:vector<optionItem>The list of data under this indicator dimension

The data structure of BigOrder is as follows:

fieldtypedescription
symbolstd::string&Stock ETF Underlying
expirystd::string&Expiration date, format: yyyyMMdd
strikestd::string&Strike price
rightstd::string&CALL/PUT
dirstd::string&Buy/Sell direction: BUY/SELL/NONE
volumedoubletarget value: volume > 1000
pricedoubletrade price
amountdoubletrade amount
tradeTimeint64_ttransaction timestamp

The data structure of OptionItem is as follows:

fieldtypedescription
symbolstd::string&Stock ETF Underlying
expirystd::string&Expiration date, format: yyyyMMdd
strikestd::string&Strike
rightstd::string&CALL/PUT
totalAmountdoubleTotal trade amount
totalVolumedoubletotal trade volume
totalOpenIntdoubleopen interest
volumeToOpenIntdoubleVolume to open interest
latestPricedoubleOption latest price
updateTimeint64_tUpdate timestamp

Example

class TestPushClient {
private:
    std::shared_ptr<IPushClient> push_client;
    std::vector<std::string> symbols;

public:
    TestPushClient(std::shared_ptr<IPushClient> client) : push_client(client) {
        std::vector<std::string> hk_option_symbols = {"TCH.HK 20241230 410.00 CALL"};
        std::vector<std::string> future_symbols = {"CL2412"};
        symbols = future_symbols;
    }

    void connected_callback() {
        ucout << "Connected to push server" << std::endl;
        push_client->subscribe_option_top("US");
    }

    void option_top_changed_callback(const tigeropen::push::pb::StockTopData& data) {
        ucout << "OptionTopData: " << std::endl;
        ucout << "- market: " << data.market() << std::endl;
        ucout << "- timestamp: " << data.timestamp() << std::endl;
    }
    
    void start_test(ClientConfig config) {
        push_client->set_option_top_changed_callback(std::bind(&TestPushClient::option_top_changed_callback, this, std::placeholders::_1));
        
        push_client->connect();

        std::signal(SIGINT, signal_handler);  //Ctrl+C
        std::signal(SIGTERM, signal_handler); //kill
        while (keep_running)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }

        push_client->unsubscribe_option_top("US");
        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 *args[]) {
    cout << "Tiger Api main" << endl;
    /************************** set config **********************/
    ClientConfig config = ClientConfig(true);

    config.private_key = "-----BEGIN RSA PRIVATE KEY-----\n"
                         "xxxxxx private key xxxxxxxx"
                         "-----END RSA PRIVATE KEY-----";
    config.tiger_id = "Tiger ID";
    config.account = "Account ID";
    
    //enable full tick
    config.use_full_tick = true;
    
    auto push_client = IPushClient::create_push_client(config);
    TestPushClient::test_push_client(push_client, config);
Last update: