1
0
This commit is contained in:
2024-11-14 15:20:18 +03:00
parent 39f827f3e7
commit 9ab033bd58
3 changed files with 198 additions and 178 deletions

View File

@@ -201,6 +201,7 @@ public class PlainCurrencyExchange implements CurrencyExchange {
oppositeRate <= orderRate : oppositeRate <= orderRate :
oppositeRate >= orderRate; oppositeRate >= orderRate;
}) })
.filter(oppositeOrder -> oppositeOrder.client() != order.client())
.sorted((o1, o2) -> { .sorted((o1, o2) -> {
double rate1 = o1.rate(); double rate1 = o1.rate();
double rate2 = o2.rate(); double rate2 = o2.rate();

View File

@@ -19,20 +19,20 @@ import static org.junit.jupiter.api.Assertions.*;
class ConcurrentCurrencyExchangeTest { class ConcurrentCurrencyExchangeTest {
private CurrencyExchange exchange; private CurrencyExchange exchange;
private Currency USD; private Currency RUB;
private Currency EUR; private Currency CNY;
private CurrencyPair USD_EUR; private CurrencyPair RUB_CNY;
private ExecutorService executorService; private ExecutorService executorService;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
USD = new Currency("USD"); RUB = new Currency("RUB");
EUR = new Currency("EUR"); CNY = new Currency("CNY");
USD_EUR = new CurrencyPair(USD, EUR); RUB_CNY = new CurrencyPair(RUB, CNY);
exchange = new PlainCurrencyExchange( exchange = new PlainCurrencyExchange(
Arrays.asList(USD, EUR), Arrays.asList(RUB, CNY),
Arrays.asList(USD_EUR) Arrays.asList(RUB_CNY)
); );
executorService = Executors.newFixedThreadPool(10); executorService = Executors.newFixedThreadPool(10);
@@ -78,7 +78,7 @@ class ConcurrentCurrencyExchangeTest {
var future = CompletableFuture.runAsync(() -> { var future = CompletableFuture.runAsync(() -> {
try { try {
for (int j = 0; j < depositsPerThread; j++) { for (int j = 0; j < depositsPerThread; j++) {
exchange.deposit(client.id(), USD, depositAmount).join(); exchange.deposit(client.id(), RUB, depositAmount).join();
} }
} finally { } finally {
latch.countDown(); latch.countDown();
@@ -91,7 +91,7 @@ class ConcurrentCurrencyExchangeTest {
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
var balances = exchange.getBalances(client.id()).join(); var balances = exchange.getBalances(client.id()).join();
assertEquals(numThreads * depositsPerThread * depositAmount, balances.get(USD)); assertEquals(numThreads * depositsPerThread * depositAmount, balances.get(RUB));
} }
@Test @Test
@@ -102,7 +102,7 @@ class ConcurrentCurrencyExchangeTest {
var withdrawalAmount = 10.0; var withdrawalAmount = 10.0;
var client = exchange.createClient("Test Client").join(); var client = exchange.createClient("Test Client").join();
exchange.deposit(client.id(), USD, initialBalance).join(); exchange.deposit(client.id(), RUB, initialBalance).join();
var futures = new ArrayList<CompletableFuture<Void>>(); var futures = new ArrayList<CompletableFuture<Void>>();
var successfulWithdrawals = new AtomicInteger(0); var successfulWithdrawals = new AtomicInteger(0);
@@ -112,7 +112,7 @@ class ConcurrentCurrencyExchangeTest {
try { try {
while (true) { while (true) {
try { try {
exchange.withdraw(client.id(), USD, withdrawalAmount).join(); exchange.withdraw(client.id(), RUB, withdrawalAmount).join();
successfulWithdrawals.incrementAndGet(); successfulWithdrawals.incrementAndGet();
} catch (CompletionException e) { } catch (CompletionException e) {
break; break;
@@ -131,7 +131,7 @@ class ConcurrentCurrencyExchangeTest {
var finalBalance = exchange.getBalances(client.id()).join(); var finalBalance = exchange.getBalances(client.id()).join();
assertEquals( assertEquals(
initialBalance, initialBalance,
successfulWithdrawals.get() * withdrawalAmount + finalBalance.get(USD), successfulWithdrawals.get() * withdrawalAmount + finalBalance.get(RUB),
0.001 0.001
); );
} }
@@ -144,7 +144,7 @@ class ConcurrentCurrencyExchangeTest {
var latch = new CountDownLatch(numThreads * 2); var latch = new CountDownLatch(numThreads * 2);
var client = exchange.createClient("Test Client").join(); var client = exchange.createClient("Test Client").join();
exchange.deposit(client.id(), USD, initialBalance).join(); exchange.deposit(client.id(), RUB, initialBalance).join();
var futures = new ArrayList<CompletableFuture<Void>>(); var futures = new ArrayList<CompletableFuture<Void>>();
var successfulWithdrawals = new AtomicInteger(0); var successfulWithdrawals = new AtomicInteger(0);
@@ -153,7 +153,7 @@ class ConcurrentCurrencyExchangeTest {
futures.add(CompletableFuture.runAsync(() -> { futures.add(CompletableFuture.runAsync(() -> {
try { try {
for (int j = 0; j < 100; j++) { for (int j = 0; j < 100; j++) {
exchange.deposit(client.id(), USD, transactionAmount).join(); exchange.deposit(client.id(), RUB, transactionAmount).join();
} }
} finally { } finally {
latch.countDown(); latch.countDown();
@@ -166,7 +166,7 @@ class ConcurrentCurrencyExchangeTest {
try { try {
while (true) { while (true) {
try { try {
exchange.withdraw(client.id(), USD, transactionAmount).join(); exchange.withdraw(client.id(), RUB, transactionAmount).join();
successfulWithdrawals.incrementAndGet(); successfulWithdrawals.incrementAndGet();
} catch (CompletionException e) { } catch (CompletionException e) {
break; break;
@@ -184,7 +184,7 @@ class ConcurrentCurrencyExchangeTest {
var finalBalances = exchange.getBalances(client.id()).join(); var finalBalances = exchange.getBalances(client.id()).join();
assertEquals( assertEquals(
initialBalance + (numThreads * 100 * transactionAmount) - (successfulWithdrawals.get() * transactionAmount), initialBalance + (numThreads * 100 * transactionAmount) - (successfulWithdrawals.get() * transactionAmount),
finalBalances.get(USD), finalBalances.get(RUB),
0.001 0.001
); );
} }
@@ -199,14 +199,14 @@ class ConcurrentCurrencyExchangeTest {
var sellers = new ArrayList<Client>(); var sellers = new ArrayList<Client>();
for (int i = 0; i < numSellers; i++) { for (int i = 0; i < numSellers; i++) {
var seller = exchange.createClient("Seller " + i).join(); var seller = exchange.createClient("Seller " + i).join();
exchange.deposit(seller.id(), EUR, 1000.0).join(); exchange.deposit(seller.id(), CNY, 1000.0).join();
sellers.add(seller); sellers.add(seller);
} }
var buyers = new ArrayList<Client>(); var buyers = new ArrayList<Client>();
for (int i = 0; i < numBuyers; i++) { for (int i = 0; i < numBuyers; i++) {
var buyer = exchange.createClient("Buyer " + i).join(); var buyer = exchange.createClient("Buyer " + i).join();
exchange.deposit(buyer.id(), USD, 1200.0).join(); exchange.deposit(buyer.id(), RUB, 1200.0).join();
buyers.add(buyer); buyers.add(buyer);
} }
@@ -214,7 +214,7 @@ class ConcurrentCurrencyExchangeTest {
.map(seller -> CompletableFuture.runAsync(() -> { .map(seller -> CompletableFuture.runAsync(() -> {
try { try {
for (int i = 0; i < ordersPerClient; i++) { for (int i = 0; i < ordersPerClient; i++) {
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 1.2, 10.0).join(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 1.2, 10.0).join();
Thread.sleep(10); Thread.sleep(10);
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
@@ -229,7 +229,7 @@ class ConcurrentCurrencyExchangeTest {
.map(buyer -> CompletableFuture.runAsync(() -> { .map(buyer -> CompletableFuture.runAsync(() -> {
try { try {
for (int i = 0; i < ordersPerClient; i++) { for (int i = 0; i < ordersPerClient; i++) {
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 1.2, 10.0).join(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 1.2, 10.0).join();
Thread.sleep(10); Thread.sleep(10);
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
@@ -267,14 +267,14 @@ class ConcurrentCurrencyExchangeTest {
var seller = exchange.createClient("Seller").join(); var seller = exchange.createClient("Seller").join();
var buyer = exchange.createClient("Buyer").join(); var buyer = exchange.createClient("Buyer").join();
exchange.deposit(seller.id(), EUR, 1000.0).join(); exchange.deposit(seller.id(), CNY, 1000.0).join();
exchange.deposit(buyer.id(), USD, 2000.0).join(); exchange.deposit(buyer.id(), RUB, 2000.0).join();
var sellerFuture = CompletableFuture.runAsync(() -> { var sellerFuture = CompletableFuture.runAsync(() -> {
try { try {
for (int i = 0; i < numOrders; i++) { for (int i = 0; i < numOrders; i++) {
var price = 1.0 + (i * 0.01); var price = 1.0 + (i * 0.01);
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, price, 10.0).join(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, price, 10.0).join();
Thread.sleep(5); Thread.sleep(5);
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
@@ -288,7 +288,7 @@ class ConcurrentCurrencyExchangeTest {
try { try {
for (var i = 0; i < numOrders; i++) { for (var i = 0; i < numOrders; i++) {
var price = 2.0 - (i * 0.01); var price = 2.0 - (i * 0.01);
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, price, 10.0).join(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, price, 10.0).join();
Thread.sleep(5); Thread.sleep(5);
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
@@ -319,7 +319,7 @@ class ConcurrentCurrencyExchangeTest {
var client = exchange.createClient("Test Client").join(); var client = exchange.createClient("Test Client").join();
var initialBalance = 1000.0; var initialBalance = 1000.0;
exchange.deposit(client.id(), USD, initialBalance).join(); exchange.deposit(client.id(), RUB, initialBalance).join();
var successfulChecks = new AtomicInteger(0); var successfulChecks = new AtomicInteger(0);
var futures = new ArrayList<CompletableFuture<Void>>(); var futures = new ArrayList<CompletableFuture<Void>>();
@@ -329,7 +329,7 @@ class ConcurrentCurrencyExchangeTest {
try { try {
startLatch.await(); startLatch.await();
var balance = exchange.getBalances(client.id()).join(); var balance = exchange.getBalances(client.id()).join();
if (Math.abs(balance.get(USD) - initialBalance) < 0.001) { if (Math.abs(balance.get(RUB) - initialBalance) < 0.001) {
successfulChecks.incrementAndGet(); successfulChecks.incrementAndGet();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
@@ -362,8 +362,8 @@ class ConcurrentCurrencyExchangeTest {
var seller = exchange.createClient("Seller " + i).join(); var seller = exchange.createClient("Seller " + i).join();
var buyer = exchange.createClient("Buyer " + i).join(); var buyer = exchange.createClient("Buyer " + i).join();
exchange.deposit(seller.id(), EUR, initialAmount).join(); exchange.deposit(seller.id(), CNY, initialAmount).join();
exchange.deposit(buyer.id(), USD, initialAmount).join(); exchange.deposit(buyer.id(), RUB, initialAmount).join();
sellers.add(seller); sellers.add(seller);
buyers.add(buyer); buyers.add(buyer);
@@ -375,9 +375,9 @@ class ConcurrentCurrencyExchangeTest {
var future = CompletableFuture.runAsync(() -> { var future = CompletableFuture.runAsync(() -> {
try { try {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 1.2, 10.0).join(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 1.2, 10.0).join();
try { try {
exchange.withdraw(seller.id(), EUR, 1.0).join(); exchange.withdraw(seller.id(), CNY, 1.0).join();
} catch (CompletionException ignored) { } catch (CompletionException ignored) {
} }
@@ -396,9 +396,9 @@ class ConcurrentCurrencyExchangeTest {
var future = CompletableFuture.runAsync(() -> { var future = CompletableFuture.runAsync(() -> {
try { try {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 1.2, 10.0).join(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 1.2, 10.0).join();
try { try {
exchange.withdraw(buyer.id(), USD, 1.0).join(); exchange.withdraw(buyer.id(), RUB, 1.0).join();
} catch (CompletionException ignored) { } catch (CompletionException ignored) {
} }
Thread.sleep(10); Thread.sleep(10);
@@ -417,8 +417,8 @@ class ConcurrentCurrencyExchangeTest {
for (var client : Stream.concat(sellers.stream(), buyers.stream()).toList()) { for (var client : Stream.concat(sellers.stream(), buyers.stream()).toList()) {
var balances = exchange.getBalances(client.id()).join(); var balances = exchange.getBalances(client.id()).join();
assertTrue(balances.get(USD) >= 0, "USD balance should not be negative"); assertTrue(balances.get(RUB) >= 0, "RUB balance should not be negative");
assertTrue(balances.get(EUR) >= 0, "EUR balance should not be negative"); assertTrue(balances.get(CNY) >= 0, "CNY balance should not be negative");
} }
} }

View File

@@ -15,19 +15,19 @@ import static org.junit.jupiter.api.Assertions.*;
class CurrencyExchangeTest { class CurrencyExchangeTest {
private CurrencyExchange exchange; private CurrencyExchange exchange;
private Currency USD; private Currency RUB;
private Currency EUR; private Currency CNY;
private CurrencyPair USD_EUR; private CurrencyPair RUB_CNY;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
USD = new Currency("USD"); RUB = new Currency("RUB");
EUR = new Currency("EUR"); CNY = new Currency("CNY");
USD_EUR = new CurrencyPair(USD, EUR); RUB_CNY = new CurrencyPair(RUB, CNY);
exchange = new PlainCurrencyExchange( exchange = new PlainCurrencyExchange(
Arrays.asList(USD, EUR), Arrays.asList(RUB, CNY),
Arrays.asList(USD_EUR) Arrays.asList(RUB_CNY)
); );
} }
@@ -57,17 +57,17 @@ class CurrencyExchangeTest {
void testDeposit() throws ExecutionException, InterruptedException { void testDeposit() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
exchange.deposit(client.id(), USD, 1000.0).get(); exchange.deposit(client.id(), RUB, 1000.0).get();
var balances = exchange.getBalances(client.id()).get(); var balances = exchange.getBalances(client.id()).get();
assertEquals(1000.0, balances.get(USD)); assertEquals(1000.0, balances.get(RUB));
} }
@Test @Test
void testDepositNegativeAmount() throws ExecutionException, InterruptedException { void testDepositNegativeAmount() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
assertThrows(ExecutionException.class, () -> exchange.deposit(client.id(), USD, -100.0).get()); assertThrows(ExecutionException.class, () -> exchange.deposit(client.id(), RUB, -100.0).get());
} }
@Test @Test
@@ -82,35 +82,35 @@ class CurrencyExchangeTest {
void testWithdraw() throws ExecutionException, InterruptedException { void testWithdraw() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
exchange.deposit(client.id(), USD, 1000.0).get(); exchange.deposit(client.id(), RUB, 1000.0).get();
exchange.withdraw(client.id(), USD, 500.0).get(); exchange.withdraw(client.id(), RUB, 500.0).get();
var balances = exchange.getBalances(client.id()).get(); var balances = exchange.getBalances(client.id()).get();
assertEquals(500.0, balances.get(USD)); assertEquals(500.0, balances.get(RUB));
} }
@Test @Test
void testWithdrawInsufficientFunds() throws ExecutionException, InterruptedException { void testWithdrawInsufficientFunds() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
exchange.deposit(client.id(), USD, 100.0).get(); exchange.deposit(client.id(), RUB, 100.0).get();
assertThrows(ExecutionException.class, () -> exchange.withdraw(client.id(), USD, 200.0).get()); assertThrows(ExecutionException.class, () -> exchange.withdraw(client.id(), RUB, 200.0).get());
} }
@Test @Test
void testSequentialDepositWithdraw() throws ExecutionException, InterruptedException { void testSequentialDepositWithdraw() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
exchange.deposit(client.id(), USD, 500.0).get(); exchange.deposit(client.id(), RUB, 500.0).get();
var balancesAfterDeposit = exchange.getBalances(client.id()).get(); var balancesAfterDeposit = exchange.getBalances(client.id()).get();
assertEquals(500.0, balancesAfterDeposit.get(USD)); // Trader has 500 USD assertEquals(500.0, balancesAfterDeposit.get(RUB)); // Trader has 500 RUB
exchange.withdraw(client.id(), USD, 200.0).get(); exchange.withdraw(client.id(), RUB, 200.0).get();
var balancesAfterWithdraw = exchange.getBalances(client.id()).get(); var balancesAfterWithdraw = exchange.getBalances(client.id()).get();
assertEquals(300.0, balancesAfterWithdraw.get(USD)); // Trader has 300 USD assertEquals(300.0, balancesAfterWithdraw.get(RUB)); // Trader has 300 RUB
assertThrows(ExecutionException.class, () -> exchange.withdraw(client.id(), USD, 400.0).get()); // Trader has only 300 USD left assertThrows(ExecutionException.class, () -> exchange.withdraw(client.id(), RUB, 400.0).get()); // Trader has only 300 RUB left
} }
// Order Tests // Order Tests
@@ -118,8 +118,8 @@ class CurrencyExchangeTest {
void testPlaceOrder() throws ExecutionException, InterruptedException { void testPlaceOrder() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
exchange.deposit(client.id(), EUR, 1000.0).get(); exchange.deposit(client.id(), CNY, 1000.0).get();
exchange.placeOrder(client.id(), USD_EUR, OrderType.SELL, 120, 100.0).get(); exchange.placeOrder(client.id(), RUB_CNY, OrderType.SELL, 120, 100.0).get();
var activeOrders = exchange.getActiveOrders(client.id()).get(); var activeOrders = exchange.getActiveOrders(client.id()).get();
assertTrue(activeOrders.iterator().hasNext()); assertTrue(activeOrders.iterator().hasNext());
@@ -130,7 +130,7 @@ class CurrencyExchangeTest {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
assertThrows(ExecutionException.class, () -> assertThrows(ExecutionException.class, () ->
exchange.placeOrder(client.id(), USD_EUR, OrderType.SELL, 120.0, 100.0).get() exchange.placeOrder(client.id(), RUB_CNY, OrderType.SELL, 120.0, 100.0).get()
); );
} }
@@ -138,10 +138,10 @@ class CurrencyExchangeTest {
void testOrderPriceValidation() throws ExecutionException, InterruptedException { void testOrderPriceValidation() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
exchange.deposit(client.id(), EUR, 100.0).get(); exchange.deposit(client.id(), CNY, 100.0).get();
assertThrows(ExecutionException.class, () -> assertThrows(ExecutionException.class, () ->
exchange.placeOrder(client.id(), USD_EUR, OrderType.SELL, -1.0, 100.0).get() exchange.placeOrder(client.id(), RUB_CNY, OrderType.SELL, -1.0, 100.0).get()
); );
} }
@@ -149,10 +149,10 @@ class CurrencyExchangeTest {
void testOrderQuantityValidation() throws ExecutionException, InterruptedException { void testOrderQuantityValidation() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get(); var client = exchange.createClient("Trader").get();
exchange.deposit(client.id(), EUR, 100.0).get(); exchange.deposit(client.id(), CNY, 100.0).get();
assertThrows(ExecutionException.class, () -> assertThrows(ExecutionException.class, () ->
exchange.placeOrder(client.id(), USD_EUR, OrderType.SELL, 120.0, -100.0).get() exchange.placeOrder(client.id(), RUB_CNY, OrderType.SELL, 120.0, -100.0).get()
); );
} }
@@ -162,19 +162,19 @@ class CurrencyExchangeTest {
var buyer = exchange.createClient("Buyer").get(); var buyer = exchange.createClient("Buyer").get();
var seller = exchange.createClient("Seller").get(); var seller = exchange.createClient("Seller").get();
exchange.deposit(buyer.id(), USD, 120.0).get(); exchange.deposit(buyer.id(), RUB, 120.0).get();
exchange.deposit(seller.id(), EUR, 100.0).get(); exchange.deposit(seller.id(), CNY, 100.0).get();
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 120.0, 100.0).get(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 120.0, 100.0).get();
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 120.0, 100.0).get(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 120.0, 100.0).get();
Map<Currency, Double> buyerBalances = exchange.getBalances(buyer.id()).get(); Map<Currency, Double> buyerBalances = exchange.getBalances(buyer.id()).get();
Map<Currency, Double> sellerBalances = exchange.getBalances(seller.id()).get(); Map<Currency, Double> sellerBalances = exchange.getBalances(seller.id()).get();
assertEquals(100.0, buyerBalances.get(EUR)); // Buyer bought 100 EUR assertEquals(100.0, buyerBalances.get(CNY)); // Buyer bought 100 CNY
assertEquals(0.0, buyerBalances.get(USD)); // Buyer sold 120 USD so he has no USD left assertEquals(0.0, buyerBalances.get(RUB)); // Buyer sold 120 RUB so he has no RUB left
assertEquals(120.0, sellerBalances.get(USD)); // Seller bought 120 USD assertEquals(120.0, sellerBalances.get(RUB)); // Seller bought 120 RUB
assertEquals(0.0, sellerBalances.get(EUR)); // Seller sold 100 EUR so he has no EUR left assertEquals(0.0, sellerBalances.get(CNY)); // Seller sold 100 CNY so he has no CNY left
} }
@Test @Test
@@ -182,23 +182,23 @@ class CurrencyExchangeTest {
var buyer = exchange.createClient("Buyer").get(); var buyer = exchange.createClient("Buyer").get();
var seller = exchange.createClient("Seller").get(); var seller = exchange.createClient("Seller").get();
exchange.deposit(buyer.id(), USD, 120.0).get(); exchange.deposit(buyer.id(), RUB, 120.0).get();
exchange.deposit(seller.id(), EUR, 100.0).get(); exchange.deposit(seller.id(), CNY, 100.0).get();
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 120.0, 100.0).get(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 120.0, 100.0).get();
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 60.0, 50.0).get(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 60.0, 50.0).get();
var buyerBalances = exchange.getBalances(buyer.id()).get(); var buyerBalances = exchange.getBalances(buyer.id()).get();
var sellerBalances = exchange.getBalances(seller.id()).get(); var sellerBalances = exchange.getBalances(seller.id()).get();
assertEquals(50.0, buyerBalances.get(EUR)); // Buyer bought 50 EUR assertEquals(50.0, buyerBalances.get(CNY)); // Buyer bought 50 CNY
assertEquals(60.0, sellerBalances.get(USD)); // Seller bought 60 USD assertEquals(60.0, sellerBalances.get(RUB)); // Seller bought 60 RUB
var sellerOrders = exchange.getActiveOrders(seller.id()).get(); var sellerOrders = exchange.getActiveOrders(seller.id()).get();
var remainingOrder = sellerOrders.iterator().next(); var remainingOrder = sellerOrders.iterator().next();
// Seller has 60/50 USD/EUR order left // Seller has 60/50 RUB/CNY order left
assertEquals(USD_EUR, remainingOrder.pair()); assertEquals(RUB_CNY, remainingOrder.pair());
assertEquals(50.0, remainingOrder.quantity()); assertEquals(50.0, remainingOrder.quantity());
assertEquals(60.0, remainingOrder.price()); assertEquals(60.0, remainingOrder.price());
} }
@@ -209,21 +209,21 @@ class CurrencyExchangeTest {
var buyer2 = exchange.createClient("Buyer2").get(); var buyer2 = exchange.createClient("Buyer2").get();
var seller = exchange.createClient("Seller").get(); var seller = exchange.createClient("Seller").get();
exchange.deposit(buyer1.id(), USD, 120.0).get(); exchange.deposit(buyer1.id(), RUB, 120.0).get();
exchange.deposit(buyer2.id(), USD, 120.0).get(); exchange.deposit(buyer2.id(), RUB, 120.0).get();
exchange.deposit(seller.id(), EUR, 100.0).get(); exchange.deposit(seller.id(), CNY, 100.0).get();
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 120.0, 100.0).get(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 120.0, 100.0).get();
exchange.placeOrder(buyer1.id(), USD_EUR, OrderType.BUY, 60.0, 50.0).get(); exchange.placeOrder(buyer1.id(), RUB_CNY, OrderType.BUY, 60.0, 50.0).get();
exchange.placeOrder(buyer2.id(), USD_EUR, OrderType.BUY, 60.0, 50.0).get(); exchange.placeOrder(buyer2.id(), RUB_CNY, OrderType.BUY, 60.0, 50.0).get();
var buyer1Balances = exchange.getBalances(buyer1.id()).get(); var buyer1Balances = exchange.getBalances(buyer1.id()).get();
var buyer2Balances = exchange.getBalances(buyer2.id()).get(); var buyer2Balances = exchange.getBalances(buyer2.id()).get();
var sellerBalances = exchange.getBalances(seller.id()).get(); var sellerBalances = exchange.getBalances(seller.id()).get();
assertEquals(50.0, buyer1Balances.get(EUR)); // Buyer1 bought 50 EUR assertEquals(50.0, buyer1Balances.get(CNY)); // Buyer1 bought 50 CNY
assertEquals(50.0, buyer2Balances.get(EUR)); // Buyer2 bought 50 EUR assertEquals(50.0, buyer2Balances.get(CNY)); // Buyer2 bought 50 CNY
assertEquals(120.0, sellerBalances.get(USD)); // Seller bought 120 USD assertEquals(120.0, sellerBalances.get(RUB)); // Seller bought 120 RUB
var sellerOrders = exchange.getActiveOrders(seller.id()).get(); var sellerOrders = exchange.getActiveOrders(seller.id()).get();
assertFalse(sellerOrders.iterator().hasNext()); // Seller has no orders left assertFalse(sellerOrders.iterator().hasNext()); // Seller has no orders left
@@ -234,19 +234,19 @@ class CurrencyExchangeTest {
var buyer = exchange.createClient("Buyer").get(); var buyer = exchange.createClient("Buyer").get();
var seller = exchange.createClient("Seller").get(); var seller = exchange.createClient("Seller").get();
exchange.deposit(buyer.id(), USD, 300.0).get(); exchange.deposit(buyer.id(), RUB, 300.0).get();
exchange.deposit(seller.id(), EUR, 200.0).get(); exchange.deposit(seller.id(), CNY, 200.0).get();
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 120.0, 100.0).get(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 120.0, 100.0).get();
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 120.0, 100.0).get(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 120.0, 100.0).get();
var buyerBalances = exchange.getBalances(buyer.id()).get(); var buyerBalances = exchange.getBalances(buyer.id()).get();
var sellerBalances = exchange.getBalances(seller.id()).get(); var sellerBalances = exchange.getBalances(seller.id()).get();
assertEquals(100.0, buyerBalances.get(EUR)); // Buyer bought 100 EUR assertEquals(100.0, buyerBalances.get(CNY)); // Buyer bought 100 CNY
assertEquals(180.0, buyerBalances.get(USD)); // Buyer spends 120 USD assertEquals(180.0, buyerBalances.get(RUB)); // Buyer spends 120 RUB
assertEquals(120.0, sellerBalances.get(USD)); // Seller bought 120 USD assertEquals(120.0, sellerBalances.get(RUB)); // Seller bought 120 RUB
assertEquals(100.0, sellerBalances.get(EUR)); // Seller retains remaining EUR assertEquals(100.0, sellerBalances.get(CNY)); // Seller retains remaining CNY
} }
@Test @Test
@@ -255,31 +255,31 @@ class CurrencyExchangeTest {
var buyer2 = exchange.createClient("Buyer2").get(); var buyer2 = exchange.createClient("Buyer2").get();
var seller = exchange.createClient("Seller").get(); var seller = exchange.createClient("Seller").get();
exchange.deposit(buyer1.id(), USD, 60.0).get(); exchange.deposit(buyer1.id(), RUB, 60.0).get();
exchange.deposit(buyer2.id(), USD, 60.0).get(); exchange.deposit(buyer2.id(), RUB, 60.0).get();
exchange.deposit(seller.id(), EUR, 100.0).get(); exchange.deposit(seller.id(), CNY, 100.0).get();
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 120.0, 100.0).get(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 120.0, 100.0).get();
exchange.placeOrder(buyer1.id(), USD_EUR, OrderType.BUY, 36.0, 30.0).get(); exchange.placeOrder(buyer1.id(), RUB_CNY, OrderType.BUY, 36.0, 30.0).get();
exchange.placeOrder(buyer2.id(), USD_EUR, OrderType.BUY, 36.0, 30.0).get(); exchange.placeOrder(buyer2.id(), RUB_CNY, OrderType.BUY, 36.0, 30.0).get();
var buyer1Balances = exchange.getBalances(buyer1.id()).get(); var buyer1Balances = exchange.getBalances(buyer1.id()).get();
var buyer2Balances = exchange.getBalances(buyer2.id()).get(); var buyer2Balances = exchange.getBalances(buyer2.id()).get();
var sellerBalances = exchange.getBalances(seller.id()).get(); var sellerBalances = exchange.getBalances(seller.id()).get();
assertEquals(30.0, buyer1Balances.get(EUR)); // Buyer1 bought 30 EUR assertEquals(30.0, buyer1Balances.get(CNY)); // Buyer1 bought 30 CNY
assertEquals(24.0, buyer1Balances.get(USD)); // Buyer1 sold 36 EUR assertEquals(24.0, buyer1Balances.get(RUB)); // Buyer1 sold 36 CNY
assertEquals(30.0, buyer2Balances.get(EUR)); // Buyer2 bought 30 EUR assertEquals(30.0, buyer2Balances.get(CNY)); // Buyer2 bought 30 CNY
assertEquals(24.0, buyer2Balances.get(USD)); // Buyer2 sold 36 EUR assertEquals(24.0, buyer2Balances.get(RUB)); // Buyer2 sold 36 CNY
var sellerOrders = exchange.getActiveOrders(seller.id()).get(); var sellerOrders = exchange.getActiveOrders(seller.id()).get();
var sellerOrder = sellerOrders.iterator().next(); var sellerOrder = sellerOrders.iterator().next();
assertEquals(40.0, sellerOrder.quantity()); // 40 EUR reserved assertEquals(40.0, sellerOrder.quantity()); // 40 CNY reserved
assertEquals(48.0, sellerOrder.price()); // 1.2 USD per EUR assertEquals(48.0, sellerOrder.price()); // 1.2 RUB per CNY
assertEquals(72.0, sellerBalances.get(USD)); // 72 USD earned assertEquals(72.0, sellerBalances.get(RUB)); // 72 RUB earned
} }
@Test @Test
@@ -287,15 +287,15 @@ class CurrencyExchangeTest {
var buyer = exchange.createClient("Buyer").get(); var buyer = exchange.createClient("Buyer").get();
var seller = exchange.createClient("Seller").get(); var seller = exchange.createClient("Seller").get();
exchange.deposit(buyer.id(), USD, 100.0).get(); exchange.deposit(buyer.id(), RUB, 100.0).get();
exchange.deposit(seller.id(), EUR, 50.0).get(); exchange.deposit(seller.id(), CNY, 50.0).get();
assertThrows(ExecutionException.class, () -> assertThrows(ExecutionException.class, () ->
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 120.0, 100.0).get() exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 120.0, 100.0).get()
); );
assertThrows(ExecutionException.class, () -> assertThrows(ExecutionException.class, () ->
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 240.0, 200.0).get() exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 240.0, 200.0).get()
); );
var buyerOrders = exchange.getActiveOrders(buyer.id()).get(); var buyerOrders = exchange.getActiveOrders(buyer.id()).get();
@@ -310,27 +310,27 @@ class CurrencyExchangeTest {
var seller1 = exchange.createClient("Seller1").get(); var seller1 = exchange.createClient("Seller1").get();
var seller2 = exchange.createClient("Seller2").get(); var seller2 = exchange.createClient("Seller2").get();
exchange.deposit(buyer.id(), USD, 200.0).get(); exchange.deposit(buyer.id(), RUB, 200.0).get();
exchange.deposit(seller1.id(), EUR, 50.0).get(); exchange.deposit(seller1.id(), CNY, 50.0).get();
exchange.deposit(seller2.id(), EUR, 50.0).get(); exchange.deposit(seller2.id(), CNY, 50.0).get();
exchange.placeOrder(seller1.id(), USD_EUR, OrderType.SELL, 75, 50.0).get(); // Higher price exchange.placeOrder(seller1.id(), RUB_CNY, OrderType.SELL, 75, 50.0).get(); // Higher price
exchange.placeOrder(seller2.id(), USD_EUR, OrderType.SELL, 60, 50.0).get(); // Lower price exchange.placeOrder(seller2.id(), RUB_CNY, OrderType.SELL, 60, 50.0).get(); // Lower price
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 75, 50.0).get(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 75, 50.0).get();
var buyerBalances = exchange.getBalances(buyer.id()).get(); var buyerBalances = exchange.getBalances(buyer.id()).get();
var seller1Balances = exchange.getBalances(seller1.id()).get(); var seller1Balances = exchange.getBalances(seller1.id()).get();
var seller2Balances = exchange.getBalances(seller2.id()).get(); var seller2Balances = exchange.getBalances(seller2.id()).get();
assertEquals(50.0, buyerBalances.get(EUR)); // Buyer gets 50 EUR from the lower-priced seller assertEquals(50.0, buyerBalances.get(CNY)); // Buyer gets 50 CNY from the lower-priced seller
assertEquals(140.0, buyerBalances.get(USD)); // Buyer spends 60 USD assertEquals(140.0, buyerBalances.get(RUB)); // Buyer spends 60 RUB
assertEquals(60.0, seller2Balances.get(USD)); // Seller2 sells at 60 price assertEquals(60.0, seller2Balances.get(RUB)); // Seller2 sells at 60 price
assertEquals(0.0, seller2Balances.get(EUR)); // Seller2 has no EUR left assertEquals(0.0, seller2Balances.get(CNY)); // Seller2 has no CNY left
assertNull(seller1Balances.get(USD)); // Seller1 remains untouched assertNull(seller1Balances.get(RUB)); // Seller1 remains untouched
assertEquals(0.0, seller1Balances.get(EUR)); // Seller1 still has their EUR reserved assertEquals(0.0, seller1Balances.get(CNY)); // Seller1 still has their CNY reserved
} }
@Test @Test
@@ -340,33 +340,33 @@ class CurrencyExchangeTest {
var seller2 = exchange.createClient("Seller2").get(); var seller2 = exchange.createClient("Seller2").get();
var seller3 = exchange.createClient("Seller3").get(); var seller3 = exchange.createClient("Seller3").get();
exchange.deposit(buyer.id(), USD, 300.0).get(); exchange.deposit(buyer.id(), RUB, 300.0).get();
exchange.deposit(seller1.id(), EUR, 50.0).get(); exchange.deposit(seller1.id(), CNY, 50.0).get();
exchange.deposit(seller2.id(), EUR, 50.0).get(); exchange.deposit(seller2.id(), CNY, 50.0).get();
exchange.deposit(seller3.id(), EUR, 50.0).get(); exchange.deposit(seller3.id(), CNY, 50.0).get();
exchange.placeOrder(seller1.id(), USD_EUR, OrderType.SELL, 75.0, 50.0).get(); // Highest price exchange.placeOrder(seller1.id(), RUB_CNY, OrderType.SELL, 75.0, 50.0).get(); // Highest price
exchange.placeOrder(seller2.id(), USD_EUR, OrderType.SELL, 65.0, 50.0).get(); // Medium price exchange.placeOrder(seller2.id(), RUB_CNY, OrderType.SELL, 65.0, 50.0).get(); // Medium price
exchange.placeOrder(seller3.id(), USD_EUR, OrderType.SELL, 60.0, 50.0).get(); // Lowest price exchange.placeOrder(seller3.id(), RUB_CNY, OrderType.SELL, 60.0, 50.0).get(); // Lowest price
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 150.0, 100.0).get(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 150.0, 100.0).get();
var buyerBalances = exchange.getBalances(buyer.id()).get(); var buyerBalances = exchange.getBalances(buyer.id()).get();
var seller1Balances = exchange.getBalances(seller1.id()).get(); var seller1Balances = exchange.getBalances(seller1.id()).get();
var seller2Balances = exchange.getBalances(seller2.id()).get(); var seller2Balances = exchange.getBalances(seller2.id()).get();
var seller3Balances = exchange.getBalances(seller3.id()).get(); var seller3Balances = exchange.getBalances(seller3.id()).get();
assertEquals(100.0, buyerBalances.get(EUR)); // Buyer receives 100 EUR (50 from seller3 and 50 from seller2) assertEquals(100.0, buyerBalances.get(CNY)); // Buyer receives 100 CNY (50 from seller3 and 50 from seller2)
assertEquals(175.0, buyerBalances.get(USD)); // Buyer spends 125 USD (60 + 65) assertEquals(175.0, buyerBalances.get(RUB)); // Buyer spends 125 RUB (60 + 65)
assertEquals(60.0, seller3Balances.get(USD)); // Seller3 sells at 60 price assertEquals(60.0, seller3Balances.get(RUB)); // Seller3 sells at 60 price
assertEquals(0.0, seller3Balances.get(EUR)); // Seller3's EUR is reduced to 0 assertEquals(0.0, seller3Balances.get(CNY)); // Seller3's CNY is reduced to 0
assertEquals(65.0, seller2Balances.get(USD)); // Seller2 sells at 65 price assertEquals(65.0, seller2Balances.get(RUB)); // Seller2 sells at 65 price
assertEquals(0.0, seller2Balances.get(EUR)); // Seller2's EUR is reduced to 0 assertEquals(0.0, seller2Balances.get(CNY)); // Seller2's CNY is reduced to 0
assertNull(seller1Balances.get(USD)); // Seller1 remains untouched assertNull(seller1Balances.get(RUB)); // Seller1 remains untouched
assertEquals(0.0, seller1Balances.get(EUR)); // Seller1 still has their EUR reserved assertEquals(0.0, seller1Balances.get(CNY)); // Seller1 still has their CNY reserved
} }
@Test @Test
@@ -375,26 +375,26 @@ class CurrencyExchangeTest {
var seller1 = exchange.createClient("Seller1").get(); var seller1 = exchange.createClient("Seller1").get();
var seller2 = exchange.createClient("Seller2").get(); var seller2 = exchange.createClient("Seller2").get();
exchange.deposit(buyer.id(), USD, 200.0).get(); exchange.deposit(buyer.id(), RUB, 200.0).get();
exchange.deposit(seller1.id(), EUR, 50.0).get(); exchange.deposit(seller1.id(), CNY, 50.0).get();
exchange.deposit(seller2.id(), EUR, 50.0).get(); exchange.deposit(seller2.id(), CNY, 50.0).get();
exchange.placeOrder(seller1.id(), USD_EUR, OrderType.SELL, 60, 50.0).get(); // Placed first exchange.placeOrder(seller1.id(), RUB_CNY, OrderType.SELL, 60, 50.0).get(); // Placed first
exchange.placeOrder(seller2.id(), USD_EUR, OrderType.SELL, 60, 50.0).get(); // Placed second exchange.placeOrder(seller2.id(), RUB_CNY, OrderType.SELL, 60, 50.0).get(); // Placed second
exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 60, 50.0).get(); exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 60, 50.0).get();
var buyerBalances = exchange.getBalances(buyer.id()).get(); var buyerBalances = exchange.getBalances(buyer.id()).get();
var seller1Balances = exchange.getBalances(seller1.id()).get(); var seller1Balances = exchange.getBalances(seller1.id()).get();
var seller2Balances = exchange.getBalances(seller2.id()).get(); var seller2Balances = exchange.getBalances(seller2.id()).get();
assertEquals(50.0, buyerBalances.get(EUR)); // Buyer gets 50 EUR assertEquals(50.0, buyerBalances.get(CNY)); // Buyer gets 50 CNY
assertEquals(140.0, buyerBalances.get(USD)); // Buyer spends 60 USD assertEquals(140.0, buyerBalances.get(RUB)); // Buyer spends 60 RUB
assertEquals(60.0, seller1Balances.get(USD)); // Seller1 sells first assertEquals(60.0, seller1Balances.get(RUB)); // Seller1 sells first
assertEquals(0.0, seller1Balances.get(EUR)); // Seller1's EUR is reduced to 0 assertEquals(0.0, seller1Balances.get(CNY)); // Seller1's CNY is reduced to 0
assertNull(seller2Balances.get(USD)); // Seller2 remains untouched assertNull(seller2Balances.get(RUB)); // Seller2 remains untouched
} }
@Test @Test
@@ -403,44 +403,44 @@ class CurrencyExchangeTest {
var buyer2 = exchange.createClient("Buyer2").get(); var buyer2 = exchange.createClient("Buyer2").get();
var seller = exchange.createClient("Seller2").get(); var seller = exchange.createClient("Seller2").get();
exchange.deposit(buyer1.id(), USD, 200.0).get(); exchange.deposit(buyer1.id(), RUB, 200.0).get();
exchange.deposit(buyer2.id(), USD, 200.0).get(); exchange.deposit(buyer2.id(), RUB, 200.0).get();
exchange.deposit(seller.id(), EUR, 50.0).get(); exchange.deposit(seller.id(), CNY, 50.0).get();
exchange.placeOrder(buyer1.id(), USD_EUR, OrderType.BUY, 80.0, 50.0).get(); exchange.placeOrder(buyer1.id(), RUB_CNY, OrderType.BUY, 80.0, 50.0).get();
exchange.placeOrder(buyer2.id(), USD_EUR, OrderType.BUY, 75.0, 50.0).get(); exchange.placeOrder(buyer2.id(), RUB_CNY, OrderType.BUY, 75.0, 50.0).get();
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 85, 50.0).get(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 85, 50.0).get();
var buyer1Balances = exchange.getBalances(buyer1.id()).get(); var buyer1Balances = exchange.getBalances(buyer1.id()).get();
var buyer2Balances = exchange.getBalances(buyer2.id()).get(); var buyer2Balances = exchange.getBalances(buyer2.id()).get();
var sellerBalances = exchange.getBalances(seller.id()).get(); var sellerBalances = exchange.getBalances(seller.id()).get();
assertNull(sellerBalances.get(USD)); // Seller did not sell anything assertNull(sellerBalances.get(RUB)); // Seller did not sell anything
assertEquals(0.0, sellerBalances.get(EUR)); // Seller has no EUR left assertEquals(0.0, sellerBalances.get(CNY)); // Seller has no CNY left
assertNull(buyer1Balances.get(EUR)); // Buyer1 did not buy anything assertNull(buyer1Balances.get(CNY)); // Buyer1 did not buy anything
assertEquals(120.0, buyer1Balances.get(USD)); assertEquals(120.0, buyer1Balances.get(RUB));
assertNull(buyer2Balances.get(EUR)); // Buyer2 did not buy anything assertNull(buyer2Balances.get(CNY)); // Buyer2 did not buy anything
assertEquals(125.0, buyer2Balances.get(USD)); assertEquals(125.0, buyer2Balances.get(RUB));
} }
@Test @Test
public void testCancelBuyOrder() throws ExecutionException, InterruptedException { public void testCancelBuyOrder() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Client1").get(); var client = exchange.createClient("Client1").get();
exchange.deposit(client.id(), USD, 100.0); exchange.deposit(client.id(), RUB, 100.0);
var order = exchange.placeOrder(client.id(), USD_EUR, OrderType.BUY, 100.0, 200.0).get().orElseThrow(); var order = exchange.placeOrder(client.id(), RUB_CNY, OrderType.BUY, 100.0, 200.0).get().orElseThrow();
var balances = exchange.getBalances(client.id()).get(); var balances = exchange.getBalances(client.id()).get();
assertEquals(0.0, balances.get(USD)); assertEquals(0.0, balances.get(RUB));
exchange.cancelOrder(client.id(), order.id()).get(); exchange.cancelOrder(client.id(), order.id()).get();
balances = exchange.getBalances(client.id()).get(); balances = exchange.getBalances(client.id()).get();
assertEquals(100.0, balances.get(USD)); assertEquals(100.0, balances.get(RUB));
var orders = exchange.getActiveOrders(client.id()).get(); var orders = exchange.getActiveOrders(client.id()).get();
assertFalse(orders.iterator().hasNext()); assertFalse(orders.iterator().hasNext());
@@ -450,17 +450,17 @@ class CurrencyExchangeTest {
public void testCancelSellOrder() throws ExecutionException, InterruptedException { public void testCancelSellOrder() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Client1").get(); var client = exchange.createClient("Client1").get();
exchange.deposit(client.id(), EUR, 200.0); exchange.deposit(client.id(), CNY, 200.0);
var order = exchange.placeOrder(client.id(), USD_EUR, OrderType.SELL, 100.0, 200.0).get().orElseThrow(); var order = exchange.placeOrder(client.id(), RUB_CNY, OrderType.SELL, 100.0, 200.0).get().orElseThrow();
var balances = exchange.getBalances(client.id()).get(); var balances = exchange.getBalances(client.id()).get();
assertEquals(0.0, balances.get(EUR)); assertEquals(0.0, balances.get(CNY));
exchange.cancelOrder(client.id(), order.id()).get(); exchange.cancelOrder(client.id(), order.id()).get();
balances = exchange.getBalances(client.id()).get(); balances = exchange.getBalances(client.id()).get();
assertEquals(200.0, balances.get(EUR)); assertEquals(200.0, balances.get(CNY));
var orders = exchange.getActiveOrders(client.id()).get(); var orders = exchange.getActiveOrders(client.id()).get();
assertFalse(orders.iterator().hasNext()); assertFalse(orders.iterator().hasNext());
@@ -471,12 +471,12 @@ class CurrencyExchangeTest {
var buyer = exchange.createClient("Buyer").get(); var buyer = exchange.createClient("Buyer").get();
var seller = exchange.createClient("Seller").get(); var seller = exchange.createClient("Seller").get();
exchange.deposit(buyer.id(), USD, 1000.0).get(); exchange.deposit(buyer.id(), RUB, 1000.0).get();
exchange.deposit(seller.id(), EUR, 500.0).get(); exchange.deposit(seller.id(), CNY, 500.0).get();
exchange.placeOrder(seller.id(), USD_EUR, OrderType.SELL, 120.0, 100.0).get(); exchange.placeOrder(seller.id(), RUB_CNY, OrderType.SELL, 120.0, 100.0).get();
var order = exchange.placeOrder(buyer.id(), USD_EUR, OrderType.BUY, 200.0, 120.0).get().orElseThrow(); var order = exchange.placeOrder(buyer.id(), RUB_CNY, OrderType.BUY, 200.0, 120.0).get().orElseThrow();
var buyerOrders = exchange.getActiveOrders(buyer.id()).get(); var buyerOrders = exchange.getActiveOrders(buyer.id()).get();
var sellerOrders = exchange.getActiveOrders(seller.id()).get(); var sellerOrders = exchange.getActiveOrders(seller.id()).get();
@@ -487,7 +487,26 @@ class CurrencyExchangeTest {
exchange.cancelOrder(buyer.id(), order.id()); exchange.cancelOrder(buyer.id(), order.id());
var buyerBalances = exchange.getBalances(buyer.id()).get(); var buyerBalances = exchange.getBalances(buyer.id()).get();
assertEquals(100.0, buyerBalances.get(EUR), 0.001); assertEquals(100.0, buyerBalances.get(CNY), 0.001);
assertEquals(880.0, buyerBalances.get(USD), 0.001); assertEquals(880.0, buyerBalances.get(RUB), 0.001);
}
@Test
public void testSameClientSellBuy() throws ExecutionException, InterruptedException {
var client = exchange.createClient("Trader").get();
exchange.deposit(client.id(), RUB, 1000.0).get();
exchange.deposit(client.id(), CNY, 1000.0).get();
exchange.placeOrder(client.id(), RUB_CNY, OrderType.BUY, 100.0, 100.0).get();
exchange.placeOrder(client.id(), RUB_CNY, OrderType.SELL, 90.0, 100.0).get();
var balances = exchange.getBalances(client.id()).get();
assertEquals(900.0, balances.get(RUB), 0.001);
assertEquals(900.0, balances.get(CNY), 0.001);
var orders = exchange.getActiveOrders(client.id()).get();
assertNotNull(orders.iterator().next());
assertNotNull(orders.iterator().next());
} }
} }