Search in sources :

Example 1 with StrategyDTO

use of tech.cassandre.trading.bot.dto.strategy.StrategyDTO 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 StrategyDTO

use of tech.cassandre.trading.bot.dto.strategy.StrategyDTO in project cassandre-trading-bot by cassandre-tech.

the class StrategiesAutoConfiguration method configure.

/**
 * Search for strategies and runs them.
 */
@PostConstruct
@SuppressWarnings("checkstyle:MethodLength")
public void configure() {
    // Retrieving all the beans have the @Strategy annotation.
    final Map<String, Object> strategies = applicationContext.getBeansWithAnnotation(CassandreStrategy.class);
    // =============================================================================================================
    // Configuration check.
    // We run tests to display and check if everything is ok with the configuration.
    final UserDTO user = checkConfiguration(strategies);
    // =============================================================================================================
    // Maintenance code.
    // If a position is blocked in OPENING or CLOSING, we send again the trades.
    // This could happen if cassandre crashes after saving a trade and did not have time to send it to
    // positionService. Here we force the status recalculation in PositionDTO, and we save it.
    positionRepository.findByStatusIn(Stream.of(OPENING, CLOSING).toList()).stream().map(POSITION_MAPPER::mapToPositionDTO).map(POSITION_MAPPER::mapToPosition).forEach(positionRepository::save);
    // =============================================================================================================
    // Importing tickers & candles into database.
    // Feature documentation is here: https://trading-bot.cassandre.tech/learn/import-historical-data.html
    loadTickersFromFiles();
    loadCandlesFromFiles();
    // =============================================================================================================
    // Creating flux.
    final ConnectableFlux<Set<AccountDTO>> connectableAccountFlux = accountFlux.getFlux().publish();
    final ConnectableFlux<Set<PositionDTO>> connectablePositionFlux = positionFlux.getFlux().publish();
    final ConnectableFlux<Set<OrderDTO>> connectableOrderFlux = orderFlux.getFlux().publish();
    final ConnectableFlux<Set<TickerDTO>> connectableTickerFlux = tickerFlux.getFlux().publish();
    final ConnectableFlux<Set<TradeDTO>> connectableTradeFlux = tradeFlux.getFlux().publish();
    // =============================================================================================================
    // Configuring strategies.
    // Data in database, services, flux...
    logger.info("Running the following strategies:");
    strategies.values().forEach(s -> {
        CassandreStrategyInterface strategy = (CassandreStrategyInterface) s;
        CassandreStrategy annotation = s.getClass().getAnnotation(CassandreStrategy.class);
        // Retrieving strategy information from annotation.
        final String strategyId = annotation.strategyId();
        final String strategyName = annotation.strategyName();
        // Displaying information about strategy.
        logger.info("- Strategy '{}/{}' (requires {})", strategyId, strategyName, strategy.getRequestedCurrencyPairs().stream().map(CurrencyPairDTO::toString).collect(Collectors.joining(", ")));
        // StrategyDTO: saving or updating the strategy in database.
        StrategyDTO strategyDTO;
        final Optional<Strategy> strategyInDatabase = strategyRepository.findByStrategyId(annotation.strategyId());
        if (strategyInDatabase.isEmpty()) {
            // =============================================================================================
            // If the strategy is NOT in database.
            Strategy newStrategy = new Strategy();
            newStrategy.setStrategyId(annotation.strategyId());
            newStrategy.setName(annotation.strategyName());
            strategyDTO = STRATEGY_MAPPER.mapToStrategyDTO(strategyRepository.save(newStrategy));
            logger.debug("Strategy created in database: {}", newStrategy);
        } else {
            // =============================================================================================
            // If the strategy is in database.
            strategyInDatabase.get().setName(strategyName);
            strategyDTO = STRATEGY_MAPPER.mapToStrategyDTO(strategyRepository.save(strategyInDatabase.get()));
            logger.debug("Strategy updated in database: {}", strategyInDatabase.get());
        }
        strategyDTO.initializeLastPositionIdUsed(positionRepository.getLastPositionIdUsedByStrategy(strategyDTO.getUid()));
        // Setting up configuration, dependencies and accounts in strategy.
        strategy.initializeAccounts(user.getAccounts());
        strategy.setConfiguration(getCassandreStrategyConfiguration(strategyDTO));
        strategy.setDependencies(getCassandreStrategyDependencies());
        // Calling user defined initialize() method.
        strategy.initialize();
        // Connecting flux to strategy.
        connectableAccountFlux.subscribe(strategy::accountsUpdates, throwable -> logger.error("AccountsUpdates failing: {}", throwable.getMessage()));
        connectablePositionFlux.subscribe(strategy::positionsUpdates, throwable -> logger.error("PositionsUpdates failing: {}", throwable.getMessage()));
        connectableOrderFlux.subscribe(strategy::ordersUpdates, throwable -> logger.error("OrdersUpdates failing: {}", throwable.getMessage()));
        connectableTradeFlux.subscribe(strategy::tradesUpdates, throwable -> logger.error("TradesUpdates failing: {}", throwable.getMessage()));
        connectableTickerFlux.subscribe(strategy::tickersUpdates, throwable -> logger.error("TickersUpdates failing: {}", throwable.getMessage()));
    });
    // =============================================================================================================
    // Starting flux.
    connectableAccountFlux.connect();
    connectablePositionFlux.connect();
    connectableOrderFlux.connect();
    connectableTradeFlux.connect();
    connectableTickerFlux.connect();
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) CassandreStrategy(tech.cassandre.trading.bot.strategy.CassandreStrategy) StrategyDTO(tech.cassandre.trading.bot.dto.strategy.StrategyDTO) UserDTO(tech.cassandre.trading.bot.dto.user.UserDTO) CassandreStrategyInterface(tech.cassandre.trading.bot.strategy.internal.CassandreStrategyInterface) CurrencyPairDTO(tech.cassandre.trading.bot.dto.util.CurrencyPairDTO) CassandreStrategy(tech.cassandre.trading.bot.strategy.CassandreStrategy) Strategy(tech.cassandre.trading.bot.domain.Strategy) PostConstruct(javax.annotation.PostConstruct)

Aggregations

StrategyDTO (tech.cassandre.trading.bot.dto.strategy.StrategyDTO)2 BigDecimal (java.math.BigDecimal)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 PostConstruct (javax.annotation.PostConstruct)1 DisplayName (org.junit.jupiter.api.DisplayName)1 Test (org.junit.jupiter.api.Test)1 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)1 Order (tech.cassandre.trading.bot.domain.Order)1 Strategy (tech.cassandre.trading.bot.domain.Strategy)1 Trade (tech.cassandre.trading.bot.domain.Trade)1 UserDTO (tech.cassandre.trading.bot.dto.user.UserDTO)1 CurrencyAmountDTO (tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO)1 CurrencyPairDTO (tech.cassandre.trading.bot.dto.util.CurrencyPairDTO)1 CassandreStrategy (tech.cassandre.trading.bot.strategy.CassandreStrategy)1 CassandreStrategyInterface (tech.cassandre.trading.bot.strategy.internal.CassandreStrategyInterface)1 BaseTest (tech.cassandre.trading.bot.test.util.junit.BaseTest)1