Skip to content

Commit

Permalink
fix: Fix bug for buy orders
Browse files Browse the repository at this point in the history
  • Loading branch information
AnthonyyHL committed Sep 1, 2024
1 parent 7ad8d81 commit 1bf93ac
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 110 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ target/
!**/src/test/**/target/

### IntelliJ IDEA ###
.idea/
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void loadCurrencies() {
CurrencyFactory.createCurrency("crypto", "ETH", "Ethereum", new BigDecimal("3000"));

CurrencyFactory.createCurrency("fiat", "USD", "Dollar", new BigDecimal("1"));
CurrencyFactory.createCurrency("fiat", "EUR", "Euro", new BigDecimal("1.2"));
CurrencyFactory.createCurrency("fiat", "EUR", "Euro", new BigDecimal("1.11"));
} catch (NoCurrencyAvailableException e) {
System.out.println(e.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public PlaceBuyOrderUCImpl(OrderBook orderBook) {

@Override
public void createBuyOrder(Currency crypto, BigDecimal amount, BigDecimal maximumPrice) {
Order buyOrder = new BuyOrder((Crypto) crypto, amount, maximumPrice);
//orderBook.matchSeller(buyOrder);
Order buyOrder = new BuyOrder(crypto, amount, maximumPrice);
orderBook.matchSeller(buyOrder);
}
@Override
public Map<Currency, TreeMap<BigDecimal, List<Order>>> getOrders() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package com.globant.domain.entities.orders;

import com.globant.domain.entities.currencies.Currency;
import com.globant.domain.util.MakeId;

import java.math.BigDecimal;

public class BuyOrder extends Order{
static int buyOrderNumberId = 1;
private final String buyOrderId;
private BigDecimal maximumPrice;

public BuyOrder(Currency cryptoType, BigDecimal amount, BigDecimal maximumPrice) {
super(cryptoType, amount);
this.maximumPrice = maximumPrice;
buyOrderId = MakeId.makeIdNumber(buyOrderNumberId);
buyOrderNumberId++;
}

public BigDecimal getMaximumPrice() {
Expand All @@ -20,6 +25,8 @@ public void setMaximumPrice(BigDecimal maximumPrice) {
this.maximumPrice = maximumPrice;
}

public String getBuyOrderId() { return buyOrderId; }

@Override
public String toString() {
return "BuyOrder{" +
Expand Down
12 changes: 1 addition & 11 deletions src/main/java/com/globant/domain/entities/orders/Order.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,18 @@
import com.globant.domain.entities.currencies.Crypto;
import com.globant.domain.entities.currencies.Currency;
import com.globant.domain.repositories.ActiveUser;
import com.globant.domain.util.MakeId;

import java.math.BigDecimal;

public abstract class Order {

static int orderNumberId = 1;
private static String orderId;
private final User orderEmitter;
private Crypto cryptoType;
private final Crypto cryptoType;
private BigDecimal amount;

public Order(Currency cryptoType, BigDecimal amount) {
this.cryptoType = (Crypto) cryptoType;
this.amount = amount;
orderEmitter = ActiveUser.getInstance().getActiveUser();

orderId = MakeId.makeIdNumber(orderNumberId);
}

public Crypto getCryptoType() {
Expand All @@ -36,9 +30,5 @@ public void setAmount(BigDecimal amount) {
this.amount = amount;
}

public String getOrderId() {
return orderId;
}

public User getOrderEmitter() { return orderEmitter; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

import com.globant.domain.entities.currencies.Currency;
import com.globant.domain.util.InvalidOrderException;
import com.globant.domain.util.MakeId;

import java.math.BigDecimal;

public class SellOrder extends Order{
static int sellOrderNumberId = 1;
private final String sellOrderId;
private BigDecimal minimumPrice;
public SellOrder(Currency cryptoType, BigDecimal amount, BigDecimal minimumPrice) throws InvalidOrderException {
public SellOrder(Currency cryptoType, BigDecimal amount, BigDecimal minimumPrice) {
super(cryptoType, amount);
this.minimumPrice = minimumPrice;
sellOrderId = MakeId.makeIdNumber(sellOrderNumberId);
sellOrderNumberId++;
}

public BigDecimal getMinimumPrice() {
Expand All @@ -20,6 +25,8 @@ public void setMinimumPrice(BigDecimal minimumPrice) {
this.minimumPrice = minimumPrice;
}

public String getSellOrderId() { return sellOrderId; }

public String toString() {
return "SellOrder{" +
"minimumPrice=" + minimumPrice +
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/globant/domain/repositories/OrderBook.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public void match(Order sellOrder, Order buyOrder) {
if (buyerFiatCurrencies.containsKey(referenceCurrency)) {
BigDecimal fiatAmount = buyerFiatCurrencies.get(referenceCurrency);
if (fiatAmount.compareTo(remainingAmount[0]) < 0) {
buyerWallet.deposit(referenceCurrency, BigDecimal.ZERO);
buyerWallet.deposit(referenceCurrency, fiatAmount.negate());
remainingAmount[0] = remainingAmount[0].subtract(fiatAmount);
} else {
buyerWallet.deposit(referenceCurrency, remainingAmount[0].negate());
Expand All @@ -169,9 +169,9 @@ public void match(Order sellOrder, Order buyOrder) {
BigDecimal equivalentAmount = remainingAmount[0].divide(fiat.getPrice(), 2, BigDecimal.ROUND_HALF_UP);
if (fiatAmount.compareTo(equivalentAmount) < 0) {
remainingAmount[0] = remainingAmount[0].subtract(fiatAmount.multiply(fiat.getPrice()));
buyerWallet.deposit(referenceCurrency, BigDecimal.ZERO);
buyerWallet.deposit(fiat, BigDecimal.ZERO);
} else {
buyerWallet.deposit(referenceCurrency, equivalentAmount.negate());
buyerWallet.deposit(fiat, equivalentAmount.negate());
remainingAmount[0] = BigDecimal.ZERO;
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/globant/domain/repositories/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public void deposit(Currency currency, BigDecimal amount) {
if (fiats.isEmpty() || !fiats.containsKey(fiat))
fiats.put(fiat, BigDecimal.ZERO);
fiats.put(fiat, fiats.get(fiat).add(amount));
updateBalance(fiat, amount);

BigDecimal amountEquivalence = fiat.getExchangeCurrencyRate();
updateBalance(fiat, amount.multiply(amountEquivalence).setScale(2, BigDecimal.ROUND_HALF_UP));
}
}
187 changes: 96 additions & 91 deletions src/test/java/PlaceOrdersTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import com.globant.application.port.out.UserRepository;
import com.globant.application.usecases.InitializeCurrencyPricesUCImpl;
import com.globant.domain.entities.currencies.Currency;
import com.globant.domain.entities.orders.BuyOrder;
import com.globant.domain.entities.orders.Order;
import com.globant.domain.entities.orders.SellOrder;
import com.globant.domain.repositories.*;
import com.globant.domain.util.TradeType;

Expand All @@ -15,117 +17,120 @@ public class PlaceOrdersTest {
static UserRepository userRepository = new UserManager();
static UsersLoader usersLoader = new UsersLoader(userRepository);
OrderBook orderBook = new OrderBook();
private void testPlacerBuyOrder() {

private void loadPlaceOrderData() {
usersLoader.loadUsers();
ActiveUser.getInstance().setActiveUser(userRepository.getByUsername("anthleon"));
Wallet wallet1 = userRepository.getByUsername("anthleon").getWallet();
Wallet wallet2 = userRepository.getByUsername("jose123").getWallet();

Exchange exchange = new Exchange();

InitializeCurrencyPricesUCImpl initializeCurrencyPricesUC = new InitializeCurrencyPricesUCImpl(exchange);
initializeCurrencyPricesUC.loadCurrencies(); //Cargar instancias de monedas disponibles en todo el sistema

Currency.setReferenceCurrency(Currency.getInstance("USD"));

Currency btc = Currency.getInstance("BTC");
Currency eth = Currency.getInstance("ETH");

wallet1.deposit(Currency.getInstance("USD"), new BigDecimal(40000));
wallet1.deposit(Currency.getInstance("EUR"), new BigDecimal(160000));
wallet1.addCryptocurrency(btc, new BigDecimal(20));
wallet1.addCryptocurrency(eth, new BigDecimal(20));

wallet2.deposit(Currency.getInstance("USD"), new BigDecimal(40000));
wallet2.deposit(Currency.getInstance("EUR"), new BigDecimal(160000));
wallet2.addCryptocurrency(btc, new BigDecimal(20));
wallet2.addCryptocurrency(eth, new BigDecimal(20));

Order buyOrder = orderBook.createOrder(TradeType.BUY, btc, new BigDecimal(1), new BigDecimal(49000));
Order buyOrder3 = orderBook.createOrder(TradeType.BUY, eth, new BigDecimal(1), new BigDecimal(2000));
Order sellOrder = orderBook.createOrder(TradeType.SELL, btc, new BigDecimal(2), new BigDecimal(51000));
Order sellOrder3 = orderBook.createOrder(TradeType.SELL, eth, new BigDecimal(1), new BigDecimal(1900));

orderBook.addOrder(buyOrder);
orderBook.addOrder(buyOrder3);
orderBook.addOrder(sellOrder);
orderBook.addOrder(sellOrder3);

ActiveUser.getInstance().logOutActiveUser();
ActiveUser.getInstance().setActiveUser(userRepository.getByUsername("jose123"));
Order buyOrder2 = orderBook.createOrder(TradeType.BUY, btc, new BigDecimal(2), new BigDecimal(53000));
Order buyOrder4 = orderBook.createOrder(TradeType.BUY, eth, new BigDecimal(2), new BigDecimal(1900));
Order sellOrder2 = orderBook.createOrder(TradeType.SELL, btc, new BigDecimal(1), new BigDecimal(48000));
Order sellOrder4 = orderBook.createOrder(TradeType.SELL, eth, new BigDecimal(2), new BigDecimal(1800));

orderBook.addOrder(buyOrder2);
orderBook.addOrder(buyOrder4);
orderBook.addOrder(sellOrder2);
orderBook.addOrder(sellOrder4);

Map<Currency, TreeMap<BigDecimal, List<Order>>> orderBuyList = orderBook.getBuyOrders();
Map<Currency, TreeMap<BigDecimal, List<Order>>> orderSellList = orderBook.getSellOrders();

orderBuyList.forEach((currency, orders) -> {
orders.forEach((price, orderList) -> {
orderList.forEach(order -> {
System.out.printf("BUY ORDER #%s = User: %s | Currency: %s | Price: %s | Amount: %s\n", order.getOrderId(), order.getOrderEmitter().getUsername(), currency.getName(), price, order.getAmount());
}

private void testPlacerBuyOrder() {
System.out.println("### TEST PLACE ORDER ###\n");
try {
Wallet wallet1 = userRepository.getByUsername("anthleon").getWallet();
Wallet wallet2 = userRepository.getByUsername("jose123").getWallet();

Currency btc = Currency.getInstance("BTC");
Currency eth = Currency.getInstance("ETH");

wallet1.deposit(Currency.getInstance("USD"), new BigDecimal(40000));
wallet1.deposit(Currency.getInstance("EUR"), new BigDecimal(160000));
wallet1.addCryptocurrency(btc, new BigDecimal(20));
wallet1.addCryptocurrency(eth, new BigDecimal(20));

wallet2.deposit(Currency.getInstance("USD"), new BigDecimal(40000));
wallet2.deposit(Currency.getInstance("EUR"), new BigDecimal(160000));
wallet2.addCryptocurrency(btc, new BigDecimal(20));
wallet2.addCryptocurrency(eth, new BigDecimal(20));

Order buyOrder = orderBook.createOrder(TradeType.BUY, btc, new BigDecimal(1), new BigDecimal(49000));
Order buyOrder3 = orderBook.createOrder(TradeType.BUY, eth, new BigDecimal(1), new BigDecimal(2000));
Order sellOrder = orderBook.createOrder(TradeType.SELL, btc, new BigDecimal(2), new BigDecimal(51000));
Order sellOrder3 = orderBook.createOrder(TradeType.SELL, eth, new BigDecimal(1), new BigDecimal(1900));

orderBook.addOrder(buyOrder);
orderBook.addOrder(buyOrder3);
orderBook.addOrder(sellOrder);
orderBook.addOrder(sellOrder3);

ActiveUser.getInstance().logOutActiveUser();
ActiveUser.getInstance().setActiveUser(userRepository.getByUsername("jose123"));
Order buyOrder2 = orderBook.createOrder(TradeType.BUY, btc, new BigDecimal(2), new BigDecimal(53000));
Order buyOrder4 = orderBook.createOrder(TradeType.BUY, eth, new BigDecimal(2), new BigDecimal(1900));
Order sellOrder2 = orderBook.createOrder(TradeType.SELL, btc, new BigDecimal(1), new BigDecimal(48000));
Order sellOrder4 = orderBook.createOrder(TradeType.SELL, eth, new BigDecimal(2), new BigDecimal(1800));

orderBook.addOrder(buyOrder2);
orderBook.addOrder(buyOrder4);
orderBook.addOrder(sellOrder2);
orderBook.addOrder(sellOrder4);

Map<Currency, TreeMap<BigDecimal, List<Order>>> orderBuyList = orderBook.getBuyOrders();
Map<Currency, TreeMap<BigDecimal, List<Order>>> orderSellList = orderBook.getSellOrders();

orderBuyList.forEach((currency, orders) -> {
orders.forEach((price, orderList) -> {
orderList.forEach(order -> {
System.out.printf("BUY ORDER #%s = User: %s | Currency: %s | Price: %s | Amount: %s\n", ((BuyOrder) order).getBuyOrderId(), order.getOrderEmitter().getUsername(), currency.getName(), price, order.getAmount());
});
});
});
});
System.out.println();
orderSellList.forEach((currency, orders) -> {
orders.forEach((price, orderList) -> {
orderList.forEach(order -> {
System.out.printf("SELL ORDER #%s = User: %s | Currency: %s | Price: %s | Amount: %s\n", order.getOrderId(), order.getOrderEmitter().getUsername(), currency.getName(), price, order.getAmount());
System.out.println();
orderSellList.forEach((currency, orders) -> {
orders.forEach((price, orderList) -> {
orderList.forEach(order -> {
System.out.printf("SELL ORDER #%s = User: %s | Currency: %s | Price: %s | Amount: %s\n", ((SellOrder) order).getSellOrderId(), order.getOrderEmitter().getUsername(), currency.getName(), price, order.getAmount());
});
});
});
});

System.out.println("Anthleon: " + userRepository.getByUsername("anthleon").getWallet().getBalance());
System.out.println("Anthleon wallet: " + userRepository.getByUsername("anthleon").getWallet().getFiats());
System.out.println("Jose123: " + userRepository.getByUsername("jose123").getWallet().getBalance());
System.out.println("Jose123 wallet: " + userRepository.getByUsername("jose123").getWallet().getFiats());

System.out.println();
orderBook.matchSeller(buyOrder);

System.out.println();
System.out.println("Anthleon: " + userRepository.getByUsername("anthleon").getWallet().getBalance());
System.out.println("Anthleon wallet: " + userRepository.getByUsername("anthleon").getWallet().getFiats());
System.out.println("Jose123: " + userRepository.getByUsername("jose123").getWallet().getBalance());
System.out.println("Jose123 wallet: " + userRepository.getByUsername("jose123").getWallet().getFiats());
System.out.println();

orderBook.matchBuyer(sellOrder);
System.out.println();

System.out.println("Anthleon: " + userRepository.getByUsername("anthleon").getWallet().getBalance());
System.out.println("Anthleon wallet: " + userRepository.getByUsername("anthleon").getWallet().getFiats());
System.out.println("Jose123: " + userRepository.getByUsername("jose123").getWallet().getBalance());
System.out.println("Jose123 wallet: " + userRepository.getByUsername("jose123").getWallet().getFiats());
System.out.println();

Map<Currency, TreeMap<BigDecimal, List<Order>>> newOrderBuyList = orderBook.getBuyOrders();
Map<Currency, TreeMap<BigDecimal, List<Order>>> newOrderSellList = orderBook.getSellOrders();

newOrderBuyList.forEach((currency, orders) -> {
orders.forEach((price, orderList) -> {
orderList.forEach(order -> {
System.out.printf("BUY ORDER #%s = User: %s | Currency: %s | Price: %s | Amount: %s\n", order.getOrderId(), order.getOrderEmitter().getUsername(), currency.getName(), price, order.getAmount());

System.out.println();
orderBook.matchSeller(buyOrder);
System.out.println("-".repeat(90));
orderBook.matchBuyer(sellOrder);
System.out.println();

Map<Currency, TreeMap<BigDecimal, List<Order>>> newOrderBuyList = orderBook.getBuyOrders();
Map<Currency, TreeMap<BigDecimal, List<Order>>> newOrderSellList = orderBook.getSellOrders();

newOrderBuyList.forEach((currency, orders) -> {
orders.forEach((price, orderList) -> {
orderList.forEach(order -> {
System.out.printf("BUY ORDER #%s = User: %s | Currency: %s | Price: %s | Amount: %s\n", ((BuyOrder) order).getBuyOrderId(), order.getOrderEmitter().getUsername(), currency.getName(), price, order.getAmount());
});
});
});
});
System.out.println();
newOrderSellList.forEach((currency, orders) -> {
orders.forEach((price, orderList) -> {
orderList.forEach(order ->
System.out.printf("SELL ORDER #%s = User: %s | Currency: %s | Price: %s | Amount: %s\n", order.getOrderId(), order.getOrderEmitter().getUsername(), currency.getName(), price, order.getAmount()));
System.out.println();
newOrderSellList.forEach((currency, orders) -> {
orders.forEach((price, orderList) -> {
orderList.forEach(order ->
System.out.printf("SELL ORDER #%s = User: %s | Currency: %s | Price: %s | Amount: %s\n", ((SellOrder) order).getSellOrderId(), order.getOrderEmitter().getUsername(), currency.getName(), price, order.getAmount()));
});
});
});

if (wallet1.getBalance().equals(new BigDecimal("217600.00").subtract(new BigDecimal(48000)).add(new BigDecimal(51000).multiply(new BigDecimal(2)))) &&
wallet2.getBalance().equals(new BigDecimal("217600.00").add(new BigDecimal(48000)).subtract(new BigDecimal(51000).multiply(new BigDecimal(2)))))
System.err.println("Place order test passed");
else {
throw new AssertionError("Place order test failed");
}
} catch (AssertionError e) {
System.err.println(e.getMessage());
}


}

public static void main(String[] args) {
PlaceOrdersTest test = new PlaceOrdersTest();
test.loadPlaceOrderData();
test.testPlacerBuyOrder();
}
}

0 comments on commit 1bf93ac

Please sign in to comment.