Vous êtes sur la page 1sur 25

     

SPREAD TRADER 3.0

Architect: Rohan S. Patil

GENEVA TRADING
980 N Michigan Avenue
Chicago, IL 60616


     
Index

1. Introduction
Purpose of SpreadTrader and its functionality

2. Background
Describes previous attempts

3. SpreadTrader 3.0
Architecture diagram and description of various components of the SpreadTrader

4. Spread
Architecture diagram and description of various components of a Spread

5. External I/O

User Inputs and system outputs

6. Screen shots
Screen shots of various windows in SpreadTrader 2

7. SpreadTrader 3.0 versus SpreadTrader 2

A comparison

8. Basics of FIX

FIX Architecture

9. Sample Code

Demonstrates use of FIX engine to construct FIX messages

10. Lime Vs REDI

How these third-party APIs work?

11. Conclusion

Looking ahead at SpreadTrader 3.0


     

Introduction

The purpose of developing the SpreadTrader is to trade multi-instrument equity spreads at rapid speeds. It
is designed to provide higher quality execution while minimizing the execution risk. My intent is to
enable the trader to trade multiple spreads simultaneously and to be able to execute spreads at right prices.
I believe that this project will greatly reduce the execution risk resulting in increased profit and free the
user to explore a lot many opportunities in today’s markets. It will directly affect the way trading is
conducted in Maggiore Fund and the use of high end technology would give it an edge.

SpreadTrader essentially is an electronic eye which continuously monitors the equity markets and
computes the pre-defined spread prices. The execution algorithm is activated once certain conditions are
met. Execution of initiating leg is started. The balancing legs are closely monitored for any adverse
change in prices. Further execution depends on whether the right price can be achieved based on the price
of balancing leg and the size available. If initiating leg is filled, balancing leg is activated. The whole
process not only gets the correct price for the spread but also provides tremendous speed of execution.
Please note that execution algorithms can be customized as per the user requirements.


     

Background

Previous attempts of developing a similar system using other platforms are described below:

1. Fall 2008: SpreadTrader 1.0

Platform: Excel / VBA Third Party API: Redi Plus (GS)

Although, scripting in VBA easier from a programming point of view, the speed of execution was
limited. Also, lack of multi-threading capabilities hampered the systems ability to trade multiple
spreads. Having said that, a basic SpreadTrader was built which could handle a 2-3 spreads with a
total of 15-20 stocks.

2. Spring 2009: SpreadTrader 2.0

Platform: C#.NET Third Party API: Redi Plus (GS)

.NET offered both speed of execution and multi-threading capabilities which lacked in the previous
version. However, a new requirement of using Level 2 quotes was added to this SpreadTrader.
Surprisingly, Redi provides L2 data through DDE links which are not supported in .NET.
Additionally, speed with which SpreadTrader could send orders in .NET was restricted by Redi to 3-4
orders per second.


     

SpreadTrader 3.0 : Architecture and description of the components

Spread Trader

SPREAD
FORM 1

CITRIUS® DYNAMIC
DATA
STORAGE

SEND
ORDERS ORDER
(SYNC) OUT

ORDER
EXECUTION
DATA

SPREAD
FORM n

FIX ENGINE

LIME SERVER


     

1. Dynamic Data Storage:

