Table of Contents


Dynamic Linking

You link to NxCore dynamically, when your program is running, and not at compile time. The benefit to this method is that it allows you to upgrade (or rollback) to a new or previous version without having to unload your process.

After reading this section, please read how the "C++" class NxCoreClass can make this setup easier.

Notes on compiler issues

The NxCoreAPI was developed using Microsoft Visual C++ and the Intel Compiler; however, only basic "C" language constructs are used. There are no classes, few type defines, and only simple primitive types. The philosophy behind the API is to keep things as plain and simple as possible. You are free to define, encapsulate, typedef, layer, wrap, as you wish.

The short and long of int

In a 64-bit environment, Windows defines both long and int as 32 bits. Linux and other Unix based Operating systems define a long as 64 bits, and an int as 32 bits. Rather than include cryptic #ifdef OS==blah, there are no variables of the type long in the Nanex Core API.

All members needing 32 bits use the type int. All members using short are 16 bits. There are a few types that require 64 bits (volume) which use the type __int64. Should there be an environment where an int is not 32 bits which Nanex wishes to support, a special NxCoreAPI.h header file will be available.

Structure Packing

Ideally, structure packing (alignment) should be on 8 byte boundaries, which is the default for most modern day compilers. The NxCoreAPI.dll supports packing sizes of 1, 2, 4, or 8. Be sure you do not set the packing size to more than 8 for the NxCoreAPI.h file. To accommodate the variety of packing sizes, Nanex has added alignment variables in several structures. These alignment variables essentially represent what the compiler would pad if structure packing was set for 8 byte alignment. There are also a few variable sized alignment structures found in places where the structure size will vary between a 32 bit and 64 bit environment which is caused when a member of the structure is a pointer. Pointers are 8 bytes in a 64 bit environment and 4 bytes in a 32 bit environment. For structures that are not embedded in other structures, there will be no alignment variable at the end of the structure since none is required.

The const keyword

The const keyword is used to alert you if you accidentally write code that attempts to change a pointer to a structure passed to you by the API. If you pass these pointers or parts of their data to other functions, you will simply need to include the const keyword to get rid of the compiler warning.

Basic Steps

  1. Load the NxCoreAPI.dll.
  2. Call the exported function sNxCoreProcessTape.
  3. Process the stream of data in your Callback Function. Your Callback Function is called once for each quote, trade, clock, spin, or symbol change message or update. Return the value NxCALLBACKRETURN_CONTINUE(0) after each call to continue processing the stream, or return NxCALLBACKRETURN_STOP to return control to the line of code after the call to sNxCoreProcessTape.
  4. At Midnight EST, the stream automatically ends with a clock time of 24:00:00:000; this completes an NxCore Tape. Your callback function is called with NxCoreSystem.Status set to NxCORESTATUS_COMPLETE (2). When your function returns, the update loop terminates and control returns to your line of code after the call to sNxCoreProcessTape. A new NxCore Tape immediately begins for the next calendar day. Your code simply loops and calls sNxCoreProcessTape again.

#include "NxCoreAPI.h"

int __stdcall OnNxCoreCallback(const NxCoreSystem* pNxCoreSys, const NxCoreMessage* pNxCoreMsg)
{
    printf("Hello World\n");
    return NxCALLBACKRETURN_STOP;
}

void StartNxCoreAPI()
{
    HMODULE hLib = ::LoadLibrary("NxCoreAPI.dll")
    if( hLib ) {
        NxCoreProcessTape pfNxProcessTape = (NxCoreProcessTape) ::GetProcAddress(hLib,"sNxCoreProcessTape");
        if( pfNxProcessTape )
            pfNxProcessTape("",0,0,123,OnNxCoreCallback);
        ::FreeLibrary(hLib);
    }
}

NxCoreAPI.h

Let's examine each line of code and understand what is going on. The first line of code instructs the preprocessor to import the one and only header file you will need: NxCoreAPI.h. This one file contains all the structures and definitions you need to process the Nanex Core API. Everything in the NxCoreAPI.h file uses standard and straightforward "C" code.


#include "NxCoreAPI.h"

Callback Function

The next lines of code contain the function OnNxCoreCallback which prints Hello World and returns NxCALLBACKRETURN_STOP. This is the one and only callback function that NxCoreAPI.dll requires and will be where all your feed processing code will appear. Over then next few dozen chapters, we will be expand this function with code.


int __stdcall OnNxCoreCallback(const NxCoreSystem* pNxCoreSys, const NxCoreMessage* pNxCoreMsg)

{
  printf("Hello World\n");
  return NxCALLBACKRETURN_STOP;
}

Callback Function return values

#define Value Comments
NxCALLBACKRETURN_CONTINUE 0 continue normal processing
NxCALLBACKRETURN_STOP 1 stop processing and return control to function that called NxCoreProcessTape
NxCALLBACKRETURN_RESTART 2 restart processing from beginning of tape. UserData and strings are preserved.

Startup Function

The next function, named StartNxCoreAPI, illustrates one way to startup the NxCoreAPI process. This function will not return until after the NxCoreAPI finishes processing the entire NxCore Tape File. Later, we'll create this function on it's own thread. The first thing we need to do in the start up function is load the NxCoreAPI.dll file which is accomplished by calling the Windows function ::LoadLibrary, illustrated below. Note, all calls to the operating system use the naming convention of beginning with a double colon.


