CIS Trade-Model Code Generator

To help you integrate your XML trade model into your trading application, CIS 6 provides a code generator that creates the necessary Java code from a single command line instruction.

Purpose and location

The code generator, like the CIS Command Line Toolkit, is a jar file that can be found in the tools directory of the unzipped CIS Toolkit. The name of the file will change from time to time, but it will always use the following structure:

trading-datasource-code-generator-[version number]-[build number].jar

For example:

trading-datasource-code-generator-6.0.1-253872.jar

If you’ve got an XML trade model set up, you can simply run the Generator, and it will parse the XML and set up all the necessary interfaces, classes and methods to write the bridging code for it (such as listeners and event-handlers, with getters and setters for any field values defined in the XML <transition> tags).

Running the code generator

To run the Code Generator, you’ll need to have an XML file set up, containing one or more trade models. If the XML contains more than one trade model, you can either nominate a particular model to generate code for, or you can allow the Generator to create code for all the trade models in the file. From the command line, enter a command with the following structure:

java -jar  code-generator-jar  src package  templates-dir  model-file  [model-name]

This command is composed of the following:

If any of the file paths included in these arguments are relative paths, they will be calculated from the location of the command prompt. If an argument contains spaces, that argument should be in quotation marks.
Parameter Description

code-generator-jar

The name of the Code Generator jar file, including the path to it from the command prompt if necessary.

src

The location of the root directory in which the code will be generated.

package

The name of the Java package to be used for the generated code.

templates-dir

The directory containing the code templates that the generator uses; usually the CIS Toolkit’s tools/templates/java directory.

The Code Generator uses the open-source Apache Velocity template engine.

model-file

The name and location of the XML file that contains the trade model for which you are generating the code.

model-name

Optional. The name of a particular trade model within the model-file you specified (i.e. the name attribute of the <trademodel> element). If this is omitted, classes will be generated for all trade models in the file.

Code generation example

Let’s assume that we have a trade model called models.xml, located in the tools/xml directory of the CIS Toolkit, which looks like this:

/tools/xml/models.xml
<tradeModels>
  <tradeModel name="ESP" initialState="Initial">
    <state name="Initial">
      <transition target="OpenSent" trigger="Open" source="client">
        <field name="StateModelName" description="ESP model name" required="true" />
        <field name="RequestID" description="Request ID" required="true" />
        <field name="QuoteID" description="Quote ID" required="true" />
        <field name="InstrumentName" description="Instrument Name" required="true" />
        <field name="DealtCurrency" description="Dealt currency" required="true" />
        <field name="BuySell" description="BuySell indicator" required="true" />
        <field name="Price" description="Price" />
      </transition>
    </state>
    <state name="Timeout" />
    <state name="OpenSent" timeout="10" timeoutState="Timeout">
      <transition target="Opened" trigger="OpenAck" source="server">
        <field name="RequestID" description="Request ID" required="true" />
        <field name="StateModelName" description="ESP model name" required="true" default="ESP" />
        <field name="BuySell" description="BuySell indicator" required="true" default="BUY" />
      </transition>
    </state>
    <state name="Opened" timeout="10" timeoutState="Timeout">
      <transition target="TradeConfirmed" trigger="TradeConfirmation" source="server">
        <field name="RequestID" description="Request ID" required="true" />
        <field name="TradeID" description="Request ID" required="true" />
      </transition>
      <transition target="TradePassed" trigger="Pass" source="server" />
      <transition target="TradeExpired" trigger="Expired" source="server" />
    </state>
    <state name="TradeConfirmed" />
    <state name="TradePassed" />
    <state name="TradeExpired" />
  </tradeModel>
</tradeModels>
Because the Generator will use the name and trigger attributes to create Java classes, it’s important to ensure that they conform to Java class naming conventions; i.e. alphanumeric characters only, with an initial capital letter and using "CamelCase".

You might then use the following command, entered from the tools directory of the unzipped CIS Toolkit:

