Table of Contents


NxMSG_CATEGORY message

The second parameter to the NxCoreCallback function, NxCoreMessage, holds the symbol and session information in pNxCoreMessage->coreHeader, and data information in pNxCoreMessage->coreData.Category, which is a NxCoreCategory data structure.

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.

Importance of SessionDate

It is critical that you look at the pNxCoreMessage->coreHeader.nxSessionDate for every Category, and ensure it's the date you need. Some category messages come in multiple times per day, for the same symbol -- but the data in them is for different dates. Good example of that is the OpenInterest category.

A simple (but incomplete) way of checking if something is "too old" is something like this:

    // if this message's is for a session that's over a week old, skip it
    if (pNxCoreMessage->coreHeader.nxSessionDate.NDays + 7 < pNxCoreSys->nxDate.NDays)
    {
        // skip
    }

Importance of NxCategoryField.Set field

It is critical that you look at the NxCategoryField.Set value for every Category field, and ensure it's set to 1 to make sure the data for that field is present in the current Category message. Some category messages come in multiple times per day, for the same symbol -- but the data in them contains only the fields that changed and not every field in the entire category.

See the code example at the bottom of this page that shows a good technique for accomplishing this.

Simplest example

Here's the simplest example.

#include <NxCoreAPI.h>
int processNxCoreCategory(const NxCoreSystem* pNxCoreSys, const NxCoreMessage* pNxCoreMsg)
{
    return NxCALLBACKRETURN_CONTINUE;
}
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:     return processNxCoreCategory(pNxCoreSys, pNxCoreMsg);
        case NxMSG_SYMBOLCHANGE: break;
        case NxMSG_SYMBOLSPIN:   break;
    }
    return NxCALLBACKRETURN_CONTINUE;
}

Example

Here's an example category dumper that reflectively pretty-prints out every category

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>

#include "NxCoreAPI.h"
#include "NxCoreAPI_class.h"

NxCoreClass nxCoreClass;

