Search in sources :

Example 1 with CurrencyAmountDTO

use of tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO in project cassandre-trading-bot by cassandre-tech.

the class TradeTest method checkStrategyValueInTrade.

@Test
@DisplayName("Check link between order and trade")
public void checkStrategyValueInTrade() {
    // =============================================================================================================
    // Loading strategy.
    StrategyDTO strategyDTO = StrategyDTO.builder().id(1L).strategyId("01").build();
    // =============================================================================================================
    // First, we have an order (NEW_ORDER) that arrives with a strategy.
    long orderCount = orderRepository.count();
    orderFlux.emitValue(OrderDTO.builder().orderId("NEW_ORDER").type(ASK).amount(new CurrencyAmountDTO("1.00001", ETH_BTC.getBaseCurrency())).currencyPair(ETH_BTC).userReference("MY_REF_3").timestamp(createZonedDateTime("01-01-2020")).status(NEW).cumulativeAmount(new CurrencyAmountDTO("1.00002", ETH_BTC.getBaseCurrency())).averagePrice(new CurrencyAmountDTO("1.00003", ETH_BTC.getQuoteCurrency())).leverage("leverage3").limitPrice(new CurrencyAmountDTO("1.00005", ETH_BTC.getQuoteCurrency())).strategy(strategyDTO).build());
    await().untilAsserted(() -> assertEquals(orderCount + 1, orderRepository.count()));
    // =============================================================================================================
    // Then a new trade arrives for order NEW_ORDER, and we check that the strategy is set.
    long tradeCount = tradeRepository.count();
    tradeFlux.emitValue(TradeDTO.builder().tradeId("NEW_TRADE").orderId("NEW_ORDER").type(BID).amount(new CurrencyAmountDTO("1.100003", ETH_BTC.getBaseCurrency())).currencyPair(ETH_BTC).price(new CurrencyAmountDTO("2.200002", ETH_BTC.getQuoteCurrency())).timestamp(createZonedDateTime("01-09-2020")).fee(new CurrencyAmountDTO(new BigDecimal("3.300003"), BTC)).build());
    await().untilAsserted(() -> assertEquals(tradeCount + 1, tradeRepository.count()));
    // Check link between order and trade.
    final Optional<Trade> t = tradeRepository.findByTradeId("NEW_TRADE");
    assertTrue(t.isPresent());
    final Optional<Order> o = orderRepository.findByOrderId("NEW_ORDER");
    assertTrue(o.isPresent());
    assertEquals(1, o.get().getTrades().size());
    assertEquals("NEW_TRADE", o.get().getTrades().iterator().next().getTradeId());
}
Also used : Order(tech.cassandre.trading.bot.domain.Order) Trade(tech.cassandre.trading.bot.domain.Trade) CurrencyAmountDTO(tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO) StrategyDTO(tech.cassandre.trading.bot.dto.strategy.StrategyDTO) BigDecimal(java.math.BigDecimal) BaseTest(tech.cassandre.trading.bot.test.util.junit.BaseTest) Test(org.junit.jupiter.api.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) DisplayName(org.junit.jupiter.api.DisplayName)

Example 2 with CurrencyAmountDTO

use of tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO in project cassandre-trading-bot by cassandre-tech.

the class BaseDataFetcherTest method getCurrencyAmountValue.

/**
 * Returns a currency amount value from a graphql result.
 *
 * @param graphqlResult graphql result
 * @return CurrencyAmountDTO
 */
public final CurrencyAmountDTO getCurrencyAmountValue(Object graphqlResult) {
    Map<String, Double> amountValue = (Map<String, Double>) graphqlResult;
    Map<String, Map<String, String>> currencyValue = (Map<String, Map<String, String>>) graphqlResult;
    final BigDecimal value = new BigDecimal(String.valueOf(amountValue.get("value")));
    final CurrencyDTO quoteCurrency = new CurrencyDTO(currencyValue.get("currency").get("code"));
    return new CurrencyAmountDTO(value, quoteCurrency);
}
Also used : CurrencyAmountDTO(tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO) Map(java.util.Map) BigDecimal(java.math.BigDecimal) CurrencyDTO(tech.cassandre.trading.bot.dto.util.CurrencyDTO)

Example 3 with CurrencyAmountDTO

use of tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO in project cassandre-trading-bot by cassandre-tech.

