Driver

org.otfeed Driver is the client-side library (JAR archive), providing access to the Opentick financial data.

Opentick provides client-side drivers in many languages, including CPP, .NET, and Java. Unfortunately, their Java client has inferior quality as compared to the .NET one. At the time of this writing, their Java client has many bugs and introduction of new features in Java code lag behind as comapred to the .NET client.

org.otfeeed presents to the user a different (better) API, as comapred to Opentick's client. Therefore, org.otfeed client can not be used as a drop-in replacement for the Opentick's client.

Following enumerates the differences between org.otfeed Driver, and Opentick's Java client:

  • Unlike Opentick's code, org.otfeed Driver does not attempt to restore the connection in case it was lost. We feel that such functionality does not belong to the driver layer, but rather should be handled by the application itself. This is because different applications have different tolerance to the data feed delay and data loss or data duplication. Opentick's algorithm for restoring connection guarantees almost certainly that historical data will be duplicated, and real-time data will be lost. Another reason for this decision is that testing such functionality is close to impossible, given the multitude of scenaria how connection may be lost.
  • Unlike Opentick's code, org.otfeed Driver currently collects less information about the source platform. Specifically, when sending a login request, it always reports "unknown" as an OS, "Java" as a platform, and null as a MAC address of local network interface. This decision has no strong reasons behind it, and may be changed in the future. Except that MAC address will never be reported, because it can not be obtained via Java means. Original Opentick's code used platform-specific code that starts OS-level command (like ifconfig) and parses the output. This is not reliable and increases dramatically the driver start-up time.
  • API architecture is completely different. org.otfeed is centered around interfaces, and implements a Command pattern for requests. We believe this architecture is superior to the one provided by Opentick Corporation.
  • org.otfeed is currently at BETA maturity level, while Opentick's code is declared to be production quality. reached production quality (stable release 0.1.0).

Using the Driver Java API

First, download the Driver, save it, and make sure that it is on your Java CLASSPATH.

Download Javadoc reference, or use the online one .

Get familiar with the following important interfaces and classes:

  • org.otfeed.IConnectionFactory the root interface - factory of the connections.
  • org.otfeed.IConnection represents connection to the server.
  • org.otfeed.IRequest represents the handler to a prepared request, allows to sumbit the request, cancel it, etc.
  • org.otfeed.event.IDataDelegate callback interface (a delegate) for receiving the data events (i.e. quotes, trades, etc.).
  • org.otfeed.event.ICompletionDelegate callback interface (a delegate) for receiving end-of-data and error events.

Look into the classes in org.otfeed.command package: these are the commands that can be sent to the server.

Next step is to look at this code that lists all possible exchanges:

import org.otfeed.*;
import org.otfeed.event.*;
import org.otfeed.command.*;
import org.otfeed.support.*;
 
public class ListExchangesSample {
 
    public static void main(String ... av) throws Exception {
 
        /// Create connection factory
        OTConnectionFactory factory = new OTConnectionFactory();
        
        /// Create connection specification, and configure it
        OTConnectionSpec spec = new OTConnectionSpec();
        spec.getHosts().add(new OTHost("feed1.opentick.com:10015"));
        spec.setUsername("your_username");
        spec.setPassword("your_password");
 
        /// Open connection to the server. Use SimpleConnectionStateListener
        /// to monitor connection progress.
        IConnection connection = factory.connect(spec, new SimpleConnectionStateListener());
 
        /// Create the command. Use simple inline implementation
        /// of dataDelegate that just prints the event to the screen.
        ListExchangesCommand command = new ListExchangesCommand();
        command.setDataDelegate(new IDataDelegate<OTExchange>(){
        	public void onData(OTExchange data) {
        		System.out.println(data);
        	}
        });
        command.setCompletionDelegate(new ICompletionDelegate() {
        	public void onDataEnd(OTError error) {
        		if(error != null) {
        			System.err.println("ERROR: " + error);
        		} else {
        			System.out.println("no more data");
        		}
        	}
        });
 
        try {
            /// Prepare the request (nothing is shipped to the server yet)
            IRequest request = connection.prepareRequest(command);
 
            /// Now we have prepared request. Send it to the server.
            request.submit();
 
            /// Wait till request finishes
            request.waitForCompletion();
        } finally {
 
            /// Disconnect from the server
            connection.shutdown();
 
            /// Wait till connection is closed and all resources are freed
            connection.waitForCompletion();
        }
    }
}

This may look like a lot of boilerplate code. But this is the price for flexibility. The good news is that far more complex requests, including multiple historical data downloads, or several streams of realtime ticks can be coded in about the same amount of code.

The most important code in the listing is the one that creates and configures the command:

ListExchangesCommand command = new ListExchangesCommand();
command.setDataDelegate(new IDataDelegate<OTExchange>(){
	public void onData(OTExchange data) {
		System.out.println(data);
	}
});
command.setCompletionDelegate(new ICompletionDelegate() {
	public void onDataEnd(OTError error) {
		if(error != null) {
			System.err.println("ERROR: " + error);
		} else {
			System.out.println("no more data");
		}
	}
});

It actually does three distinct things:
  • creates the command. The one above is pretty simple, but others may requre setting more parameters, including exchange code, ticker symbol code, etc.
  • determines how the data will be received (via IDataDelegate implementation). In the real life you will need a better sink for the data that just printing it to the screen. Luckily, its not hard, and org.otfeed provides some utility classes that help in solving typical tasks (like saving information to a file in a comma-separated values (CSV) format).
  • monitors data stream completion events by registering a completionDelegate. This is optional step.
Another important part is the one that passes an instance implementing IConnectionStateListener to the factory's connect method. This listener is used to monitor the connection status.

Asynchronous processing and threading

Lets take another look at the workflow in the listing. This time we want to stress that all calls there, except the ones that are named waitForCompletion are non-blocking. Specifically, connection instance is returned immediately, while the actual connection process will be happening in a separate thread. We call it the event-dispatching thread.

This means, that we may prepare a request, and event call submit method on the request handle well before the real connection is established. The request will be queued and actually sent to the server after connection is established and a successfull logon completed.

One can submit as many requests as she wishes. The requests will be sent to the server in the order they were submitted. The server will respond, and the resulting events will be dispatched to corresponding data handlers (delegates) in the order they come from the server. Note that this order is not well-defined (it depends on how server is processing the requests: answer to a request that was sent last may come first).

All calls to the delegates are made from the same thread (the event-dispatching thread). Therefore, normally there is no need to synchronize the delegate implementation.

There is one event-dispatching thread per connection. Formally, it is possible to open several simultaneous connections from one factory. However, this is very rarely needed and generally is not recommended, because it gives no real benefits. Its much more effective to use a single connection to submit all your requests. Single connection approach has the advantage of having only one event-dispatching thread, and, therefore, eliminates the need to synchroize objects that are common to multiple connections. It takes less local resources (one socket and three threads per connection), and is capable of processing multiple requests simultaneously.