void categoryDump(const NxCoreSystem* pNxCoreSys, const NxCoreMessage* pNxCoreMessage)
{
    const NxCoreHeader   &ch  = pNxCoreMessage->coreHeader;
    const NxCoreCategory &cat = pNxCoreMessage->coreData.Category;

    char option[128] = {0};

    if (ch.pnxOptionHdr)
    {
        if (ch.pnxOptionHdr->pnxsDateAndStrike)
        {
            int n = sprintf(option, "Root='%s' Symbol='%s%c%c'",
                    ch.pnxStringSymbol->String,
                    ch.pnxStringSymbol->String + 1,
                    ch.pnxOptionHdr->pnxsDateAndStrike->String[0],
                    ch.pnxOptionHdr->pnxsDateAndStrike->String[1]);
            if (ch.pnxOptionHdr->pnxsUnderlying)
            {
                sprintf(option + n, " Underlying='%s'",
                    ch.pnxOptionHdr->pnxsUnderlying->String);
            }
        }
    }

    printf("Category         : %s(%ld)\n",          cat.pnxStringCategory->String, cat.pnxStringCategory->Atom);
    printf("  nxTime         : %.2d:%.2d:%.2d\n",   (int) pNxCoreSys->nxTime.Hour, (int) pNxCoreSys->nxTime.Minute, (int) pNxCoreSys->nxTime.Second);
    printf("  symbol         : %s\n",               ch.pnxStringSymbol->String);
    printf("  pnxOptionHdr   : %s\n",               option);
    printf("  listedExch     : %ld\n",              ch.ListedExg);
    printf("  sessionDate    : %d%.2d%.2d\n",       (int) ch.nxSessionDate.Year, (int) ch.nxSessionDate.Month, (int) ch.nxSessionDate.Day);
    printf("  time           : %.2d:%.2d:%.2d\n",   (int) ch.nxExgTimestamp.Hour, (int) ch.nxExgTimestamp.Minute, (int) ch.nxExgTimestamp.Second);
    printf("  reportExch     : %ld\n",              ch.ReportingExg);
    printf("  sessionId      : %ld\n",              (int) ch.SessionID);
    printf("  permissionId   : %ld [%s]\n",         ch.PermissionID, nxCoreClass.GetDefinedString(NxST_PERMID, ch.PermissionID));
    printf("  NFields        : %ld\n",              cat.NFields);

    for (int i = 0; i < cat.NFields; i++)
    {
        const NxCategoryField& cf = cat.pnxFields[i];

        printf("     %ld|%s|[%s] {%ld} :", i, cf.FieldName, cf.FieldInfo, (int) cf.Set);

        if (!cf.Set)
        {
            printf("  -- !Set --\n");
            continue;
        }

        switch (cf.FieldType)
        {
            case NxCFT_UNKNOWN:
            {
                printf("  -- unknown --");
                break;
            }
            case NxCFT_64BIT:
            {
                printf("  %I64d", cf.data.i64Bit);
                break;
            }
            case NxCFT_32BIT:
            {
                printf("  %ld", cf.data.i32Bit);
                break;
            }
            case NxCFT_STRINGZ:
            {
                printf("  %s", cf.data.StringZ);
                break;
            }
            case NxCFT_DOUBLE:
            {
                printf("  %lf", cf.data.Double);
                break;
            }
            case NxCFT_PRICE:
            {
                printf("  %.2lf", nxCoreClass.PriceToDouble(cf.data.nxPrice.Price, cf.data.nxPrice.PriceType));
                break;
            }
            case NxCFT_DATE:
            {
                printf("  %d%.2d%.2d",  (int) cf.data.nxDate.Year, (int) cf.data.nxDate.Month, (int) cf.data.nxDate.Day);
                break;
            }
            case NxCFT_TIME:
            {
                printf("  %.2d:%.2d:%.2d.%.3d", (int) cf.data.nxTime.Hour, (int) cf.data.nxTime.Minute, (int) cf.data.nxTime.Second, (int) cf.data.nxTime.Millisecond);
                break;
            }
            case NxCFT_NxSTRING:
            {
                if (cf.data.pnxString)
                {
                    const NxString& s = (const NxString&) *cf.data.pnxString;
                    printf("  '%s'", s.String);
                }
                break;
            }
            case NxCFT_STRING_IDX:
            {
                const StringTableItem& stItem = (const StringTableItem&) cf.data.stringTableItem;
                const char* ss = nxCoreClass.GetDefinedString(stItem.ixTable, stItem.idString);
                if (!ss)
                {
                    ss = "***NULL***";
                }
                printf("  [%ld:%ld] '%s'", stItem.ixTable, stItem.idString, ss);
                break;
            }
            case NxCFT_STRING_MAP:
            {
                const StringTableItem& stItem = (const StringTableItem&) cf.data.stringTableItem;
                bool printed = false;
                unsigned int id = stItem.idString;
                for (int i = 0; id; ++i, id >>= 1)
                {
                    if (id & 1)
                    {
                        const char* ss = nxCoreClass.GetDefinedString(stItem.ixTable, i);
                        if (!ss)
                        {
                            ss = "***NULL***";
                        }
                        if (!printed)
                        {
                            printf("  [%ld:%ld] '%s'", stItem.ixTable, i, ss);
                            printed = true;
                        }
                        else
                        {
                            printf(",  [%ld:%ld] '%s'", stItem.ixTable, i, ss);
                        }
                    }
                }
                break;
            }
        }

        printf("\n");
    }
}

int __stdcall nxCoreCallback(const NxCoreSystem* pNxCoreSys, const NxCoreMessage* pNxCoreMessage)
{
    switch (pNxCoreMessage->MessageType)
    {
        case NxMSG_CATEGORY:
        {
            categoryDump(pNxCoreSys, pNxCoreMessage);
            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;
    }
    nxCoreClass.ProcessTape(argv[1], 0, NxCF_EXCLUDE_CRC_CHECK | NxCF_EXCLUDE_QUOTES | NxCF_EXCLUDE_QUOTES2, 0, nxCoreCallback);
    return 0;
}