Table of Contents


Reminder about the const keyword modifier

Note in the code examples that the first formal parameter, pNxCoreSys, is a pointer to a structure of type NxCoreSystem. The c keyword const appears before the two formal variables pNxCoreSys and pNxCoreMsg instructing the compiler the data pointed to by the pointer will not be modified. That is, the data pointed to by pNxCoreSys and pNxCoreMsg will not be modified by your callback function. And here, we come to one of the few rules of processing the NxCoreAPI Feed:

Rule #1. Never change the data in the structures passed to your callback function.

The const keywords are added for your convenience. Should you write code that attempts to modify the data structures NxCoreSystem or NxCoreMessage, the compiler, at compile time, will generate an error. When you pass these pointers, or data members within the structures to other functions, you need to include the const keyword to keep the compiler quiet. As you can see in the sample code, the function we added, processNxCoreStatus also uses the const keyword in the formal parameter list: if it did not, the compiler would have generated an compile-time error. Propagating this const keyword further ensures the other functions don't make the mistake of modifying the contents of these structures.

Callback Return Values

Previously, we learned how to dynamically link to the NxCoreAPI.dll and initiate the processing of NxCore Feed in our call back. We now examine the basic form and function of the callback function. Our callback function looked like this:

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

If you had run this callback code, you would have received only one callback and then the call you made to nxapiProcessTape would have returned. The quick termination was result of our example callback returning NxCALLBACKRETURN_STOP. The other possible callback return values are defined in NxCoreAPI.h as:

#define Value Comments
NxCALLBACKRETURN_CONTINUE 0 Returning this continues the processing and calls into your callback function: millions of "Hello World" printouts (one for each call back) would have flooded your output terminal. This is the normal return value for your callback, barring any unexpected errors
NxCALLBACKRETURN_STOP 1 Returning this terminates processing and halts futher call to your callback function
NxCALLBACKRETURN_RESTART 2 Returning this instructs the NxCoreAPI.dll to restart processing from the beginning of the NxCore Tape

Skeleton Callback

After removing "Hello World", changing the return value, and adding a switch statement with a case for each possible message type, we have a callback which looks like this:

#include "NxCoreAPI.h"
int __stdcall OnNxCoreCallback(const NxCoreSystem* pNxCoreSys, const NxCoreMessage* pNxCoreMsg)
{
    switch( pNxCoreMsg->MessageType ) {
        case NxMSG_STATUS:       break;
        case NxMSG_EXGQUOTE:     break;
        case NxMSG_MMQUOTE:      break;
        case NxMSG_TRADE:        break;
        case NxMSG_CATEGORY:     break;
        case NxMSG_SYMBOLCHANGE: break;
        case NxMSG_SYMBOLSPIN:   break;
    }
    return NxCALLBACKRETURN_CONTINUE;
}

The 7 Message Types

As you can see from the code and defined in NxCoreAPI.h, there are 7 different message types. The second parameter to the callback, pNxCoreMsg, points to a structure of type NxCoreMessage which has the data member MessageType. The switch statement in our callback selects a case statement based on the message type. Briefly, the 7 message types are:

