From 14061a2d21664079767bde06b029cf1518955b7a Mon Sep 17 00:00:00 2001 From: 7u83 <7u83@mail.ru> Date: Tue, 10 Jan 2017 19:27:11 +0100 Subject: [PATCH] new oder book and order execution system --- src/main/java/chart/Chart.java | 2 +- src/main/java/gui/AskBook.java | 5 +- src/main/java/gui/BidBook.java | 5 +- src/main/java/gui/MainWin.java | 26 ++++ src/main/java/gui/OrderBook.java | 11 +- src/main/java/sesim/Exchange.java | 225 +++++++++++++++-------------- src/main/java/sesim/Locker.java | 10 +- src/main/java/sesim/OrderData.java | 4 + src/main/java/sesim/Quote.java | 2 +- src/test/java/sesim/Test.java | 48 ++++-- 10 files changed, 204 insertions(+), 134 deletions(-) diff --git a/src/main/java/chart/Chart.java b/src/main/java/chart/Chart.java index 0ca687e..cb30f5c 100644 --- a/src/main/java/chart/Chart.java +++ b/src/main/java/chart/Chart.java @@ -171,7 +171,7 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver { @Override public void UpdateQuote(Quote q) { // System.out.print("Quote Received\n"); - this.realTimeAdd(q.time, (float) q.price, q.volume); + this.realTimeAdd(q.time, (float) q.price, (float)q.volume); // this.invalidate(); this.repaint(); } diff --git a/src/main/java/gui/AskBook.java b/src/main/java/gui/AskBook.java index 92fcbdc..41c5338 100644 --- a/src/main/java/gui/AskBook.java +++ b/src/main/java/gui/AskBook.java @@ -27,6 +27,7 @@ package gui; import sesim.Order_old.*; import java.util.ArrayList; +import sesim.Exchange.*; /** * @@ -36,7 +37,7 @@ public class AskBook extends OrderBook { @Override ArrayList getOrderBook() { - return MainWin.se.getOrderBook(OrderType_old.ask,40); + return MainWin.se.getOrderBook(OrderType.ASK,40); } @Override @@ -48,7 +49,7 @@ public class AskBook extends OrderBook { if (MainWin.se == null) { return; } - MainWin.se.addBookReceiver(OrderType_old.ask, this); + MainWin.se.addBookReceiver(OrderType.ASK, this); } diff --git a/src/main/java/gui/BidBook.java b/src/main/java/gui/BidBook.java index ee7b259..3e05892 100644 --- a/src/main/java/gui/BidBook.java +++ b/src/main/java/gui/BidBook.java @@ -27,6 +27,7 @@ package gui; import sesim.Order_old.*; import java.util.ArrayList; +import sesim.Exchange.*; /** * @@ -36,13 +37,13 @@ public class BidBook extends OrderBook { @Override ArrayList getOrderBook() { - return MainWin.se.getOrderBook(OrderType_old.bid, 40); + return MainWin.se.getOrderBook(OrderType.BID, 40); } public BidBook() { if (MainWin.se == null) { return; } - MainWin.se.addBookReceiver(OrderType_old.bid, this); + MainWin.se.addBookReceiver(OrderType.BID, this); } } diff --git a/src/main/java/gui/MainWin.java b/src/main/java/gui/MainWin.java index 8cd29cf..7618d21 100644 --- a/src/main/java/gui/MainWin.java +++ b/src/main/java/gui/MainWin.java @@ -33,6 +33,7 @@ import sesim.Exchange; import sesim.BuyOrder; import javax.swing.UIManager; import javax.swing.*; +import sesim.AccountData; /** @@ -51,7 +52,31 @@ public class MainWin extends javax.swing.JFrame { public MainWin() { initComponents(); + + + double aid1 = se.createAccount(100, 100); + double aid2 = se.createAccount(100, 100); + + AccountData a1 = se.getAccountData(aid1); + AccountData a2 = se.getAccountData(aid2); + + se.createOrder(aid2, Exchange.OrderType.ASK, 20, 11); + se.createOrder(aid2, Exchange.OrderType.ASK, 10, 10); + se.createOrder(aid2, Exchange.OrderType.ASK, 10, 9); + se.createOrder(aid1, Exchange.OrderType.BID, 50, 7); + + /* + System.out.print("Exec Orders\n"); + se.executeOrders(); + System.out.print("Executed Orders\n"); + + a1 = se.getAccountData(aid1); + a2 = se.getAccountData(aid2); + */ + + +/* AutoTraderLIst at = new AutoTraderLIst(); // RandomTraderConfig rcfg = new RandomTraderConfig(); SwitchingTraderConfig rcfg = new SwitchingTraderConfig(); @@ -61,6 +86,7 @@ public class MainWin extends javax.swing.JFrame { SwitchingTraderConfig scfg = new SwitchingTraderConfig(); at.add(1, scfg, se, 1000000, 0); + */ } diff --git a/src/main/java/gui/OrderBook.java b/src/main/java/gui/OrderBook.java index 15a9405..f02e7c4 100644 --- a/src/main/java/gui/OrderBook.java +++ b/src/main/java/gui/OrderBook.java @@ -26,6 +26,7 @@ package gui; import sesim.Exchange; +import sesim.Exchange.*; import java.util.ArrayList; import java.util.Formatter; import javax.swing.table.AbstractTableModel; @@ -96,7 +97,7 @@ public abstract class OrderBook extends javax.swing.JPanel implements Exchange.B protected class OrderBookListModel extends AbstractTableModel { - private ArrayList list; + private ArrayList list; //private final boolean desc = false; public OrderBookListModel() { @@ -113,7 +114,7 @@ public abstract class OrderBook extends javax.swing.JPanel implements Exchange.B this.fireTableDataChanged(); this.update_calls++; - int hc = this.hashCode(); + // int hc = this.hashCode(); //System.out.print("Update/ColCalls = " + update_calls + "/" + colcount_calls + " HC: " + hc + "\n"); } @@ -145,15 +146,15 @@ public abstract class OrderBook extends javax.swing.JPanel implements Exchange.B @Override public Object getValueAt(int r, int c) { - sesim.Order_old o; + OrderBookItem o; int s = list.size(); //System.out.print("Looking for Value at" + r + ":" + c + " w size:" + s + "\n"); if (!getDesc()) { - o = (sesim.Order_old) list.get(r); + o = list.get(r); } else { - o = (sesim.Order_old) list.get(list.size() - r - 1); + o = list.get(list.size() - r - 1); } Formatter f = new Formatter(); switch (c) { diff --git a/src/main/java/sesim/Exchange.java b/src/main/java/sesim/Exchange.java index 00a3bbf..6ec6394 100644 --- a/src/main/java/sesim/Exchange.java +++ b/src/main/java/sesim/Exchange.java @@ -23,7 +23,8 @@ public class Exchange extends Thread { protected double id; protected double shares; protected double money; - protected HashMap orders; + + protected HashMap orders; @Override public int compareTo(Object a) { @@ -34,6 +35,8 @@ public class Exchange extends Thread { Account(double money, double shares) { id = (Math.random() + (account_id.getNext())); orders = new HashMap(); + this.money = money; + this.shares = shares; } } @@ -71,7 +74,7 @@ public class Exchange extends Thread { if (d != 0) { return d > 0 ? 1 : -1; } - + return left.id < right.id ? -1 : 1; } @@ -93,9 +96,9 @@ public class Exchange extends Thread { long created; Account account; - Order(Account account,OrderType type, double volume, double limit) { + Order(Account account, OrderType type, double volume, double limit) { id = order_id.getNext(); - this.account=account; + this.account = account; this.type = type; this.limit = limit; this.volume = volume; @@ -123,8 +126,6 @@ public class Exchange extends Thread { } } - - class BidBook extends TreeSet { @@ -182,23 +183,23 @@ public class Exchange extends Thread { final private ArrayList ask_bookreceivers = new ArrayList<>(); final private ArrayList bid_bookreceivers = new ArrayList<>(); - private ArrayList selectBookReceiver(OrderType_old t) { + private ArrayList selectBookReceiver(OrderType t) { switch (t) { - case ask: + case ASK: return ask_bookreceivers; - case bid: + case BID: return bid_bookreceivers; } return null; } - public void addBookReceiver(OrderType_old t, BookReceiver br) { + public void addBookReceiver(OrderType t, BookReceiver br) { ArrayList bookreceivers; bookreceivers = selectBookReceiver(t); bookreceivers.add(br); } - void updateBookReceivers(OrderType_old t) { + void updateBookReceivers(OrderType t) { ArrayList bookreceivers; bookreceivers = selectBookReceiver(t); @@ -272,20 +273,33 @@ public class Exchange extends Thread { return null; } + + public class OrderBookItem { + public long id; + public double limit; + public double volume; + } - public ArrayList getOrderBook(OrderType_old t, int depth) { + public ArrayList getOrderBook(OrderType type, int depth) { - TreeSet book = selectOrderBook(t); + TreeSet book = order_books.get(type); if (book == null) { return null; } - ArrayList ret = new ArrayList<>(); - Iterator it = book.iterator(); + ArrayList ret = new ArrayList<>(); + + Iterator it = book.iterator(); + for (int i = 0; i < depth && it.hasNext(); i++) { - Order_old o; - o = it.next(); - ret.add(o); + + Order o = it.next(); + OrderBookItem n = new OrderBookItem(); + n.id=o.id; + n.limit=o.limit; + n.volume=o.volume; + + ret.add(n); //System.out.print("Order_old" + o.limit); //System.out.println(); } @@ -345,14 +359,13 @@ public class Exchange extends Thread { tradelock.lock(); TreeSet book = this.selectOrderBook(o.type); book.remove(o); - this.updateBookReceivers(o.type); +/* this.updateBookReceivers(o.type); o.account.pending.remove(o); o.status = OrderStatus.canceled; tradelock.unlock(); + */ } - - /** * Transfer shares from one account to another account @@ -371,19 +384,31 @@ public class Exchange extends Thread { long nextQuoteId = 0; + private void removeOrderIfExecuted(Order o) { + if (o.volume != 0) { + return; + } + o.account.orders.remove(o.id); + order_books.get(o.type).pollFirst(); + + } + /** * */ public void executeOrders() { - TreeSet bid=order_books.get(OrderType.BID); - TreeSet ask=order_books.get(OrderType.ASK); + TreeSet bid = order_books.get(OrderType.BID); + TreeSet ask = order_books.get(OrderType.ASK); + double volume_total=0; + double money_total=0; + while (!bid.isEmpty() && !ask.isEmpty()) { Order b = bid.first(); Order a = ask.first(); - + if (b.limit < a.limit) { System.out.print("No match\n"); // no match, nothing to do @@ -394,82 +419,29 @@ public class Exchange extends Thread { double price = b.id < a.id ? b.limit : a.limit; double volume = b.volume >= a.volume ? a.volume : b.volume; - transferMoneyAndShares(b.account, a.account, volume * price, -volume); + // Transfer money and shares + transferMoneyAndShares(b.account, a.account, volume * price, -volume); + + // Update volume + b.volume -= volume; + a.volume -= volume; - System.out.print(price+","+volume); - - - System.exit(0); + volume_total+=volume; + money_total+=price*volume; + removeOrderIfExecuted(a); + removeOrderIfExecuted(b); -/* if (a.volume == 0) { - // This order is fully executed, remove - a.account.orderpending = false; - a.status = OrderStatus.executed; - - a.account.pending.remove(a); - - ask.pollFirst(); - this.updateBookReceivers(OrderType_old.ask); - continue; - } - - if (b.volume == 0) { - // This order is fully executed, remove - b.account.orderpending = false; - b.status = OrderStatus.executed; - b.account.pending.remove(b); - bid.pollFirst(); - this.updateBookReceivers(OrderType_old.bid); - continue; - } -*/ - if (b.limit >= a.limit) { - - price = b.id < a.id ? b.limit : a.limit; - - /* if (b.id < a.id) { - price = b.limit; - } else { - price = a.limit; - } - */ - if (b.volume >= a.volume) { - volume = a.volume; - } else { - volume = b.volume; - } - -// transferShares(a.account, b.account, volume, price); - - // b.account.Buy(a.account, volume, price); - b.volume -= volume; - a.volume -= volume; - - lastprice = price; -// lastsvolume = volume; - - Quote q = new Quote(); - -// q.volume = volume; - q.price = price; - q.time = System.currentTimeMillis(); - - q.ask = a.limit; - q.bid = b.limit; - q.id = nextQuoteId++; - - this.updateQuoteReceivers(q); - this.updateBookReceivers(OrderType_old.bid); - this.updateBookReceivers(OrderType_old.ask); - - quoteHistory.add(q); - continue; - - } - - return; } + + + Quote q = new Quote(); + q.price=money_total/volume_total; + q.volume=volume_total; + q.time=System.currentTimeMillis(); + + System.out.print("Price" + q.price + "," + q.volume + "\n"); + } private void executeOrders_old() { @@ -492,7 +464,7 @@ public class Exchange extends Thread { a.account.pending.remove(a); ask.pollFirst(); - this.updateBookReceivers(OrderType_old.ask); +// this.updateBookReceivers(OrderType_old.ask); continue; } @@ -502,7 +474,7 @@ public class Exchange extends Thread { b.status = OrderStatus.executed; b.account.pending.remove(b); bid.pollFirst(); - this.updateBookReceivers(OrderType_old.bid); +// this.updateBookReceivers(OrderType_old.bid); continue; } @@ -545,8 +517,8 @@ public class Exchange extends Thread { q.id = nextQuoteId++; this.updateQuoteReceivers(q); - this.updateBookReceivers(OrderType_old.bid); - this.updateBookReceivers(OrderType_old.ask); +// this.updateBookReceivers(OrderType_old.bid); +// this.updateBookReceivers(OrderType_old.ask); /* System.out.print( "Executed: " @@ -592,7 +564,7 @@ public class Exchange extends Thread { } if (ret) { - this.updateBookReceivers(o.type); +// this.updateBookReceivers(o.type); } return ret; } @@ -615,12 +587,11 @@ public class Exchange extends Thread { return o; } - - private void addOrderToBook(Order o){ + private void addOrderToBook(Order o) { order_books.get(o.type).add(o); - + } - + /** * * @param account_id @@ -636,15 +607,51 @@ public class Exchange extends Thread { return -1; } - Order o = new Order(a,type, volume, limit); + Order o = new Order(a, type, volume, limit); addOrderToBook(o); - a.orders.put(o.id,o); + a.orders.put(o.id, o); + + this.executeOrders(); + this.updateBookReceivers(type); return o.id; } + + public AccountData getAccountData(double account_id) { + Account a = accounts.get(account_id); + if (a == null) { + return null; + } + + AccountData ad = new AccountData(); + ad.id = account_id; + ad.money = a.money; + ad.shares = a.shares; + return ad; + } - - + public ArrayList getOpenOrders(double account_id){ + + Account a = accounts.get(account_id); + if (a==null) + return null; + + ArrayList al = new ArrayList(); + + Iterator it = a.orders.entrySet().iterator(); + while (it.hasNext()){ + Order o = (Order)it.next(); + OrderData od = new OrderData(); + od.limit=o.limit; + od.volume=o.initial_volume; + od.executed=o.initial_volume-o.volume; + od.id=o.id; + al.add(od); + } + + return al; + } + /* public void SendOrder(BuyOrder o) { diff --git a/src/main/java/sesim/Locker.java b/src/main/java/sesim/Locker.java index 6cd2a83..8c621f0 100644 --- a/src/main/java/sesim/Locker.java +++ b/src/main/java/sesim/Locker.java @@ -33,11 +33,15 @@ import java.util.concurrent.Semaphore; */ public class Locker { - private final Semaphore avail = new Semaphore(1, true); + private final Semaphore AVAIL = new Semaphore(1, true); + /** + * + * @return + */ public boolean lock() { try { - avail.acquire(); + AVAIL.acquire(); } catch (InterruptedException e) { return false; } @@ -45,7 +49,7 @@ public class Locker { } public void unlock() { - avail.release(); + AVAIL.release(); } } diff --git a/src/main/java/sesim/OrderData.java b/src/main/java/sesim/OrderData.java index bbde878..e4af64a 100644 --- a/src/main/java/sesim/OrderData.java +++ b/src/main/java/sesim/OrderData.java @@ -30,5 +30,9 @@ package sesim; * @author 7u83 <7u83@mail.ru> */ public class OrderData { + long id; + double limit; + double volume; + double executed; } diff --git a/src/main/java/sesim/Quote.java b/src/main/java/sesim/Quote.java index 3f973b8..7e45132 100644 --- a/src/main/java/sesim/Quote.java +++ b/src/main/java/sesim/Quote.java @@ -37,7 +37,7 @@ public class Quote implements Comparable { public double ask_volume; public double price; - public long volume; + public double volume; public long time; Locker lock = new Locker(); diff --git a/src/test/java/sesim/Test.java b/src/test/java/sesim/Test.java index 322cba2..c9237a9 100644 --- a/src/test/java/sesim/Test.java +++ b/src/test/java/sesim/Test.java @@ -30,26 +30,52 @@ package sesim; * @author tobias */ public class Test { + + static void print_account(AccountData ad) { + System.out.print( + "Account ID:" + + ad.id + + " Ballance:" + + ad.money + + " Shares:" + + ad.shares + + "\n" + ); + } + /** * @param args the command line arguments */ public static void main(String[] args) { Exchange se = new Exchange(); - - double aid1 = se.createAccount(100, 110); - - - double aid2 = se.createAccount(100, 110); - se.createOrder(aid2, Exchange.OrderType.ASK, 50, 9); + + double aid1 = se.createAccount(100, 100); + double aid2 = se.createAccount(100, 100); + + AccountData a1 = se.getAccountData(aid1); + AccountData a2 = se.getAccountData(aid2); + Test.print_account(a1); + Test.print_account(a2); + + se.createOrder(aid2, Exchange.OrderType.ASK, 20, 11); + se.createOrder(aid2, Exchange.OrderType.ASK, 10, 10); + se.createOrder(aid2, Exchange.OrderType.ASK, 10, 9); se.createOrder(aid1, Exchange.OrderType.BID, 50, 11); - - + + System.out.print("Exec Orders\n"); se.executeOrders(); + System.out.print("Executed Orders\n"); + + a1 = se.getAccountData(aid1); + a2 = se.getAccountData(aid2); + Test.print_account(a1); + Test.print_account(a2); + + + //S/ystem.out.print(aid); //System.out.print("\n"); - - } - + }