This is essentially a data source which is rapidly updated by Citrius®. A sort algorithm is used to
store the data in ascending (ask prices) and descending (bid prices) order. Stocks contained in this
data are added and removed after a spread is added or removed by the user. Technically, this is a
listener to the data providing API which is updated using RMI (remote method invocation). All the
technicalities are take care of by their class libraries. SpreadTrader simply adds a listener method.
(More on RMI: http://java.sun.com/javase/technologies/core/basic/rmi/whitepaper/index.jsp)

Data acquired from Lime Servers using RMI. (Source: java.sun.com)

2. FIX Engine and FIX communication:

For basic information on Financial Information eXchange (FIX), please refer this.

FIX communication is essential for rapid execution. Orders are sent over the FIX server and status
messages are received at great speeds. SpreadTrader uses FIX for these basic operations. A FIX
engine is used to communicate with the LIME’s FIX server (Note: This is server is different from the
Citrius® server which only provides data). Technically FIX engine provides the required support on
session layer of the OSI model and it provides us with an interface at the Application layer. Later in
this document I explore this interface in detail. Please note that although FIX protocol is standardized,
the FIX API is not. Thus, although the functionality remains the same, syntax for different engines is
different. We may use following free, open source FIX engine but there are other available engines
which come at a cost.


     

QuickFIX/J:

QuickFIX/J is a full featured messaging engine for the FIX protocol. It is a 100% Java open source
implementation of the popular C++ QuickFIX engine. Essential features of this engine can be found
here: http://www.quickfixj.org/.

2. (A) Order Execution Data:

This stores the status messages of the orders sent in the market. This is a static data storage which is
updated at real time speed by the FIX server.

This is read by the spreads running at regular intervals for updates on the orders sent by the spreads.
Each order has a unique id called “SecurityIDSource” which is an encoded string used to identify the
spread that sent the order, long or short leg and the stock number. This greatly reduces the
computational efforts to sort out these messages. SecurityIDSource is attached to the order when it is
sent and it is basically “echoed” back through FIX.

2. (B) FIX Messenger:

This messenger is used to construct the FIX messages. Please refer sample codes in appendix to know
more about how a FIX message is constructed.

2. (B) Send-order sync:

Synchronization of order-sending is achieved using this block of code. It would serialize the orders
when multiple spreads are active and send orders at the same time. It is only a precaution against any
thread-safety issues which “may” arise.


     

Spread : Architecture and description of the components

Blocks using
User settings

DYNAMIC
DDS of SPREADTRADER
DATA
STORAGE

BID / ASK
PRICES, SIZES
CALCULATOR

SPREAD
PRICES

MONITOR
BALANCING PRICE of
BALANCING LEG
LEG INITIATOR
ORDER EXECUTION

START
MONITORING
BALANCING LEG

EXECUTE
INITIATING
LEG
BALANCE To SEND ORDER
(SYNC)
FIX MESSANGER

CANCEL

UPDATE
INVENTORY
DATA UPDATE
SPREAD
DATA

ORDER EXECUTION USER SETTINGS


AND AND
INVENTORY DATA SPREAD DATA


     

1. Dynamic Data Storage:

Similar to the DDS of the SpreadTrader as a whole, every Spread has its own data storage which is
synchronously updated. It is a subset of the SpreadTrader’s DDS and it contains only those stocks
which are part of the concerned spread. Every spread runs a separate thread to delegate the task of
updating the data. This activity continues as long as the spread is open.

2. Calculator:

A calculator, as the name suggests, calculates the spread price using four combinations of bid and ask
prices of long and short legs of the spread. These combinations are Bid / Bid, Bid / Ask, Ask / Bid
and Ask / Ask. Intermediate steps involve calculating long leg on Bid and Ask and short leg on Bid
and Ask. Calculations are done for the sizes executable for each of these four combinations.
Following is the list of variables calculated synchronously by the calculator:

A. Spread Price B. Spread Size

a. Bid / Bid a. Bid / Bid


b. Bid / Ask b. Bid / Ask
c. Ask / Bid c. Ask / Bid
d. Ask / Ask d. Ask / Ask

C. Price of Long Leg D. Size of Long Leg

a. Bid a. Bid
b. Ask b. Ask

E. Price of Short Leg F. Size of Short Leg

a. Bid a. Bid
b. Ask b. Ask

* (Except for sizes of long and short legs sizes every other variable is displayed in GUI)

3. Initiator:

A set of conditions are created based on the user settings (slops, quantity desired, algo trading etc).
These conditions are tested continually by the Initiator. When all the conditions are favorable,
Initiator creates two signals: -

A. Send initiating orders: Details of the initiating orders are sent to the FIX messenger.

B. Start Monitor Balancing Leg (MBL).


     

4. MBL: (Monitor Balancing Leg)

This thread is started once the initiating orders are sent. The main purpose of MBL is to monitor the
price of the balancing leg. If the price of the spread (with fixed price of initiating leg and floating
price of balancing leg) falls out of the required range, MBL generates a signal to cancel the spread
and balances the spreads if the initiating leg is partially filled.

It also monitors the incoming messages from FIX server. After a certain percentage of the initiating
leg is filled, balancing leg orders are sent to hedge our market exposure.

MBL directly communicates with the FIX messenger to cancel orders or send new orders on the
balancing side.

5. User settings and spread data

Mandatory user settings with their default values are listed below:

i. SenderCompID is the required “pre-arranged” account name (Default:Geneva_Trade)

ii. Order Settings: Order types for initiating and balancing leg for long and short side

(Default: Initiating leg : Limit Orders, Balancing leg: Market Orders)

iii. Quantity desired (Default: 1000)

iv. Inside and Outside slops (Default: ±3% of spreadPrice ± 10 cents for inside and
outside respectively)

v. Liquidity constraint (Default: 0%)

vi. Maximum inventory (in case of algo trading). (Default: 5000)

Additionally, certain optional settings can be added later on by the user.

6. Order execution data and inventory:

This block stores the orders sent and is updated synchronously.

10 
     
External I/O
User Inputs:

Single Trade: A single buy or sell trade would require the user to enter the following data:

1. Names of long and short symbols

Stocks traded on any of the available exchanges can be traded using SpreadTrader.
Validation of availability can be done.

2. Corresponding ratios

A ratio is a positive integer or a fraction.

3. Inside and outside slops

An inside slop is used an upper limit on the spread price when one is buying the spread.
Similarly, outside slop is a lower limit on the spread price when the spread is being sold.
While buying the spread, outside slop is not required and while selling the spread inside
slop is not required.

4. Liquidity constraint

It is a proper fraction which is used to determine whether the quantity available on the
balancing side of the spread trader is sufficient to continue the trade. The quantity on the
balancing leg is actually divided by the liquidity constraint to obtain a much higher
quantity which is then compared with the required quantity on the balancing leg.

Maximum Inventory:

This input is used only when the algo trading options is selected. Algo trading is a
continuing process of buys and sells at the prices defined by the inside and outside slops.

Note that once the algo trading option is selected, both the inside and outside slops are
required. Once the price is right SpreadTrader would start executing spread until the
maximum inventory level is reached.

11 
     

System Outputs:

A well-designed GUI is used to display following results of the trades.

1. When the spread is getting executed the user is notified of the execution progress through a
status bar.

2. Buying price and quantity, selling price and quantity along with the total inventory price and
quantity are displayed.

3. Also, a detailed report of the orders executed is also recorded in a data grid.

Screen Shots
1. Log in

12 
     

2. New Spread:

3. Spread:

13 
     
4. Execution:

5. Settings:

14 
     

6. Order grid:

15 
     

SpreadTrader 3.0 vs. SpreadTrader 2

1. Live data reception:

Previously we used REDI Plus for L1 data reception. There were two issues which have been solved
in this system.

a. L2 data was available with DDE links which are quite slow. This is not the case with
Citrius. It provides Level 2 data with tremendous speed in Java.

b. ActiveX controls used in REDI give data updates whenever anything associated with the
symbol changes. This results in unnecessary updates and waste of computational time. In
Citrius, I can subscribe to the fields I want updates on and thus this problem is avoided.

2. Interfaces used:

In REDI Plus, a single interface is used to receive data and to send orders. I believe they use a market
/order router which results in asynchronous time-multiplexing on a single thread. Thus, it reduces
speed. With Lime, I receive the data using Citrius API and sending orders and getting confirmations
is done through the FIX interface. Thus, multiprocessing can be achieved; not to mention it’s much
faster.

3. Order sending:

Speed with which orders can be sent on REDI is restricted to 3-4 orders/ second. On the other hand,
the FIX protocol can handle thousands of messages every second and supports basket orders which
enables us to buy or sell an entire leg (with multiple stocks) with a single message.

4. Simulation environment:

REDI Plus provides two exchange-traded dummy stocks which can be used for testing a program. But
since these two stocks are quite illiquid they are useless to test the speed of execution.

Lime provides a simulation environment wherein I can trade using fake money at real time speeds.

5. Clearing agency for both of them is GSEC.

16 
     

Basics of FIX

(Source: www.onixs.biz)

The Engine provides the following services:

 manages a network connection

 manages the session layer (for the delivery of application messages)

 manages the application layer (defines business related data content)

 creates (outgoing) messages

 parses (incoming) messages

 validates messages

 persists messages (the ability to log data to a flat file)

 session recovery in accordance with the FIX state model

17 
     

FIX message:

Every FIX message consists of three parts. Headers and trailers are explained in the Basic information of
FIX. Following is an example of a FIX message:

8=FIX.4.0\u00019=86\u000135=D\u000149=0\u000156=0\u000134=1\u000152=999909
09-
17:17:17\u000111=90001008\u000121=1\u000155=IBM\u000154=1\u000138=100\u000
140=1\u000159=0\u000110=191\u0001";

Basic building block of the message is a “tag = value” pair. Following table shows some of the tags
usually used in an order message and their values:

Tag Value
ClOrdID 90001008 Unique identifier
Side 1 Buy
TimeInForce 0 Day
OrderType 1 Market
OrderQty 100 Quantity
Symbol IBM Ticker Symbol

In the message u0001 represents a Unicode character which serves as a separator in the tag=value format
of FIX.

e.g.

8 = FIX4.0

Tag 8 marks the beginning of every FIX message. Its value is the version of FIX being used.

9 = 86

Tag 9 follows tag 8. This contains the length of the FIX message; generated by the FIX engine.

38 = 100

Tag 38 contains the order quantity.

18 
     

Sample Code

Following code demonstrates the use of FIX engine. (I hope this helps to allay qualms about using FIX.)

Note that following code is written with QuickFix/ J in mind. Different FIX engines have different
syntaxes but same functionality.

Every FIX message has a header which identifies the FIX message and a trailer which is used for error
detection and possibly error correction.

1. Log in:

FIX protocol is used to communicate with Lime’s server. First step in client –server communication
is the Log in.

Header:

8= “FIX4.2”•9 = “Body Length” • 35 = “A” • 49 = “GENEVA” • 56 = “LIME” • 34 = “1” • 50 =


“”• 57 = “PASSWORD” • 52 = “Current Time”

Body of Message:

98 = “0” • 108 = “15” • 553 = “JOHN” • 554 = “John’s Password”

Trailer:

10 = “Modulo 256 checksum”

2. Log out:

Header:

8= “FIX4.2”•9 = “Body Length” • 35 = “5” • 49 = “GENEVA” • 56 = “LIME” • 34 = “1” • 50 =


“”• 57 = “PASSWORD” • 52 = “Current Time”

Body of Message:

Empty

Trailer:

10 = “Modulo 256 checksum”

19 
     

3. Send Order:

Following is the FIX message to send an order:

Header:

8= “FIX4.2”•9 = “Body Length” • 35 = “D” • 49 = “GENEVA” • 56 = “NYSE” • 34 = “1” • 50 =


“”• 57 = “PASSWORD” • 52 = “Current Time”

Body of Message:

11 = “Client ID” • 55 = “IBM” • 54 = “1” • 38 = “1000” • 40 = “2” • 44 = “75.45” • 100 =


“NYSE” • 59 = “0”

Trailer:

10 = “Modulo 256 checksum”

4. Cancel Order:

Header:

8= “FIX4.2”•9 = “Body Length” • 35 = “F” • 49 = “GENEVA” • 56 = “NYSE” • 34 = “1” • 50 =


“”• 57 = “PASSWORD” • 52 = “Current Time”

Body of Message:

11 = “Client ID” • 41 = “Client ID of the Send Order Message”

Trailer:

10 = “Modulo 256 checksum”

20 
     

Code that creates these messages by employing the API of the FIX engine:

Import QuickFix.*;

1. Log in

Message message = new Message ();

Header:

message.getHeader().setField(new StringField(8, “FIX4.2”));


message.getHeader().setField(new StringField(35, “A”));
message.getHeader().setField(new StringField(49, “GENEVA”));
message.getHeader().setField(new StringField(56, “LIME”));
message.getHeader().setField(new StringField(34, “1”));
message.getHeader().setField(new StringField(50, “”));
message.getHeader().setField(new StringField(57, “PASSWORD”));
message.getHeader().setField(new StringField(35, TimeDate.Now.ToString));

Body of the Message:

message.setField(new StringField(98, “0”));


message.setField(new StringField(108, “15”));
message.setField(new StringField(553, “JOHN”));
message.setField(new StringField(554, “John’s Password”));

Trailer:

Checksum is generated internally when the message is validated.

2. Log out:

Only thing different in the log out message is the type of Message field (i.e. tag 35) which is set
to “5” indicating that it’s a log out message.

Header:

message.getHeader().setField(new StringField(35, “5”));

21 
     

3. Send order:

Header:

message.getHeader().setField(new StringField(35, “D”));

Body:

message.setField(new StringField(11, “Client ID”));


message.setField(new StringField(55, “IBM”));
message.setField(new StringField(54, “1”));
message.setField(new StringField(38, “Quantity”));
message.setField(new StringField(40, “2”));
message.setField(new StringField(44, “75.45”));
message.setField(new StringField(100, “NYSE”));
message.setField(new StringField(59, “0”));

Trailer:

This is generated by the FIX engine.

4. Cancel Order:

Header:

message.getHeader().setField(new StringField(35, “F”));

Body:

message.setField(new String Field(11, “Client ID”);


message.setField(new String Field(41, “Client ID of the order”);

Trailer:

This is generated by the FIX engine.

After the message is constructed, it is sent through the FIX engine using the active “Session”

Session.sendToTarget(message);

Here the target is the Lime Server: IP: 12.189.151.195 Port: 7000

22 
     

Just for comparison:

message.getHeader().setField(new StringField(35, hOrder.Side = ActiveSheet.Range("C8").Value


“D”)); hOrder.symbol =(ActiveSheet.Range("C9").Value)
message.setField(new StringField(11, “ClientID”)); hOrder.Exchange = ActiveSheet.Range("C10").Value
message.setField(new StringField(55, “IBM”)); hOrder.Quantity = ActiveSheet.Range("C11").Value
message.setField(new StringField(54, “1”)); hOrder.Price = ActiveSheet.Range("C12").Value
message.setField(new StringField(38, “Quantity”)); hOrder.PriceType = ActiveSheet.Range("C13").Value
message.setField(new StringField(40, “2”)); hOrder.TIF = ActiveSheet.Range("C15").Value
message.setField(new StringField(44, “75.45”)); hOrder.Account = ActiveSheet.Range("C16").Value
message.setField(new StringField(100, “NYSE”)); hOrder.UserID = ActiveSheet.Range("G2").Value
message.setField(new StringField(59, “0”)); hOrder.Password = ActiveSheet.Range("G3").Value

(Trailer is generated by the FIX engine.)

Session.sendToTarget(message); b = hOrder.Submit(myerr)

(Target: IP and Port of the LIME server)

As you can see, the only difference between using FIX and using REDI is the use of a FIX engine object
“Message” and use of a CacheControl object in REDI for the order construction. Technically, the client
side of LIME consists of the FIX engine and the client side of REDI is defined by its Interop.REDI
library. The application has to make use of the API of these “stubs” and “skeletons”.

23 
     

Difference between using REDI and LIME for execution

In order to understand the difference between the two, let’s first look at the basic structure of a
Distributed Object Communication.

REDI:

Both the stubs and skeleton are implemented by GS and the CacheControl object class can invoke
methods on their server and similarly their server can invoke methods on the CacheControl object. Since
they only provide the limited API of this model (Class library: Interop.Redi), we do not know how the
communication takes place. Usually the data associated with “caller” is serialized into byte-streams and
then sent over the network.(TCP/IP) But the protocol used to define the streaming data, sent over the
network, is unknown to us and will remain so.

LIME:

We know that FIX protocol is used to communicate with the Lime server which then relays the order to
the desired exchange. The stub and skeleton shown in the diagram are implemented in the FIX engine.
(Stub in our engine and skeleton in their).We can select the network but I think TCP / IP would suffice
given that we do not generate enough volume. Also, note that Citrius® is more like REDI (although it
provides L2 data) but the Citrius API and FIX API are different. Thus, FIX is used only for order
execution and management and not for market quotes.

24 
     
Conclusion

Addition of FIX technology to the SpreadTrader not only improves the speed of execution but also
separates out the “GetData” and “SendOrder” functions which are at the heart of this system. This
improves the overall stability of the application. Although, a large amount of Level 2 data is to be handled
in this system, efficient use of multiple threads enables us to compute number of spread prices at any
given time (on different threads, of course.)
The application can be loosely separated into three parts:

1. Handling L2 Market quotes


2. Computing Prices and checking conditions
3. Order Execution and Management system (OMS)

The first part is implemented solely in Java and is not much different than any other third party API.
However, this API (called Citrius®) has many more functions compared to REDI (Refer the Comparison
of SpreadTrader 3.0 vs. SpreadTrader 2.)

Second part reads the live data from Dynamic data storage of the main program, to compute spread prices
and spread sizes. Note that every spread runs on a different thread, thus computations are carried out
independent of each other. All the basic data types in Java are thread-safe for “reading” and “writing” is
done by a single thread (which deals with Citrius®)

The FIX engine works on a lower level (sessions level) and performs the functions necessary to make the
FIX protocol compatible with Java program ( Refer the Functions of FIX engine.) Please note that FIX
communication takes place in “text format” but our program is concerned with only the application level
interface of the FIX engine. We don’t engage in using FIX protocol ourselves; another program (i.e. FIX
engine) does it for us.

25 

Vous aimerez peut-être aussi