Skip to content

Commit ad69e73

Browse files
Merge pull request #450 from pran9v/main
Added OrderBook Project
2 parents 3e8c99d + 3a5b78b commit ad69e73

File tree

4 files changed

+233
-0
lines changed

4 files changed

+233
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import java.io.*;
2+
import java.nio.file.*;
3+
4+
public class Helpers {
5+
6+
public static void printFileContents(String filePath) {
7+
try {
8+
String content = Files.readString(Paths.get(filePath));
9+
System.out.println(content);
10+
} catch (IOException e) {
11+
System.err.println("Unable to open " + filePath);
12+
}
13+
}
14+
15+
public static void printFill(OrderFill fill, int quantity, long startTime, long endTime) {
16+
double averagePrice = fill.unitsTransacted > 0 ? fill.totalValue / fill.unitsTransacted : 0.0;
17+
long timeTaken = endTime - startTime;
18+
System.out.println("Filled "+fill.unitsTransacted+"/"+quantity+" units @ $"+averagePrice+" avg. price in "+timeTaken+" ns");
19+
}
20+
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import java.util.*;
2+
3+
class Order {
4+
int quantity;
5+
double price;
6+
String side;
7+
8+
Order(int quantity, double price, String side) {
9+
this.quantity = quantity;
10+
this.price = price;
11+
this.side = side;
12+
}
13+
}
14+
15+
final class Orderbook {
16+
private final TreeMap<Double, List<Order>> bids = new TreeMap<>(Collections.reverseOrder());
17+
private final TreeMap<Double, List<Order>> asks = new TreeMap<>();
18+
19+
public Orderbook(boolean generateDummies) {
20+
if (generateDummies) {
21+
Random random = new Random(12);
22+
23+
for (int i = 0; i < 10; i++) {
24+
double randomPrice = 90.0 + random.nextInt(1001) / 100.0;
25+
addOrder(random.nextInt(100) + 1, randomPrice, "BUY");
26+
addOrder(random.nextInt(100) + 1, randomPrice, "BUY");
27+
}
28+
29+
for (int i = 0; i < 10; i++) {
30+
double randomPrice = 100.0 + random.nextInt(1001) / 100.0;
31+
addOrder(random.nextInt(100) + 1, randomPrice, "SELL");
32+
addOrder(random.nextInt(100) + 1, randomPrice, "SELL");
33+
}
34+
35+
}
36+
}
37+
38+
public void addOrder(int qty, double price, String side) {
39+
Order order = new Order(qty, price, side.equals("BUY") ? "BUY" : "SELL");
40+
TreeMap<Double, List<Order>> book = side.equals("BUY") ? bids : asks;
41+
42+
book.computeIfAbsent(price, k -> new ArrayList<>()).add(order);
43+
}
44+
45+
public void print() {
46+
System.out.println("========== Orderbook =========");
47+
printLeg(asks, "ASK");
48+
49+
double bestAsk = bestQuote("SELL");
50+
double bestBid = bestQuote("BUY");
51+
System.out.println("====== " + String.format("%.2f", (bestAsk - bestBid) / bestBid * 10000) + "bps ======");
52+
53+
printLeg(bids, "BUY");
54+
System.out.println("==============================\n\n");
55+
}
56+
57+
private void printLeg(TreeMap<Double, List<Order>> book, String side) {
58+
if (side.equals("ASK")) {
59+
for (Map.Entry<Double, List<Order>> entry : book.entrySet()) {
60+
printPriceLevel(entry.getKey(), entry.getValue(), "31");
61+
}
62+
} else {
63+
NavigableSet<Double> descendingKeys = book.navigableKeySet().descendingSet();
64+
for (Double key : descendingKeys) {
65+
printPriceLevel(key, book.get(key), "32");
66+
}
67+
}
68+
}
69+
70+
private void printPriceLevel(double price, List<Order> orders, String color) {
71+
int totalQuantity = 0;
72+
for (Order order : orders) {
73+
totalQuantity += order.quantity;
74+
}
75+
System.out.printf("\t\033[1;%sm\u20B9%6.2f%5d\033[0m ", color, price, totalQuantity);
76+
for (int i = 0; i < totalQuantity / 10; i++) {
77+
System.out.print("█");
78+
}
79+
System.out.println();
80+
}
81+
82+
private double bestQuote(String side) {
83+
TreeMap<Double, List<Order>> book = side.equals("BUY") ? bids : asks;
84+
return book.isEmpty() ? 0.0 : book.firstKey();
85+
}
86+
87+
88+
89+
public OrderFill handleOrder(String type, int orderQuantity, String side, double price) {
90+
int unitsTransacted = 0;
91+
double totalValue = 0.0;
92+
93+
TreeMap<Double, List<Order>> book = side.equals("BUY") ? asks : bids;
94+
95+
Iterator<Map.Entry<Double, List<Order>>> iterator = book.entrySet().iterator();
96+
while (iterator.hasNext() && orderQuantity > 0) {
97+
Map.Entry<Double, List<Order>> entry = iterator.next();
98+
double priceLevel = entry.getKey();
99+
100+
if (type.equals("LIMIT") && ((side.equals("BUY") && priceLevel > price)
101+
|| (side.equals("SELL") && priceLevel < price))) {
102+
break;
103+
}
104+
105+
List<Order> orders = entry.getValue();
106+
Iterator<Order> orderIterator = orders.iterator();
107+
while (orderIterator.hasNext() && orderQuantity > 0) {
108+
Order order = orderIterator.next();
109+
110+
if (order.quantity > orderQuantity) {
111+
unitsTransacted += orderQuantity;
112+
totalValue += orderQuantity * priceLevel;
113+
order.quantity -= orderQuantity;
114+
orderQuantity = 0;
115+
} else {
116+
unitsTransacted += order.quantity;
117+
totalValue += order.quantity * priceLevel;
118+
orderQuantity -= order.quantity;
119+
orderIterator.remove();
120+
}
121+
}
122+
123+
if (orders.isEmpty()) {
124+
iterator.remove();
125+
}
126+
}
127+
128+
if (type.equals("LIMIT") && orderQuantity > 0) {
129+
addOrder(orderQuantity, price, side.equals("BUY") ? "BUY" : "SELL");
130+
}
131+
132+
return new OrderFill(unitsTransacted, totalValue);
133+
}
134+
}
135+
136+
class OrderFill {
137+
int unitsTransacted;
138+
double totalValue;
139+
140+
OrderFill(int unitsTransacted, double totalValue) {
141+
this.unitsTransacted = unitsTransacted;
142+
this.totalValue = totalValue;
143+
}
144+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import java.util.Scanner;
2+
3+
public class OrderBookApp {
4+
5+
public static void main(String[] args) {
6+
Orderbook ob = new Orderbook(true);
7+
Scanner scanner = new Scanner(System.in);
8+
System.out.println("""
9+
___ _ ____ _ __ _ \r
10+
/ _ \\ _ __ __| | ___ _ __| __ ) ___ ___ | | __ / / (_) __ ___ ____ _ \r
11+
| | | | '__/ _` |/ _ \\ '__| _ \\ / _ \\ / _ \\| |/ / / / | |/ _` \\ \\ / / _` |\r
12+
| |_| | | | (_| | __/ | | |_) | (_) | (_) | < / / | | (_| |\\ V / (_| |\r
13+
\\___/|_| \\__,_|\\___|_| |____/ \\___/ \\___/|_|\\_\\ /_/ _/ |\\__,_| \\_/ \\__,_|\r
14+
|__/ """ //
15+
//
16+
//
17+
//
18+
//
19+
);
20+
while (true) {
21+
System.out.println("Options\n-----------------------------------\n|1. Print Orderbook |\n|2. Submit order |\n|3. Exit |\n-----------------------------------\nChoice: ");
22+
int action = scanner.nextInt();
23+
24+
if (action == 1) {
25+
ob.print();
26+
} else if (action == 2) {
27+
System.out.println("Enter order type:\n1. Market order\n2. Limit order\nSelection: ");
28+
int orderTypeInput = scanner.nextInt();
29+
String orderType = (orderTypeInput == 1) ? "MARKET" : "LIMIT";
30+
31+
System.out.println("\nEnter side:\n1. Buy\n2. Sell\nSelection: ");
32+
int sideInput = scanner.nextInt();
33+
String side = (sideInput == 1) ? "BUY" : "SELL";
34+
35+
System.out.println("\nEnter order quantity: ");
36+
int quantity = scanner.nextInt();
37+
38+
if (orderType.equals("MARKET")) {
39+
System.out.println("\nSubmitting market " + (side.equals("BUY") ? "buy" : "sell")
40+
+ " order for " + quantity + " units..\n");
41+
42+
long startTime = System.nanoTime();
43+
OrderFill fill = ob.handleOrder(orderType, quantity, side, 0.0);
44+
long endTime = System.nanoTime();
45+
46+
Helpers.printFill(fill, quantity, startTime, endTime);
47+
} else if (orderType.equals("LIMIT")) {
48+
System.out.println("\nEnter limit price: ");
49+
double price = scanner.nextDouble();
50+
51+
System.out.println("\nSubmitting limit " + (side.equals("BUY") ? "buy" : "sell")
52+
+ " order for " + quantity + " units @ \u20B9" + price + "..\n");
53+
54+
long startTime = System.nanoTime();
55+
OrderFill fill = ob.handleOrder(orderType, quantity, side, price);
56+
long endTime = System.nanoTime();
57+
58+
Helpers.printFill(fill, quantity, startTime, endTime);
59+
}
60+
System.out.println();
61+
} else if(action == 3) {
62+
break;
63+
}
64+
}
65+
scanner.close();
66+
System.out.println("Program terminated.");
67+
}
68+
}

orderBook

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 1e5ed09f70b085b47e64eb25ec32a4f3267be627

0 commit comments

Comments
 (0)