java -jar trading-datasource-code-generator-6.0.1-253872.jar samplesrc example.generated templates/java xml/model.xml ESP

Breaking this down into its component parts, this would do the following:

Command component Description

java -jar trading-datasource-code-generator-6.0.1-253872.jar

Runs the Trade Model Code Generator script.

samplesrc

Specifies that the name of the root directory in which our new code will be created is called samplesrc. It will be created (if it doesn’t exist already) in the command line’s working directory.

example.generated

Defines a Java package in which the code will be generated. Combined with the samplesrc parameter above, this means that the code will be generated in the samplesrc/example/generated directory.

templates/java

The location of the Generator’s code templates, relative to the working directory.

xml/model.xml

The name and location of the XML file containing the trade model (again, relative to the working directory).

ESP

The name of the trade model for which we want to generate code. As our XML contains only one <trademodel> element, we could omit this, but if it contained others, this parameter would allow us to generate code only for the specified model.

What code is generated?

The Code Generator creates all necessary interfaces, classes and methods needed for your trade model, and includes the generic classes and interfaces from the Caplin Trading API, to integrate your trade model with a fully functional trading system. You’ll be happy to hear that all the code created by the Generator contains extensive comments to help you understand what the various interfaces, classes and methods are doing.

Code shared between trade models

In the directory you specified in the [package] argument of your command (in our example this is the example/generated directory), there will be two files that are common to all the trade models for which you’ve generated code:

TradingAdapter.java

This defines the TradingAdapter class, which implements the TradingApplicationListener and TradeChannelListener interfaces, and acts as a wrapper for the whole trading library.

CleanupListener.java

This file defines the CleanupListener interface, which is used to initiate clean-up operations after a trade (whether or not the trade has completed successfully).

Code specific to the trade model

Within the [package] directory will be a separate directory with the name of each trade model for which code has been generated. In our case, there’s only one: example/generated/esp. These contain four java files that are specific to the trade models themselves, and an additional java file for each <transition> element in the trade model that contains one or more <field> tags.

Filename Format Filenames in this Example

[ModelName]Trade.java

ESPTrade.java

[ModelName]TradeListener.java

ESPTradeListener.java

[ModelName]TradeListenerAdapter.java

ESPTradeListenerAdapter.java

[ModelName]TradeListenerFactory.java

ESPTradeListenerFactory.java

[TransitionTriggerName]TradeEvent.java

OpenTradeEvent.java, OpenAckTradeEvent.java, TradeConfirmationTradeEvent.java

[ModelName]Trade.java

This defines the [ModelName]Trade class (ESPTrade in our example), which implements the Trade interface and represents a particular trade. It also imports the valid responder classes that have been created for this trade model (see below).

[ModelName]TradeListener.java

This defines a TradeListener interface for this trade model, which in our example, would be: ESPTradeListener.

A class that implements it would "listen" for the client action that initiates the trade process, based on the <transition> tag’s trigger attribute, and would then use that action’s TradeEvent to create a new trade.

The interface identifies the methods called if invalid transitions or fields occur, and defines the CleanUp() method for this trade model.

For Example:

The first client action defined in the ESP trade model is "Open", as shown in the XML below:

xml/model.xml
<transition target="OpenSent" trigger="Open" source="client">

The ESPTradeListener interface listens for the Open trigger, and then calls the TradeEvent associated with that transition (OpenTradeEvent), as shown here:

samplesrc/example/generated/esp/ESPTradeListener.java
public interface ESPTradeListener

{

public void onOpen(OpenTradeEvent event);

...

}

[ModelName]TradeListenerAdapter.java

This defines a TradeListenerAdapter class for this trade model, implementing the TradeListener and CleanUpListener interfaces.

[ModelName]TradeListenerFactory.java

This defines a TradeListenerFactory interface, which enables you to use a factory class for this trade model, giving you a simple way to create new instances of TradeListener classes for it.

In our example, this would be: ESPTradeListenerFactory.

[TransitionTrigger]TradeEvent.java

