diff --git a/src/main/java/chart/Chart.java b/src/main/java/chart/Chart.java index cb30f5c..c1ad629 100644 --- a/src/main/java/chart/Chart.java +++ b/src/main/java/chart/Chart.java @@ -9,6 +9,8 @@ import java.awt.*; import sesim.Exchange.*; import sesim.Quote; import gui.MainWin; +import java.util.ArrayList; +import java.util.Iterator; /** * @@ -33,9 +35,9 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver { int item_width = 10; int items = 350; - long ntime = -1; + long ntime = 0; - OHLCData data; + OHLCData data = new OHLCData(); OHLCDataItem current = null; @@ -48,14 +50,14 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver { private void realTimeAdd(long time, float price, float volume) { - /* System.out.print("Diff:" + /*System.out.print("Diff:" +(ntime-time) +"\n" - ); - */ + );*/ + if (time > ntime) { - System.out.print("new raster ----------------------------------\n"); +// System.out.print("new raster ----------------------------------\n"); current = null; ntime = rasterTime(time) + 5000; // System.out.print(ntime+"\n"); @@ -95,8 +97,12 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver { this.getSize(); int pwidth = item_width * items; + int phight = 40; - this.setPreferredSize(new Dimension(pwidth, 400)); + this.setPreferredSize(new Dimension(pwidth, phight)); + + Dimension dim = this.getSize(); + // System.out.print("Diemension "+dim.width+" "+dim.height+"\n"); g.setColor(Color.RED); g.drawLine(0,0,100,100); @@ -109,13 +115,58 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver { - if (this.current == null) { - return; + // if (this.current == null) { + // return; + // } + + ArrayList od = data.data; + + System.out.print("OD S: "+od.size()+"\n"); + g.setColor(Color.BLUE); + + + + Iterator it = od.iterator(); + int myi=0; + while (it.hasNext()){ + OHLCDataItem di = it.next(); + + float val = di.close; + float max = data.max; + float min = data.min; + + if (min==max){ + min = val/2; + max = val*2; + + + } + + + + System.out.print("Fval: "+val+" "+min+"\n"); + val -= min; + System.out.print("VAL New"+val+"\n"); + + //val/ ((data.max-data.min)/dim.height); + + + System.out.print("MINMAX "+min+" "+max+"\n"); + + val = dim.height*val/(data.max-data.min); + + + int x = myi * this.item_width; + myi++; + g.drawLine(x, 0, x, (int)val); + + System.out.print("Draw Line: "+x+" "+val+"\n"); + } - g.setColor(Color.BLUE); - g.drawLine(0, 0, 100, (int) ((this.current.close-80.0)*80.0)); + + // g.drawLine(0, 0, 100, (int) ((this.current.close-80.0)*80.0)); } @@ -131,7 +182,7 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver { // g.get Rectangle bounds = g.getDeviceConfiguration().getBounds(); - System.out.print(bounds.width + "\n"); + // System.out.print(bounds.width + "\n"); //g.fillRect(0, 0, 100, 100); Dimension d = this.getSize(); @@ -170,8 +221,10 @@ 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, (float)q.volume); + // System.out.print("Quote Received\n"); +// this.realTimeAdd(q.time, (float) q.price, (float)q.volume); + + data.realTimeAdd(q.time, (float)q.price, (float)q.volume); // this.invalidate(); this.repaint(); } diff --git a/src/main/java/chart/OHLCData.java b/src/main/java/chart/OHLCData.java index a5123ce..93d6551 100644 --- a/src/main/java/chart/OHLCData.java +++ b/src/main/java/chart/OHLCData.java @@ -33,7 +33,8 @@ import java.util.*; */ public class OHLCData { //extends ArrayList { - float max; + float max=0; + float min=0; long time_start; long time_step; @@ -55,19 +56,36 @@ public class OHLCData { //extends ArrayList { private void updateMinMax(float price){ - // if (price>max) + if (price > max){ + + max = price; + } + if (price < min){ + min = price; + } + } private long ntime = 0; boolean realTimeAdd(long time, float price, float volume) { + + if (time > ntime) { + if (ntime==0){ + System.out.print ("Setting ntimt was zero\n"); + this.min=price; + this.max=price; + } + ntime = rasterTime(time) + 5000; data.add(new OHLCDataItem(price, price, price, price, volume)); + this.updateMinMax(price); return true; } OHLCDataItem d = data.get(data.size() - 1); + this.updateMinMax(price); boolean rc = d.update(price, volume); return rc; } diff --git a/src/main/java/gui/AskBook.java b/src/main/java/gui/AskBook.java index 41c5338..060360b 100644 --- a/src/main/java/gui/AskBook.java +++ b/src/main/java/gui/AskBook.java @@ -25,7 +25,6 @@ */ package gui; -import sesim.Order_old.*; import java.util.ArrayList; import sesim.Exchange.*; @@ -36,7 +35,7 @@ import sesim.Exchange.*; public class AskBook extends OrderBook { @Override - ArrayList getOrderBook() { + ArrayList getOrderBook() { return MainWin.se.getOrderBook(OrderType.ASK,40); } diff --git a/src/main/java/gui/BidBook.java b/src/main/java/gui/BidBook.java index 3e05892..ffddbe2 100644 --- a/src/main/java/gui/BidBook.java +++ b/src/main/java/gui/BidBook.java @@ -25,7 +25,6 @@ */ package gui; -import sesim.Order_old.*; import java.util.ArrayList; import sesim.Exchange.*; @@ -36,7 +35,7 @@ import sesim.Exchange.*; public class BidBook extends OrderBook { @Override - ArrayList getOrderBook() { + ArrayList getOrderBook() { return MainWin.se.getOrderBook(OrderType.BID, 40); } diff --git a/src/main/java/gui/Chart.java b/src/main/java/gui/Chart.java index e17d164..7d195e4 100644 --- a/src/main/java/gui/Chart.java +++ b/src/main/java/gui/Chart.java @@ -25,6 +25,7 @@ */ package gui; +import sesim.*; import sesim.Exchange; import sesim.Exchange.*; import java.awt.Color; @@ -68,6 +69,10 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver { */ public Chart() { initComponents(); + + sesim.IDGenerator idgen = new IDGenerator(); + + /* String stockSymbol = "Schliemanz Koch AG"; //String stockSymbol = "MSFT"; @@ -192,7 +197,7 @@ public class Chart extends javax.swing.JPanel implements QuoteReceiver { data.add(d); } - System.out.print(data.size() + "\n"); + // System.out.print(data.size() + "\n"); // System.exit(0); return data.toArray(new OHLCDataItem[data.size()]); diff --git a/src/main/java/gui/MainWin.java b/src/main/java/gui/MainWin.java index ea59dc1..d39fdaf 100644 --- a/src/main/java/gui/MainWin.java +++ b/src/main/java/gui/MainWin.java @@ -25,14 +25,7 @@ */ package gui; -import traders.RandomTraderConfig_old; -import traders.SwitchingTraderConfig; -import sesim.AutoTraderLIst; import sesim.Exchange; -import sesim.BuyOrder; -import javax.swing.UIManager; -import javax.swing.*; -import sesim.AccountData; import traders.RandomTrader; import traders.RandomTraderConfig; @@ -188,15 +181,21 @@ public class MainWin extends javax.swing.JFrame { se = new Exchange(); - RandomTraderConfig rcfg = new RandomTraderConfig(); - RandomTrader rt = rcfg.createTrader(se, 1000, 100); - rt.start(); + //RandomTraderConfig rcfg = new RandomTraderConfig(); + //RandomTrader rt = rcfg.createTrader(se, 1000, 100); + //rt.start(); RandomTraderConfig rcfg1 = new RandomTraderConfig(); - RandomTrader rt1 = rcfg.createTrader(se, 1000, 100); + RandomTrader rt1 = rcfg1.createTrader(se, 1000000000, 0); rt1.start(); + RandomTraderConfig cfg = new RandomTraderConfig(); + for (int i=0; i<5000; i++){ + RandomTrader randt = cfg.createTrader(se, 100, 100); + randt.start(); + } + //RandomTrader rt = new RandomTrader(); //rt.start(); diff --git a/src/main/java/gui/OrderBook.java b/src/main/java/gui/OrderBook.java index 3335497..da46078 100644 --- a/src/main/java/gui/OrderBook.java +++ b/src/main/java/gui/OrderBook.java @@ -48,7 +48,7 @@ public abstract class OrderBook extends javax.swing.JPanel implements Exchange.B OrderBookListModel model; - abstract ArrayList getOrderBook(); + abstract ArrayList getOrderBook(); private Color hdr_color = Color.LIGHT_GRAY; @@ -71,7 +71,7 @@ public abstract class OrderBook extends javax.swing.JPanel implements Exchange.B class Updater implements Runnable{ OrderBookListModel model; - ArrayList newlist; + ArrayList newlist; @Override public void run() { @@ -97,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() { @@ -146,7 +146,7 @@ public abstract class OrderBook extends javax.swing.JPanel implements Exchange.B @Override public Object getValueAt(int r, int c) { - OrderBookItem o; + Order o; int s = list.size(); //System.out.print("Looking for Value at" + r + ":" + c + " w size:" + s + "\n"); @@ -159,12 +159,12 @@ public abstract class OrderBook extends javax.swing.JPanel implements Exchange.B Formatter f = new Formatter(); switch (c) { case 0: - return String.format("#%06x", o.id); + return String.format("#%06x", o.getID()); case 1: - return String.format("%.4f",o.limit); + return String.format("%.4f",o.getLimit()); case 2: - return String.format("%.4f", o.volume); + return String.format("%.4f", o.getVolume()); } return ""; } diff --git a/src/main/java/gui/QuotePanel.java b/src/main/java/gui/QuotePanel.java index b49b3ab..91c8aeb 100644 --- a/src/main/java/gui/QuotePanel.java +++ b/src/main/java/gui/QuotePanel.java @@ -125,7 +125,7 @@ public class QuotePanel extends javax.swing.JPanel implements sesim.Exchange.Quo - u.text = String.format("%.2f\n(%d)", q.price,q.volume); + u.text = String.format("%.2f\n(%.0f)", q.price,q.volume); SwingUtilities.invokeLater(u); diff --git a/src/main/java/sesim/AutoTraderConfig.java b/src/main/java/sesim/AutoTraderConfig.java index 236f9e6..f30dd4f 100644 --- a/src/main/java/sesim/AutoTraderConfig.java +++ b/src/main/java/sesim/AutoTraderConfig.java @@ -27,7 +27,7 @@ package sesim; /** * - * @author tobias + * @author 7u83 */ public abstract class AutoTraderConfig { public abstract AutoTrader createTrader(Exchange se, double money, double shares); diff --git a/src/main/java/sesim/Exchange.java b/src/main/java/sesim/Exchange.java index 00699c0..da16897 100644 --- a/src/main/java/sesim/Exchange.java +++ b/src/main/java/sesim/Exchange.java @@ -1,7 +1,6 @@ package sesim; import java.util.*; -import java.util.concurrent.*; import sesim.Order_old.OrderStatus; import sesim.Order_old.OrderType_old; @@ -17,15 +16,18 @@ public class Exchange extends Thread { } IDGenerator account_id = new IDGenerator(); - public static Timer timer=new Timer(); + public static Timer timer = new Timer(); - private class Account implements Comparable { + /** + * + */ + public class Account implements Comparable { protected double id; protected double shares; protected double money; - protected HashMap orders; + private final HashMap orders; @Override public int compareTo(Object a) { @@ -39,6 +41,19 @@ public class Exchange extends Thread { this.money = money; this.shares = shares; } + + public double getID() { + return id; + } + + public double getShares() { + return shares; + } + + public double getMoney() { + return money; + } + } //private TreeSet accounts = new TreeSet<>(); @@ -75,14 +90,15 @@ public class Exchange extends Thread { if (d != 0) { return d > 0 ? 1 : -1; } - - if(left.idright.id) + } + if (left.id > right.id) { return 1; - + } + return 0; - // return left.id < right.id ? -1 : 1; } @@ -95,15 +111,15 @@ public class Exchange extends Thread { IDGenerator order_id = new IDGenerator(); - private class Order { + public class Order { OrderType type; - double limit; - double volume; - double initial_volume; - long id; + private double limit; + private double volume; + private final double initial_volume; + private long id; long created; - Account account; + private Account account; Order(Account account, OrderType type, double volume, double limit) { id = order_id.getNext(); @@ -114,6 +130,31 @@ public class Exchange extends Thread { this.initial_volume = volume; this.created = System.currentTimeMillis(); } + + public long getID() { + return id; + } + + public double getVolume() { + return volume; + } + + public double getLimit() { + return limit; + } + + public OrderType getType() { + return type; + } + + public double getExecuted() { + return initial_volume - volume; + } + + public double getInitialVolume() { + return initial_volume; + } + } /** @@ -168,6 +209,36 @@ public class Exchange extends Thread { } + public Quote getCurrentPrice() { + + TreeSet bid = order_books.get(OrderType.BID); + TreeSet ask = order_books.get(OrderType.ASK); + + Quote q = null; + + tradelock.lock(); + if (!bid.isEmpty() && !ask.isEmpty()) { + q = new Quote(); + q.price = (bid.first().limit + ask.first().limit) / 2.0; + + } + tradelock.unlock(); + + if (q != null) { + return q; + } + + if (this.quoteHistory.isEmpty()) { + + return null; + } + + q = this.quoteHistory.last(); + + return q; + + } + /* public SortedSet getQuoteHistory(int seconds) { Quote last = quoteHistory.last(); return this.getQuoteHistory(seconds, last.time); @@ -283,38 +354,25 @@ public class Exchange extends Thread { } - public class OrderBookItem { - - public long id; - public double limit; - public double volume; - } - - public ArrayList getOrderBook(OrderType type, int depth) { + public ArrayList getOrderBook(OrderType type, int depth) { TreeSet book = order_books.get(type); if (book == null) { return null; } - ArrayList ret = new ArrayList<>(); + ArrayList ret = new ArrayList<>(); Iterator it = book.iterator(); for (int i = 0; i < depth && it.hasNext(); i++) { - - 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(); + ret.add(it.next()); } return ret; + } + public Quote getLastQuoete() { + return this.quoteHistory.first(); } public void print_current() { @@ -371,22 +429,13 @@ public class Exchange extends Thread { tradelock.lock(); Order o = a.orders.get(order_id); - - // System.out.print("The Order:"+o.limit+"\n"); - - if (o != null) { - TreeSet ob =order_books.get(o.type); - - System.out.print("We have the orderbook"+ob.size()+"\n"); - - System.out.print("Want to remove:"+o.limit+" "+o.volume+" "+o.id+"\n"); - - - - boolean rc = ob.remove(o); - - System.out.print("My first rc = :" + rc); + // System.out.print("The Order:"+o.limit+"\n"); + if (o != null) { + TreeSet ob = order_books.get(o.type); + + boolean rc = ob.remove(o); + a.orders.remove(o.id); ret = true; } @@ -456,9 +505,7 @@ public class Exchange extends Thread { Order a = ask.first(); if (b.limit < a.limit) { - System.out.print("No match\n"); - // no match, nothing to do - return; + break; } // There is a match, calculate price and volume @@ -467,7 +514,7 @@ public class Exchange extends Thread { // Transfer money and shares transferMoneyAndShares(b.account, a.account, volume * price, -volume); - +//System.out.print("Transfer Shares was called with volume "+volume+"\n"); // Update volume b.volume -= volume; a.volume -= volume; @@ -479,14 +526,20 @@ public class Exchange extends Thread { removeOrderIfExecuted(b); } - +//System.out.print("Volume total is "+volume_total+"\n"); + if (volume_total == 0) { + 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"); -//this.updateQuoteReceivers(q); +// System.out.print("There was a trade:"+q.price+"\n"); + + this.quoteHistory.add(q); + this.updateQuoteReceivers(q); + } private void executeOrders_old() { @@ -661,7 +714,7 @@ public class Exchange extends Thread { tradelock.unlock(); this.updateBookReceivers(OrderType.ASK); this.updateBookReceivers(OrderType.BID); - + return o.id; } @@ -681,6 +734,10 @@ public class Exchange extends Thread { return a.orders.size(); } + public Account getAccount(double account_id) { + return accounts.get(account_id); + } + public AccountData getAccountData(double account_id) { Account a = accounts.get(account_id); if (a == null) { @@ -692,18 +749,18 @@ public class Exchange extends Thread { ad.money = a.money; ad.shares = a.shares; - ad.orders = new ArrayList(); + ad.orders = new ArrayList<>(); ad.orders.iterator(); a.orders.values(); Set s = a.orders.keySet(); Iterator it = s.iterator(); - System.out.print("Keys list" + s.size() + "\n"); + while (it.hasNext()) { long x = (long) it.next(); - System.out.print("X" + x + "\n"); + Order o = a.orders.get(x); - System.out.print("oGot: " + o.limit + " " + o.volume + "\n"); + OrderData od = new OrderData(); od.id = o.id; od.limit = o.limit; diff --git a/src/main/java/sesim/IDGenerator.java b/src/main/java/sesim/IDGenerator.java index 9526d94..3cb5048 100644 --- a/src/main/java/sesim/IDGenerator.java +++ b/src/main/java/sesim/IDGenerator.java @@ -26,37 +26,40 @@ package sesim; /** + * Implementation of a simple ID generator to create uniqe IDs of type long * * @author 7u83 <7u83@mail.ru> */ - class IDGenerator{ - private final Locker ID_LOCKER = new Locker(); - private long next_id; - - /** - * Initialize the ID generator - * @param start ID value to start with - */ - public IDGenerator(long start){ - next_id=start; - } - - /** - * Initialize ID Generator with start ID = 0 - */ - public IDGenerator(){ - this(0); - } - - /** - * Get the next ID - * @return the next generated ID - */ - public long getNext(){ - ID_LOCKER.lock(); - long id = next_id++; - ID_LOCKER.unlock(); - return id; - } +public class IDGenerator { + + private final Locker ID_LOCKER = new Locker(); + private long next_id; + + /** + * Initialize the ID generator + * + * @param start ID value to start with + */ + public IDGenerator(long start) { + next_id = start; } - \ No newline at end of file + + /** + * Initialize ID Generator with start ID = 0 + */ + public IDGenerator() { + this(0); + } + + /** + * Get the next ID + * + * @return the next generated ID + */ + public long getNext() { + ID_LOCKER.lock(); + long id = next_id++; + ID_LOCKER.unlock(); + return id; + } +} diff --git a/src/main/java/sesim/Locker.java b/src/main/java/sesim/Locker.java index 8c621f0..bf59db3 100644 --- a/src/main/java/sesim/Locker.java +++ b/src/main/java/sesim/Locker.java @@ -36,7 +36,7 @@ public class Locker { private final Semaphore AVAIL = new Semaphore(1, true); /** - * + * Acquire a lock * @return */ public boolean lock() { diff --git a/src/main/java/traders/RandomTrader.java b/src/main/java/traders/RandomTrader.java index 5b5a59f..be1c05b 100644 --- a/src/main/java/traders/RandomTrader.java +++ b/src/main/java/traders/RandomTrader.java @@ -52,7 +52,7 @@ public class RandomTrader extends AutoTrader { long event(){ - System.out.print("Hello world Iam a trader\n"); +// System.out.print("Hello world Iam a trader\n"); return this.doTrade(); // doBuy(); @@ -129,16 +129,16 @@ public class RandomTrader extends AutoTrader { public long cancelOrders(){ int n = se.getNumberOfOpenOrders(account_id); - System.out.print("Open Orders: "+n+"\n"); +// System.out.print("Open Orders: "+n+"\n"); if (n>0){ - System.out.print("Want to killń\n"); +// System.out.print("Want to killń\n"); AccountData ad = se.getAccountData(account_id); Iterator it = ad.orders.iterator(); while (it.hasNext()){ OrderData od=it.next(); boolean rc = se.cancelOrder(account_id, od.id); - System.out.print("killer rc "+rc+"\n"); - System.out.print("Killing: "+od.id+"\n"); +// System.out.print("killer rc "+rc+"\n"); + // System.out.print("Killing: "+od.id+"\n"); } } @@ -155,8 +155,10 @@ public class RandomTrader extends AutoTrader { // how much money we ant to envest? double money = getRandomAmmount(ad.money, myconfig.buy_volume); + Quote q = se.getCurrentPrice(); + double lp = q == null ? 100.0 : q.price; - double lp = 100.0; //se.getBestLimit(type); + double limit; limit = lp + getRandomAmmount(lp, myconfig.buy_limit); @@ -165,8 +167,8 @@ public class RandomTrader extends AutoTrader { return 0; } - System.out.print("Volume is:"+volume+"\n"); - System.out.print("My Ammount is: "+money+" My limit si:"+limit+ "\n"); +// System.out.print("Volume is:"+volume+"\n"); +// System.out.print("My Ammount is: "+money+" My limit si:"+limit+ "\n"); se.createOrder(account_id, type, volume, limit); @@ -187,7 +189,12 @@ public class RandomTrader extends AutoTrader { double volume = (long)getRandomAmmount(ad.shares, myconfig.sell_volume); - double lp = 100.0; //se.getBestLimit(type); + // double lp = 100.0; //se.getBestLimit(type); + + Quote q = se.getCurrentPrice(); + double lp = q == null ? 100.0 : q.price; + + double limit; limit = lp + getRandomAmmount(lp, myconfig.sell_limit); @@ -196,8 +203,8 @@ public class RandomTrader extends AutoTrader { // return false; // } - System.out.print("Volume is:"+volume+"\n"); - System.out.print("My Ammount is: "+volume+" My limit si:"+limit+ "\n"); +// System.out.print("Volume is:"+volume+"\n"); + // System.out.print("My Ammount is: "+volume+" My limit si:"+limit+ "\n"); se.createOrder(account_id, type, volume, limit);