lab 9 .
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user