API Documentation

Language: C++ Java Python
Basic: Intro/Trade Quote Category Status Symbol Options
Detailed: Trade Quote

Introduction to Options

This example should use the demo.DO.nx2 tape instead of demo.XU.nx2. Messages for option contracts are very similar to messages for equities. The primary difference is the addition of pnxOptionHdr to the coreHeader object. The major challenge for options processing is the number of messages. In addition to parsing options messages, this guide will also cover some recommended performance improvements.

Code

import net.nanex.NxCoreClass;
class OptionSample {
    public static void main(String args[]) throws InterruptedException {
        if(args.length < 2)
            return;

        Thread[] threads = {
            new Thread(new NxCoreThread(args[0],args[1],2)),
            new Thread(new NxCoreThread(args[0],args[1],20)),
            new Thread(new NxCoreThread(args[0],args[1],21)),
            new Thread(new NxCoreThread(args[0],args[1],22))
        };
        for(Thread thread : threads)
            thread.start();
        for(Thread thread : threads)
            thread.join();
    }
}

class NxCoreThread extends NxCoreClass implements Runnable {
    private String library;
    private String filename;
    private int threadPermission;
    private boolean successfulExclude = false;

    public NxCoreThread(String libraryPath, String tapePath,int perm) {
        this.library = libraryPath;
        this.filename = tapePath;
        this.threadPermission = perm;
    }

    public void run() {
        if(LoadNxCore(library) != 0){
            int returnValue = ProcessTape(filename, 0, defines.NxCF_EXCLUDE_CRC_CHECK | defines.NxCF_EXCLUDE_QUOTES, 0);
            ProcessReturnValue(returnValue);
        }
        else
            System.out.println("loading library failed");
    }

    @Override
    public int OnNxCoreCallback( NxCoreSystem nxCoreSys, NxCoreMessage nxCoreMsg) {
        if (nxCoreMsg.MessageType == defines.NxMSG_STATUS && !successfulExclude) {
            int[] optionPermissions = {2, 20, 21, 22};
            for (int permission : optionPermissions) {
                if (threadPermission != permission && ExcludeOpraExch(defines.NxPERMID_REMOVE | permission) != 0)
                    return defines.NxCALLBACKRETURN_CONTINUE;
            }
            successfulExclude = true;
        }
        if (nxCoreMsg.MessageType ==  defines.NxMSG_TRADE) {
            NxCoreHeader header = nxCoreMsg.coreHeader;
            NxOptionHdr optionHeader = header.pnxOptionHdr;
            if (optionHeader != null){
                String symbol = header.pnxStringSymbol.String;
                NxTime timestamp = header.nxExgTimestamp;
                NxDate expireDate = optionHeader.nxExpirationDate;
                double strikePrice = PriceToDouble(optionHeader.strikePrice, 7);
                String contractType;
                if (optionHeader.PutCall == 1)
                    contractType = "Put";
                else
                    contractType = "Call";

                NxCoreTrade trade = nxCoreMsg.coreData.Trade;
                double price = PriceToDouble(trade.Price,trade.PriceType);
                int size = trade.Size;

                System.out.println("Trade for " + symbol + " " + contractType + " expiring "
                    + String.format("%d%02d%02d", expireDate.Year, expireDate.Month, expireDate.Day)
                    + "with strike $" + String.format("%.2f", strikePrice) + " at "
                    + String.format("%02d:%02d:%02d", timestamp.Hour, timestamp.Minute, timestamp.Second)
                    + " for " + size + " shares at $" + String.format("%.2f", price));
            }
        }
        return defines.NxCALLBACKRETURN_CONTINUE;
    }
}

Splitting data

One way of improving performance is limiting what part of the options feed is processed on a thread. Nanex splits the option feed into 4 permissions 2, 20, 21, and 22 each corresponding to different ranges of option roots. The function ExcludeOpraExch is used to remove a permission from processing. By removing all option permissions except for the one assigned to threadPermission, each thread will only process a quarter of the data.

if (nxCoreMsg.MessageType == defines.NxMSG_STATUS && !successfulExclude) {
    int[] optionPermissions = {2, 20, 21, 22};
    for (int permission : optionPermissions) {
        if (threadPermission != permission 
            && ExcludeOpraExch(defines.NxPERMID_REMOVE | permission) != 0)
            return defines.NxCALLBACKRETURN_CONTINUE;
    }
    successfulExclude = true;
}

Option Header

Option contract information is contained within pnxOptionHdr in the coreHeader object. For this example we will get the expiration date, strike price, and put/call. The strike price always has a price type of 7.

NxCoreHeader header = nxCoreMsg.coreHeader;
NxOptionHdr optionHeader = header.pnxOptionHdr;
if (optionHeader != null){
    String symbol = header.pnxStringSymbol.String;
    NxTime timestamp = header.nxExgTimestamp;
    NxDate expireDate = optionHeader.nxExpirationDate;
    double strikePrice = PriceToDouble(
        optionHeader.strikePrice, 7);
    String contractType;
    if (optionHeader.PutCall == 1)
        contractType = "Put";
    else
        contractType = "Call";

    ...
}

Thread Constructor

the NxCoreThread object is created with the parameters necessary to process the file.

public NxCoreThread(String libraryPath, String tapePath,int perm) {
    this.library = libraryPath;
    this.filename = tapePath;
    this.threadPermission = perm;
}

Process Tape Flags

To improve performance we are going to use two control flags, joined by a bitwise or, as the 3rd argument of ProcessTape. NxCF_EXCLUDE_CRC_CHECK disables frequent CRC calculations. CRC checks will still be performed, but not as frequently. Since we are only processing trades in this example we will also set NxCF_EXCLUDE_QUOTES which prevents all quote messages from being sent to the Java callback.

int returnValue = ProcessTape(
    filename,
    0,
    defines.NxCF_EXCLUDE_CRC_CHECK | defines.NxCF_EXCLUDE_QUOTES, 
    0);

Launching Threads

On the main thread we first create an array of Runnable objects with the 4 different option permission value. Next, we start each process. Then, we wait for every process to finish.

Thread[] threads = {
    new Thread(new NxCoreThread(args[0],args[1],2)),
    new Thread(new NxCoreThread(args[0],args[1],20)),
    new Thread(new NxCoreThread(args[0],args[1],21)),
    new Thread(new NxCoreThread(args[0],args[1],22))
};
for(Thread thread : threads)
    thread.start();
for(Thread thread : threads)
    thread.join();