Search in sources :

Example 1 with CassandreStrategyInterface

use of tech.cassandre.trading.bot.strategy.internal.CassandreStrategyInterface in project cassandre-trading-bot by cassandre-tech.

the class UserServiceDryModeAOP method addToBalance.

/**
 * Update balance of trade account (method called by trade service).
 *
 * @param strategy strategy
 * @param currency currency
 * @param amount   amount
 */
public void addToBalance(final CassandreStrategy strategy, final Currency currency, final BigDecimal amount) {
    final Optional<AccountDTO> tradeAccount = strategy.getTradeAccount();
    if (tradeAccount.isEmpty()) {
        logger.error("Trading account not found!");
    } else {
        // We build a new account information from what we saved.
        Collection<Wallet> wallets = new LinkedHashSet<>();
        // We retreat all the wallets we have.
        accountInfo.getWallets().forEach((name, wallet) -> {
            HashMap<Currency, Balance> balances = new LinkedHashMap<>();
            // For each balance, we add it if nothing changed or, if on trading account, and we need to change the amount,
            // Then we do it.
            wallet.getBalances().forEach((balanceCurrency, balance) -> {
                if (name.equals(tradeAccount.get().getName()) && balanceCurrency.equals(currency)) {
                    // If we are on the account and currency to update, we calculate the new value.
                    balances.put(balanceCurrency, new Balance(balanceCurrency, balance.getTotal().add(amount)));
                } else {
                    // Else we keep the same value.
                    balances.put(balanceCurrency, balance);
                }
            });
            // amounts, then we create a new balance.
            if (name.equals(tradeAccount.get().getName()) && balances.get(currency) == null) {
                balances.put(currency, new Balance(currency, amount));
            }
            // We add the wallet.
            wallets.add(new Wallet(name, name, balances.values(), Collections.emptySet(), ZERO, ZERO));
        });
        // Creates the account info.
        accountInfo = new AccountInfo(USER_ID, wallets);
        // Updates all strategies.
        final UserDTO userDTO = ACCOUNT_MAPPER.mapToUserDTO(accountInfo);
        applicationContext.getBeansWithAnnotation(tech.cassandre.trading.bot.strategy.CassandreStrategy.class).values().stream().map(o -> (CassandreStrategyInterface) o).forEach(cassandreStrategyInterface -> cassandreStrategyInterface.initializeAccounts(userDTO.getAccounts()));
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Arrays(java.util.Arrays) Scanner(java.util.Scanner) HashMap(java.util.HashMap) Balance(org.knowm.xchange.dto.account.Balance) PathMatchingResourcePatternResolver(org.springframework.core.io.support.PathMatchingResourcePatternResolver) LinkedHashMap(java.util.LinkedHashMap) CassandreStrategyInterface(tech.cassandre.trading.bot.strategy.internal.CassandreStrategyInterface) BigDecimal(java.math.BigDecimal) ConditionalOnExpression(org.springframework.boot.autoconfigure.condition.ConditionalOnExpression) Aspect(org.aspectj.lang.annotation.Aspect) LinkedHashSet(java.util.LinkedHashSet) Resource(org.springframework.core.io.Resource) AccountInfo(org.knowm.xchange.dto.account.AccountInfo) Wallet(org.knowm.xchange.dto.account.Wallet) AccountDTO(tech.cassandre.trading.bot.dto.user.AccountDTO) CassandreStrategy(tech.cassandre.trading.bot.strategy.internal.CassandreStrategy) Collection(java.util.Collection) ZERO(java.math.BigDecimal.ZERO) IOException(java.io.IOException) ApplicationContext(org.springframework.context.ApplicationContext) Around(org.aspectj.lang.annotation.Around) FileNotFoundException(java.io.FileNotFoundException) UserDTO(tech.cassandre.trading.bot.dto.user.UserDTO) Currency(org.knowm.xchange.currency.Currency) Component(org.springframework.stereotype.Component) List(java.util.List) BaseService(tech.cassandre.trading.bot.util.base.service.BaseService) Optional(java.util.Optional) Collections(java.util.Collections) ProceedingJoinPoint(org.aspectj.lang.ProceedingJoinPoint) Wallet(org.knowm.xchange.dto.account.Wallet) UserDTO(tech.cassandre.trading.bot.dto.user.UserDTO) CassandreStrategyInterface(tech.cassandre.trading.bot.strategy.internal.CassandreStrategyInterface) LinkedHashMap(java.util.LinkedHashMap) Currency(org.knowm.xchange.currency.Currency) AccountDTO(tech.cassandre.trading.bot.dto.user.AccountDTO) Balance(org.knowm.xchange.dto.account.Balance) AccountInfo(org.knowm.xchange.dto.account.AccountInfo)

Example 2 with CassandreStrategyInterface

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

UserDTO (tech.cassandre.trading.bot.dto.user.UserDTO)2 CassandreStrategyInterface (tech.cassandre.trading.bot.strategy.internal.CassandreStrategyInterface)2 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 BigDecimal (java.math.BigDecimal)1 ZERO (java.math.BigDecimal.ZERO)1 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1 Optional (java.util.Optional)1 Scanner (java.util.Scanner)1 Set (java.util.Set)1 PostConstruct (javax.annotation.PostConstruct)1 ProceedingJoinPoint (org.aspectj.lang.ProceedingJoinPoint)1 Around (org.aspectj.lang.annotation.Around)1