package fauxExchange; import java.util.*; public class OrderBook { Security sec; OrderBookStateController obsc; List buyOrders = new ArrayList(); List sellOrders = new ArrayList(); double lastPrice = 0.0; double openingPrice = 0.0; double threshhold = 0.10; OrderBook ob = this; final Queue or = new Queue(); //----------------------------CONSTRUCTOR------------------------------------// public OrderBook (Security sec) { this.sec = sec; // Create the OrderBookStateController for this OrderBook //System.out.println("Creating the OrderBookStateController..."); obsc = new OrderBookStateController(new TradingState()); obsc.setOrderBook(this); //System.out.println("Registering the OrderBookStateController with the Segment..."); registerOrderBookStateController(); } /** * This method starts the OrderBook Worker Thread */ void startWorker () { // Start the worker thread for processing requests //System.out.println("Creating the Order request processing thread..."); WorkerThread wt = new WorkerThread(); wt.start(); } /** * Registers this OrderBook's order book state controller with the segment for * this order book */ public void registerOrderBookStateController(){ if (sec != null){ Segment tmpSegment = sec.getSegment(); tmpSegment.addObserver(obsc); } } /** Returns a sorted iterator of the buy orders */ public Iterator getBuyOrders () { // Collections.sort(buyOrders); return buyOrders.iterator(); } /** Returns a sorted iterator of the sell orders */ public Iterator getSellOrders () { // Collections.sort(sellOrders); return sellOrders.iterator(); } /** This method requests that an order be removed from the order book */ public void removeOrder (Order o){ //System.out.println("Queuing a remove order request for:"); //o.print(null)null); or.enqueue(new OrderRequest(o, false)); } /** This method requests that an order be entered into the order book */ public void insertOrder (Order o){ //System.out.println("Queuing an insert order request for:"); //o.print(null); or.enqueue(new OrderRequest(o, true)); } public void publishTrade (Trade t){ sec.getSegment().getExchange().publishTrade(t); } /** * Method used by package classes that need to delete an order from the order book. * This method may be called when the rules find a match that creates a trade and the * order is removed. */ synchronized void deleteOrder (Order o){ if (o instanceof BuyOrder){ //System.out.println("Removing a buy order from the list"); //o.print(null); buyOrders.remove(o); Collections.sort(buyOrders); }else{ //System.out.println("Removing a sell order from the list"); //o.print(null); sellOrders.remove(o); Collections.sort(sellOrders); } } /** * Method used to insert an order into the appropriate part * of the OrderBook */ synchronized void addOrder (Order o){ if (o instanceof BuyOrder){ //System.out.println("Placing a buy order into the list"); buyOrders.add(o); Collections.sort(buyOrders); }else{ //System.out.println("Placing a sell order into the list"); sellOrders.add(o); Collections.sort(sellOrders); } } /** * Method to set the last price at which a trade occured */ public void setLastPrice (double price) throws TradeClosedException { //System.out.println("Setting last price => " + price); if ((Math.abs(this.lastPrice - price) / lastPrice) > threshhold) throw new TradeClosedException(); else this.lastPrice = price; //System.out.println("Succeeded in setting last price..."); } /** * This method allows the system to initialize the opening and last prices */ void initializePrice (double lastPrice, double openingPrice){ this.lastPrice = lastPrice; this.openingPrice = openingPrice; } /** * Returns the last price at which this stock was traded */ public double getLastPrice () { return lastPrice; } /** * Returns the current theoretical opening price */ public double getOpeningPrice () { return openingPrice; } /** * Method to set the current opening price * * @throws TradeClosedException Thrown when the calculated opening price * is too far away from the last price */ public void setOpeningPrice (double price) throws TradeClosedException { if (Math.abs(this.lastPrice - price) / lastPrice > threshhold) throw new TradeClosedException(); else this.openingPrice = price; } /** Used to set the Threshhold for this OrderBook */ public void setThreshhold (double threshhold) { this.threshhold = threshhold; } public Security getSecurity(){ return sec; } /** * This Thread processes the incoming insert order and remove * order requests from the request queue */ protected class WorkerThread extends Thread { public WorkerThread () { setDaemon(true); } public void run () { //System.out.println("Worked thread created for OrderBook tracking Security " + ob.getSecurity().getSecurityId()); while (true){ if (or.isEmpty()) { try{ this.sleep(1000); }catch(Exception e){} continue; } synchronized (ob){ OrderRequest request = (OrderRequest)or.dequeue(); //System.out.println("Processing order: "); request.getOrder().print(null); if (request.isInserting()){ // Add order to OrderBook addOrder(request.getOrder()); // Here the OrderBookStateController for this OrderBook will // apply matching rules to attempt to find the optimum rate // of execution (or opening price) or to find trades for this // new order obsc.applyRules(ob, request.getOrder()); }else{ // Delete the order from the queue // deleteOrder(request.getOrder()); // // obsc.applyRules(ob, request.getOrder()); } } } } } public void print(java.io.PrintStream io){ outputBook(io); } /** * Outputs the current book to a PrintStream */ public void outputBook (java.io.PrintStream io){ if (io == null) io = System.out; java.text.NumberFormat nf = java.text.NumberFormat.getCurrencyInstance(); ArrayList tmpBuys = new ArrayList(buyOrders); ArrayList tmpSells = new ArrayList(sellOrders); Iterator buys = tmpBuys.iterator(); Iterator sells = tmpSells.iterator(); io.println(" --- THE CURRENT OrderBook STATE --- "); io.println(""); if (!(obsc.getOrderBookState() instanceof TradingState)) { io.println(" Current Opening Price: " + nf.format(getOpeningPrice())); } io.println(" Last Paid Price: " + nf.format(getLastPrice())); io.println(""); io.println(" Buy Orders --- Sell Orders "); io.println(" ---------------------------------------------"); while (buys.hasNext() || sells.hasNext()){ Order buy = null; Order sell = null; if (buys.hasNext()){ buy = (Order)buys.next(); io.print(" " + buy.getSize() + " - "); if (buy.isMarket()) io.print("MARKET"); else io.print(nf.format(buy.getPrice())); }else{ //System.out.print(" "); } if (sells.hasNext()){ sell = (Order)sells.next(); io.print(" | " + sell.getSize() + " - "); if (sell.isMarket()) io.print("MARKET"); else io.print(nf.format(sell.getPrice())); } io.println(""); } io.println(""); } public void printHtml(java.io.PrintStream io){ if (io == null) io = System.out; java.text.NumberFormat nf = java.text.NumberFormat.getCurrencyInstance(); ArrayList tmpBuys = new ArrayList(buyOrders); ArrayList tmpSells = new ArrayList(sellOrders); Iterator buys = tmpBuys.iterator(); Iterator sells = tmpSells.iterator(); io.println(" "); io.println(""); while (buys.hasNext() || sells.hasNext()){ Order buy = null; Order sell = null; io.println(""); }else{ io.print(" "); } if (sells.hasNext()){ sell = (Order)sells.next(); io.print("

Current OrderBook State

"); if (!(obsc.getOrderBookState() instanceof TradingState)) { io.println("
Current Opening Price: " + nf.format(getOpeningPrice())); } io.println("
Last Paid Price: " + nf.format(getLastPrice())); io.println("
Buy OrdersSell Orders
"); if (buys.hasNext()){ buy = (Order)buys.next(); io.print(buy.getSize() + ""); if (buy.isMarket()) io.print("MARKET"); else io.print(nf.format(buy.getPrice())); io.print(" " + nf.format(sell.getSize()) + ""); if (sell.isMarket()) io.print("MARKET"); else io.print(sell.getPrice()); } io.println("
"); } } public static void main (String [] args) throws Exception { BuyOrder buy = new BuyOrder(200, 40.0, 1, false, 1030); SellOrder sell = new SellOrder(100, 39.0, 2, false, 1030); OrderBook ob = new OrderBook (null); ob.insertOrder(buy); ob.insertOrder(sell); ob.insertOrder(new BuyOrder(200, 38.0, 4, false, 1030)); // And now for some matching ob.insertOrder(new SellOrder(80, 39.0, 10, false, 1030)); Thread.currentThread().sleep(90); ob.outputBook(System.out); } }