Spread Trader 3.0

25
1 SPREAD TRADER 3.0 Architect: Rohan S. Patil GENEVA TRADING 980 N Michigan Avenue Chicago, IL 60616

description

A document on the architecture of the trading system developed for Geneva Trading. Was presented to the Head of Technology at Geneva Trading, Chicago.

Transcript of Spread Trader 3.0

Page 1: Spread Trader 3.0

     

SPREAD TRADER 3.0

Architect: Rohan S. Patil

GENEVA TRADING

980 N Michigan Avenue

Chicago, IL 60616

Page 2: Spread Trader 3.0

     

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

Page 3: Spread Trader 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.

Page 4: Spread Trader 3.0

     

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.

Page 5: Spread Trader 3.0

     

SpreadTrader 3.0 : Architecture and description of the components

SPREADFORM 1

SPREADFORM n

SENDORDERS(SYNC)

ORDEROUT

CITRIUS® DYNAMIC DATA

STORAGE

ORDEREXECUTION

DATA

FIX ENGINE

LIME SERVER

Spread Trader

Page 6: Spread Trader 3.0

     

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.

Page 7: Spread Trader 3.0

     

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.

Page 8: Spread Trader 3.0

     

Spread : Architecture and description of the components

DYNAMIC DATA

STORAGE

USER SETTINGSAND

SPREAD DATA

ORDER EXECUTION AND

INVENTORY DATA

FIX MESSANGER

MONITORBALANCING

LEG

CALCULATOR

INITIATOR

DDS of SPREADTRADER

ORDER EXECUTION

BALANCE

CANCEL

UPDATESPREAD

DATA

UPDATEINVENTORY

DATA

EXECUTEINITIATING

LEG

STARTMONITORING

BALANCING LEG

Blocks using User settings

To SEND ORDER(SYNC)

SPREADPRICES

PRICE of BALANCING LEG

BID / ASK PRICES, SIZES

Page 9: Spread Trader 3.0

     

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).

Page 10: Spread Trader 3.0

     

10 

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.

Page 11: Spread Trader 3.0

     

11 

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.

Page 12: Spread Trader 3.0

     

12 

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

Page 13: Spread Trader 3.0

     

13 

2. New Spread:

3. Spread:

Page 14: Spread Trader 3.0

     

14 

4. Execution:

5. Settings:

Page 15: Spread Trader 3.0

     

15 

6. Order grid:

Page 16: Spread Trader 3.0

     

16 

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.

Page 17: Spread Trader 3.0

     

17 

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

Page 18: Spread Trader 3.0

     

18 

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=99990909-17:17:17\u000111=90001008\u000121=1\u000155=IBM\u000154=1\u000138=100\u000140=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.

Page 19: Spread Trader 3.0

     

19 

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”

Page 20: Spread Trader 3.0

     

20 

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”

Page 21: Spread Trader 3.0

     

21 

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”));

Page 22: Spread Trader 3.0

     

22 

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

Page 23: Spread Trader 3.0

     

23 

Just for comparison:

message.getHeader().setField(new StringField(35, “D”)); message.setField(new StringField(11, “ClientID”)); 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 is generated by the FIX engine.) Session.sendToTarget(message);

(Target: IP and Port of the LIME server)

hOrder.Side = ActiveSheet.Range("C8").Value hOrder.symbol =(ActiveSheet.Range("C9").Value) hOrder.Exchange = ActiveSheet.Range("C10").Value hOrder.Quantity = ActiveSheet.Range("C11").Value hOrder.Price = ActiveSheet.Range("C12").Value hOrder.PriceType = ActiveSheet.Range("C13").Value hOrder.TIF = ActiveSheet.Range("C15").Value hOrder.Account = ActiveSheet.Range("C16").Value hOrder.UserID = ActiveSheet.Range("G2").Value hOrder.Password = ActiveSheet.Range("G3").Value

b = hOrder.Submit(myerr)

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”.

Page 24: Spread Trader 3.0

     

24 

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.

Page 25: Spread Trader 3.0

     

25 

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.