Each <transition> element that contains one or more <field> tags will produce a class that implements the TradeEvent interface, with get() and set() methods for the defined fields. If any of the fields have default values, they will be included in the generated code. The class will be named after the trigger attribute of the <transition> it describes.

In our example, this would generate three classes, OpenTradeEvent, OpenAckTradeEvent and TradeConfirmationTradeEvent.

It’s possible for a trade model to have more than one transition with the same trigger name, but if so, all such transitions must have the same fields. If you want one transition to have different fields, you’ll have to give it a different name! Transitions that don’t contain any fields don’t have a custom class generated for them, and are handled using the generic TradeEvent class.

Responders

[StateName]Responder.java

Each trade model also has a responders directory generated for it. This contains a java file for each <state> element in the trade model that contains at least one <transition> tag. Each of these files contains a class called [StateName]Responder, which defines a method for each valid transition from that state, as defined in the trade model. These methods will be named after the trigger attributes of the applicable <transition> tags.

In our example, the states containing transitions are Initial, Opened and OpenSent, so the responder classes generated are InitialResponder, OpenedResponder and OpenSentResponder.

For Example:

The OpenSent state contains a single transition, the trigger of which is OpenAck, as we can see here:

xml/model.xml
<state name="OpenSent" timeout="10" timeoutState="Timeout">
    <transition source="server" target="Opened" trigger="OpenAck">
        <field description="Request ID" name="RequestID" required="true"/>
    </transition>
</state>

The Code Generator therefore creates a class called OpenSentResponder, which, since there’s only one valid transition from this state, contains only one method: sendOpenAckTradeEvent(), which calls the OpenAckTradeEvent class generated to handle that transition type, as shown below:

samplesrc/example/generated/esp/responders/OpenSentResponder.java
public class OpenSentResponder
{
       Trade trade;

       public OpenSentResponder(Trade trade)
       {
              this.trade = trade;
       }

       public void sendOpenAckEvent(OpenAckTradeEvent event)  throws TradeException
       {
              trade.sendEvent(event);
       }

}

A point to remember about generated code

The thing about generated code, is that it’s…​ well…​ generated. The interfaces, classes and methods are there to make your life easier, because they are designed to let you integrate trade models into your trading system, keeping the need for manually produced code and the likelihood of errors to a minimum.

It’s strongly recommended though, that you don’t actually edit the generated code, not least because if you generate code using the same parameters again (maybe because you’ve added an extra field to your trade model), the Code Generator will overwrite any existing files with new versions.

That’s not to say that you won’t have to write a bit of your own code in order to implement the trade model into your own application, but we’d strongly advise you to keep it separate from the code produced by the Generator.

So what code do I have to write myself?

Once the Generator has done its stuff, you’ll still have to write a small amount of code yourself, to serve as an entry point into the trade and to create implementations of some of the classes that have been generated. The code you’ll need is going to vary depending on the nature of your application (not to mention your trade model), but some examples are provided to give you an idea of what you’ll need. The examples given fit in with the ESP trade model shown earlier, and the code that the Generator produced for it. Note that the ESP trade model is a very simple example, and almost anything else you do will be more complicated!

As an example, we’ve produced three files that would implement the ESP trade model, using the generated files, and which we’ve given similar names to the classes they implement or instantiate. We’ve put them in the example folder, within the generated directory structure, but above the level of any of the generated files themselves.

MyTradingAdapter

samplesrc/example/MyTradingAdapter.java
package example;

import com.caplin.datasource.DataSource;
import example.generated.TradingAdapter;
import java.io.IOException;

public class MyTradingAdapter {

   public MyTradingAdapter(DataSource datasource) throws IOException {
       TradingAdapter adapter = new TradingAdapter(datasource);

       adapter.registerTradeListenerFactory(new MyESPTradeListenerFactory());
   }

}

This would be the entry point for the trade, and includes the generated TradingAdapter class, as well as Caplin’s DataSource interface. It creates a new instance of TradingAdapter, and registers MyESPTradeListenerFactory - the second of the three implementation classes we’ve written - as a new ESPTradeListenerFactory, using the registerTradeListenerFactory() method from the TradingAdapter class.

