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());
}
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();
}
Aggregations