the class TradeDataFetcherTest method getTradeById.

@Test
@DisplayName("Get trade by id")
void getTradeById() {
    Map<String, Object> result = dgsQueryExecutor.executeAndExtractJsonPath(" { trade(id: 24) {" + "id " + "tradeId " + "type " + "orderId " + "order {id orderId}" + "currencyPair {baseCurrency{code} quoteCurrency{code}}" + "amount {value currency{code}}" + "price {value currency{code}}" + "fee {value currency{code}}" + "timestamp" + "} }", "data.trade");
    assertEquals(24, result.get("id"));
    assertEquals("60df231c2e113d2923052d18", result.get("tradeId"));
    assertEquals("ASK", result.get("type"));
    assertEquals("60df231c38ec01000687554e", result.get("orderId"));
    Map<String, String> order = (Map<String, String>) result.get("order");
    assertEquals(19, order.get("id"));
    assertEquals("60df231c38ec01000687554e", order.get("orderId"));
    assertEquals(BTC_USDT, getCurrencyPairValue(result.get("currencyPair")));
    final CurrencyAmountDTO amount = getCurrencyAmountValue(result.get("amount"));
    assertEquals(0, new BigDecimal("0.001").compareTo(amount.getValue()));
    assertEquals(BTC, amount.getCurrency());
    final CurrencyAmountDTO price = getCurrencyAmountValue(result.get("price"));
    assertEquals(0, new BigDecimal("33591.90000000").compareTo(price.getValue()));
    assertEquals(USDT, price.getCurrency());
    final CurrencyAmountDTO fee = getCurrencyAmountValue(result.get("fee"));
    assertEquals(0, new BigDecimal("0.03359190").compareTo(fee.getValue()));
    assertEquals(USDT, fee.getCurrency());
    assertTrue(result.get("timestamp").toString().contains("2021-07-02T16:30:53"));
}
Also used : CurrencyAmountDTO(tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO) Map(java.util.Map) BigDecimal(java.math.BigDecimal) BaseDataFetcherTest(tech.cassandre.trading.bot.api.graphql.test.util.base.BaseDataFetcherTest) Test(org.junit.jupiter.api.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) DisplayName(org.junit.jupiter.api.DisplayName)

Example 4 with CurrencyAmountDTO

use of tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO in project cassandre-trading-bot by cassandre-tech.

the class UserServiceWithPositionsTest method checkUserBalancesUpdatesWithPosition.