MyESPTradeListenerFactory

samplesrc/example/ MyESPTradeListenerFactory.java
package example;

import com.caplin.trading.TradeException;
import example.generated.esp.ESPTrade;
import example.generated.esp.ESPTradeListener;
import example.generated.esp.ESPTradeListenerFactory;

public class MyESPTradeListenerFactory implements ESPTradeListenerFactory {
    @Override
    public ESPTradeListener createESPTradeListener(ESPTrade trade) throws TradeException
    {
        return new MyESPTradeListener();
    }
}

The MyESPTradeListenerFactory class (which has been registered by MyTradingAdapter) implements the ESPTradeListenerFactory interface. It uses the generated ESPTradeListener and ESPTrade classes in order to create a new instance of MyESPTradeListener.

MyESPTradeListener

Now our trading adapter has registered the factory class, which in turn has created an instance of MyESPTradeListener, this is really where it all happens.

First, we import all of the classes generated for the ESP trade model, as well as a couple of classes from the Caplin Trading API to handle invalid fields or transitions, and then we create our MyESPTradeListener class, implementing the ESPTradeListener interface that the Code Generator conveniently created for us.

samplesrc/example/MyESPTradeListener.java
package example;

import com.caplin.trading.InvalidFieldsEvent;
import com.caplin.trading.InvalidTransitionEvent;
import example.generated.esp.*;

public class MyESPTradeListener implements ESPTradeListener {
    public MyESPTradeListener()
    {

    }

We then need an event-handler to pick up when a user initiates an ESP trade. As we established earlier, there’s only one actual event in the ESP trade model that comes from the client, which is initiated by the Open trigger. Having detected it, we then want to call the appropriate class for this kind of trade event; in this case an OpenTradeEvent.

samplesrc/example/MyESPTradeListener.java (continued...)
@Override
    public void onOpen(OpenTradeEvent event) {

Once a user has triggered the OpenTradeEvent, we need to be able to handle the trade events that might come back from the server, and we’ll also want to make sure that the trade was in the correct state when those events occur. As the Code Generator has already given us a TradeEvent class for each event that can occur in our trade model, get() and set() methods for all the fields associated with those events, and responder classes to ensure that we know which events are valid from which states, this is all quite easy to do:

samplesrc/example/MyESPTradeListener.java (continued...)
try {

            OpenAckTradeEvent ackEvent = new OpenAckTradeEvent(event.getESPTrade());
              // Fields for OpenAckTradeEvent
              ackEvent.setRequestID(event.getRequestID());

event.getESPTrade().getOpenSentResponder().sendOpenAckEvent(ackEvent);

            TradeConfirmationTradeEvent confirmEvent = new TradeConfirmationTradeEvent(event.getESPTrade());
              // Fields for TradeConfirmationTradeEvent
              confirmEvent.setRequestID(event.getRequestID());
              confirmEvent.setTradeID(event.getTradeID());

event.getESPTrade().getOpenedResponder().sendTradeConfirmationEvent(confirmEvent);

        } catch (Exception e) {

        }
    }

Finally, if we do catch any invalid transitions, or events that don’t have the required fields, we can use the classes we imported from the Caplin Trading API in order to handle them, and also clean up afterwards.

samplesrc/example/MyESPTradeListener.java (continued...)
@Override
    public void receiveInvalidTransitionEvent(InvalidTransitionEvent event) {
        // An invalid transition has been received from the client
    }

    @Override
    public void receiveInvalidFieldsEvent(InvalidFieldsEvent event) {
        // An event from the client has been received without the required fields
    }

    @Override
    public void doCleanup(ESPTrade trade) {
        // Cleanup after the trade. This doesn't necessarily mean that the trade has completed!
    }
}

Remember that ESP is a very simple, one-click trade model. Most trades will require more user interaction than this, and would therefore need to capture more than one client-sourced event, not to mention quite a few more states, transitions and fields.