diff --git a/src/main/java/gui/Clock.java b/src/main/java/gui/Clock.java index 6fe4a2c..b28c920 100644 --- a/src/main/java/gui/Clock.java +++ b/src/main/java/gui/Clock.java @@ -38,6 +38,26 @@ public class Clock extends javax.swing.JPanel { protected final Timer timer; TimerTask clockUpdater; + + + class ClockUpdater implements sesim.Scheduler.TimerTaskRunner{ + + @Override + public long timerTask() { + long t = Globals.se.timer.currentTimeMillis(); + jLabel1.setText(Scheduler.formatTimeMillis(t)); + return 1000; + } + + @Override + public long getID() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + } + + + /** * Creates new form Clock */ @@ -51,7 +71,7 @@ public class Clock extends javax.swing.JPanel { return; - clockUpdater = new TimerTask() { + clockUpdater = new TimerTask () { @Override public void run() { long t = Globals.se.timer.currentTimeMillis(); diff --git a/src/main/java/gui/NewMDIApplication.java b/src/main/java/gui/NewMDIApplication.java index 411774a..473c95e 100644 --- a/src/main/java/gui/NewMDIApplication.java +++ b/src/main/java/gui/NewMDIApplication.java @@ -547,7 +547,7 @@ public class NewMDIApplication extends javax.swing.JFrame { Globals.se.timer.start(); Globals.se.timer.setAcceleration((Double) this.accelSpinner.getValue()); - Scheduler.TimerTask tt = new Scheduler.TimerTask() { + Scheduler.TimerTaskRunner tt = new Scheduler.TimerTaskRunner() { @Override public long timerTask() { System.out.printf("Hello i will inject money\n"); diff --git a/src/main/java/sesim/AutoTraderBase.java b/src/main/java/sesim/AutoTraderBase.java index 5cdaa43..a804940 100644 --- a/src/main/java/sesim/AutoTraderBase.java +++ b/src/main/java/sesim/AutoTraderBase.java @@ -26,13 +26,13 @@ package sesim; import org.json.JSONObject; -import sesim.Scheduler.TimerTask; +import sesim.Scheduler.TimerTaskRunner; /** * * @author 7u83 <7u83@mail.ru> */ -public abstract class AutoTraderBase implements AutoTraderInterface, TimerTask { +public abstract class AutoTraderBase implements AutoTraderInterface, TimerTaskRunner { protected double account_id; protected Exchange se; diff --git a/src/main/java/sesim/Clock.java b/src/main/java/sesim/Clock.java new file mode 100644 index 0000000..0db7039 --- /dev/null +++ b/src/main/java/sesim/Clock.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, tobias + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package sesim; + +import java.util.Date; + +/** + * + * @author tobias + * + * Implements an adjustable clock + * + */ +public class Clock { + + private double acceleration=1.0; + private double current_time_millis=0.0; + private long last_time_millis=System.currentTimeMillis(); + private boolean pause=false; + + + + public synchronized long currentTimeMillis1() { + + long cur = System.currentTimeMillis(); + + double diff = cur - last_time_millis; + last_time_millis = cur; + + + if (pause) { + return (long) this.current_time_millis; + } + + // System.out.printf("Floaf TM: %f\n", this.current_time_millis); + + this.current_time_millis += diff * acceleration; + return (long) this.current_time_millis; + } + + /** + * Set the clock acceleration + * @param acceleration + */ + public void setAcceleration(double acceleration){ + this.acceleration=acceleration; + } + + + public void setPause(boolean p){ + pause=p; + } + + +} diff --git a/src/main/java/sesim/Exchange.java b/src/main/java/sesim/Exchange.java index e2880b5..c9d0963 100644 --- a/src/main/java/sesim/Exchange.java +++ b/src/main/java/sesim/Exchange.java @@ -1,6 +1,7 @@ package sesim; import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.BiConsumer; @@ -15,6 +16,8 @@ import org.json.JSONObject; */ public class Exchange { + ConcurrentLinkedQueue order_queue = new ConcurrentLinkedQueue(); + private double money_df = 10000; /** @@ -299,14 +302,13 @@ public class Exchange { OrderType type; private double limit; private double volume; - - + private final double initial_volume; private final long id; private final long created; - + private final Account account; - + double cost; Order(Account account, OrderType type, double volume, double limit) { @@ -318,7 +320,7 @@ public class Exchange { this.initial_volume = this.volume; this.created = timer.currentTimeMillis(); this.status = OrderStatus.OPEN; - this.cost=0; + this.cost = 0; } public long getID() { @@ -344,16 +346,17 @@ public class Exchange { public double getInitialVolume() { return initial_volume; } - - public double getCost(){ + + public double getCost() { return cost; } - - public double getAvaragePrice(){ + + public double getAvaragePrice() { double e = getExecuted(); - if (e<=0) + if (e <= 0) { return -1; - return cost/e; + } + return cost / e; } public Account getAccount() { @@ -364,7 +367,7 @@ public class Exchange { return status; } - public long getCreated(){ + public long getCreated() { return created; } } @@ -435,7 +438,14 @@ public class Exchange { this.wait(); - executeOrders(); + Order o; + while (null != (o = order_queue.poll())) { + addOrderToBook(o); + Account a = o.account; + a.orders.put(o.id, o); + a.update(o); + executeOrders(); + } updateBookReceivers(OrderType.SELLLIMIT); updateBookReceivers(OrderType.BUYLIMIT); @@ -583,76 +593,76 @@ public class Exchange { public Quote getBestPrice_0() { - synchronized (executor){ - SortedSet bid = order_books.get(OrderType.BUYLIMIT); - SortedSet ask = order_books.get(OrderType.SELLLIMIT); + synchronized (executor) { + SortedSet bid = order_books.get(OrderType.BUYLIMIT); + SortedSet ask = order_books.get(OrderType.SELLLIMIT); - Quote lq = this.getLastQuoete(); - Order b = null, a = null; - if (!bid.isEmpty()) { - b = bid.first(); - } - if (!ask.isEmpty()) { - a = ask.first(); - } - - // If there is neither bid nor ask and no last quote - // we can't return a quote - if (lq == null && b == null && a == null) { - return null; - } - - // there is bid and ask - if (a != null && b != null) { - Quote q = new Quote(); - - // if there is no last quote calculate from bid and ask - if (lq == null) { - q.price = (bid.first().limit + ask.first().limit) / 2.0; - return q; + Quote lq = this.getLastQuoete(); + Order b = null, a = null; + if (!bid.isEmpty()) { + b = bid.first(); + } + if (!ask.isEmpty()) { + a = ask.first(); } - if (lq.price < b.limit) { - q.price = b.limit; - return q; + // If there is neither bid nor ask and no last quote + // we can't return a quote + if (lq == null && b == null && a == null) { + return null; } - if (lq.price > a.limit) { - q.price = a.limit; - return q; - } - return lq; - } - if (a != null) { - Quote q = new Quote(); - if (lq == null) { + // there is bid and ask + if (a != null && b != null) { + Quote q = new Quote(); - q.price = a.limit; - return q; - } - if (lq.price > a.limit) { - q.price = a.limit; - return q; - } - return lq; - } + // if there is no last quote calculate from bid and ask + if (lq == null) { + q.price = (bid.first().limit + ask.first().limit) / 2.0; + return q; + } - if (b != null) { - Quote q = new Quote(); - if (lq == null) { - q.price = b.limit; - return q; + if (lq.price < b.limit) { + q.price = b.limit; + return q; + } + if (lq.price > a.limit) { + q.price = a.limit; + return q; + } + return lq; } - if (lq.price < b.limit) { - q.price = b.limit; - return q; + + if (a != null) { + Quote q = new Quote(); + if (lq == null) { + + q.price = a.limit; + return q; + } + if (lq.price > a.limit) { + q.price = a.limit; + return q; + } + return lq; + } + + if (b != null) { + Quote q = new Quote(); + if (lq == null) { + q.price = b.limit; + return q; + } + if (lq.price < b.limit) { + q.price = b.limit; + return q; + } + + return lq; } return lq; } - - return lq; - } } // Class to describe an executed order @@ -689,7 +699,7 @@ public class Exchange { if (br == null) { // System.out.printf("Br is null\n"); } else { - // System.out.printf("Br is not Nukk\n"); + // System.out.printf("Br is not Nukk\n"); } ArrayList bookreceivers; @@ -901,9 +911,9 @@ public class Exchange { // Update volume b.volume -= volume; a.volume -= volume; - - b.cost+=price*volume; - a.cost+=price*volume; + + b.cost += price * volume; + a.cost += price * volume; removeOrderIfExecuted(a); removeOrderIfExecuted(b); @@ -1038,16 +1048,21 @@ public class Exchange { // System.out.printf("Getting executor in create Order\n", Thread.currentThread().getId()); synchronized (executor) { -// System.out.printf("Have executor in create Order\n", Thread.currentThread().getId()); + num_orders++; addOrderToBook(o); a.orders.put(o.id, o); -// System.out.printf("Calling in create Order oupdate for %s\n", o.getOrderStatus().toString()); a.update(o); - executor.notify(); + executeOrders(); + updateBookReceivers(OrderType.SELLLIMIT); + updateBookReceivers(OrderType.BUYLIMIT); + +// System.out.printf("Order to Queeue %s %f %f\n",o.type.toString(),o.volume,o.limit); +// order_queue.add(o); +// executor.notify(); } - // a.update(o); +// a.update(o); return o.id; } diff --git a/src/main/java/sesim/OldAutoTrader.java b/src/main/java/sesim/OldAutoTrader.java index 0538807..d152dd4 100644 --- a/src/main/java/sesim/OldAutoTrader.java +++ b/src/main/java/sesim/OldAutoTrader.java @@ -32,7 +32,7 @@ import sesim.Exchange.Account; * * @author 7u83 */ -public abstract class OldAutoTrader implements Scheduler.TimerTask { +public abstract class OldAutoTrader implements Scheduler.TimerTaskRunner { protected double account_id; protected Exchange se; diff --git a/src/main/java/sesim/Scheduler.java b/src/main/java/sesim/Scheduler.java index e5be37c..11a645b 100644 --- a/src/main/java/sesim/Scheduler.java +++ b/src/main/java/sesim/Scheduler.java @@ -33,14 +33,12 @@ import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; -import java.util.Queue; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; /** * @@ -154,12 +152,13 @@ public class Scheduler extends Thread { public class TimerTaskDef implements Comparable { TimerTaskRunner taskRunner; - long evtime; + long curevtime; + long newevtime; int id; TimerTaskDef(TimerTaskRunner e, long t) { taskRunner = e; - evtime = t; + newevtime = t; id = nextTimerTask.getAndAdd(1); } @@ -167,7 +166,7 @@ public class Scheduler extends Thread { @Override public int compareTo(Object o) { return ((TimerTaskDef) o).id - this.id; - + } } @@ -184,8 +183,8 @@ public class Scheduler extends Thread { public TimerTaskDef startTimerTask(TimerTaskRunner e, long time) { long evtime = time + currentTimeMillis(); - - TimerTaskDef task = new TimerTaskDef(e,evtime); + + TimerTaskDef task = new TimerTaskDef(e, evtime); set_tasks.add(task); synchronized (this) { @@ -194,6 +193,15 @@ public class Scheduler extends Thread { return task; } + public void XXXrescheduleTimerTask(TimerTaskDef task, long time) { + long evtime = time + currentTimeMillis(); + set_tasks.add(task); + + synchronized (this) { + notify(); + } + } + private boolean pause = false; public void pause() { @@ -217,18 +225,20 @@ public class Scheduler extends Thread { return e.timerTask(); } - HashMap tasks = new HashMap<>(); + // HashMap tasks = new HashMap<>(); - private boolean addTimerTask(TimerTaskDef e, long evtime) { + private boolean addTimerTask(TimerTaskDef e) { // long evtime = time + currentTimeMillis(); - SortedSet s = event_queue.get(evtime); + SortedSet s = event_queue.get(e.newevtime); if (s == null) { s = new TreeSet<>(); - event_queue.put(evtime, s); + event_queue.put(e.newevtime, s); } + + e.curevtime=e.newevtime; - tasks.put(e, evtime); + // tasks.put(e, e.evtime); return s.add(e); } @@ -241,13 +251,13 @@ public class Scheduler extends Thread { private void cancelMy(TimerTaskDef e) { - Long evtime = tasks.get(e); +// Long evtime = tasks.get(e.curevtime); - if (evtime == null) { - return; - } +// if (evtime == null) { +// return; +// } - SortedSet s = event_queue.get(evtime); + SortedSet s = event_queue.get(e.curevtime); if (s == null) { return; @@ -257,7 +267,7 @@ public class Scheduler extends Thread { if (s.isEmpty()) { - event_queue.remove(evtime); + event_queue.remove(e.curevtime); } } @@ -287,7 +297,8 @@ public class Scheduler extends Thread { while (it.hasNext()) { TimerTaskDef e = it.next(); long next_t = this.fireEvent(e.taskRunner); - this.addTimerTask(e, next_t + t); + e.newevtime = next_t + t; + this.addTimerTask(e); } return 0; @@ -325,7 +336,7 @@ public class Scheduler extends Thread { while (!set_tasks.isEmpty()) { TimerTaskDef td = set_tasks.poll(); this.cancelMy(td); - this.addTimerTask(td, td.evtime); + this.addTimerTask(td); } diff --git a/src/main/java/traders/RandomTraderA.java b/src/main/java/traders/RandomTraderA.java index d5689bb..1693228 100644 --- a/src/main/java/traders/RandomTraderA.java +++ b/src/main/java/traders/RandomTraderA.java @@ -73,7 +73,7 @@ public class RandomTraderA extends AutoTraderBase implements AccountListener { a.setListener(this); long delay = (long) (getRandom(initial_delay[0], initial_delay[1]) * 1000); - se.timer.startTimerTask(this, delay); + timerTask = se.timer.startTimerTask(this, delay); } @Override @@ -183,19 +183,22 @@ public class RandomTraderA extends AutoTraderBase implements AccountListener { return null; } + sesim.Scheduler.TimerTaskDef timerTask; + @Override public void accountUpdated(Account a, Exchange.Order o) { // System.out.printf("Order what %s %d\n", o.getOrderStatus().toString(), Thread.currentThread().getId()); if (o.getOrderStatus() == OrderStatus.CLOSED ) { // System.out.printf("Enteter canel timer %d\n", Thread.currentThread().getId()); - se.timer.cancelTimerTask(this); + // se.timer.cancelTimerTask(this); //System.out.printf("back from canel timer %d\n", System.identityHashCode(this)); //System.exit(0); Long w = waitAfterOrder(); // System.out.printf("We have now to wait for %d\n", w); - se.timer.startTimerTask(this, w); + //timerTask = se.timer.startTimerTask(this, w); + se.timer.XXXrescheduleTimerTask(timerTask, w); } // System.out.printf("Updatetd Account\n", ""); diff --git a/src/test/java/sesim/Test.java b/src/test/java/sesim/Test.java index 153b302..4138791 100644 --- a/src/test/java/sesim/Test.java +++ b/src/test/java/sesim/Test.java @@ -38,6 +38,9 @@ import java.util.ArrayList; import java.util.SortedMap; import java.util.TreeMap; import java.lang.ClassLoader.*; +import java.util.logging.Level; +import java.util.logging.Logger; +import sesim.Scheduler.TimerTaskRunner; /** * @@ -80,25 +83,85 @@ public class Test { } */ - - static class Z{ - Double x; + static class Exer extends Thread { + + int value = 0; + + @Override + public void run() { + + while (true) { + try { + System.out.printf("Exer getting Exer Lock"); + synchronized (this) { + System.out.printf("Exer having Exer Lock wait 30000\n"); + this.wait(); + } + + } catch (InterruptedException ex) { + System.out.printf("Interrupted\n"); + } + + System.out.printf("Exer Value %d\n", value); + } + } + } + + static class Runner extends Thread { + + } + static Scheduler s = new Scheduler(); + + static class MyTask implements TimerTaskRunner{ + + long ctr=0; + @Override + public long timerTask() { + ctr++; + double r=1; + for (int i=0; i<100000; i++){ + r=r+i*r; + r=r+1.0; + } + synchronized (this){ + try { + wait(500); + } catch (InterruptedException ex) { + Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); + } + } + System.out.printf("TimerTask %d %d %f\n",ctr,s.currentTimeMillis(),r); + + return 1000; + } + + @Override + public long getID() { + return 0; + } + + } + + /** * @param args the command line arguments */ public static void main(String[] args) throws InterruptedException, MalformedURLException, InstantiationException, IllegalAccessException, IOException { + + Clock clock = new Clock(); - Z z = new Z(); + + s.start(); + + s.setAcceleration(1); + + MyTask t = new MyTask(); - z.x = 3.1415926; - - System.out.printf("ID: %d\n", System.identityHashCode(z)); - - z.x = 90.0; - - System.out.printf("ID: %d\n", System.identityHashCode(z)); + s.setAcceleration(1.0); + s.startTimerTask(t, 0); + s.join(); } }