@Test
@DisplayName("Check user balances updates with positions")
public void checkUserBalancesUpdatesWithPosition() {
    assertTrue(strategy.getConfiguration().isDryMode());
    final PositionRulesDTO rules = PositionRulesDTO.builder().stopGainPercentage(100f).build();
    // =============================================================================================================
    // This is what we have in our trade account.
    // Loaded from spring-boot-starter/autoconfigure/src/test/resources/user-trade.csv
    // BTC  0.99962937
    // USDT 1000
    // ETH  10
    accountFlux.update();
    await().until(() -> !strategy.getAccountsUpdatesReceived().isEmpty());
    Map<CurrencyDTO, BalanceDTO> balances = strategy.getTradeAccountBalances();
    assertEquals(0, new BigDecimal("0.99962937").compareTo(balances.get(BTC).getAvailable()));
    assertEquals(0, new BigDecimal("1000").compareTo(balances.get(USDT).getAvailable()));
    assertEquals(0, new BigDecimal("10").compareTo(balances.get(ETH).getAvailable()));
    assertEquals(0, strategy.getAmountsLockedByPosition().size());
    // =============================================================================================================
    // We set the currency pair prices.
    // CP1 : ETH/BTC    - Price is 0.03 meaning 1 ETH costs 0.03 BTC.
    // CP2 : ETH/USDT   - Price is 1 500 meaning 1 ETH costs 1500 USDT.
    // CP3 : BTC/USDT   - Price is 50 000 meaning 1 BTC costs 50000 USDT.
    // CP4 : KCS/USDT   - Price is 4 meaning 1 KCS costs 4 USDT.
    // CP5 : BTC/ETH    - Price is 50 meaning 1 BTC costs 50 ETH.
    tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_BTC).last(new BigDecimal("0.03")).build());
    tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_USDT).last(new BigDecimal("1500")).build());
    tickerFlux.emitValue(TickerDTO.builder().currencyPair(BTC_USDT).last(new BigDecimal("50000")).build());
    tickerFlux.emitValue(TickerDTO.builder().currencyPair(KCS_USDT).last(new BigDecimal("4")).build());
    tickerFlux.emitValue(TickerDTO.builder().currencyPair(BTC_ETH).last(new BigDecimal("50")).build());
    await().untilAsserted(() -> assertEquals(5, strategy.getTickersUpdatesReceived().size()));
    // =============================================================================================================
    // We check what we can do thx to canBuy() methods.
    // With our BTC, we should be able to buy 10 ETH but not 100 ETH.
    assertTrue(strategy.canBuy(ETH_BTC, new BigDecimal("10")));
    assertFalse(strategy.canBuy(ETH_BTC, new BigDecimal("100")));
    // With our USDT, we should be able to buy 0.5 ETH but not 1 ETH.
    assertTrue(strategy.canBuy(ETH_USDT, new BigDecimal("0.5")));
    assertFalse(strategy.canBuy(ETH_USDT, new BigDecimal("1")));
    // With our USDT, we should be able to buy 0.01 BTC but not 0.1 BTC.
    assertTrue(strategy.canBuy(BTC_USDT, new BigDecimal("0.01")));
    assertFalse(strategy.canBuy(BTC_USDT, new BigDecimal("0.1")));
    // With our USDT, we should be able to buy 200 KCS but not 300 KCS.
    assertTrue(strategy.canBuy(KCS_USDT, new BigDecimal("200")));
    assertFalse(strategy.canBuy(KCS_USDT, new BigDecimal("300")));
    // With our ETH, we should be able to buy 0.2 BTC but not 0.25 BTC.
    assertTrue(strategy.canBuy(BTC_ETH, new BigDecimal("0.2")));
    assertFalse(strategy.canBuy(BTC_ETH, new BigDecimal("0.25")));
    // =============================================================================================================
    // We check what we can do thx to canSell() methods.
    // We can sell 0.99962937 BTC but not 1 BTC.
    assertTrue(strategy.canSell(BTC, new BigDecimal("0.99962937")));
    assertFalse(strategy.canSell(BTC, new BigDecimal("1")));
    // We can sell 1000 USDT.
    assertTrue(strategy.canSell(USDT, new BigDecimal("1000")));
    assertFalse(strategy.canSell(USDT, new BigDecimal("1001")));
    // We can sell 10 ETH.
    assertTrue(strategy.canSell(ETH, new BigDecimal("10")));
    assertFalse(strategy.canSell(ETH, new BigDecimal("11")));
    // =============================================================================================================
    // We create a first long position on ETH/USDT.
    // CP2 : ETH/USDT - 1 ETH costs 1500 USDT - We buy 0.5 ETH, and it will cost 750 USDT.
    // Before.              After.
    // 0.99962937 BTC   =>  0.99962937 BTC.
    // 1000 USDT        =>  250 USDT.
    // 10 ETH           =>  10.5 ETH (0.5 locked in positions).
    final PositionCreationResultDTO position1 = strategy.createLongPosition(ETH_USDT, new BigDecimal("0.5"), rules);
    long position1Id = position1.getPosition().getPositionId();
    await().untilAsserted(() -> assertEquals(OPENED, getPositionDTO(position1Id).getStatus()));
    balances = strategy.getTradeAccountBalances();
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("0.99962937").compareTo(strategy.getTradeAccountBalances().get(BTC).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("250").compareTo(strategy.getTradeAccountBalances().get(USDT).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("10.5").compareTo(strategy.getTradeAccountBalances().get(ETH).getAvailable())));
    // We check that the position locked amount is well stored.
    // Opened long position of 0.5 ETH (so we can't sell them).
    assertEquals(1, strategy.getAmountsLockedByPosition().size());
    final CurrencyAmountDTO currencyAmountForPosition1 = strategy.getAmountsLockedByPosition().get(position1Id);
    assertNotNull(currencyAmountForPosition1);
    assertEquals(0, new BigDecimal("0.5").compareTo(currencyAmountForPosition1.getValue()));
    assertEquals(ETH, currencyAmountForPosition1.getCurrency());
    // As we now have 10.5 ETH and 0.5 locked in positions, we should be able to sell 10 ETH but not 10.5 ETH.
    assertEquals(0, new BigDecimal("10.5").compareTo(balances.get(ETH).getAvailable()));
    assertEquals(0, new BigDecimal("0.5").compareTo(strategy.getAmountsLockedByCurrency(ETH)));
    assertTrue(strategy.canSell(ETH, new BigDecimal("10")));
    assertFalse(strategy.canSell(ETH, new BigDecimal("10.5")));
    // As we now have 10.5 ETH and 0.5 locked in positions, we should still be able to buy 0.2 but not more.
    assertTrue(strategy.canBuy(BTC_ETH, new BigDecimal("0.2")));
    assertFalse(strategy.canBuy(BTC_ETH, new BigDecimal("0.20001")));
    // Price updates for CP2.
    // CP2 : ETH/USDT - 1 ETH costs 10 USDT - We buy 10 ETH, and it will cost 100 USDT.
    tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_USDT).last(new BigDecimal("10")).build());
    await().untilAsserted(() -> assertEquals(6, strategy.getTickersUpdatesReceived().size()));
    // =============================================================================================================
    // We create another long position on ETH/USDT.
    // CP2 : ETH/USDT - 1 ETH costs 10 USDT - We buy 10 ETH, and it will cost 100 USDT.
    // Before.              After.
    // 0.99962937 BTC   =>  0.99962937 BTC.
    // 250 USDT         =>  150 USDT.
    // 10.5 ETH         =>  20.5 ETH (10.5 locked in positions).
    final PositionCreationResultDTO position2 = strategy.createLongPosition(ETH_USDT, new BigDecimal("10"), rules);
    long position2Id = position2.getPosition().getPositionId();
    await().untilAsserted(() -> assertEquals(OPENED, getPositionDTO(position2Id).getStatus()));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("0.99962937").compareTo(strategy.getTradeAccountBalances().get(BTC).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("150").compareTo(strategy.getTradeAccountBalances().get(USDT).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("20.5").compareTo(strategy.getTradeAccountBalances().get(ETH).getAvailable())));
    // We check that the position locked amount is well stored.
    // Opened long position of 0.5 ETH (so we can't sell them).
    // Opened long position of 10 ETH (so we can't sell them).
    assertEquals(2, strategy.getAmountsLockedByPosition().size());
    assertEquals(0, new BigDecimal("10.5").compareTo(strategy.getAmountsLockedByCurrency(ETH)));
    final CurrencyAmountDTO currencyAmountForPosition2 = strategy.getAmountsLockedByPosition().get(position2Id);
    assertNotNull(currencyAmountForPosition2);
    assertEquals(0, new BigDecimal("10").compareTo(currencyAmountForPosition2.getValue()));
    assertEquals(ETH, currencyAmountForPosition2.getCurrency());
    // As we now have 20.5 ETH and 10.5 locked in positions, we should not be able to sell 10 ETH but not 10.1 ETH.
    assertEquals(0, new BigDecimal("20.5").compareTo(strategy.getTradeAccountBalances().get(ETH).getAvailable()));
    assertTrue(strategy.canSell(ETH, new BigDecimal("10")));
    assertFalse(strategy.canSell(ETH, new BigDecimal("10.1")));
    assertFalse(strategy.canSell(ETH, new BigDecimal("20.5")));
    // As we now have 20.5 ETH and 10.5 locked in positions, we should still be able to buy 0.2 but not more.
    assertTrue(strategy.canBuy(BTC_ETH, new BigDecimal("0.2")));
    assertFalse(strategy.canBuy(BTC_ETH, new BigDecimal("0.20001")));
    // =============================================================================================================
    // We create a third long position on KCS/USDT.
    // CP4 : KCS/USDT - 1 KCS costs 4 USDT - We buy 20 KCS, and it will cost 80 USDT.
    // Before.              After.
    // 0.99962937 BTC   =>  0.99962937 BTC.
    // 150 USDT         =>  70 USDT.
    // 20.5 ETH ETH     =>  20.5 ETH (10.5 locked in positions).
    // 0 KCS            =>  20 KCS (20 lock in positions).
    final PositionCreationResultDTO position3 = strategy.createLongPosition(KCS_USDT, new BigDecimal("20"), rules);
    long position3Id = position3.getPosition().getPositionId();
    await().untilAsserted(() -> assertEquals(OPENED, getPositionDTO(position3Id).getStatus()));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("0.99962937").compareTo(strategy.getTradeAccountBalances().get(BTC).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("70").compareTo(strategy.getTradeAccountBalances().get(USDT).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("20.5").compareTo(strategy.getTradeAccountBalances().get(ETH).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("20").compareTo(strategy.getTradeAccountBalances().get(KCS).getAvailable())));
    // We check that the position locked amount is well stored.
    // Opened long position of 0.5 ETH (so we can't sell them).
    // Opened long position of 10 ETH (so we can't sell them).
    // Opened long position of 20 KCS (so we can't sell them).
    assertEquals(3, strategy.getAmountsLockedByPosition().size());
    assertEquals(0, new BigDecimal("10.5").compareTo(strategy.getAmountsLockedByCurrency(ETH)));
    assertEquals(0, new BigDecimal("20").compareTo(strategy.getAmountsLockedByCurrency(KCS)));
    final CurrencyAmountDTO currencyAmountForPosition3 = strategy.getAmountsLockedByPosition().get(position3Id);
    assertNotNull(currencyAmountForPosition3);
    assertEquals(0, new BigDecimal("20").compareTo(currencyAmountForPosition3.getValue()));
    assertEquals(KCS, currencyAmountForPosition3.getCurrency());
    // As we now have 20 KCS locked in positions, we should not be able to sell them.
    assertEquals(0, new BigDecimal("20").compareTo(strategy.getTradeAccountBalances().get(KCS).getAvailable()));
    assertFalse(strategy.canSell(KCS, new BigDecimal("10")));
    // =============================================================================================================
    // We create a first short position on ETH/USDT.
    // CP2 : ETH/USDT - 1 ETH costs 10 USDT - We sell 1 ETH, and it will give us 10 USDT.
    // Before.              After.
    // 0.99962937 BTC   =>  0.99962937 BTC
    // 70 USDT          =>  80 USDT (10 locked in positions).
    // 20.5 ETH         =>  19.5 (10.5 locked in positions).
    // 0 KCS            =>  20 KCS (20 lock in positions).
    final PositionCreationResultDTO position4 = strategy.createShortPosition(ETH_USDT, new BigDecimal("1"), rules);
    long position4Id = position4.getPosition().getPositionId();
    await().untilAsserted(() -> assertEquals(OPENED, getPositionDTO(position4Id).getStatus()));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("0.99962937").compareTo(strategy.getTradeAccountBalances().get(BTC).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("80").compareTo(strategy.getTradeAccountBalances().get(USDT).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("19.5").compareTo(strategy.getTradeAccountBalances().get(ETH).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("20").compareTo(strategy.getTradeAccountBalances().get(KCS).getAvailable())));
    // We check that the position locked amount is well stored.
    // Opened long position of 0.5 ETH (so we can't sell them).
    // Opened long position of 10 ETH (so we can't sell them).
    // Opened long position of 20 ETH (so we can't sell them).
    // Opened short position of 10 USDT (so we can't sell them).
    assertEquals(4, strategy.getAmountsLockedByPosition().size());
    assertEquals(0, new BigDecimal("10.5").compareTo(strategy.getAmountsLockedByCurrency(ETH)));
    assertEquals(0, new BigDecimal("20").compareTo(strategy.getAmountsLockedByCurrency(KCS)));
    assertEquals(0, new BigDecimal("10").compareTo(strategy.getAmountsLockedByCurrency(USDT)));
    final CurrencyAmountDTO currencyAmountForPosition4 = strategy.getAmountsLockedByPosition().get(position4Id);
    assertNotNull(currencyAmountForPosition4);
    assertEquals(0, new BigDecimal("10").compareTo(currencyAmountForPosition4.getValue()));
    assertEquals(USDT, currencyAmountForPosition4.getCurrency());
    // As we now have 10 USDT locked in positions, we should not be able to sell 80 but 70.
    assertEquals(0, new BigDecimal("80").compareTo(strategy.getTradeAccountBalances().get(USDT).getAvailable()));
    assertFalse(strategy.canSell(USDT, new BigDecimal("80")));
    assertTrue(strategy.canSell(USDT, new BigDecimal("70")));
    // =============================================================================================================
    // We will now close position 2 on ETH/USDT (long) & position 4 on ETH/USDT (short).
    // They both have a 100% stop gain rule.
    // For the position long 2, we started at :
    // CP2 : ETH/USDT - 1 ETH costs 10 USDT - We buy 10 ETH, and it will cost 100 USDT.
    // For the position long 2, we send :
    // CP2 : ETH/USDT - 1 ETH costs 100 USDT - We sell 10 ETH, and it will give us 1 000 USDT.
    // Result: -10 ETH + 1 000 USDT
    tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_USDT).last(new BigDecimal("100")).build());
    await().untilAsserted(() -> assertEquals(CLOSED, getPositionDTO(position2Id).getStatus()));
    // For the position short 4, we started at :
    // CP2 : ETH/USDT - 1 ETH costs 10 USDT - We sell 1 ETH, and it will give us 10 USDT.
    // And now we are at :
    // CP2 : ETH/USDT - 1 ETH costs 2 USDT - We buy 5 ETH, and it will cost us 10 USDT.
    // Result: -10 USDT + 5 ETH
    tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_USDT).last(new BigDecimal("2")).build());
    await().untilAsserted(() -> assertEquals(CLOSED, getPositionDTO(position4Id).getStatus()));
    // We should now have the following amounts
    // Before.              After.
    // 0.99962937 BTC       =>  0.99962937 BTC.
    // 80 USDT              =>  80 + 1 000 (position 2 sell) - 10 (position 4 buy)
    // 19.5 ETH             =>  19.5 - 10 (position 2 sell) + 5 (position 4 buy)
    // 0 KCS                =>  20 KCS (20 lock in positions).
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("0.99962937").compareTo(strategy.getTradeAccountBalances().get(BTC).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("1070").compareTo(strategy.getTradeAccountBalances().get(USDT).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("14.5").compareTo(strategy.getTradeAccountBalances().get(ETH).getAvailable())));
    await().untilAsserted(() -> assertEquals(0, new BigDecimal("20").compareTo(strategy.getTradeAccountBalances().get(KCS).getAvailable())));
    // We check that the position don't lock amount anymore.
    // 0.5 ETH locked because of position 1.
    // 20 KCS because of position 3.
    assertEquals(2, strategy.getAmountsLockedByPosition().size());
    assertEquals(0, new BigDecimal("0.5").compareTo(strategy.getAmountsLockedByCurrency(ETH)));
    assertEquals(0, new BigDecimal("20").compareTo(strategy.getAmountsLockedByCurrency(KCS)));
    // As we now have 1070 ETH and 10.5 locked in positions, we should be able to buy 0.02 BTC but not 0.03 BTC.
    assertTrue(strategy.canBuy(BTC_USDT, new BigDecimal("0.02")));
    assertFalse(strategy.canBuy(BTC_USDT, new BigDecimal("0.03")));
}
Also used : PositionCreationResultDTO(tech.cassandre.trading.bot.dto.position.PositionCreationResultDTO) CurrencyAmountDTO(tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO) PositionRulesDTO(tech.cassandre.trading.bot.dto.position.PositionRulesDTO) BalanceDTO(tech.cassandre.trading.bot.dto.user.BalanceDTO) CurrencyDTO(tech.cassandre.trading.bot.dto.util.CurrencyDTO) BigDecimal(java.math.BigDecimal) BaseTest(tech.cassandre.trading.bot.test.util.junit.BaseTest) Test(org.junit.jupiter.api.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) DisplayName(org.junit.jupiter.api.DisplayName)

