From d2c9ff458a4352a5ce48ee67127c80d7759d074b Mon Sep 17 00:00:00 2001 From: bublyapplejuice2 Date: Sat, 4 Mar 2023 15:40:06 -0500 Subject: [PATCH 1/2] init commit --- .idea/runConfigurations.xml | 10 ---------- Data-Integration.iml | 24 ++++++++++++------------ src/test/testOrderBook.java | 16 ++++++++++++++-- 3 files changed, 26 insertions(+), 24 deletions(-) delete mode 100644 .idea/runConfigurations.xml diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 797acea..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Data-Integration.iml b/Data-Integration.iml index 6f3b297..0133fd5 100644 --- a/Data-Integration.iml +++ b/Data-Integration.iml @@ -6,7 +6,7 @@ - + @@ -20,24 +20,24 @@ - - + + - + - - - - - - - - + + + + + + + + diff --git a/src/test/testOrderBook.java b/src/test/testOrderBook.java index 30d1653..ec48001 100644 --- a/src/test/testOrderBook.java +++ b/src/test/testOrderBook.java @@ -63,8 +63,9 @@ void placeOneBid() { assertEquals(-1f, testSubject.bestBidPrice); assertEquals(0f, testSubject.sittingVolume); // Operation - Order newAsk = new Order(3.39f, 0.25f, Side.BID, 1677541289L); - testSubject.placeOrder(newAsk); + Order /* newAsk */ newBid = new Order(3.39f, 0.25f, Side.BID, 1677541289L); // Typo Found + // The typo does not affect functionality + testSubject.placeOrder(newBid); // Checking Operation assertEquals(0, testSubject.asks.size()); assertEquals(1, testSubject.bids.size()); @@ -168,4 +169,15 @@ void placeTwoAsk() { assertEquals(-1f, testSubject.bestBidPrice); assertEquals(1.8f, testSubject.sittingVolume); } + + @Test + void placeOneSTOPLIMIT() { + // Init and checking start conditions + OrderBook testSubject = new OrderBook(); + assertEquals(0, testSubject.asks.size()); + assertEquals(0, testSubject.bids.size()); + assertEquals(-1f, testSubject.bestAskPrice); + assertEquals(-1f, testSubject.bestBidPrice); + assertEquals(0f, testSubject.sittingVolume); + } } From 76e76ff15d7be43254b629536f962fa24f3e04f9 Mon Sep 17 00:00:00 2001 From: bublyapplejuice2 Date: Sat, 4 Mar 2023 18:17:16 -0500 Subject: [PATCH 2/2] Changes: 4 tests cases: oneBidstoplimit, oneAsklimit, twoAskmarketoneBidlimitCROSSED, oneBidoneAskFILL, throw exception on CROSSEDMARKET condition --- src/OrderBook/OrderBook.java | 16 +++- src/test/testOrderBook.java | 156 ++++++++++++++++++++++++++++++++--- 2 files changed, 158 insertions(+), 14 deletions(-) diff --git a/src/OrderBook/OrderBook.java b/src/OrderBook/OrderBook.java index b0e15c9..770e215 100644 --- a/src/OrderBook/OrderBook.java +++ b/src/OrderBook/OrderBook.java @@ -16,7 +16,8 @@ public class OrderBook { // Helpers private void sortedPlace(Order order){ - LinkedList sideOfBook = order.side==Side.ASK ? asks : bids; + boolean isAsk = order.side==Side.ASK; + LinkedList sideOfBook = isAsk ? asks : bids; for (int i = 0; i < sideOfBook.size(); i++) { if (sideOfBook.get(i).price == order.price){ order.size += sideOfBook.get(i).size; @@ -27,7 +28,8 @@ private void sortedPlace(Order order){ bids.set(i, order); return; } - else if (sideOfBook.get(i).price < order.price){ + else if (sideOfBook.get(i).price < order.price && !isAsk || + sideOfBook.get(i).price > order.price && isAsk){ if (order.side == Side.ASK) asks.add(i,order); else @@ -75,15 +77,21 @@ private void adjustBBO(){ * @param order A valid order */ public void placeOrder(Order order){ - if (placedOrders.containsKey(order.orderID)) + if (order.orderID != null && placedOrders.containsKey(order.orderID)) return; // Don't place an order we already placed // Insert OrderBook.Order into proper book sortedPlace(order); sittingVolume += order.size; adjustBBO(); placedOrders.put(order.orderID, order.orderID); + + if (bestBidPrice > bestAskPrice && bestBidPrice != -1 && bestAskPrice != -1) { + // NEW ASSERTION, check for crossed orderbook condition where best bid over best ask + throw new RuntimeException("Crossed orderbook condition!"); + } } + /** * Registers fill event on the order book * WARNING: Will throw if fill event doesn't fill any sitting order @@ -98,4 +106,4 @@ public void fillEvent(Fill fill){ adjustBBO(); recordedFills.put(fill.orderID, fill.orderID); } -} +} \ No newline at end of file diff --git a/src/test/testOrderBook.java b/src/test/testOrderBook.java index ec48001..bd5c24d 100644 --- a/src/test/testOrderBook.java +++ b/src/test/testOrderBook.java @@ -1,6 +1,12 @@ import OrderBook.Order; +import OrderBook.Fill; import OrderBook.OrderBook; import OrderBook.Side; + +import static OrderBook.OrderType.MARKET_ORDER; +import static OrderBook.OrderType.LIMIT_ORDER; +import static OrderBook.OrderType.STOP_LIMIT_ORDER; + import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -47,7 +53,7 @@ void placeOneAskTwo() { assertEquals(0, testSubject.bids.size()); assertEquals(5.3f, testSubject.asks.getFirst().price); assertEquals(0.3f, testSubject.asks.getFirst().size); - assertEquals(1677599362L, testSubject.bids.getFirst().createdTs); + assertEquals(1677599362L, testSubject.asks.getFirst().createdTs); assertEquals(5.3f, testSubject.bestAskPrice); assertEquals(-1f, testSubject.bestBidPrice); assertEquals(0.3f, testSubject.sittingVolume); @@ -63,9 +69,8 @@ void placeOneBid() { assertEquals(-1f, testSubject.bestBidPrice); assertEquals(0f, testSubject.sittingVolume); // Operation - Order /* newAsk */ newBid = new Order(3.39f, 0.25f, Side.BID, 1677541289L); // Typo Found - // The typo does not affect functionality - testSubject.placeOrder(newBid); + Order newAsk = new Order(3.39f, 0.25f, Side.BID, 1677541289L); + testSubject.placeOrder(newAsk); // Checking Operation assertEquals(0, testSubject.asks.size()); assertEquals(1, testSubject.bids.size()); @@ -162,16 +167,64 @@ void placeTwoAsk() { //Checking Operation assertEquals(2, testSubject.asks.size()); assertEquals(0, testSubject.bids.size()); - assertEquals(5.3f, testSubject.asks.getLast().price); - assertEquals(0.3f, testSubject.asks.getLast().size); - assertEquals(1677598183L, testSubject.bids.getFirst().createdTs); - assertEquals(10.2f, testSubject.bestAskPrice); + assertEquals(5.3f, testSubject.asks.getFirst().price); + assertEquals(0.3f, testSubject.asks.getFirst().size); + assertEquals(1677598183L, testSubject.asks.getFirst().createdTs); + assertEquals(5.3f, testSubject.bestAskPrice); assertEquals(-1f, testSubject.bestBidPrice); assertEquals(1.8f, testSubject.sittingVolume); } @Test - void placeOneSTOPLIMIT() { + void placeOneBidSTOPLIMIT() { + // Init and checking start conditions + OrderBook testSubject = new OrderBook(); + assertEquals(0, testSubject.asks.size()); + assertEquals(0, testSubject.bids.size()); + assertEquals(-1f, testSubject.bestAskPrice); + assertEquals(-1f, testSubject.bestBidPrice); + assertEquals(0f, testSubject.sittingVolume); + // Operation + Order newSTOPLIMIT = new Order("helloUUID!", "helloproductID!", 2.2f, 99.99f, + STOP_LIMIT_ORDER, false, Side.BID, 1677598183L); + testSubject.placeOrder(newSTOPLIMIT); + // Checking Operation + assertEquals(0, testSubject.asks.size()); + assertEquals(1, testSubject.bids.size()); + assertEquals(99.99f, testSubject.bids.getFirst().price); + assertEquals(2.2f, testSubject.bids.getFirst().size); + assertEquals(1677598183L, testSubject.bids.getFirst().createdTs); + assertEquals(-1f, testSubject.bestAskPrice); + assertEquals(99.99f, testSubject.bestBidPrice); + assertEquals(2.2f, testSubject.sittingVolume); + } + + @Test + void placeOneAskLIMITORDER() { + // Init and checking start conditions + OrderBook testSubject = new OrderBook(); + assertEquals(0, testSubject.asks.size()); + assertEquals(0, testSubject.bids.size()); + assertEquals(-1f, testSubject.bestAskPrice); + assertEquals(-1f, testSubject.bestBidPrice); + assertEquals(0f, testSubject.sittingVolume); + // Operation + Order newLIMIT = new Order("helloUUID!", "helloproductID!", 6.9f, 69.69f, + LIMIT_ORDER, false, Side.ASK, 69L); + testSubject.placeOrder(newLIMIT); + // Checking Operation + assertEquals(1, testSubject.asks.size()); + assertEquals(0, testSubject.bids.size()); + assertEquals(69.69f, testSubject.asks.getFirst().price); + assertEquals(6.9f, testSubject.asks.getFirst().size); + assertEquals(69L, testSubject.asks.getFirst().createdTs); + assertEquals(69.69f, testSubject.bestAskPrice); + assertEquals(-1f, testSubject.bestBidPrice); + assertEquals(6.9f, testSubject.sittingVolume); + } + + @Test + void placeTwoAskMARKETORDERandOneBidLIMITORDERthrowCROSSED_ORDERBOOK() { // Init and checking start conditions OrderBook testSubject = new OrderBook(); assertEquals(0, testSubject.asks.size()); @@ -179,5 +232,88 @@ void placeOneSTOPLIMIT() { assertEquals(-1f, testSubject.bestAskPrice); assertEquals(-1f, testSubject.bestBidPrice); assertEquals(0f, testSubject.sittingVolume); + // Operation + Order newMARKETORDER = new Order("helloUUID!", "helloproductID_1!", 106.0f, + 99.99f, MARKET_ORDER, false, Side.ASK, 1677598097L); + testSubject.placeOrder(newMARKETORDER); + // Checking Operation + assertEquals(1, testSubject.asks.size()); + assertEquals(0, testSubject.bids.size()); + assertEquals(99.99f, testSubject.asks.getFirst().price); // No orders have been filled yet + assertEquals(106.0f, testSubject.asks.getFirst().size); // No orders have been filled yet + assertEquals(1677598097L, testSubject.asks.getFirst().createdTs); + assertEquals(99.99f, testSubject.bestAskPrice); + assertEquals(-1f, testSubject.bestBidPrice); + assertEquals(106.0f, testSubject.sittingVolume); + // Operation + newMARKETORDER = new Order("helloUUID!", "helloproductID_2!", 3.7f, + 0.01f, MARKET_ORDER, false, Side.ASK, 1677598150L); + testSubject.placeOrder(newMARKETORDER); + // Checking Operation + assertEquals(2, testSubject.asks.size()); + assertEquals(0, testSubject.bids.size()); + assertEquals(0.01f, testSubject.asks.getFirst().price); + assertEquals(3.7f, testSubject.asks.getFirst().size); + assertEquals(1677598150L, testSubject.asks.getFirst().createdTs); + assertEquals(0.01f, testSubject.bestAskPrice); + assertEquals(-1f, testSubject.bestBidPrice); + assertEquals(109.7f, testSubject.sittingVolume); + /* // Operation + Order newLIMITORDER = new Order("helloUUID!", "helloproductID_3!", 100.0f, + 49.97f, LIMIT_ORDER, false, Side.BID, 1677598167L); + testSubject.placeOrder(newLIMITORDER); + // Checking Operation, note CROSSED ORDERBOOK */ + } + + @Test + void placeOneBidandOneAskLIMITORDERfillEvent() { + // Init and checking start conditions + OrderBook testSubject = new OrderBook(); + assertEquals(0, testSubject.asks.size()); + assertEquals(0, testSubject.bids.size()); + assertEquals(-1f, testSubject.bestAskPrice); + assertEquals(-1f, testSubject.bestBidPrice); + assertEquals(0f, testSubject.sittingVolume); + // Operation + Order newLIMITORDER = new Order("helloUUID!", "helloproductID_1!", 100.0f, + 27.37f, LIMIT_ORDER, false, Side.BID, 100L); + testSubject.placeOrder(newLIMITORDER); + assertEquals(0, testSubject.asks.size()); + assertEquals(1, testSubject.bids.size()); + assertEquals(27.37f, testSubject.bids.getFirst().price); + assertEquals(100.0f, testSubject.bids.getFirst().size); + assertEquals(100L, testSubject.bids.getFirst().createdTs); + assertEquals(-1f, testSubject.bestAskPrice); + assertEquals(27.37f, testSubject.bestBidPrice); + assertEquals(100.0f, testSubject.sittingVolume); + // Operation + newLIMITORDER = new Order("helloUUID!", "helloproductID_2!", 50.0f, + 34.31f, LIMIT_ORDER, false, Side.ASK, 200L); + testSubject.placeOrder(newLIMITORDER); + assertEquals(1, testSubject.asks.size()); + assertEquals(1, testSubject.bids.size()); + assertEquals(34.31f, testSubject.asks.getFirst().price); + assertEquals(50.0f, testSubject.asks.getFirst().size); + assertEquals(27.37f, testSubject.bids.getFirst().price); + assertEquals(100.0f, testSubject.bids.getFirst().size); + assertEquals(200L, testSubject.asks.getFirst().createdTs); + assertEquals(100L, testSubject.bids.getFirst().createdTs); + assertEquals(34.31f, testSubject.bestAskPrice); + assertEquals(27.37f, testSubject.bestBidPrice); + assertEquals(150.0f, testSubject.sittingVolume); + // Operation + Fill newFill = new Fill("helloproductID_2!", "helloclientID!", 35.5f, + 34.31f, 1.5f, LIMIT_ORDER, Side.ASK, 330L); + testSubject.fillEvent(newFill); + assertEquals(1, testSubject.asks.size()); + assertEquals(1, testSubject.bids.size()); + assertEquals(34.31f, testSubject.asks.getFirst().price); + assertEquals(14.5f, testSubject.asks.getFirst().size); + assertEquals(27.37f, testSubject.bids.getFirst().price); + assertEquals(100.0f, testSubject.bids.getFirst().size); + assertEquals(100L, testSubject.bids.getFirst().createdTs); + assertEquals(34.31f, testSubject.bestAskPrice); + assertEquals(27.37f, testSubject.bestBidPrice); + assertEquals(114.5f, testSubject.sittingVolume); } -} +} \ No newline at end of file