void StartNxCoreAPI()
{
  HMODULE hLib = ::LoadLibrary("NxCoreAPI.dll")
   if( hLib ) {

Loading the NxCoreAPI.dll Library

The Windows function LoadLibrary first searches the current directory, and then the directories specified in the path settings for your computer. You can specify the exact location by including the path in the filename specifier, for example the following code tells Windows to look in the directory "C:\\Program Files\\Nanex\\NxCoreAPI\\NxCoreAPI.dll".


hLib = ::LoadLibrary("C:\\Program Files\\Nanex\\NxCoreAPI\NxCoreAPI.dll"");

(note: Windows documentation warns against using '/' path specifiers). LoadLibrary returns a non-zero value if it is successful. About the only reason it would fail in our example is if the file NxCoreAPI.dll was not present, you mistyped the name, or the NxCoreAPI.dll file is somehow corrupt. If LoadLibrary fails, then call the Windows function ::GetLastError() to find out the reason.

We store the value returned by LoadLibrary in the local variable hLib so that we can unload the NxCoreAPI.dll after we finish processing a tape. It is not necessary to unload the NxCoreAPI.dll right away after processing a tape, but a good practice that will allow you to update the NxCoreAPI.dll without unloading your application should you desire.

Getting the Function Pointers

The next two lines of code call the Windows function ::GetProcAddress, store the returned values in the local variables pfNxSetCallback and pfNxProcessTape, and test that they are non-zero.


NxCoreProcessTape pfNxProcessTape = (NxCoreProcessTape) ::GetProcAddress(hLib,"sNxCoreProcessTape");
if( pfNxProcessTape ) {

The variable pfNxProcessTape is of the type NxCoreProcessTape which is type defined in NxCoreAPI.h. Function pointers require obscure type casting when declaring and when assigning which is the one case where the c construct typedef makes things clearer and more readable. Calling function pointers is the same as calling regular functions, as it uses the same syntax, which we will see in a moment. More on ::GetProcAddress first.

GetProcAddress

The Windows function ::GetProcAddress locates and returns a pointer to a function in a DLL that you can then call. It takes two parameters, an HMODULE, which is simply what was returned from ::LoadLibrary, and the name of the exported function in the DLL. NxCoreAPI.dll exports several functions; here we are only interested in sNxCoreProcessTape. If ::GetProcAddress returns null (0), the most likely cause is the specified name is mistyped. Check the spelling and case.

The sNxCoreProcessTape Function

Calling the dynamically linked function pfNxProcessTape instructs the NxCoreAPI.dll to begin processing an NxCore Tape. sNxCoreProcessTape takes 5 arguments which we see in the following example:


// realtime
pfNxProcessTape("", 0, NxCF_EXCLUDE_CRC_CHECK, 123, OnNxCoreCallback);

// or historical tape
pfNxProcessTape("20050104.AA.nxc", 0, NxCF_EXCLUDE_CRC_CHECK, 123, OnNxCoreCallback);

// or state tape
pfNxProcessTape("20050104.AA.1000.nxstate",0x10000000, NxCF_EXCLUDE_CRC_CHECK | NxCF_MEMORY_ADDRESS, 123, OnNxCoreCallback);

The first argument is a null terminated string containing the filename of the NxCore Tape to process: "20050104.AA.nxc". Tape names use the convention: a 4 digit year (2005), 2 digit zero-padded month (01), 2 digit zero padded day (04), a dot (.), a string of 1 to 5 upper case letters (AA), and finally the NxCore extension (.nxc). To process the current NxCore Feed (real-time stream) , pass an empty string ("") as the first parameter.

The 2nd argument (0) is used for an advanced feature of the NxCoreAPI which is not required and you may never even use. Set this parameter to 0 and ignore it for now.

The 3rd parameter is a 32 bit variable that uses one or more bits to control various aspects of the NxCore Tape processing algorithm. For example, if you had one thread that only processed Trade messages, you could set the control bits to instruct the NxCoreAPI.dll to skip all quote updates to that thread's call back -- significantly improve performance for that thread. In our example, we don't want any special processing so we pass the value 0.

The 4th parameter (123) is a 32 bit variable that you can assign any value, and that value will be stored and available on every update to your callback. A typical use of this parameter is to assign it the address of your class instance (this) or data structure rather than use global variables. The example uses the value of 123 simply to improve readability here.

The final argument is a pointer to your call back function, which is called OnNxCoreCallback in the example. You can use any function name you wish, but it must be one that matches the prototype NxStdCallbackFunction: it must take exactly two arguments "const NxCoreSystem*" and "const NxCoreMessage*", and it must return an int.

The call to pfProcessTape will NOT return until the entire NxCore Tape has been processed, or your callback returns NxCALLBACKRETURN_STOP, or an error is encountered. The callback function (OnNxCoreCallback in this example) will be called once for each trade, quote, level2 quote, status, clock, symbol change and category message as it is processed by NxCoreAPI.dll.

Unloading NxCoreAPI.dll

When pfNxProcessTape returns, the NxCoreAPI.dll will have already closed the Tape it was processing and deallocated all it's memory structures used in processing the specified NxCore Tape. It is a wise practice to unload the NxCoreAPI library by calling ::FreeLibrary as shown in the following line of code:


::FreeLibrary(hLib);

Alternatively, use the "C++" class NxCoreClass

NxCoreClass wraps many of the boiler-plate steps above into an easier-to-use C++ class.