Example 5 with CurrencyAmountDTO

use of tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO in project cassandre-trading-bot by cassandre-tech.

the class PositionServiceTest method checkOpeningOrderFailure.

@Test
@DisplayName("Check opening order failure")
public void checkOpeningOrderFailure() {
    // =============================================================================================================
    // Creates a position. Then send an order update with an error.
    // The position must end up being in OPENING_FAILURE
    // Creates position 1 (ETH/BTC, 0.0001, 10% stop gain).
    final PositionCreationResultDTO p1 = strategy.createLongPosition(ETH_BTC, new BigDecimal("0.0001"), PositionRulesDTO.builder().stopGainPercentage(10f).build());
    assertTrue(p1.isSuccessful());
    assertEquals(1, p1.getPosition().getUid());
    assertEquals("ORDER00010", p1.getPosition().getOpeningOrder().getOrderId());
    assertNull(p1.getErrorMessage());
    assertNull(p1.getException());
    assertTrue(positionService.getPositionByUid(1).isPresent());
    assertEquals(OPENING, positionService.getPositionByUid(1).get().getStatus());
    long position1Uid = p1.getPosition().getUid();
    // We retrieve the order from the service, and we wait for the order to update the position.
    // Only one order updates (we don't send the PENDING_NOW order in flux).
    // Two positions updates because order status change from PENDING_NEW to NEW.
    orderFlux.update();
    await().untilAsserted(() -> assertEquals(1, strategy.getOrdersUpdatesReceived().size()));
    await().untilAsserted(() -> assertEquals(2, strategy.getPositionsUpdatesReceived().size()));
    // Position 1.
    Optional<PositionDTO> position1 = strategy.getPositionByPositionId(position1Uid);
    assertTrue(position1.isPresent());
    // Opening order.
    OrderDTO p1OpeningOrder = position1.get().getOpeningOrder();
    assertNotNull(p1OpeningOrder);
    assertEquals("ORDER00010", p1OpeningOrder.getOrderId());
    assertEquals(BID, p1OpeningOrder.getType());
    assertEquals(ETH_BTC, p1OpeningOrder.getCurrencyPair());
    assertEquals(NEW, p1OpeningOrder.getStatus());
    // Closing order.
    OrderDTO p1ClosingOrder = position1.get().getClosingOrder();
    assertNull(p1ClosingOrder);
    // =============================================================================================================
    // An update for opening order ORDER00020 (position 2) arrives and change status with an error !
    OrderDTO order00010 = OrderDTO.builder().orderId("ORDER00010").type(BID).strategy(strategyDTO).amount(new CurrencyAmountDTO("0.00012", ETH_BTC.getBaseCurrency())).currencyPair(ETH_BTC).timestamp(ZonedDateTime.now()).status(STOPPED).build();
    orderFlux.emitValue(order00010);
    // The position should move to failure.
    await().untilAsserted(() -> assertEquals(OPENING_FAILURE, getPositionDTO(position1Uid).getStatus()));
    assertEquals("Position 1 - Opening failure", getPositionDTO(position1Uid).getDescription());
}
Also used : PositionCreationResultDTO(tech.cassandre.trading.bot.dto.position.PositionCreationResultDTO) CurrencyAmountDTO(tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO) OrderDTO(tech.cassandre.trading.bot.dto.trade.OrderDTO) BigDecimal(java.math.BigDecimal) PositionDTO(tech.cassandre.trading.bot.dto.position.PositionDTO) Test(org.junit.jupiter.api.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) BaseTest(tech.cassandre.trading.bot.test.util.junit.BaseTest) DisplayName(org.junit.jupiter.api.DisplayName)

