Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Java RTS Real-Time Enables Financial Applications : Page 2

Version 2.0 of Sun's Java Real-time System (Java RTS) contains a real-time garbage collector and RTSJ-compliant programming models. Find out how it can lend predictability and deterministic behavior to financial applications.


advertisement
The Java RTS Financial Demonstration Application
The limit/stop order trading system has three main components (see Figure 1):
  • A data feed application
  • A trading engine application
  • A charting application

Click to enlarge

Figure 1. Main Components of Trading System

The trading engine (the focus of this discussion) executes two main threads:

  1. A thread that listens to the data feed and updates the current market price for stocks it tracks (the MarketManager)
  2. A thread that runs a time-critical loop that compares existing limit/stop orders against the current market values (the OrderManager) (see Figure 2). When the market price of a stock moves within range of a limit or stop order, the trading engine executes the trade.



Click to enlarge

Figure 2. The OrderManager Thread

For the non-real-time implementation of the trading engine, an outside event (such as garbage collection) could interrupt the time-critical loop and cause unbounded latency. In that time frame, the market may move within range and then out of range of one or more of the open orders in the system. In fact, this is exactly what happens in the demonstration.

In this scenario, the missed opportunity represents a financial loss to the operating institution since it will still be required to honor its customers' affected orders, even though the ideal trading window was missed (see Figure 3). Although the chance of garbage collection affecting trades is marginal, it represents significant risk. This demo shows that the risk is real.

Click to enlarge

Figure 3. Missed Ideal Trading Window

However, when the same trading engine (with minor changes to the threading model) runs with Java RTS, the JVM is able to honor the deadlines within the time-critical code, and no trade opportunities are missed. The engine captures all market ticks and responds to all trading opportunities. The result is a system that can reliably respond to market events and trade customer orders precisely when the right conditions occur.

The Time-Critical Portion of the Trading Engine
The trading engine's order book is composed of a HashMap that itself is composed of objects of class SubBook, which is composed of two LinkedLists of prices: one for buy orders (from low to high) and the second for sell orders (from high to low) (see Figure 4).

Click to enlarge

Figure 4. The Trading Engine's Order Book

The following listing shows the code for this data structure:

class OrderEntry { private boolean active; private double price; private long quantity; private StringBuffer symbol; private int type; } class SubBook { LinkedList<OrderEntry> buy; LinkedList<OrderEntry> sell; } HashMap<StringBuffer,SubBook> orderBook = new HashMap<StringBuffer,SubBook>(INITIAL_CAPACITY);

The following listing shows the time-critical loop for the standard Java version of the OrderManager, where the order book is compared to the latest market prices:

public class OrderManager implements Runnable { ... public void run() { // Loop to compare market to order prices while ( true ) { for ( int i = 0; i < orderBookKeys.length; i++ ) { StringBuffer symbol = orderBookKeys[i]; StringBuffer sPrice = marketMgr.marketBook.get(symbol); if ( sPrice == null ) continue; double marketPrice = Double.parseDouble( sPrice.toString() ); // Get the sub book for this symbol SubBook sb = orderBook.get(symbol); // Walk the list of sell orders for ( int x = 0; x < sb.sell.size(); x++ ) { OrderEntry entry = sb.sell.get(x); if ( checkForTrade( entry, marketPrice ) == true ) break; } // Walk the list of buy orders for ( int x = 0; x < sb.buy.size(); x++ ) { OrderEntry entry = sb.buy.get(x); if ( checkForTrade( entry, marketPrice ) == true ) break; } } Thread.sleep(1); // one-millisecond sleep time } } ... }

Every millisecond, the sell and buy orders for each stock are compared to that stock's market price. If conditions are met, a trade is executed. In the demo, a message is sent about the trade, and the user interface component then graphs the difference between the limit price and the execution price. In most cases, the difference will be zero; although garbage collection pauses may cause a difference (a loss) to occur.

The real-time version of the loop is almost identical. The one minor change is the call to Thread.sleep is replaced with RealtimeThread.waitForNextPeriod (see listing below). This change offers two main advantages:

  1. It ensures that the loop executes at exactly the period specified when the RealtimeThread is created. In other words, if you specify a one-millisecond period and processing takes 250 microseconds, waitForNextPeriod will block for precisely 750 microseconds. This ensures that the code executes at every one-millisecond time boundary. Standard Java does not provide this behavior.
  2. The call to waitForNextPeriod uses JavaRTS's high-resolution timers, making it more accurate than those built into standard Java.

public class OrderManager implements Runnable { ... public void run() { // Loop to compare market to order prices while ( true ) { for ( int i = 0; i < orderBookKeys.length; i++ ) { StringBuffer symbol = orderBookKeys[i]; StringBuffer sPrice = marketMgr.marketBook.get(symbol); if ( sPrice == null ) continue; double marketPrice = Double.parseDouble( sPrice.toString() ); // Get the sub book for this symbol SubBook sb = orderBook.get(symbol); // Walk the list of sell orders for ( int x = 0; x < sb.sell.size(); x++ ) { OrderEntry entry = sb.sell.get(x); if ( checkForTrade( entry, marketPrice ) == true ) break; } // Walk the list of buy orders for ( int x = 0; x < sb.buy.size(); x++ ) { OrderEntry entry = sb.buy.get(x); if ( checkForTrade( entry, marketPrice ) == true ) break; } } // Wait for the beginning of the next period RealtimeThread.waitForNextPeriod(); } } ... }

Both versions of OrderManager implement the Runnable interface, requiring that a thread be created. For the real-time version of the trading engine, a javax.realtime.RealtimeThread is created, as opposed to a standard java.lang.Thread (see listing below). You specify a period and a priority when creating the RealtimeThread—a priority that's truly implemented in Java RTS.

// Create the runnable OrderManager orderMgr = new OrderManager(); // Determine the thread priority long maxPriority = PriorityScheduler.instance().getMaxPriority(); PriorityParameters sched = new PriorityParameters( maxPriority ); // Determine the thread period RelativeTime one_millisecond = new RelativeTime(1,0); PeriodicParameters period = new PeriodicParameters(one_millisecond); // Create the real-time thread with the above parameters RealtimeThread orderThread = new RealtimeThread(sched,period,null,null,null,orderMgr);



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap