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