use of java.math.RoundingMode.FLOOR in project cassandre-trading-bot by cassandre-tech.
the class TradeServiceDryModeAOP method getTradeHistory.
@Around(value = "execution(* org.knowm.xchange.service.trade.TradeService.getTradeHistory(..)) && args(params))", argNames = "pjp, params")
public final UserTrades getTradeHistory(final ProceedingJoinPoint pjp, final TradeHistoryParams params) {
// We will check for every order not fulfilled, if this order is used to close a position.
// If so, we change the price of the trade to the price of the trade according to the position price.
Map<String, BigDecimal> tradePrices = new HashMap<>();
orderRepository.findByOrderByTimestampAsc().stream().filter(order -> order.getStatus() == OrderStatusDTO.FILLED).map(ORDER_MAPPER::mapToOrderDTO).filter(// Only orders with trades not arrived
orderDTO -> !orderDTO.isFulfilled()).forEach(orderDTO -> {
tradePrices.put(orderDTO.getOrderId(), orderDTO.getMarketPriceValue());
// We search to see if the order is used to close a position.
final Optional<PositionDTO> positionDTO = positionRepository.findAll().stream().filter(position -> position.getClosingOrder() != null).filter(position -> position.getClosingOrder().getOrderId().equals(orderDTO.getOrderId())).map(POSITION_MAPPER::mapToPositionDTO).findFirst();
// A gain was made, we recalculate it from the order.
if (positionDTO.isPresent()) {
final Optional<GainDTO> gainDTO = positionDTO.get().calculateGainFromPrice(orderDTO.getMarketPriceValue());
if (gainDTO.isPresent()) {
// We need the trade of the opening order to know the price the asset was bought.
final TradeDTO openingTrade = positionDTO.get().getOpeningOrder().getTrades().iterator().next();
if (positionDTO.get().getType().equals(LONG)) {
if (positionDTO.get().getRules().isStopGainPercentageSet() && gainDTO.get().getPercentage() >= 0) {
// If the position has a stop gain percentage and the real gain is superior to this percentage.
// This means the stop gain won, and we should transform the price.
// Long position n°1 (rules: 200.0 % gain).
// Opening order: 20 000 USDT.
// Closed with trade DRY_TRADE_000000007: 70 000 USDT.
// 250 % evolution => ((70000 - 20000) / 20000) * 100 = 250 %
// How to calculate the new price.
// openingTrade market price * (( openingTrade market price * rules gain)/100)
final BigDecimal augmentation = positionDTO.get().getOpeningOrder().getMarketPriceValue().multiply(BigDecimal.valueOf(positionDTO.get().getRules().getStopGainPercentage())).divide(ONE_HUNDRED_BIG_DECIMAL, BIGINTEGER_SCALE, FLOOR);
tradePrices.put(orderDTO.getOrderId(), openingTrade.getPriceValue().add(augmentation));
} else if (positionDTO.get().getRules().isStopLossPercentageSet() && gainDTO.get().getPercentage() < 0) {
// If the position has a stop gain percentage and the real gain is superior to this percentage.
// This means the stop gain won, and we should transform the price.
// Long position n°2 (rules: 20.0 % loss).
// Opening order: 50 000 USDT.
// Closed with trade DRY_TRADE_000000004: 30 000 USDT.
// -40 % evolution => ((30000 - 50000) / 50000) * 100 = -40 %
// How to calculate the new price.
// openingTrade market price * (( openingTrade market price * rules gain)/100)
final BigDecimal reduction = positionDTO.get().getOpeningOrder().getMarketPriceValue().multiply(BigDecimal.valueOf(positionDTO.get().getRules().getStopLossPercentage())).divide(ONE_HUNDRED_BIG_DECIMAL, BIGINTEGER_SCALE, FLOOR);
tradePrices.put(orderDTO.getOrderId(), openingTrade.getPriceValue().subtract(reduction));
}
// =====================================================================================
} else {
if (positionDTO.get().getRules().isStopGainPercentageSet() && gainDTO.get().getPercentage() >= 0) {
// If the position has a stop gain percentage and the real gain is superior to this percentage.
// This means the stop gain won, and we should transform the price.
// Short position n°4 (rules: 100.0 % gain)
// Opening order: 70 000 USDT.
// Closed with DRY_TRADE_000000009: 25 000 USDT.
// It's a shot position so:
// We sold one bitcoin for 70 000 USDT.
// When the price reached 25 000 USDT, with the 70 000 USDT, we could buy 2.8 BTC.
// 180 % evolution => ((2.8 - 1) / 1) * 100 = 180 %
// How to calculate the new price.
// Amount I gained = opening trade amount * 70 000 USDT.
// To gain 100%, I should be able to by 2 bitcoins: opening trade amount * (opening trade amount * stop gain/100)
// so the question is how much a bitcoin should cost, so I can buy 2 with 70 000 USDT
// 2 * price = 70 000 USDT => price = 70 000/2 = 35 000
final BigDecimal augmentation = openingTrade.getAmountValue().multiply(BigDecimal.valueOf(positionDTO.get().getRules().getStopGainPercentage())).divide(ONE_HUNDRED_BIG_DECIMAL, BIGINTEGER_SCALE, FLOOR);
orderRepository.updateAmount(orderDTO.getUid(), openingTrade.getAmountValue().add(augmentation));
tradePrices.put(orderDTO.getOrderId(), positionDTO.get().getOpeningOrder().getMarketPriceValue().divide(openingTrade.getAmountValue().add(augmentation), BIGINTEGER_SCALE, FLOOR));
} else if (positionDTO.get().getRules().isStopLossPercentageSet() && gainDTO.get().getPercentage() < 0) {
// If the position has a stop gain percentage and the real gain is superior to this percentage.
// This means the stop gain won, and we should transform the price.
// Short position n°3 (rules: 10.0 % loss)
// Opening order: 40 000 USDT.
// Closed with trade DRY_TRADE_000000008: 70 000 USDT.
// It's a shot position so:
// We sold 1 bitcoin for 40 000 USDT.
// When the price reached 70 000 USDT, with the 40 000 USDT, we could buy 0.57 BTC.
// We had 1 BTC, we now only have 0.57 BTC
// -43 % evolution => ((0.57 - 1) / 1) * 100 = -43 %
// How to calculate the new price.
// Amount I gained = opening trade amount * 40 000 USDT.
// To lose 10%, I should finish by only being able to buy 0,90 BTC: opening trade amount * (opening trade amount * stop gain/100)
// so the question is how much a bitcoin should cost, so I can buy 0,90 with 40 000 USDT
// 0.9 * price = 40 000 USDT => price = 40 000/0.9
final BigDecimal reduction = openingTrade.getAmountValue().multiply(BigDecimal.valueOf(positionDTO.get().getRules().getStopLossPercentage())).divide(ONE_HUNDRED_BIG_DECIMAL, BIGINTEGER_SCALE, FLOOR);
orderRepository.updateAmount(orderDTO.getUid(), openingTrade.getAmountValue().subtract(reduction));
tradePrices.put(orderDTO.getOrderId(), positionDTO.get().getOpeningOrder().getMarketPriceValue().divide(openingTrade.getAmountValue().subtract(reduction), BIGINTEGER_SCALE, FLOOR));
}
// =====================================================================================
}
}
}
});
// For every orders not fulfilled in database, we will simulate an equivalent trade to close it.
List<UserTrade> trades = orderRepository.findByOrderByTimestampAsc().stream().map(ORDER_MAPPER::mapToOrderDTO).filter(// Only orders without trade.
orderDTO -> !orderDTO.isFulfilled()).filter(// Only orders with price calculated.
orderDTO -> tradePrices.get(orderDTO.getOrderId()) != null).map(orderDTO -> UserTrade.builder().id(orderDTO.getOrderId().replace(DRY_ORDER_PREFIX, DRY_TRADE_PREFIX)).type(UTIL_MAPPER.mapToOrderType(orderDTO.getType())).orderId(orderDTO.getOrderId()).currencyPair(CURRENCY_MAPPER.mapToCurrencyPair(orderDTO.getCurrencyPair())).originalAmount(orderDTO.getAmountValue()).price(tradePrices.get(orderDTO.getOrderId())).feeAmount(ZERO).timestamp(Timestamp.valueOf(orderDTO.getTimestamp().toLocalDateTime())).build()).toList();
return new UserTrades(trades, SortByTimestamp);
}
Aggregations