use of tech.cassandre.trading.bot.domain.Order 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());
}
use of tech.cassandre.trading.bot.domain.Order in project cassandre-trading-bot by cassandre-tech.
the class TradeServiceXChangeImplementation method createLimitOrder.
/**
* Creates limit order.
*
* @param strategy strategy
* @param orderTypeDTO order type
* @param currencyPair currency pair
* @param amount amount
* @param limitPrice In a BID this is the highest acceptable price, in an ASK this is the lowest acceptable price
* @return order creation result
*/
private OrderCreationResultDTO createLimitOrder(final GenericCassandreStrategy strategy, final OrderTypeDTO orderTypeDTO, final CurrencyPairDTO currencyPair, final BigDecimal amount, final BigDecimal limitPrice) {
try {
// Making the order.
LimitOrder l = new LimitOrder(UTIL_MAPPER.mapToOrderType(orderTypeDTO), amount.setScale(currencyPair.getBaseCurrencyPrecision(), FLOOR), CURRENCY_MAPPER.mapToCurrencyPair(currencyPair), getGeneratedOrderId(), null, limitPrice);
logger.debug("Sending limit order: {} - {} - {}", orderTypeDTO, currencyPair, amount.setScale(currencyPair.getBaseCurrencyPrecision(), FLOOR));
// Sending & creating the order.
OrderDTO order = OrderDTO.builder().orderId(tradeService.placeLimitOrder(l)).type(orderTypeDTO).strategy(strategy.getStrategyDTO()).currencyPair(currencyPair).amount(CurrencyAmountDTO.builder().value(amount).currency(currencyPair.getBaseCurrency()).build()).cumulativeAmount(CurrencyAmountDTO.builder().value(amount).currency(currencyPair.getBaseCurrency()).build()).averagePrice(CurrencyAmountDTO.builder().value(strategy.getLastPriceForCurrencyPair(currencyPair)).currency(currencyPair.getQuoteCurrency()).build()).limitPrice(CurrencyAmountDTO.builder().value(limitPrice).currency(currencyPair.getQuoteCurrency()).build()).marketPrice(CurrencyAmountDTO.builder().value(strategy.getLastPriceForCurrencyPair(currencyPair)).currency(currencyPair.getQuoteCurrency()).build()).status(PENDING_NEW).timestamp(ZonedDateTime.now()).build();
// We save the order.
Optional<Order> savedOrder = orderRepository.findByOrderId(order.getOrderId());
if (savedOrder.isEmpty()) {
savedOrder = Optional.of(orderRepository.save(ORDER_MAPPER.mapToOrder(order)));
}
final OrderCreationResultDTO result = new OrderCreationResultDTO(ORDER_MAPPER.mapToOrderDTO(savedOrder.get()));
logger.debug("Order creation result: {}", result);
return result;
} catch (Exception e) {
final String error = "TradeService - Error calling createLimitOrder for " + amount + " " + currencyPair + ": " + e.getMessage();
e.printStackTrace();
logger.error(error);
return new OrderCreationResultDTO(error, e);
}
}
use of tech.cassandre.trading.bot.domain.Order in project cassandre-trading-bot by cassandre-tech.
the class OrderTest method checkSaveOrderInDatabase.
@Test
@DisplayName("Check save order in database")
public void checkSaveOrderInDatabase() {
// =============================================================================================================
// Emit an order to be saved in database.
long orderCount = orderRepository.count();
OrderDTO order01 = OrderDTO.builder().orderId("BACKUP_ORDER_03").type(ASK).strategy(strategyDTO).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("1.00001", ETH_BTC.getBaseCurrency())).averagePrice(new CurrencyAmountDTO("1.00003", ETH_BTC.getQuoteCurrency())).limitPrice(new CurrencyAmountDTO("1.00005", ETH_BTC.getQuoteCurrency())).marketPrice(new CurrencyAmountDTO("1.00006", ETH_BTC.getBaseCurrency())).leverage("leverage3").status(NEW).cumulativeAmount(new CurrencyAmountDTO("1.00002", ETH_BTC.getBaseCurrency())).userReference("MY_REF_3").timestamp(createZonedDateTime("01-01-2020")).build();
orderFlux.emitValue(order01);
await().untilAsserted(() -> assertEquals(orderCount + 1, orderRepository.count()));
// =============================================================================================================
// Order - Check the order created previously (domain).
final Optional<Order> orderInDatabase = orderRepository.findByOrderId("BACKUP_ORDER_03");
assertTrue(orderInDatabase.isPresent());
assertEquals(11, orderInDatabase.get().getUid());
assertEquals("BACKUP_ORDER_03", orderInDatabase.get().getOrderId());
assertEquals(ASK, orderInDatabase.get().getType());
assertEquals(1, orderInDatabase.get().getStrategy().getUid());
assertEquals("01", orderInDatabase.get().getStrategy().getStrategyId());
assertEquals(ETH_BTC.toString(), orderInDatabase.get().getCurrencyPair());
assertEquals(0, new BigDecimal("1.00001").compareTo(orderInDatabase.get().getAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency().toString(), orderInDatabase.get().getAmount().getCurrency());
assertEquals(0, new BigDecimal("1.00003").compareTo(orderInDatabase.get().getAveragePrice().getValue()));
assertEquals(ETH_BTC.getQuoteCurrency().toString(), orderInDatabase.get().getAveragePrice().getCurrency());
assertEquals(0, new BigDecimal("1.00005").compareTo(orderInDatabase.get().getLimitPrice().getValue()));
assertEquals(ETH_BTC.getQuoteCurrency().toString(), orderInDatabase.get().getLimitPrice().getCurrency());
assertEquals(0, new BigDecimal("1.00006").compareTo(orderInDatabase.get().getMarketPrice().getValue()));
assertEquals(ETH_BTC.getBaseCurrency().toString(), orderInDatabase.get().getMarketPrice().getCurrency());
assertEquals("leverage3", orderInDatabase.get().getLeverage());
assertEquals(NEW, orderInDatabase.get().getStatus());
assertEquals(0, new BigDecimal("1.00002").compareTo(orderInDatabase.get().getCumulativeAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency().toString(), orderInDatabase.get().getCumulativeAmount().getCurrency());
assertEquals("MY_REF_3", orderInDatabase.get().getUserReference());
assertTrue(createZonedDateTime("01-01-2020").isEqual(orderInDatabase.get().getTimestamp()));
ZonedDateTime createdOn = orderInDatabase.get().getCreatedOn();
assertNotNull(createdOn);
assertNull(orderInDatabase.get().getUpdatedOn());
// =============================================================================================================
// Order - Check the order created previously (dto).
Optional<OrderDTO> order = this.strategy.getOrderByOrderId("BACKUP_ORDER_03");
assertTrue(order.isPresent());
assertEquals(11, order.get().getUid());
assertEquals("BACKUP_ORDER_03", order.get().getOrderId());
assertEquals(ASK, order.get().getType());
assertEquals(1, order.get().getStrategy().getUid());
assertEquals("01", order.get().getStrategy().getStrategyId());
assertEquals(ETH_BTC, order.get().getCurrencyPair());
assertEquals(0, new BigDecimal("1.00001").compareTo(order.get().getAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency(), order.get().getAmount().getCurrency());
assertEquals(0, new BigDecimal("1.00003").compareTo(order.get().getAveragePrice().getValue()));
assertEquals(ETH_BTC.getQuoteCurrency(), order.get().getAveragePrice().getCurrency());
assertEquals(0, new BigDecimal("1.00005").compareTo(order.get().getLimitPrice().getValue()));
assertEquals(ETH_BTC.getQuoteCurrency(), order.get().getLimitPrice().getCurrency());
assertEquals(0, new BigDecimal("1.00006").compareTo(order.get().getMarketPrice().getValue()));
assertEquals(ETH_BTC.getBaseCurrency(), order.get().getMarketPrice().getCurrency());
assertEquals("leverage3", order.get().getLeverage());
assertEquals(NEW, order.get().getStatus());
assertEquals(0, new BigDecimal("1.00002").compareTo(order.get().getCumulativeAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency(), order.get().getCumulativeAmount().getCurrency());
assertEquals("MY_REF_3", order.get().getUserReference());
assertTrue(createZonedDateTime("01-01-2020").isEqual(order.get().getTimestamp()));
// =============================================================================================================
// Updating the order and also adding a trade - first time.
orderFlux.emitValue(OrderDTO.builder().orderId("BACKUP_ORDER_03").type(ASK).strategy(strategyDTO).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("1.00002", ETH_BTC.getBaseCurrency())).averagePrice(new CurrencyAmountDTO("1.00003", ETH_BTC.getQuoteCurrency())).limitPrice(new CurrencyAmountDTO("1.00005", ETH_BTC.getQuoteCurrency())).leverage("leverage3").status(NEW).cumulativeAmount(new CurrencyAmountDTO("1.00002", ETH_BTC.getBaseCurrency())).userReference("MY_REF_3").timestamp(createZonedDateTime("01-01-2020")).build());
await().untilAsserted(() -> assertNotNull(getOrder("BACKUP_ORDER_03").getUpdatedOn()));
assertEquals(createdOn, getOrder("BACKUP_ORDER_03").getCreatedOn());
ZonedDateTime updatedOn = orderInDatabase.get().getCreatedOn();
tradeFlux.emitValue(TradeDTO.builder().tradeId("BACKUP_TRADE_11").type(BID).orderId("BACKUP_ORDER_03").currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("1.100001", ETH_BTC.getBaseCurrency())).price(new CurrencyAmountDTO("2.200002", ETH_BTC.getQuoteCurrency())).fee(new CurrencyAmountDTO(new BigDecimal("3.300003"), BTC)).timestamp(createZonedDateTime("01-09-2020")).userReference("TRADE MY_REF_3").build());
await().untilAsserted(() -> assertEquals(1, strategy.getTradesUpdatesReceived().size()));
Optional<Order> backupOrder03 = orderRepository.findByOrderId("BACKUP_ORDER_03");
assertTrue(backupOrder03.isPresent());
assertEquals(1, backupOrder03.get().getTrades().size());
Iterator<Trade> orderTrades = backupOrder03.get().getTrades().iterator();
assertEquals("BACKUP_TRADE_11", orderTrades.next().getTradeId());
// =============================================================================================================
// Updating the order - second time.
orderFlux.emitValue(OrderDTO.builder().orderId("BACKUP_ORDER_03").type(ASK).strategy(strategyDTO).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("1.00003", ETH_BTC.getBaseCurrency())).averagePrice(new CurrencyAmountDTO("1.00003", ETH_BTC.getQuoteCurrency())).limitPrice(new CurrencyAmountDTO("1.00005", ETH_BTC.getQuoteCurrency())).leverage("leverage3").status(NEW).cumulativeAmount(new CurrencyAmountDTO("1.00002", ETH_BTC.getBaseCurrency())).userReference("MY_REF_3").timestamp(createZonedDateTime("01-01-2020")).build());
await().untilAsserted(() -> assertTrue(updatedOn.isBefore(getOrder("BACKUP_ORDER_03").getUpdatedOn())));
assertEquals(createdOn, getOrder("BACKUP_ORDER_03").getCreatedOn());
// We check if we still have the strategy set.
final Optional<OrderDTO> optionalOrder = strategy.getOrderByOrderId("BACKUP_ORDER_03");
assertTrue(optionalOrder.isPresent());
assertNotNull(optionalOrder.get().getStrategy());
assertEquals("01", optionalOrder.get().getStrategy().getStrategyId());
// We check if we still have the trade linked to the order.
backupOrder03 = orderRepository.findByOrderId("BACKUP_ORDER_03");
assertTrue(backupOrder03.isPresent());
assertEquals(1, backupOrder03.get().getTrades().size());
orderTrades = backupOrder03.get().getTrades().iterator();
assertEquals("BACKUP_TRADE_11", orderTrades.next().getTradeId());
}
use of tech.cassandre.trading.bot.domain.Order in project cassandre-trading-bot by cassandre-tech.
the class Issue427Test method checkSaveLocalOrderBeforeRemote.
@Test
@DisplayName("Local order must be saved before saving distant order")
public void checkSaveLocalOrderBeforeRemote() throws InterruptedException {
// Check that a distant order is not saved before the local order is created.
// Call getOrders to retrieve the distant order.
orderFlux.update();
// We wait a bit, the order should not be here as the local order is not saved.
TimeUnit.SECONDS.sleep(5L);
assertEquals(0, orderRepository.count());
// The local order is saved
orderFlux.emitValue(OrderDTO.builder().orderId("ORDER_000001").type(ASK).strategy(strategyDTO).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("1", ETH_BTC.getBaseCurrency())).averagePrice(new CurrencyAmountDTO("3", ETH_BTC.getQuoteCurrency())).limitPrice(new CurrencyAmountDTO("5", ETH_BTC.getQuoteCurrency())).leverage("leverage2").status(NEW).cumulativeAmount(new CurrencyAmountDTO("2", ETH_BTC.getBaseCurrency())).userReference("MY_REF_1").timestamp(ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"))).build());
// We wait a bit, the local order should be here.
TimeUnit.SECONDS.sleep(5L);
assertEquals(1, orderRepository.count());
Optional<Order> o = orderRepository.findByOrderId("ORDER_000001");
assertTrue(o.isPresent());
assertEquals("leverage2", o.get().getLeverage());
// Call getOrders to retrieve the distant order.
orderFlux.update();
// We wait a bit, the order in database should be updated with the distant one.
TimeUnit.SECONDS.sleep(5L);
assertEquals(1, orderRepository.count());
o = orderRepository.findByOrderId("ORDER_000001");
assertTrue(o.isPresent());
assertEquals("leverage1", o.get().getLeverage());
}
use of tech.cassandre.trading.bot.domain.Order in project cassandre-trading-bot by cassandre-tech.
the class PositionLongFluxTest method checkReceivedData.
@Test
@DisplayName("Check received data")
public void checkReceivedData() {
// =============================================================================================================
// Creates long position n°1 - 10 ETH bought with BTC.
// Position will be closed if 1 000% gain or 100% loss.
final PositionCreationResultDTO position1Result = strategy.createLongPosition(ETH_BTC, new BigDecimal("10"), PositionRulesDTO.builder().stopGainPercentage(// 1 000% max gain.
1_000f).stopLossPercentage(// 100% max lost.
100f).build());
assertEquals("ORDER00010", position1Result.getPosition().getOpeningOrder().getOrderId());
long position1Uid = position1Result.getPosition().getUid();
// onPositionStatusUpdate - Position 1 should arrive (OPENING).
// 1 position status update:
// - The position is created with the OPENING status.
await().untilAsserted(() -> assertEquals(1, strategy.getPositionsStatusUpdatesCount()));
PositionDTO p = strategy.getLastPositionStatusUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(OPENING, p.getStatus());
assertEquals("Long position n°1 of 10 ETH (rules: 1000.0 % gain / 100.0 % loss) - Opening - Waiting for the trades of order ORDER00010", p.getDescription());
// onPositionUpdate - Position 1 should arrive (OPENING).
// 2 positions updates:
// - Position created with a local order saved in database (Order with status PENDING_NEW).
// - Position updated with the local order retrieved from getOrders with status NEW.
await().untilAsserted(() -> assertEquals(2, strategy.getPositionsUpdatesReceived().size()));
p = strategy.getLastPositionUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(OPENING, p.getStatus());
// Check data in strategy & database.
assertEquals(1, positionRepository.count());
assertEquals(1, strategy.getPositions().size());
Optional<PositionDTO> p1 = strategy.getPositionByPositionId(position1Uid);
assertTrue(p1.isPresent());
assertEquals(1, p1.get().getUid());
assertEquals(1, p1.get().getPositionId());
assertEquals(LONG, p1.get().getType());
assertNotNull(p1.get().getStrategy());
assertEquals(1, p1.get().getStrategy().getUid());
assertEquals("01", p1.get().getStrategy().getStrategyId());
assertEquals(ETH_BTC, p1.get().getCurrencyPair());
assertEquals(0, new BigDecimal("10").compareTo(p1.get().getAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency(), p1.get().getAmount().getCurrency());
assertTrue(p1.get().getRules().isStopGainPercentageSet());
assertEquals(1_000f, p1.get().getRules().getStopGainPercentage());
assertTrue(p1.get().getRules().isStopLossPercentageSet());
assertEquals(100f, p1.get().getRules().getStopLossPercentage());
assertEquals(OPENING, p1.get().getStatus());
assertEquals("ORDER00010", p1.get().getOpeningOrder().getOrderId());
assertEquals("ORDER00010", p1.get().getOpeningOrder().getOrderId());
assertTrue(p1.get().getOpeningOrder().getTrades().isEmpty());
assertNull(p1.get().getClosingOrder());
assertNull(p1.get().getLowestGainPrice());
assertNull(p1.get().getHighestGainPrice());
assertNull(p1.get().getLatestGainPrice());
// =============================================================================================================
// Creates long position n°2 - 0.0002 ETH bought with BTC.
// Position will be closed if 10 000% gain or 10 000% loss.
final PositionCreationResultDTO position2Result = strategy.createLongPosition(ETH_USDT, new BigDecimal("0.0002"), PositionRulesDTO.builder().stopGainPercentage(10_000f).stopLossPercentage(10_000f).build());
assertEquals("ORDER00020", position2Result.getPosition().getOpeningOrder().getOrderId());
long position2Id = position2Result.getPosition().getUid();
// onPositionStatusUpdate - Position 2 should arrive (OPENING).
// 1 position status update - The position is created with the OPENING status.
await().untilAsserted(() -> assertEquals(2, strategy.getPositionsStatusUpdatesCount()));
p = strategy.getLastPositionStatusUpdate();
assertNotNull(p);
assertEquals(position2Id, p.getUid());
assertEquals(OPENING, p.getStatus());
assertEquals("Long position n°2 of 0.0002 ETH (rules: 10000.0 % gain / 10000.0 % loss) - Opening - Waiting for the trades of order ORDER00020", p.getDescription());
// onPositionUpdate - Position 2 should arrive (OPENING).
// - Position created with a local order saved in database (Order with status PENDING_NEW).
// - Position updated with the local order retrieved from getOrders with status NEW.
await().untilAsserted(() -> assertEquals(4, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertNotNull(p);
assertEquals(position2Id, p.getUid());
assertEquals(OPENING, p.getStatus());
// Check data we have in strategy & database.
assertEquals(2, positionRepository.count());
assertEquals(2, strategy.getPositions().size());
Optional<PositionDTO> p2 = strategy.getPositionByPositionId(position2Id);
assertTrue(p2.isPresent());
assertEquals(2, p2.get().getUid());
assertEquals(2, p2.get().getPositionId());
assertEquals(LONG, p2.get().getType());
assertNotNull(p2.get().getStrategy());
assertEquals(1, p2.get().getStrategy().getUid());
assertEquals("01", p2.get().getStrategy().getStrategyId());
assertEquals(ETH_USDT, p2.get().getCurrencyPair());
assertEquals(0, new BigDecimal("0.0002").compareTo(p2.get().getAmount().getValue()));
assertEquals(ETH_USDT.getBaseCurrency(), p2.get().getAmount().getCurrency());
assertTrue(p2.get().getRules().isStopGainPercentageSet());
assertEquals(10_000f, p2.get().getRules().getStopGainPercentage());
assertTrue(p2.get().getRules().isStopLossPercentageSet());
assertEquals(10_000f, p2.get().getRules().getStopLossPercentage());
assertEquals(OPENING, p2.get().getStatus());
assertEquals("ORDER00020", p2.get().getOpeningOrder().getOrderId());
assertTrue(p2.get().getOpeningOrder().getTrades().isEmpty());
assertNull(p2.get().getClosingOrder());
assertNull(p2.get().getLowestGainPrice());
assertNull(p2.get().getHighestGainPrice());
assertNull(p2.get().getLatestGainPrice());
// =============================================================================================================
// Position n°1 is buying 10 ETH with BTC.
// Two trades arrives with 5 ETH each (so the two makes 10 ETH).
// 11 is before 1 to test the timestamp order of getOpenTrades & getCloseTrades.
// First trade.
tradeFlux.emitValue(TradeDTO.builder().tradeId("000011").type(BID).orderId("ORDER00010").currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("5", ETH_BTC.getBaseCurrency())).price(new CurrencyAmountDTO("0.02", ETH_BTC.getQuoteCurrency())).timestamp(createZonedDateTime("02-02-2020")).build());
// The same trade is emitted two times with an update (on timestamp).
tradeFlux.emitValue(TradeDTO.builder().tradeId("000011").orderId("ORDER00010").type(BID).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("5", ETH_BTC.getBaseCurrency())).price(new CurrencyAmountDTO("0.02", ETH_BTC.getQuoteCurrency())).timestamp(createZonedDateTime("03-02-2020")).build());
// Second trade.
tradeFlux.emitValue(TradeDTO.builder().tradeId("000001").orderId("ORDER00010").type(BID).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("5", ETH_BTC.getBaseCurrency())).price(new CurrencyAmountDTO("0.04", ETH_BTC.getQuoteCurrency())).timestamp(createZonedDateTime("01-01-2020")).build());
// The same trade is emitted two times with an update (on timestamp).
tradeFlux.emitValue(TradeDTO.builder().tradeId("000001").orderId("ORDER00010").type(BID).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("5", ETH_BTC.getBaseCurrency())).price(new CurrencyAmountDTO("0.04", ETH_BTC.getQuoteCurrency())).timestamp(createZonedDateTime("02-01-2020")).build());
// onPositionStatusUpdate - Position 1 should change to OPENED.
// With the two trades emitted, status should change to OPENED.
await().untilAsserted(() -> assertEquals(3, strategy.getPositionsStatusUpdatesCount()));
p = strategy.getLastPositionStatusUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(OPENED, p.getStatus());
assertEquals("Long position n°1 of 10 ETH (rules: 1000.0 % gain / 100.0 % loss) - Opened", p.getDescription());
// onPositionUpdate - 2 trades emitted 2 times so 4 updates (+4 already received for position opening).
// We were at 4 first.
// Trade 000011 arrives with 5 ETH.
// Trade 000011 arrives with timestamp updated.
// Trade 000001 arrives with 5 ETH.
// Trade 000001 arrives with timestamp updated.
// Now we have 8 updates.
await().untilAsserted(() -> assertEquals(8, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(OPENED, p.getStatus());
// Checking what we have in database.
assertEquals(2, strategy.getPositions().size());
p1 = strategy.getPositionByPositionId(position1Uid);
assertTrue(p1.isPresent());
assertEquals(1, p1.get().getUid());
assertEquals(1, p1.get().getPositionId());
assertEquals(LONG, p1.get().getType());
assertNotNull(p1.get().getStrategy());
assertEquals(1, p1.get().getStrategy().getUid());
assertEquals("01", p1.get().getStrategy().getStrategyId());
assertEquals(ETH_BTC, p1.get().getCurrencyPair());
assertEquals(0, new BigDecimal("10").compareTo(p1.get().getAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency(), p1.get().getAmount().getCurrency());
assertTrue(p1.get().getRules().isStopGainPercentageSet());
assertEquals(1_000f, p1.get().getRules().getStopGainPercentage());
assertTrue(p1.get().getRules().isStopLossPercentageSet());
assertEquals(100f, p1.get().getRules().getStopLossPercentage());
assertEquals(OPENED, p1.get().getStatus());
assertEquals("ORDER00010", p1.get().getOpeningOrder().getOrderId());
Iterator<TradeDTO> openingTradesIterator = p1.get().getOpeningOrder().getTrades().iterator();
assertEquals("000001", openingTradesIterator.next().getTradeId());
assertEquals("000011", openingTradesIterator.next().getTradeId());
assertNull(p1.get().getClosingOrder());
assertNull(p1.get().getLowestGainPrice());
assertNull(p1.get().getHighestGainPrice());
assertNull(p1.get().getLatestGainPrice());
// Check if we don't have duplicated trades in database !
assertEquals(2, tradeRepository.count());
Optional<Order> order00010 = orderRepository.findByOrderId("ORDER00010");
assertTrue(order00010.isPresent());
assertEquals(2, order00010.get().getTrades().size());
// =============================================================================================================
// Test of tickers updating position n°1.
// From the trades, we had:
// 000011 = 5 * 0.02
// 000001 = 5 * 0.04
// so the price is 0.03.
// First ticker arrives (500% gain) - min, max and last gain should be set to that value.
// Price update so a new position update.
tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_BTC).last(new BigDecimal("0.18")).build());
await().untilAsserted(() -> assertEquals(9, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertEquals(position1Uid, p.getUid());
assertEquals(0, new BigDecimal("0.18").compareTo(p.getLowestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.18").compareTo(p.getHighestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.18").compareTo(p.getLatestGainPrice().getValue()));
assertEquals("Long position n°1 of 10 ETH (rules: 1000.0 % gain / 100.0 % loss) - Opened - Last gain calculated 500 %", p.getDescription());
// We check the gain.
Optional<GainDTO> latestCalculatedGain = p.getLatestCalculatedGain();
assertTrue(latestCalculatedGain.isPresent());
assertEquals(500, latestCalculatedGain.get().getPercentage());
assertEquals(0, new BigDecimal("1.5").compareTo(latestCalculatedGain.get().getAmount().getValue()));
assertEquals(BTC, latestCalculatedGain.get().getAmount().getCurrency());
// Second ticker arrives (100% gain) - min and last gain should be set to that value.
// Price update so a new position update.
tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_BTC).last(new BigDecimal("0.06")).build());
await().untilAsserted(() -> assertEquals(10, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertEquals(position1Uid, p.getUid());
assertEquals(0, new BigDecimal("0.06").compareTo(p.getLowestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.18").compareTo(p.getHighestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.06").compareTo(p.getLatestGainPrice().getValue()));
// We check the gain.
latestCalculatedGain = p.getLatestCalculatedGain();
assertTrue(latestCalculatedGain.isPresent());
assertEquals(100, latestCalculatedGain.get().getPercentage());
assertEquals(0, new BigDecimal("0.3").compareTo(latestCalculatedGain.get().getAmount().getValue()));
assertEquals(BTC, latestCalculatedGain.get().getAmount().getCurrency());
// Third ticker arrives (200% gain) - only last should change.
// Price update so a new position update.
tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_BTC).last(new BigDecimal("0.09")).build());
await().untilAsserted(() -> assertEquals(11, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertEquals(position1Uid, p.getUid());
assertEquals(0, new BigDecimal("0.06").compareTo(p.getLowestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.18").compareTo(p.getHighestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.09").compareTo(p.getLatestGainPrice().getValue()));
// Fourth ticker arrives (50% loss) - min and last gain should be set to that value.
// Price update so a new position update.
tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_BTC).last(new BigDecimal("0.015")).build());
await().untilAsserted(() -> assertEquals(12, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertEquals(position1Uid, p.getUid());
assertEquals(0, new BigDecimal("0.015").compareTo(p.getLowestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.18").compareTo(p.getHighestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.015").compareTo(p.getLatestGainPrice().getValue()));
// A ticker arrive for another cp. Nothing should change.
// And no position update.
tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_USDT).last(new BigDecimal("100")).build());
// Fifth ticker arrives (600% gain) - max and last gain should be set to that value.
// Price update so a new position update.
tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_BTC).last(new BigDecimal("0.21")).build());
await().untilAsserted(() -> assertEquals(13, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertEquals(position1Uid, p.getUid());
assertEquals(0, new BigDecimal("0.015").compareTo(p.getLowestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.21").compareTo(p.getHighestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.21").compareTo(p.getLatestGainPrice().getValue()));
// Checking what we have in database.
assertEquals(2, strategy.getPositions().size());
p1 = strategy.getPositionByPositionId(position1Uid);
assertTrue(p1.isPresent());
assertEquals(1, p1.get().getUid());
assertEquals(1, p1.get().getPositionId());
assertEquals(LONG, p1.get().getType());
assertNotNull(p1.get().getStrategy());
assertEquals(1, p1.get().getStrategy().getUid());
assertEquals("01", p1.get().getStrategy().getStrategyId());
assertEquals(ETH_BTC, p1.get().getCurrencyPair());
assertEquals(0, new BigDecimal("10").compareTo(p1.get().getAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency(), p1.get().getAmount().getCurrency());
assertTrue(p1.get().getRules().isStopGainPercentageSet());
assertEquals(1_000f, p1.get().getRules().getStopGainPercentage());
assertTrue(p1.get().getRules().isStopLossPercentageSet());
assertEquals(100f, p1.get().getRules().getStopLossPercentage());
assertEquals(OPENED, p1.get().getStatus());
assertEquals("ORDER00010", p1.get().getOpeningOrder().getOrderId());
openingTradesIterator = p1.get().getOpeningOrder().getTrades().iterator();
assertEquals("000001", openingTradesIterator.next().getTradeId());
assertEquals("000011", openingTradesIterator.next().getTradeId());
assertNull(p1.get().getClosingOrder());
assertEquals(0, new BigDecimal("0.015").compareTo(p1.get().getLowestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.21").compareTo(p1.get().getHighestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.21").compareTo(p1.get().getLatestGainPrice().getValue()));
// =============================================================================================================
// Trade arrives for position 2 - should now be OPENED
tradeFlux.emitValue(TradeDTO.builder().tradeId("000002").type(BID).orderId("ORDER00020").currencyPair(ETH_USDT).amount(new CurrencyAmountDTO("0.0002", ETH_USDT.getBaseCurrency())).price(new CurrencyAmountDTO("0.03", ETH_USDT.getQuoteCurrency())).build());
// onPositionStatusUpdate - Position 2 should be opened.
// - Update 1 : position n°1 OPENING.
// - Update 2 : position n°2 OPENING.
// - Update 3 : position n°1 OPENED.
// - Update 4 : position n°2 OPENED.
await().untilAsserted(() -> assertEquals(4, strategy.getPositionsStatusUpdatesCount()));
p = strategy.getLastPositionStatusUpdate();
assertNotNull(p);
assertEquals(position2Id, p.getUid());
assertEquals(OPENED, p.getStatus());
assertEquals("Long position n°2 of 0.0002 ETH (rules: 10000.0 % gain / 10000.0 % loss) - Opened", p.getDescription());
// onPositionUpdate.
// One trade arrives, so we have a position update because of this trade.
await().untilAsserted(() -> assertEquals(14, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertNotNull(p);
assertEquals(position2Id, p.getUid());
assertEquals(OPENED, p.getStatus());
// Checking what we have in database.
assertEquals(2, strategy.getPositions().size());
p2 = strategy.getPositionByPositionId(position2Id);
assertTrue(p2.isPresent());
assertEquals(2, p2.get().getUid());
assertEquals(2, p2.get().getPositionId());
assertEquals(LONG, p2.get().getType());
assertNotNull(p2.get().getStrategy());
assertEquals(1, p2.get().getStrategy().getUid());
assertEquals("01", p2.get().getStrategy().getStrategyId());
assertEquals(ETH_USDT, p2.get().getCurrencyPair());
assertEquals(0, new BigDecimal("0.0002").compareTo(p2.get().getAmount().getValue()));
assertEquals(ETH_USDT.getBaseCurrency(), p2.get().getAmount().getCurrency());
assertTrue(p2.get().getRules().isStopGainPercentageSet());
assertEquals(10_000f, p2.get().getRules().getStopGainPercentage());
assertTrue(p2.get().getRules().isStopLossPercentageSet());
assertEquals(10_000f, p2.get().getRules().getStopLossPercentage());
assertEquals(OPENED, p2.get().getStatus());
assertEquals("ORDER00020", p2.get().getOpeningOrder().getOrderId());
openingTradesIterator = p2.get().getOpeningOrder().getTrades().iterator();
assertEquals("000002", openingTradesIterator.next().getTradeId());
assertNull(p2.get().getClosingOrder());
assertNull(p2.get().getLowestGainPrice());
assertNull(p2.get().getHighestGainPrice());
assertNull(p2.get().getLatestGainPrice());
// =============================================================================================================
// A ticker arrives that triggers max gain rules of position 1 - should now be CLOSING.
// From the trades, we had:
// 000011 = 5 * 0.02
// 000001 = 5 * 0.04
// The mean price is 0.03 BTC, and we now receive a new price of 100.
tickerFlux.emitValue(TickerDTO.builder().currencyPair(ETH_BTC).last(new BigDecimal("100")).build());
// onPositionStatusUpdate - Position 1 should be closing.
// - Update 1 : position n°1 OPENING.
// - Update 2 : position n°2 OPENING.
// - Update 3 : position n°1 OPENED.
// - Update 4 : position n°2 OPENED.
// - Update 5 : position n°1 CLOSING.
await().untilAsserted(() -> assertEquals(5, strategy.getPositionsStatusUpdatesCount()));
p = strategy.getLastPositionStatusUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(CLOSING, p.getStatus());
assertEquals("Long position n°1 of 10 ETH (rules: 1000.0 % gain / 100.0 % loss) - Closing - Waiting for the trades of order ORDER00011", p.getDescription());
// OnPositionUpdate - We were having 14 updates.
// - A ticker triggering position closure arrives.
// - Position closed with the local order (status PENDING_NEW).
// - Position updated with the distant order (status NEW).
await().untilAsserted(() -> assertEquals(17, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(CLOSING, p.getStatus());
// Checking what we have in database.
assertEquals(2, strategy.getPositions().size());
p1 = strategy.getPositionByPositionId(position1Uid);
assertTrue(p1.isPresent());
assertEquals(1, p1.get().getUid());
assertEquals(1, p1.get().getPositionId());
assertEquals(LONG, p1.get().getType());
assertNotNull(p1.get().getStrategy());
assertEquals(1, p1.get().getStrategy().getUid());
assertEquals("01", p1.get().getStrategy().getStrategyId());
assertEquals(ETH_BTC, p1.get().getCurrencyPair());
assertEquals(0, new BigDecimal("10").compareTo(p1.get().getAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency(), p1.get().getAmount().getCurrency());
assertTrue(p1.get().getRules().isStopGainPercentageSet());
assertEquals(1_000f, p1.get().getRules().getStopGainPercentage());
assertTrue(p1.get().getRules().isStopLossPercentageSet());
assertEquals(100f, p1.get().getRules().getStopLossPercentage());
assertEquals(CLOSING, p1.get().getStatus());
assertEquals("ORDER00010", p1.get().getOpeningOrder().getOrderId());
openingTradesIterator = p1.get().getOpeningOrder().getTrades().iterator();
assertEquals("000001", openingTradesIterator.next().getTradeId());
assertEquals("000011", openingTradesIterator.next().getTradeId());
assertEquals("ORDER00011", p1.get().getClosingOrder().getOrderId());
assertTrue(p1.get().getClosingOrder().getTrades().isEmpty());
assertEquals(0, new BigDecimal("0.015").compareTo(p1.get().getLowestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.21").compareTo(p1.get().getHighestGainPrice().getValue()));
assertEquals(0, new BigDecimal("100").compareTo(p1.get().getLatestGainPrice().getValue()));
// =============================================================================================================
// Position 1 will move to CLOSED status when the trades arrive.
// The first close trade arrives but the amount is not enough.
tradeFlux.emitValue(TradeDTO.builder().tradeId("000003").orderId("ORDER00011").type(ASK).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("5", ETH_BTC.getBaseCurrency())).price(new CurrencyAmountDTO("1", ETH_BTC.getQuoteCurrency())).timestamp(createZonedDateTime("01-01-2020")).build());
// We send a duplicated value.
tradeFlux.emitValue(TradeDTO.builder().tradeId("000003").orderId("ORDER00011").type(ASK).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("5", ETH_BTC.getBaseCurrency())).price(new CurrencyAmountDTO("1", ETH_BTC.getQuoteCurrency())).timestamp(createZonedDateTime("01-01-2020")).build());
// onPosition for first trade arrival.
// Two new updates : the two trades received (even if they were the same as we use emit method).
await().untilAsserted(() -> assertEquals(19, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(CLOSING, p.getStatus());
// The second close trade arrives now closed.
tradeFlux.emitValue(TradeDTO.builder().tradeId("000004").orderId("ORDER00011").type(ASK).currencyPair(ETH_BTC).amount(new CurrencyAmountDTO("5", ETH_BTC.getBaseCurrency())).price(new CurrencyAmountDTO("1", ETH_BTC.getQuoteCurrency())).timestamp(createZonedDateTime("02-01-2020")).build());
// onPositionStatusUpdate - Position should be closed.
// - Update 1 : position n°1 OPENING.
// - Update 2 : position n°2 OPENING.
// - Update 3 : position n°1 OPENED.
// - Update 4 : position n°2 OPENED.
// - Update 5 : position n°1 CLOSING.
// - Update 6 : position n°1 CLOSED.
await().untilAsserted(() -> assertEquals(6, strategy.getPositionsStatusUpdatesCount()));
p = strategy.getLastPositionStatusUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(CLOSED, p.getStatus());
assertEquals("Long position n°1 of 10 ETH (rules: 1000.0 % gain / 100.0 % loss) - Closed - Gains: 9.7 BTC (3233.33 %)", p.getDescription());
// onPositionUpdate.
// - Trade 000004 arrives.
await().untilAsserted(() -> assertEquals(20, strategy.getPositionsUpdatesCount()));
p = strategy.getLastPositionUpdate();
assertNotNull(p);
assertEquals(position1Uid, p.getUid());
assertEquals(CLOSED, p.getStatus());
// Checking what we have in database.
assertEquals(2, strategy.getPositions().size());
p1 = strategy.getPositionByPositionId(position1Uid);
assertTrue(p1.isPresent());
assertEquals(1, p1.get().getUid());
assertEquals(1, p1.get().getPositionId());
assertEquals(LONG, p1.get().getType());
assertNotNull(p1.get().getStrategy());
assertEquals(1, p1.get().getStrategy().getUid());
assertEquals("01", p1.get().getStrategy().getStrategyId());
assertEquals(ETH_BTC, p1.get().getCurrencyPair());
assertEquals(0, new BigDecimal("10").compareTo(p1.get().getAmount().getValue()));
assertEquals(ETH_BTC.getBaseCurrency(), p1.get().getAmount().getCurrency());
assertTrue(p1.get().getRules().isStopGainPercentageSet());
assertEquals(1_000f, p1.get().getRules().getStopGainPercentage());
assertTrue(p1.get().getRules().isStopLossPercentageSet());
assertEquals(100f, p1.get().getRules().getStopLossPercentage());
assertEquals(CLOSED, p1.get().getStatus());
assertEquals("ORDER00010", p1.get().getOpeningOrder().getOrderId());
openingTradesIterator = p1.get().getOpeningOrder().getTrades().iterator();
assertEquals("000001", openingTradesIterator.next().getTradeId());
assertEquals("000011", openingTradesIterator.next().getTradeId());
assertEquals("ORDER00011", p1.get().getClosingOrder().getOrderId());
final Iterator<TradeDTO> closingTradesIterator = p1.get().getClosingOrder().getTrades().iterator();
assertEquals("000003", closingTradesIterator.next().getTradeId());
assertEquals("000004", closingTradesIterator.next().getTradeId());
assertEquals(0, new BigDecimal("0.015").compareTo(p1.get().getLowestGainPrice().getValue()));
assertEquals(0, new BigDecimal("0.21").compareTo(p1.get().getHighestGainPrice().getValue()));
assertEquals(0, new BigDecimal("100").compareTo(p1.get().getLatestGainPrice().getValue()));
// Just checking trades creation.
assertNotNull(strategy.getPositionByPositionId(position1Uid));
assertNotNull(strategy.getPositionByPositionId(position2Id));
assertEquals(5, strategy.getTrades().size());
// Check if we don't have duplicated trades in database !
assertEquals(5, tradeRepository.count());
order00010 = orderRepository.findByOrderId("ORDER00010");
assertTrue(order00010.isPresent());
assertEquals(2, order00010.get().getTrades().size());
final Optional<Order> order00011 = orderRepository.findByOrderId("ORDER00011");
assertTrue(order00011.isPresent());
assertEquals(2, order00011.get().getTrades().size());
}
Aggregations