#define Value pNxCoreMessage.coreData Comments
NxMSG_STATUS 0
Sent on initialization, whenever the NxCore millisecond clock changes, if any errors are detected, when a tape completes or restarts, on shutdown and when paused waiting for more data. Nanex Clock changes occur at 25 millisecond intervals when trading is active making this the most frequent reason for receiving a NxMSG_STATUS message.
NxMSG_EXGQUOTE 1 NxCoreExgQuote Sent for every exchange quote (regular quote) and BBO (Exchange-determined Best Bid/Offer). Each quote update includes the bid and ask prices, sizes and condition codes, plus price/size changes. Also for symbols trading on multiple exchanges, each ExgQuote also contains fields with the current values of the best bid/best ask prices, sizes and condition codes. This message type is by far the most active of all messages your callback will receive (depending of course on the exchanges you subscribe to). A typical trading day will have 700+ million option quotes!
NxMSG_MMQUOTE 2 NxCoreMMQuote Sent for every Market Maker Quote ("level 2") from either Nasdaq SuperMontage, Intermarket quotes on Nasdaq issues (e.g. Cincinnati -- ISLD, pacific -- ARCA), or Nasdaq Intermarket quotes on listed (NYSE/AMEX) securities. A typical trading day will have 40+ million or so of these messages. MMQuotes contain Market Maker identifiers and quote types in addition to bid and ask prices, sizes, condition codes and price/size changes. For depth messages, the market makers will be D1/D2/D3/D4/D5 to signify the 5 levels of depth
NxMSG_TRADE 3 NxCoreTrade Sent for every trade (last sale) message. There is an abundance of information included with each trade message you won't find, or will rarely find in other feeds, such as original Exchange Sequence numbers, trade condition processing flags (is the trade elgible to update last, high, low, open?), NxCore QuoteMatch (matches each trade to the recent regional and BBO quotes), NxCore Realtime Trade Filter analysis results, and NxCore Significant High/Low data on each trade message. A typical trading day will have 10+ million of these message types.
NxMSG_CATEGORY 4 NxCoreCategory Sent for all other data types, such as fundamental information, 52 week/contract/YTD high/low data, additional trade correction information, exchange code translations, trade/quote condition code translation, trading halts, trading imbalances, open trade indications, etc. A typical trading day will have 1-2 million or so of these message types, with the bulk of them occurring at the start of each tape summarizing the previous trading session.
NxMSG_SYMBOLCHANGE 5 NxCoreSymbolChange Sent when an issue changes symbols or trading venues (switches exchanges). The most frequent user of this message type are Nasdaq equities changing between Pink Sheets, Bulletin Board, Over-The-Counter, or when the adding/removing the fifth letter 'E' because of a change in delinquency filing status. Also, when option symbols change, each option contract in the series generates one of these messages. Usually the only task you need to perform to handle this type of message is to transfer any UserData1 or UserData2 values from the old symbol to the new symbol.
NxMSG_SYMBOLSPIN 6 NxCoreSymbolSpin Near the beginning of each NxCore tape, the NxCore Feed encodes all the symbols used in the previous trading session. When the NxCoreAPI.dll has processed all the symbols for one exchange, it calls your callback function once for each symbol from that exchange in the order of most active symbol to least active symbol. Each exchange in your Permission Set is iterate. For option contracts, NxCoreAPI.dll calls your function once for every Option Contract (250,000+ from OPRA). All Option Contracts are iterated for an Option Series Symbol before the next Option Series Symbol is iterated (all MSQ options are iterated before IBM options for example). For each symbol spin message, the total number of symbols, option contracts and option symbols are available in data members of NxCoreSymbolSpin allowing you to preallocated an exact number of items/structures. The Symbol Spin message is an excellent place to initialize and prepare your data structures for the next trading session. At any time when your callback is processing a message, you can also force NxCoreAPI.dll to execute a symbol spin for any or all exchanges by calling the exported function SpinSymbols You may find this function to be very useful.

Setting the Callback

The simple example shows how to set the callback function:

#include <windows.h>
#include "NxCoreAPI.h"
#include "NxCoreAPI_class.h" 			 
 			 
NxCoreClass nxCoreClass; 			 
 			 

// The callback
int __stdcall nxCoreCallback(const NxCoreSystem* pNxCoreSys, const NxCoreMessage* pNxCoreMessage)
{
    switch( pNxCoreMsg->MessageType ) {
        case NxMSG_STATUS:       break;
        case NxMSG_EXGQUOTE:     break;
        case NxMSG_MMQUOTE:      break;
        case NxMSG_TRADE:        break;
        case NxMSG_CATEGORY:     break;
        case NxMSG_SYMBOLCHANGE: break;
    }
    return NxCALLBACKRETURN_CONTINUE;
} 			 
 			 
int main(int argc, char** argv)
{
    if (!nxCoreClass.LoadNxCore("NxCoreAPI.dll") &&
        !nxCoreClass.LoadNxCore("C:\\Program Files\\Nanex\\NxCoreAPI\\NxCoreAPI.dll"))
    {
        fprintf(stderr, "Can't find NxCoreAPI.dll\n");
        return -1;
    } 			 
 			 

    // Set the callback function
    nxCoreClass.ProcessTape(argv[1], 0, NxCF_EXCLUDE_CRC_CHECK, 0, nxCoreCallback);
    return 0;
}