Overview and Conventions
Using our market data API is straightforward. Simply include the nanoconda.h header file in your project and link your program with the -lnanoconda library.
Nanoconda threads
Nanoconda API allows for a very flexible and powerful threading model. Here is how it works:
Whenever you subscribe to a topic, such as market data for an instrument or exchange updates for your trading session, you have a choice of placing the callbacks of the new topic to an existing thread or to create a new thread for the topic.
This is controlled by the last argument to subscribe() / subscribeUnderlying or to dmasession::init()
static dmasession* init(const char* accountName, reasoncode& reason, short cpu = -1);
reasoncode subscribe(const char* symbol, const char* entitlement, short cpu = -1);
reasoncode subscribeUnderlying(const char* symbol, const char* entitlement, short cpu = -1);
nanoconda::subscribe("ESM5", "XCME", 3); // subscribe to ESM5 Futures on a new thread pinned to cpu #3
nanoconda::subscribeUnderlying("NQ", "XCME", 3); // subscribe to ESM5 Futures on same thread on cpu #3
nanoconda::reasoncode rcode;
nanoconda::dmasession::init("useraccount1", rcode, 1); //subscribe to account updates on a new thread on cpu #1
Tip
a) Whenever a new cpu argument is provided the library creates a new thread pinned to the cpu ID.
b) If cpu number was provided in a previous subscription method then the new subscription will be placed onto the same thread.
c) If cpu argument is ommited then the new subscription will be placed onto a default thread and it will not be pinned.
d) If cpu is invalid then reasoncode::CPU_OUT_OF_BOUNDS will be returned.
User threads
You may create additional threads for any internal processing as needed. The environment provides full access to both C++ std::thread and POSIX pthread APIs.
Order submissions to nanoconda::dmaSession require no additional user-level synchronization. All order-management functions are internally implemented in a thread-safe manner.
API functions
Note
API Calls return nanoconda::reasoncode to notify the user if the call was successful or if there was an error. It is users responsibility to handle any errors returned. Please refer to Reason Codes for explanation of each code and to Sample Application for an example on how to handle the codes.
Register Application
To ensure user is entitled to a market data set and allocated trading session, credentials must be set and each application must be registered. Please supply your credentials and a pointer to your callback listenerobject
reasoncode registerApplication(const char* username, const char* password, listener* l);
//Example: rcode = nanoconda::registerApplication("username1","password", mdApp);
Start nanoconda Threads
When your application is ready to receive callbacks, call start() which will trigger listening to live updates and generage callbacks for both market data and dmasession.
Stop nanoconda Threads
It is recommended to call stop() when terminating your application or when you intend to stop receiving callbacks.
Note
After invoking stop(), the internal state may take several seconds to fully clear and remove your application's logged-in status. Do not call start() earlier than five seconds after stop() has returned.
Memory Architecture
Your container will have access to a shared memory region.
All communications between your application and the exchange are handled via the API and are going through the memory region.
Nanoconda Managed Services are in charge of running the market data normalization processes and keeping trading sessions in operational state.
You can start and stop your application at any time.
Server Diagram

Prices
All prices are stored and communicated as long long type. To display any price as a human readable double, use double nacoPx(long long px) (1) method.
- Please refer to Market Data API for more usage examples.
Info
For most instruments prices are stored as 10^5 multiplier of the original price. Some instruments have 10^9 price precision, they are identified by security::highPrecisionPrice set to 1
Security ID
Securities are idendified by symbolid field only inside all data structures except struct security.
-
To get symbol name as a
stringplease callconst char* getSymbolName(unsigned long long symbolId) -
Securities are idendified by
symbolidfield inside all data structures. To get full symbol object with product information you can callsecurity* getSecurity(unsigned long long symbolId)at any time.From nanoconda.henum securityStatus : unsigned short { HALT = 0, CLOSE = 200, POST_CLOSE = 220, PRE_OPEN = 120, OPEN = 100 }; //... struct security { char symbol[32]; unsigned long long symbolId; unsigned long long exchangeSecurityId; unsigned long long tickSize; unsigned long long multiplier; unsigned long long underlyingId; long long lowLimitBand; long long highLimitBand; securityStatus status; char entCode[6]; char highPrecisionPrice; unsigned char segmentId; char reserved[6]; long long settlementPrice; int openInterest; int clearedVolume; long long reservedL2; static inline unsigned short size() { return 128; } };
Reason Codes
Most of API calls return or populate nanoconda::reasoncode to notify the program of any errors. It is user responsibility to log and handle errors returned by the system.
enum reasoncode : unsigned short
{
SUCCESS = 0,
ERROR = 10,
SYSTEM_ERROR = 12,
API_VERSION_ERROR = 15,
ENTITLEMENT_EMPTY = 1002,
MARKET_NOT_FOUND = 1004,
USER_NOT_ENTITLED = 1006,
SYMBOL_EMPTY = 1010,
SYMBOL_NOT_FOUND = 1012,
ORDER_TYPE_NOT_SET = 1022,
ORDER_SIDE_EMPTY = 1032,
CPU_OUT_OF_BOUNDS = 1111,
QUANTITY_EMPTY = 1020,
PRICE_BAND_BREACHED = 1025,
ORDER_IS_NULL=1015,
ORDERID_EMPTY = 1030,
ORDER_NOT_FOUND = 1035,
ORDER_NOT_LIVE = 1036,
ORDER_IN_FLIGHT = 1044,
ACCOUNTNAME_EMPTY = 1052,
DUPLICATE_REQUEST_SESSION = 1055,
USERNAME_EMPTY = 1060,
PASSWORD_EMPTY = 1070,
LISTENER_NOT_PROVIDED = 1090,
RISK_LIMIT_EXCEEDED = 1220,
RISK_CLIP_SIZE_EXCEEDED = 1230,
RISK_MAX_LOSS_EXCEEDED = 1250,
PERMISSION_ERROR = 2070,
SESSION_IN_USE = 2075,
ALGO_BLOCKED = 2080,
SESSION_DOWN = 2099,
SESSION_UP = 4000,
SECURITY_DELETED = 9012,
RISK_NOT_SET = 9212,
REQUEST_LIMIT = 9370,
};