Search in sources :

Example 1 with FLOOR

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);
}
Also used : TradeHistoryParams(org.knowm.xchange.service.trade.params.TradeHistoryParams) RequiredArgsConstructor(lombok.RequiredArgsConstructor) HashMap(java.util.HashMap) LONG(tech.cassandre.trading.bot.dto.position.PositionTypeDTO.LONG) BigDecimal(java.math.BigDecimal) ConditionalOnExpression(org.springframework.boot.autoconfigure.condition.ConditionalOnExpression) OrderStatusDTO(tech.cassandre.trading.bot.dto.trade.OrderStatusDTO) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Aspect(org.aspectj.lang.annotation.Aspect) Map(java.util.Map) CurrencyPairDTO(tech.cassandre.trading.bot.dto.util.CurrencyPairDTO) OpenOrders(org.knowm.xchange.dto.trade.OpenOrders) FLOOR(java.math.RoundingMode.FLOOR) CLOSED(tech.cassandre.trading.bot.dto.trade.OrderStatusDTO.CLOSED) PositionDTO(tech.cassandre.trading.bot.dto.position.PositionDTO) LimitOrder(org.knowm.xchange.dto.trade.LimitOrder) BIGINTEGER_SCALE(tech.cassandre.trading.bot.util.math.MathConstants.BIGINTEGER_SCALE) AccountDTO(tech.cassandre.trading.bot.dto.user.AccountDTO) CassandreStrategy(tech.cassandre.trading.bot.strategy.internal.CassandreStrategy) PositionRepository(tech.cassandre.trading.bot.repository.PositionRepository) Timestamp(java.sql.Timestamp) GainDTO(tech.cassandre.trading.bot.dto.util.GainDTO) ZERO(java.math.BigDecimal.ZERO) UserTrades(org.knowm.xchange.dto.trade.UserTrades) UserTrade(org.knowm.xchange.dto.trade.UserTrade) TradeDTO(tech.cassandre.trading.bot.dto.trade.TradeDTO) Around(org.aspectj.lang.annotation.Around) FILLED(org.knowm.xchange.dto.Order.OrderStatus.FILLED) Component(org.springframework.stereotype.Component) List(java.util.List) OrderRepository(tech.cassandre.trading.bot.repository.OrderRepository) BaseService(tech.cassandre.trading.bot.util.base.service.BaseService) SortByTimestamp(org.knowm.xchange.dto.marketdata.Trades.TradeSortType.SortByTimestamp) BalanceDTO(tech.cassandre.trading.bot.dto.user.BalanceDTO) ONE_HUNDRED_BIG_DECIMAL(tech.cassandre.trading.bot.util.math.MathConstants.ONE_HUNDRED_BIG_DECIMAL) MarketOrder(org.knowm.xchange.dto.trade.MarketOrder) OrderCreationResultDTO(tech.cassandre.trading.bot.dto.trade.OrderCreationResultDTO) DryModeException(tech.cassandre.trading.bot.util.exception.DryModeException) Optional(java.util.Optional) TickerDTO(tech.cassandre.trading.bot.dto.market.TickerDTO) ProceedingJoinPoint(org.aspectj.lang.ProceedingJoinPoint) TradeDTO(tech.cassandre.trading.bot.dto.trade.TradeDTO) HashMap(java.util.HashMap) UserTrade(org.knowm.xchange.dto.trade.UserTrade) BigDecimal(java.math.BigDecimal) PositionDTO(tech.cassandre.trading.bot.dto.position.PositionDTO) UserTrades(org.knowm.xchange.dto.trade.UserTrades) GainDTO(tech.cassandre.trading.bot.dto.util.GainDTO) Around(org.aspectj.lang.annotation.Around)

Aggregations

BigDecimal (java.math.BigDecimal)1 ZERO (java.math.BigDecimal.ZERO)1 FLOOR (java.math.RoundingMode.FLOOR)1 Timestamp (java.sql.Timestamp)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 Optional (java.util.Optional)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 RequiredArgsConstructor (lombok.RequiredArgsConstructor)1 ProceedingJoinPoint (org.aspectj.lang.ProceedingJoinPoint)1 Around (org.aspectj.lang.annotation.Around)1 Aspect (org.aspectj.lang.annotation.Aspect)1 FILLED (org.knowm.xchange.dto.Order.OrderStatus.FILLED)1 SortByTimestamp (org.knowm.xchange.dto.marketdata.Trades.TradeSortType.SortByTimestamp)1 LimitOrder (org.knowm.xchange.dto.trade.LimitOrder)1 MarketOrder (org.knowm.xchange.dto.trade.MarketOrder)1 OpenOrders (org.knowm.xchange.dto.trade.OpenOrders)1 UserTrade (org.knowm.xchange.dto.trade.UserTrade)1 UserTrades (org.knowm.xchange.dto.trade.UserTrades)1