Aggregations

CurrencyAmountDTO (tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO)38 BigDecimal (java.math.BigDecimal)32 DisplayName (org.junit.jupiter.api.DisplayName)31 Test (org.junit.jupiter.api.Test)31 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)26 BaseTest (tech.cassandre.trading.bot.test.util.junit.BaseTest)22 PositionCreationResultDTO (tech.cassandre.trading.bot.dto.position.PositionCreationResultDTO)15 PositionDTO (tech.cassandre.trading.bot.dto.position.PositionDTO)13 OrderDTO (tech.cassandre.trading.bot.dto.trade.OrderDTO)12 GainDTO (tech.cassandre.trading.bot.dto.util.GainDTO)12 TradeDTO (tech.cassandre.trading.bot.dto.trade.TradeDTO)10 CurrencyDTO (tech.cassandre.trading.bot.dto.util.CurrencyDTO)8 Map (java.util.Map)6 Optional (java.util.Optional)6 ZERO (java.math.BigDecimal.ZERO)5 TickerDTO (tech.cassandre.trading.bot.dto.market.TickerDTO)5 CLOSED (tech.cassandre.trading.bot.dto.position.PositionStatusDTO.CLOSED)5 FLOOR (java.math.RoundingMode.FLOOR)4 HALF_UP (java.math.RoundingMode.HALF_UP)4 LinkedHashSet (java.util.LinkedHashSet)4