2017-01-05 19:20:44 +01:00
|
|
|
package sesim;
|
|
|
|
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.concurrent.*;
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
import sesim.Order_old.OrderStatus;
|
|
|
|
import sesim.Order_old.OrderType_old;
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @author tube
|
|
|
|
*/
|
|
|
|
public class Exchange extends Thread {
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
public enum OrderType {
|
|
|
|
BID, ASK
|
|
|
|
}
|
|
|
|
|
|
|
|
IDGenerator account_id = new IDGenerator();
|
2017-01-12 09:07:08 +01:00
|
|
|
public static Timer timer=new Timer();
|
2017-01-10 07:41:52 +01:00
|
|
|
|
|
|
|
private class Account implements Comparable {
|
2017-01-09 17:00:05 +01:00
|
|
|
|
|
|
|
protected double id;
|
|
|
|
protected double shares;
|
|
|
|
protected double money;
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
protected HashMap<Long, Order> orders;
|
2017-01-09 17:00:05 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public int compareTo(Object a) {
|
2017-01-10 07:41:52 +01:00
|
|
|
Account account = (Account) a;
|
2017-01-09 17:00:05 +01:00
|
|
|
return this.id - account.id < 0 ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
Account(double money, double shares) {
|
|
|
|
id = (Math.random() + (account_id.getNext()));
|
|
|
|
orders = new HashMap();
|
2017-01-10 19:27:11 +01:00
|
|
|
this.money = money;
|
|
|
|
this.shares = shares;
|
2017-01-09 17:00:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
//private TreeSet<Account> accounts = new TreeSet<>();
|
|
|
|
HashMap<Double, Account> accounts = new HashMap<>();
|
2017-01-09 17:00:05 +01:00
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
public double createAccount(double money, double shares) {
|
|
|
|
Account a = new Account(money, shares);
|
|
|
|
accounts.put(a.id, a);
|
2017-01-09 17:00:05 +01:00
|
|
|
return a.id;
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
class OrderComparator implements Comparator<Order> {
|
|
|
|
|
|
|
|
OrderType type;
|
|
|
|
|
|
|
|
OrderComparator(OrderType type) {
|
|
|
|
this.type = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int compare(Order left, Order right) {
|
|
|
|
double d;
|
|
|
|
switch (this.type) {
|
|
|
|
case BID:
|
|
|
|
d = right.limit - left.limit;
|
|
|
|
break;
|
|
|
|
case ASK:
|
|
|
|
d = left.limit - right.limit;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
d = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (d != 0) {
|
|
|
|
return d > 0 ? 1 : -1;
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
if(left.id<right.id)
|
|
|
|
return -1;
|
|
|
|
if(left.id>right.id)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
|
2017-01-12 01:44:50 +01:00
|
|
|
// return left.id < right.id ? -1 : 1;
|
2017-01-10 07:41:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//TreeSet <Order> bid_bbook = new TreeSet <> (new OrderComperator(OrderType.BID) );
|
|
|
|
//TreeSet <Order> ask_dbook = new TreeSet <> (new OrderComperator(OrderType.BID) );
|
|
|
|
HashMap<OrderType, TreeSet<Order>> order_books = new HashMap();
|
|
|
|
|
|
|
|
IDGenerator order_id = new IDGenerator();
|
|
|
|
|
|
|
|
private class Order {
|
|
|
|
|
|
|
|
OrderType type;
|
|
|
|
double limit;
|
|
|
|
double volume;
|
|
|
|
double initial_volume;
|
|
|
|
long id;
|
|
|
|
long created;
|
|
|
|
Account account;
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
Order(Account account, OrderType type, double volume, double limit) {
|
2017-01-10 07:41:52 +01:00
|
|
|
id = order_id.getNext();
|
2017-01-10 19:27:11 +01:00
|
|
|
this.account = account;
|
2017-01-10 07:41:52 +01:00
|
|
|
this.type = type;
|
|
|
|
this.limit = limit;
|
|
|
|
this.volume = volume;
|
|
|
|
this.initial_volume = volume;
|
|
|
|
this.created = System.currentTimeMillis();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-05 19:20:44 +01:00
|
|
|
/**
|
|
|
|
* Histrory of quotes
|
|
|
|
*/
|
|
|
|
public TreeSet<Quote> quoteHistory = new TreeSet<>();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
|
|
|
public Exchange() {
|
|
|
|
this.ask = new TreeSet<>();
|
|
|
|
this.bid = new TreeSet<>();
|
|
|
|
this.qrlist = new ArrayList<>();
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
// Create order books
|
|
|
|
for (OrderType type : OrderType.values()) {
|
|
|
|
order_books.put(type, new TreeSet(new OrderComparator(type)));
|
|
|
|
}
|
|
|
|
|
2017-01-05 19:20:44 +01:00
|
|
|
}
|
2017-01-10 07:41:52 +01:00
|
|
|
|
|
|
|
class BidBook extends TreeSet {
|
|
|
|
|
2017-01-09 18:38:01 +01:00
|
|
|
TreeSet t = new TreeSet();
|
2017-01-10 07:41:52 +01:00
|
|
|
|
|
|
|
boolean hallo() {
|
2017-01-09 18:38:01 +01:00
|
|
|
t.comparator();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2017-01-05 19:20:44 +01:00
|
|
|
|
2017-01-06 00:37:21 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
*/
|
2017-01-05 23:18:19 +01:00
|
|
|
public static long getCurrentTimeSeconds() {
|
2017-01-06 00:37:21 +01:00
|
|
|
long ct = System.currentTimeMillis();
|
2017-01-08 01:39:14 +01:00
|
|
|
return ct / 1000;
|
2017-01-05 19:20:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public SortedSet<Quote> getQuoteHistory(long start) {
|
|
|
|
|
|
|
|
Quote s = new Quote();
|
2017-01-08 01:39:14 +01:00
|
|
|
s.time = start * 1000;
|
2017-01-05 23:18:19 +01:00
|
|
|
s.id = 0;
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
TreeSet<Quote> result = new TreeSet<>();
|
|
|
|
result.addAll(this.quoteHistory.tailSet(s));
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-05 23:18:19 +01:00
|
|
|
/* public SortedSet<Quote> getQuoteHistory(int seconds) {
|
2017-01-05 19:20:44 +01:00
|
|
|
Quote last = quoteHistory.last();
|
|
|
|
return this.getQuoteHistory(seconds, last.time);
|
|
|
|
}
|
2017-01-05 23:18:19 +01:00
|
|
|
*/
|
2017-01-05 19:20:44 +01:00
|
|
|
// Class to describe an executed order
|
|
|
|
// QuoteReceiver has to be implemented by objects that wants
|
|
|
|
// to receive quote updates
|
|
|
|
public interface QuoteReceiver {
|
|
|
|
|
|
|
|
void UpdateQuote(Quote q);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Bookreceiver Interface
|
|
|
|
*/
|
|
|
|
public interface BookReceiver {
|
|
|
|
|
|
|
|
void UpdateOrderBook();
|
|
|
|
}
|
|
|
|
|
2017-01-08 01:39:14 +01:00
|
|
|
final private ArrayList<BookReceiver> ask_bookreceivers = new ArrayList<>();
|
|
|
|
final private ArrayList<BookReceiver> bid_bookreceivers = new ArrayList<>();
|
2017-01-05 19:20:44 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
private ArrayList<BookReceiver> selectBookReceiver(OrderType t) {
|
2017-01-05 19:20:44 +01:00
|
|
|
switch (t) {
|
2017-01-10 19:27:11 +01:00
|
|
|
case ASK:
|
2017-01-05 19:20:44 +01:00
|
|
|
return ask_bookreceivers;
|
2017-01-10 19:27:11 +01:00
|
|
|
case BID:
|
2017-01-05 19:20:44 +01:00
|
|
|
return bid_bookreceivers;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
public void addBookReceiver(OrderType t, BookReceiver br) {
|
2017-01-05 19:20:44 +01:00
|
|
|
ArrayList<BookReceiver> bookreceivers;
|
|
|
|
bookreceivers = selectBookReceiver(t);
|
|
|
|
bookreceivers.add(br);
|
|
|
|
}
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
void updateBookReceivers(OrderType t) {
|
2017-01-05 19:20:44 +01:00
|
|
|
ArrayList<BookReceiver> bookreceivers;
|
|
|
|
bookreceivers = selectBookReceiver(t);
|
|
|
|
|
|
|
|
Iterator<BookReceiver> i = bookreceivers.iterator();
|
|
|
|
while (i.hasNext()) {
|
|
|
|
i.next().UpdateOrderBook();
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
sleep(10);
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
System.out.println("I was Interrupted");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Here we store the list of quote receivers
|
|
|
|
private final ArrayList<QuoteReceiver> qrlist;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param qr
|
|
|
|
*/
|
|
|
|
public void addQuoteReceiver(QuoteReceiver qr) {
|
|
|
|
qrlist.add(qr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// send updated quotes to all quote receivers
|
|
|
|
private void updateQuoteReceivers(Quote q) {
|
|
|
|
Iterator<QuoteReceiver> i = qrlist.iterator();
|
|
|
|
while (i.hasNext()) {
|
|
|
|
i.next().UpdateQuote(q);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// long time = 0;
|
|
|
|
double theprice = 12.9;
|
|
|
|
long orderid = 1;
|
|
|
|
|
|
|
|
double lastprice = 100.0;
|
|
|
|
long lastsvolume;
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
public TreeSet<Order_old> bid;
|
|
|
|
public TreeSet<Order_old> ask;
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
private Locker tradelock = new Locker();
|
|
|
|
|
|
|
|
/*
|
|
|
|
private final Semaphore available = new Semaphore(1, true);
|
|
|
|
|
|
|
|
private void Lock() {
|
|
|
|
try {
|
|
|
|
available.acquire();
|
|
|
|
} catch (InterruptedException s) {
|
|
|
|
System.out.println("Interrupted\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private void Unlock() {
|
|
|
|
available.release();
|
|
|
|
}
|
|
|
|
*/
|
2017-01-10 07:41:52 +01:00
|
|
|
private TreeSet<Order_old> selectOrderBook(OrderType_old t) {
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
switch (t) {
|
|
|
|
case bid:
|
|
|
|
return this.bid;
|
|
|
|
case ask:
|
|
|
|
return this.ask;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
public class OrderBookItem {
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
public long id;
|
|
|
|
public double limit;
|
|
|
|
public double volume;
|
|
|
|
}
|
2017-01-05 19:20:44 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
public ArrayList<OrderBookItem> getOrderBook(OrderType type, int depth) {
|
2017-01-05 19:20:44 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
TreeSet<Order> book = order_books.get(type);
|
2017-01-05 19:20:44 +01:00
|
|
|
if (book == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
ArrayList<OrderBookItem> ret = new ArrayList<>();
|
|
|
|
|
|
|
|
Iterator<Order> it = book.iterator();
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-05 19:20:44 +01:00
|
|
|
for (int i = 0; i < depth && it.hasNext(); i++) {
|
2017-01-10 19:27:11 +01:00
|
|
|
|
2017-01-12 01:44:50 +01:00
|
|
|
Order o = it.next();
|
2017-01-10 19:27:11 +01:00
|
|
|
OrderBookItem n = new OrderBookItem();
|
2017-01-12 01:44:50 +01:00
|
|
|
n.id = o.id;
|
|
|
|
n.limit = o.limit;
|
|
|
|
n.volume = o.volume;
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
ret.add(n);
|
2017-01-10 07:41:52 +01:00
|
|
|
//System.out.print("Order_old" + o.limit);
|
2017-01-05 19:20:44 +01:00
|
|
|
//System.out.println();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void print_current() {
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
Order_old b;
|
|
|
|
Order_old a;
|
2017-01-05 19:20:44 +01:00
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
//String BID;
|
2017-01-05 19:20:44 +01:00
|
|
|
if (bid.isEmpty()) {
|
|
|
|
b = new BuyOrder();
|
|
|
|
b.limit = -1;
|
|
|
|
b.volume = 0;
|
|
|
|
} else {
|
|
|
|
b = bid.first();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ask.isEmpty()) {
|
|
|
|
a = new SellOrder();
|
|
|
|
a.limit = -1;
|
|
|
|
a.volume = 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
a = ask.first();
|
|
|
|
}
|
|
|
|
|
|
|
|
Logger.info(String.format("BID: %s(%s) LAST: %.2f(%d) ASK: %s(%s)\n",
|
|
|
|
b.format_limit(), b.format_volume(),
|
|
|
|
lastprice, lastsvolume,
|
|
|
|
a.format_limit(), a.format_volume())
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
public void transferMoney(Account_old src, Account_old dst, double money) {
|
2017-01-05 19:20:44 +01:00
|
|
|
src.money -= money;
|
|
|
|
dst.money += money;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
private void transferMoneyAndShares(Account src, Account dst, double money, double shares) {
|
2017-01-09 17:00:05 +01:00
|
|
|
src.money -= money;
|
|
|
|
dst.money += money;
|
|
|
|
src.shares -= shares;
|
|
|
|
dst.shares += shares;
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
public boolean cancelOrder(double account_id, long order_id) {
|
2017-01-12 01:00:42 +01:00
|
|
|
Account a = accounts.get(account_id);
|
2017-01-12 01:44:50 +01:00
|
|
|
if (a == null) {
|
2017-01-12 01:00:42 +01:00
|
|
|
return false;
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
boolean ret = false;
|
|
|
|
|
2017-01-12 01:00:42 +01:00
|
|
|
tradelock.lock();
|
|
|
|
Order o = a.orders.get(order_id);
|
|
|
|
|
2017-01-12 01:44:50 +01:00
|
|
|
// System.out.print("The Order:"+o.limit+"\n");
|
2017-01-12 01:00:42 +01:00
|
|
|
|
2017-01-12 01:44:50 +01:00
|
|
|
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);
|
|
|
|
a.orders.remove(o.id);
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
|
2017-01-12 01:00:42 +01:00
|
|
|
tradelock.unlock();
|
|
|
|
this.updateBookReceivers(OrderType.BID);
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-12 01:00:42 +01:00
|
|
|
return ret;
|
|
|
|
}
|
2017-01-09 17:00:05 +01:00
|
|
|
|
2017-01-08 13:16:00 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param o
|
|
|
|
*/
|
2017-01-12 01:00:42 +01:00
|
|
|
public void cancelOrder_old(Order_old o) {
|
2017-01-05 19:20:44 +01:00
|
|
|
tradelock.lock();
|
2017-01-10 07:41:52 +01:00
|
|
|
TreeSet<Order_old> book = this.selectOrderBook(o.type);
|
2017-01-05 19:20:44 +01:00
|
|
|
book.remove(o);
|
2017-01-12 01:44:50 +01:00
|
|
|
/* this.updateBookReceivers(o.type);
|
2017-01-05 19:20:44 +01:00
|
|
|
o.account.pending.remove(o);
|
|
|
|
o.status = OrderStatus.canceled;
|
|
|
|
tradelock.unlock();
|
2017-01-12 01:44:50 +01:00
|
|
|
*/
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Transfer shares from one account to another account
|
|
|
|
*
|
|
|
|
* @param src source account
|
|
|
|
* @param dst destination account
|
|
|
|
* @param volumen number of shares
|
|
|
|
* @param price price
|
|
|
|
*/
|
2017-01-10 07:41:52 +01:00
|
|
|
protected void transferShares(Account_old src, Account_old dst, long volume, double price) {
|
2017-01-05 19:20:44 +01:00
|
|
|
dst.shares += volume;
|
|
|
|
src.shares -= volume;
|
|
|
|
dst.money -= price * volume;
|
|
|
|
src.money += price * volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
long nextQuoteId = 0;
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
private void removeOrderIfExecuted(Order o) {
|
|
|
|
if (o.volume != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
o.account.orders.remove(o.id);
|
|
|
|
order_books.get(o.type).pollFirst();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-08 13:16:00 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
2017-01-10 07:41:52 +01:00
|
|
|
public void executeOrders() {
|
2017-01-05 19:20:44 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
TreeSet<Order> bid = order_books.get(OrderType.BID);
|
|
|
|
TreeSet<Order> ask = order_books.get(OrderType.ASK);
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
double volume_total = 0;
|
|
|
|
double money_total = 0;
|
2017-01-10 19:27:11 +01:00
|
|
|
|
2017-01-08 03:25:18 +01:00
|
|
|
while (!bid.isEmpty() && !ask.isEmpty()) {
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
Order b = bid.first();
|
|
|
|
Order a = ask.first();
|
2017-01-10 19:27:11 +01:00
|
|
|
|
2017-01-08 03:25:18 +01:00
|
|
|
if (b.limit < a.limit) {
|
2017-01-10 07:41:52 +01:00
|
|
|
System.out.print("No match\n");
|
2017-01-08 03:25:18 +01:00
|
|
|
// no match, nothing to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-09 18:38:01 +01:00
|
|
|
// There is a match, calculate price and volume
|
2017-01-08 13:16:00 +01:00
|
|
|
double price = b.id < a.id ? b.limit : a.limit;
|
2017-01-10 07:41:52 +01:00
|
|
|
double volume = b.volume >= a.volume ? a.volume : b.volume;
|
2017-01-08 13:16:00 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
// Transfer money and shares
|
|
|
|
transferMoneyAndShares(b.account, a.account, volume * price, -volume);
|
2017-01-08 13:16:00 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
// Update volume
|
|
|
|
b.volume -= volume;
|
|
|
|
a.volume -= volume;
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
volume_total += volume;
|
|
|
|
money_total += price * volume;
|
2017-01-08 13:16:00 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
removeOrderIfExecuted(a);
|
|
|
|
removeOrderIfExecuted(b);
|
2017-01-08 13:16:00 +01:00
|
|
|
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
Quote q = new Quote();
|
2017-01-12 01:44:50 +01:00
|
|
|
q.price = money_total / volume_total;
|
|
|
|
q.volume = volume_total;
|
|
|
|
q.time = System.currentTimeMillis();
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
System.out.print("Price" + q.price + "," + q.volume + "\n");
|
2017-01-12 09:07:08 +01:00
|
|
|
//this.updateQuoteReceivers(q);
|
2017-01-08 13:16:00 +01:00
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
private void executeOrders_old() {
|
2017-01-05 19:20:44 +01:00
|
|
|
|
2017-01-08 13:16:00 +01:00
|
|
|
while (!bid.isEmpty() && !ask.isEmpty()) {
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
Order_old b = bid.first();
|
|
|
|
Order_old a = ask.first();
|
2017-01-08 13:16:00 +01:00
|
|
|
|
|
|
|
if (b.limit < a.limit) {
|
|
|
|
// no match, nothing to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2017-01-10 19:27:11 +01:00
|
|
|
// this.updateBookReceivers(OrderType_old.ask);
|
2017-01-08 13:16:00 +01:00
|
|
|
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();
|
2017-01-10 19:27:11 +01:00
|
|
|
// this.updateBookReceivers(OrderType_old.bid);
|
2017-01-08 13:16:00 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b.limit >= a.limit) {
|
|
|
|
double price;
|
|
|
|
|
|
|
|
price = b.id < a.id ? b.limit : a.limit;
|
|
|
|
|
|
|
|
/* if (b.id < a.id) {
|
|
|
|
price = b.limit;
|
|
|
|
} else {
|
|
|
|
price = a.limit;
|
|
|
|
}
|
|
|
|
*/
|
2017-01-05 19:20:44 +01:00
|
|
|
long volume;
|
|
|
|
|
|
|
|
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);
|
2017-01-10 19:27:11 +01:00
|
|
|
// this.updateBookReceivers(OrderType_old.bid);
|
|
|
|
// this.updateBookReceivers(OrderType_old.ask);
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
/* System.out.print(
|
|
|
|
"Executed: "
|
|
|
|
+ q.price
|
|
|
|
+ " / "
|
|
|
|
+ q.volume
|
|
|
|
+ "\n"
|
|
|
|
);
|
|
|
|
*/
|
|
|
|
quoteHistory.add(q);
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ExecuteOrder(BuyOrder o) {
|
2017-01-10 07:41:52 +01:00
|
|
|
// SellOrder op = ASK.peek();
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
private boolean InitOrder(Order_old o) {
|
2017-01-05 19:20:44 +01:00
|
|
|
double moneyNeeded = o.volume * o.limit;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add an order to the orderbook
|
2017-01-10 07:41:52 +01:00
|
|
|
private boolean addOrder(Order_old o) {
|
2017-01-05 19:20:44 +01:00
|
|
|
boolean ret = false;
|
|
|
|
switch (o.type) {
|
|
|
|
case bid:
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
// System.out.print("Exchange adding BID order \n");
|
2017-01-05 19:20:44 +01:00
|
|
|
ret = bid.add(o);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ask:
|
2017-01-10 07:41:52 +01:00
|
|
|
// System.out.print("Exchange adding ASK order \n");
|
2017-01-05 19:20:44 +01:00
|
|
|
ret = ask.add(o);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret) {
|
2017-01-10 19:27:11 +01:00
|
|
|
// this.updateBookReceivers(o.type);
|
2017-01-05 19:20:44 +01:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
public Order_old SendOrder(Order_old o) {
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
boolean rc = InitOrder(o);
|
|
|
|
if (!rc) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
tradelock.lock();
|
|
|
|
o.timestamp = System.currentTimeMillis();
|
|
|
|
o.id = orderid++;
|
|
|
|
addOrder(o);
|
|
|
|
o.account.pending.add(o);
|
2017-01-10 07:41:52 +01:00
|
|
|
executeOrders_old();
|
2017-01-05 19:20:44 +01:00
|
|
|
tradelock.unlock();
|
|
|
|
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
private void addOrderToBook(Order o) {
|
2017-01-10 07:41:52 +01:00
|
|
|
order_books.get(o.type).add(o);
|
2017-01-10 19:27:11 +01:00
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
}
|
2017-01-10 19:27:11 +01:00
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param account_id
|
|
|
|
* @param type
|
|
|
|
* @param volume
|
|
|
|
* @param limit
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public long createOrder(double account_id, OrderType type, double volume, double limit) {
|
|
|
|
|
|
|
|
Account a = accounts.get(account_id);
|
|
|
|
if (a == null) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
Order o = new Order(a, type, volume, limit);
|
2017-01-10 07:41:52 +01:00
|
|
|
addOrderToBook(o);
|
2017-01-10 19:27:11 +01:00
|
|
|
a.orders.put(o.id, o);
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-12 01:00:42 +01:00
|
|
|
tradelock.lock();
|
2017-01-10 19:27:11 +01:00
|
|
|
this.executeOrders();
|
2017-01-12 01:00:42 +01:00
|
|
|
tradelock.unlock();
|
2017-01-11 19:11:17 +01:00
|
|
|
this.updateBookReceivers(OrderType.ASK);
|
|
|
|
this.updateBookReceivers(OrderType.BID);
|
2017-01-12 09:07:08 +01:00
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
return o.id;
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
public double getBestLimit(OrderType type) {
|
2017-01-11 19:11:17 +01:00
|
|
|
Order o = order_books.get(type).first();
|
2017-01-12 01:44:50 +01:00
|
|
|
if (o == null) {
|
2017-01-11 19:11:17 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return o.limit;
|
|
|
|
}
|
2017-01-10 19:27:11 +01:00
|
|
|
|
2017-01-12 01:44:50 +01:00
|
|
|
public int getNumberOfOpenOrders(double account_id) {
|
|
|
|
Account a = accounts.get(account_id);
|
|
|
|
if (a == null) {
|
2017-01-11 19:11:17 +01:00
|
|
|
return 0;
|
2017-01-12 01:44:50 +01:00
|
|
|
}
|
2017-01-11 19:11:17 +01:00
|
|
|
return a.orders.size();
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
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;
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
ad.orders = new ArrayList<OrderData>();
|
2017-01-12 01:00:42 +01:00
|
|
|
ad.orders.iterator();
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
od.volume = o.volume;
|
|
|
|
ad.orders.add(od);
|
|
|
|
}
|
|
|
|
|
|
|
|
//System.exit(0);
|
2017-01-12 01:00:42 +01:00
|
|
|
//a.orders.keySet();
|
|
|
|
//KeySet ks = a.orders.keySet();
|
2017-01-10 19:27:11 +01:00
|
|
|
return ad;
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
|
|
|
public ArrayList<OrderData> getOpenOrders(double account_id) {
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
Account a = accounts.get(account_id);
|
2017-01-12 01:44:50 +01:00
|
|
|
if (a == null) {
|
2017-01-10 19:27:11 +01:00
|
|
|
return null;
|
2017-01-12 01:44:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ArrayList<OrderData> al = new ArrayList();
|
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
Iterator it = a.orders.entrySet().iterator();
|
2017-01-12 01:44:50 +01:00
|
|
|
while (it.hasNext()) {
|
|
|
|
Order o = (Order) it.next();
|
2017-01-10 19:27:11 +01:00
|
|
|
OrderData od = new OrderData();
|
2017-01-12 01:44:50 +01:00
|
|
|
od.limit = o.limit;
|
|
|
|
od.volume = o.initial_volume;
|
|
|
|
od.executed = o.initial_volume - o.volume;
|
|
|
|
od.id = o.id;
|
2017-01-10 19:27:11 +01:00
|
|
|
al.add(od);
|
|
|
|
}
|
2017-01-12 01:44:50 +01:00
|
|
|
|
2017-01-10 19:27:11 +01:00
|
|
|
return al;
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
|
2017-01-05 19:20:44 +01:00
|
|
|
/*
|
|
|
|
public void SendOrder(BuyOrder o) {
|
|
|
|
//System.out.println("EX Buyorder");
|
|
|
|
Lock();
|
|
|
|
o.timestamp = System.currentTimeMillis();
|
|
|
|
o.id = orderid++;
|
2017-01-10 07:41:52 +01:00
|
|
|
BID.add(o);
|
2017-01-05 19:20:44 +01:00
|
|
|
|
|
|
|
Unlock();
|
|
|
|
Lock();
|
2017-01-10 07:41:52 +01:00
|
|
|
// executeOrders_old();
|
2017-01-05 19:20:44 +01:00
|
|
|
Unlock();
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
2017-01-10 07:41:52 +01:00
|
|
|
* public void SendOrder(Order_old o){
|
2017-01-05 19:20:44 +01:00
|
|
|
*
|
|
|
|
*
|
2017-01-10 07:41:52 +01:00
|
|
|
* if ( o.getClass() == BuyOrder.class){ BID.add((BuyOrder)o); }
|
2017-01-05 19:20:44 +01:00
|
|
|
*
|
2017-01-10 07:41:52 +01:00
|
|
|
* if ( o.getClass() == SellOrder.class){ ASK.add((SellOrder)o); }
|
2017-01-05 19:20:44 +01:00
|
|
|
*
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
public double getlastprice() {
|
|
|
|
/*
|
|
|
|
* SellOrder so = new SellOrder(); so.limit=1000.0; so.volume=500;
|
|
|
|
* SendOrder(so);
|
|
|
|
*
|
|
|
|
* BuyOrder bo = new BuyOrder(); bo.limit=1001.0; bo.volume=300;
|
|
|
|
* SendOrder(bo);
|
|
|
|
*/
|
|
|
|
|
|
|
|
return lastprice;
|
|
|
|
}
|
|
|
|
|
2017-01-10 07:41:52 +01:00
|
|
|
/* public double sendOrder(Account_old o) {
|
2017-01-05 19:20:44 +01:00
|
|
|
return 0.7;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
while (true) {
|
|
|
|
try {
|
|
|
|
sleep(1500);
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
System.out.println("I was Interrupted");
|
|
|
|
}
|
|
|
|
print_current();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|