To create a basic TT Core SDK application that downloads the Order Book on start up, you need to:
After the initialization is started, TT Core SDK downloads:
TT Core SDK synchronizes the Order Book and positions by account. As such, any given account can be used to trade without needing to wait for all accounts to be ready. An OnAccountDownloadEnd event is fired when an account is ready to be used for trading. An OnOrderBookDownloadEnd event is fired when all accounts are ready.
The following code snippet demonstrates an example of this process.
#include <iostream>
#include <iomanip>
#include <atomic>
#include <sstream>
#include <string.h>
#include <tt_cplus_sdk.h>
#include <condition_variable>
std::mutex mutex;
std::condition_variable sdkReadyCondition;
//
// SDK event handler class
//
class SDKEventHandler : public ttsdk::IEventHandler
{
public:
SDKEventHandler() : IEventHandler() {}
virtual ~SDKEventHandler() {}
// received on an SDK managed thread that can be used for processing.
// beware that time consuming tasks can delay the delivery of another status event.
virtual void OnStatus(const ttsdk::IEventHandler::Status status) override
{
std::cout << "SDKEventHandler::OnStatus (" << (uint32_t)status << ")" << std::endl;
}
};
//
// Order Book event handler class
//
class MyOrderBookHandler : public ttsdk::IOrderBookEventHandler
{
public:
MyOrderBookHandler() : IOrderBookEventHandler() {};
virtual ~MyOrderBookHandler() {};
virtual void OnExecutionReport(ttsdk::OrderPtr order,
ttsdk::ExecutionReportPtr execRpt) override
{
// ...
}
virtual void OnReject(ttsdk::OrderPtr order, ttsdk::RejectResponsePtr rejResp) override
{
// ...
}
virtual void OnSendFailed(ttsdk::OrderPtr order, const ttsdk::OrderProfile& profile,
const SendCode code) override
{
// ...
}
virtual void OnUnsubscribed(const char* orderId) override
{
// ...
}
// account and book sync events are sent on the position thread so they are sequenced
// properly with the position update events
virtual void OnOrderBookDownloadEnd() override
{
std::cout << "---All assigned accounts are ready to use." << std::endl;
std::lock_guard lock(mutex);
sdkReadyCondition.notify_one();
}
// the SDK synchronizes the order book and positions by account. as such,
// any given account can be able to trade without needing to wait
// for all accounts to be ready
virtual void OnAccountDownloadEnd(const uint64_t accountId) override
{
std::cout << "---Account accountId:" << accountId
<< " is synchronized and ready to use." << std::endl;
}
virtual void OnAccountDownloadFailed(const uint64_t accountId, const char* msg) override
{
std::cout << "---Account accountId:" << accountId <<" download failed details: "
<< msg << std::endl;
}
// all position events are received on the SDK position processing thread.
// holding up processing for a given position event will impact all
// subsequent position updates
virtual void OnPositionUpdate(const ttsdk::Position& updatedPosition) override
{
std::cout << "---OnPositionUpdate for AccountId:" << updatedPosition.account_id
<< " Instrument:" << updatedPosition.instrument->GetAlias() << std::endl;
std::cout << " SOD:" << updatedPosition.sod_quantity << "@"
<< updatedPosition.sod_price
<< " Buys:" << updatedPosition.buy_quantity << "@"
<< updatedPosition.buy_average_price
<< " Sells:" << updatedPosition.sell_quantity << "@"
<< updatedPosition.sell_average_price
<< " Net:" << updatedPosition.net_position
<< " P/L:" << updatedPosition.native_currency_pnl
<< " AvgPrc:" << updatedPosition.open_average_price
<< std::endl;
}
};
//
// Main
//
int main(int argc, char* argv[])
{
//Set the environment the app needs to run in here
ttsdk::Environment env = ttsdk::Environment::ProdLive;
// Add your app secret Key here. It looks like:
00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000
std::string app_key = “Your App Key”;
ttsdk::TTSDKOptions options;
options.environment = env;
options.app_key_secret = app_key.c_str();
SDKEventHandler myObserver;
MyOrderBookHandler myOrderBookObserver;
if (!ttsdk::Initialize(options, &myObserver, myOrderBookObserver))
{
std::cout << "Unable to initialize SDK!" << std::endl;
return -1;
}
std::unique_lock lock(mutex);
if (sdkReadyCondition.wait_for(lock, std::chrono::seconds(300)) == std::cv_status::timeout)
{
std::cout << "Timeout waiting for SDK to initialize!" << std::endl;
return -1;
}
std::cout << std::endl;
std::cout << "<<<<< TT CORE SDK is initialized. >>>>>" << std::endl;
std::cout << std::endl << "Press q to exit....." << std::endl;
std::string command;
while (std::cin >> command)
{
if (command == "q")
{
std::cout << "Quitting...\n";
break;
}
}
std::cout << "Exiting..." << std::endl;
ttsdk::Shutdown();
}
The servers on which TT Core SDK applications execute are equipped to utilize Onload which supports a kernel bypass accelerated user-level TCP/IP network stack, providing extremely low latency.
To take advantage of this, you will first need to run the onload.sh script included with the TT Core SDK software bundle. This script sets a number of environment variables. Alternatively, you could copy these environment variables to your own startup scripts. Regardless of the method you choose, these must be available to your application when it is initialized.
Note: Onload should only be used if you are running one TT Core SDK application on the server.