ch.algotrader.service.LookupServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for ch.algotrader.service.LookupServiceImpl.java

Source

/***********************************************************************************
 * AlgoTrader Enterprise Trading Framework
 *
 * Copyright (C) 2015 AlgoTrader GmbH - All rights reserved
 *
 * All information contained herein is, and remains the property of AlgoTrader GmbH.
 * The intellectual and technical concepts contained herein are proprietary to
 * AlgoTrader GmbH. Modification, translation, reverse engineering, decompilation,
 * disassembly or reproduction of this material is strictly forbidden unless prior
 * written permission is obtained from AlgoTrader GmbH
 *
 * Fur detailed terms and conditions consult the file LICENSE.txt or contact
 *
 * AlgoTrader GmbH
 * Aeschstrasse 6
 * 8834 Schindellegi
 ***********************************************************************************/
package ch.algotrader.service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections.map.MultiValueMap;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import ch.algotrader.cache.CacheManager;
import ch.algotrader.dao.GenericDao;
import ch.algotrader.dao.NamedParam;
import ch.algotrader.entity.Account;
import ch.algotrader.entity.AccountImpl;
import ch.algotrader.entity.Position;
import ch.algotrader.entity.PositionImpl;
import ch.algotrader.entity.Subscription;
import ch.algotrader.entity.SubscriptionImpl;
import ch.algotrader.entity.Transaction;
import ch.algotrader.entity.TransactionImpl;
import ch.algotrader.entity.exchange.Exchange;
import ch.algotrader.entity.marketData.Bar;
import ch.algotrader.entity.marketData.Tick;
import ch.algotrader.entity.security.Combination;
import ch.algotrader.entity.security.Component;
import ch.algotrader.entity.security.EasyToBorrow;
import ch.algotrader.entity.security.Forex;
import ch.algotrader.entity.security.Future;
import ch.algotrader.entity.security.FutureFamily;
import ch.algotrader.entity.security.IntrestRate;
import ch.algotrader.entity.security.Option;
import ch.algotrader.entity.security.OptionFamily;
import ch.algotrader.entity.security.Security;
import ch.algotrader.entity.security.SecurityFamily;
import ch.algotrader.entity.security.SecurityFamilyImpl;
import ch.algotrader.entity.security.SecurityImpl;
import ch.algotrader.entity.security.SecurityReference;
import ch.algotrader.entity.security.Stock;
import ch.algotrader.entity.strategy.CashBalance;
import ch.algotrader.entity.strategy.Measurement;
import ch.algotrader.entity.strategy.Strategy;
import ch.algotrader.entity.strategy.StrategyImpl;
import ch.algotrader.entity.trade.Order;
import ch.algotrader.enumeration.Currency;
import ch.algotrader.enumeration.Direction;
import ch.algotrader.enumeration.Duration;
import ch.algotrader.enumeration.QueryType;
import ch.algotrader.util.DateTimeLegacy;
import ch.algotrader.util.collection.CollectionUtil;
import ch.algotrader.util.collection.Pair;
import ch.algotrader.visitor.InitializationVisitor;

/**
 * @author <a href="mailto:aflury@algotrader.ch">Andy Flury</a>
 */
@Transactional(propagation = Propagation.SUPPORTS)
public class LookupServiceImpl implements LookupService {

    private final GenericDao genericDao;

    private final CacheManager cacheManager;

    public LookupServiceImpl(final GenericDao genericDao, final CacheManager cacheManager) {

        Validate.notNull(genericDao, "GenericDao is null");
        Validate.notNull(cacheManager, "CacheManager is null");

        this.genericDao = genericDao;
        this.cacheManager = cacheManager;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Security getSecurity(final long id) {

        return this.cacheManager.get(SecurityImpl.class, id);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Security getSecurityByIsin(final String isin) {

        Validate.notEmpty(isin, "isin is empty");

        return this.cacheManager.findUnique(Security.class, "Security.findByIsin", QueryType.BY_NAME,
                new NamedParam("isin", isin));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Security getSecurityBySymbol(final String symbol) {

        return this.cacheManager.findUnique(Security.class, "Security.findBySymbol", QueryType.BY_NAME,
                new NamedParam("symbol", symbol));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Security getSecurityByBbgid(final String bbgid) {

        Validate.notEmpty(bbgid, "bbgid is empty");

        return this.cacheManager.findUnique(Security.class, "Security.findByBbgid", QueryType.BY_NAME,
                new NamedParam("bbgid", bbgid));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Security getSecurityByRic(final String ric) {

        Validate.notEmpty(ric, "ric is empty");

        return this.cacheManager.findUnique(Security.class, "Security.findByRic", QueryType.BY_NAME,
                new NamedParam("ric", ric));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Security getSecurityByConid(final String conid) {

        Validate.notEmpty(conid, "Con id is empty");

        return this.cacheManager.findUnique(Security.class, "Security.findByConid", QueryType.BY_NAME,
                new NamedParam("conid", conid));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Security getSecurityInclUnderlyingFamilyAndExchange(final long id) {

        return this.cacheManager.findUnique(Security.class, "Security.findByIdInclUnderlyingFamilyAndExchange",
                QueryType.BY_NAME, new NamedParam("id", id));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Security> getSecuritiesByIds(final Collection<Long> ids) {

        return this.cacheManager.find(Security.class, "Security.findByIds", QueryType.BY_NAME,
                new NamedParam("ids", ids));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T extends SecurityFamily> Collection<T> getAllSecurityFamilies(Class<T> familyClass) {

        return this.cacheManager.getAll(familyClass);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Security> getAllSecurities() {

        return this.cacheManager.getAll(Security.class);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public SecurityFamily getSecurityFamilyBySecurity(long securityId) {

        Security security = getSecurityInclUnderlyingFamilyAndExchange(securityId);
        return security != null ? security.getSecurityFamily() : null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Exchange getExchangeBySecurity(long securityId) {

        Security security = getSecurityInclUnderlyingFamilyAndExchange(securityId);
        return security != null ? security.getSecurityFamily().getExchange() : null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Security> getSubscribedSecuritiesForAutoActivateStrategies() {

        return this.cacheManager.find(Security.class, "Security.findSubscribedForAutoActivateStrategies",
                QueryType.BY_NAME);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Pair<Security, String>> getSubscribedSecuritiesAndFeedTypeForAutoActivateStrategiesInclComponents() {

        List<SubscriptionImpl> subscriptions = this.cacheManager.find(SubscriptionImpl.class,
                "Subscription.findSubscribedAndFeedTypeForAutoActivateStrategies", QueryType.BY_NAME);
        List<Pair<Security, String>> list = subscriptions.stream()
                .map(s -> new Pair<>(s.getSecurity(), s.getFeedType())).collect(Collectors.toList());

        // initialize components
        for (Pair<Security, String> pair : list) {
            if (pair.getFirst() instanceof Combination) {
                pair.getFirst().accept(InitializationVisitor.INSTANCE, this.cacheManager);
            }
        }

        return list;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Stock> getStocksBySector(final String code) {

        Validate.notEmpty(code, "Code is empty");

        return this.cacheManager.find(Stock.class, "Stock.findBySectory", QueryType.BY_NAME,
                new NamedParam("code", code));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Stock> getStocksByIndustryGroup(final String code) {

        Validate.notEmpty(code, "Code is empty");

        return this.cacheManager.find(Stock.class, "Stock.findByIndustryGroup", QueryType.BY_NAME,
                new NamedParam("code", code));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Stock> getStocksByIndustry(final String code) {

        Validate.notEmpty(code, "Code is empty");

        return this.cacheManager.find(Stock.class, "Stock.findByIndustry", QueryType.BY_NAME,
                new NamedParam("code", code));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Stock> getStocksBySubIndustry(final String code) {

        Validate.notEmpty(code, "Code is empty");

        return this.cacheManager.find(Stock.class, "Stock.findBySubIndustry", QueryType.BY_NAME,
                new NamedParam("code", code));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Option> getSubscribedOptions() {

        return this.cacheManager.find(Option.class, "Option.findSubscribedOptions", QueryType.BY_NAME);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Future> getSubscribedFutures() {

        return this.cacheManager.find(Future.class, "Future.findSubscribedFutures", QueryType.BY_NAME);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Combination> getSubscribedCombinationsByStrategy(final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Combination.class, "Combination.findSubscribedByStrategy", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Combination> getSubscribedCombinationsByStrategyAndUnderlying(final String strategyName,
            final long underlyingId) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Combination.class, "Combination.findSubscribedByStrategyAndUnderlying",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("underlyingId", underlyingId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Combination> getSubscribedCombinationsByStrategyAndComponent(final String strategyName,
            final long securityId) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Combination.class, "Combination.findSubscribedByStrategyAndComponent",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("securityId", securityId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Combination> getSubscribedCombinationsByStrategyAndComponentClass(final String strategyName,
            final Class<? extends Security> type) {

        Validate.notEmpty(strategyName, "Strategy name is empty");
        Validate.notNull(type, "Type is null");

        return this.cacheManager.find(Combination.class, "Combination.findSubscribedByStrategyAndComponentType",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("type", type.getSimpleName()));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Component> getSubscribedComponentsByStrategyInclSecurity(final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Component.class, "Component.findSubscribedByStrategyInclSecurity",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Component> getSubscribedComponentsBySecurityInclSecurity(final long securityId) {

        return this.cacheManager.find(Component.class, "Component.findSubscribedBySecurityInclSecurity",
                QueryType.BY_NAME, new NamedParam("securityId", securityId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Component> getSubscribedComponentsByStrategyAndSecurityInclSecurity(final String strategyName,
            final long securityId) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Component.class, "Component.findSubscribedByStrategyAndSecurityInclSecurity",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("securityId", securityId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Subscription getSubscriptionByStrategyAndSecurity(final String strategyName, final long securityId) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.findUnique(Subscription.class, "Subscription.findByStrategyAndSecurity",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("securityId", securityId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Subscription> getSubscriptionsByStrategy(final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        List<Subscription> subscriptions = this.cacheManager.find(Subscription.class, "Subscription.findByStrategy",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName));

        // initialize components
        for (Subscription subscription : subscriptions) {
            if (subscription.getSecurity() instanceof Combination) {
                subscription.getSecurity().accept(InitializationVisitor.INSTANCE, this.cacheManager);
            }
        }

        return subscriptions;

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Subscription> getNonPositionSubscriptions(final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Subscription.class, "Subscription.findNonPositionSubscriptions",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Strategy> getAllStrategies() {

        return this.cacheManager.getAll(Strategy.class);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Strategy getStrategy(final long id) {

        return this.cacheManager.get(StrategyImpl.class, id);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Strategy getStrategyByName(final String name) {

        Validate.notEmpty(name, "Name is empty");

        return this.cacheManager.findUnique(Strategy.class, "Strategy.findByName", QueryType.BY_NAME,
                new NamedParam("name", name));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public SecurityFamily getSecurityFamily(final long id) {

        return this.cacheManager.get(SecurityFamilyImpl.class, id);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public SecurityFamily getSecurityFamilyByName(final String name) {

        Validate.notEmpty(name, "Name is empty");

        return this.cacheManager.findUnique(SecurityFamily.class, "SecurityFamily.findByName", QueryType.BY_NAME,
                new NamedParam("name", name));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Security getSecurityReferenceTargetByOwnerAndName(long securityId, String name) {

        Validate.notEmpty(name, "Name is empty");

        final SecurityReference ref = this.cacheManager.findUnique(SecurityReference.class,
                "SecurityReference.findByOwnerAndName", QueryType.BY_NAME,
                new NamedParam("ownerSecurityId", securityId), new NamedParam("name", name));
        return ref == null ? null : ref.getTarget();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public OptionFamily getOptionFamilyByUnderlying(final long underlyingId) {

        return this.cacheManager.findUnique(OptionFamily.class, "OptionFamily.findByUnderlying", QueryType.BY_NAME,
                new NamedParam("underlyingId", underlyingId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FutureFamily getFutureFamilyByUnderlying(final long underlyingId) {

        return this.cacheManager.findUnique(FutureFamily.class, "FutureFamily.findByUnderlying", QueryType.BY_NAME,
                new NamedParam("underlyingId", underlyingId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Exchange> getAllExchanges() {

        return this.cacheManager.getAll(Exchange.class);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Exchange getExchangeByName(String name) {

        return this.cacheManager.findUnique(Exchange.class, "Exchange.findByName", QueryType.BY_NAME,
                new NamedParam("name", name));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Position> getAllPositions() {

        return this.cacheManager.getAll(Position.class);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Position getPosition(final long id) {

        return this.cacheManager.get(PositionImpl.class, id);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Position getPositionInclSecurityAndSecurityFamily(final long id) {

        return this.cacheManager.findUnique(Position.class, "Position.findByIdInclSecurityAndSecurityFamily",
                QueryType.BY_NAME, new NamedParam("id", id));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getPositionsByStrategy(final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Position.class, "Position.findByStrategy", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Position getPositionBySecurityAndStrategy(final long securityId, final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.findUnique(Position.class, "Position.findBySecurityAndStrategy", QueryType.BY_NAME,
                new NamedParam("securityId", securityId), new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenPositions() {

        return this.cacheManager.find(Position.class, "Position.findOpenPositions", QueryType.BY_NAME);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenTradeablePositions() {

        return this.cacheManager.find(Position.class, "Position.findOpenTradeablePositions", QueryType.BY_NAME);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenPositionsByStrategy(final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Position.class, "Position.findOpenPositionsByStrategy", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenTradeablePositionsByStrategy(final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Position.class, "Position.findOpenTradeablePositionsByStrategy",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenPositionsBySecurity(final long securityId) {

        return this.cacheManager.find(Position.class, "Position.findOpenPositionsBySecurity", QueryType.BY_NAME,
                new NamedParam("securityId", securityId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenPositionsByStrategyAndType(final String strategyName,
            final Class<? extends Security> type) {

        Validate.notEmpty(strategyName, "Strategy name is empty");
        Validate.notNull(type, "Type is null");

        return this.cacheManager.find(Position.class, "Position.findOpenPositionsByStrategyAndType",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("type", type.getSimpleName()));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenPositionsByStrategyTypeAndUnderlyingType(final String strategyName,
            final Class<? extends Security> type, final Class<? extends Security> underlyingType) {

        Validate.notEmpty(strategyName, "Strategy name is empty");
        Validate.notNull(type, "Type is null");
        Validate.notNull(underlyingType, "Underlying type is null");

        return this.cacheManager.find(Position.class, "Position.findOpenPositionsByStrategyTypeAndUnderlyingType",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("type", type.getSimpleName()),
                new NamedParam("underlyingType", underlyingType.getSimpleName()));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenPositionsByStrategyAndSecurityFamily(final String strategyName,
            final long securityFamilyId) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Position.class, "Position.findOpenPositionsByStrategyAndSecurityFamily",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("securityFamilyId", securityFamilyId));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenFXPositions() {

        return this.cacheManager.find(Position.class, "Position.findOpenFXPositions", QueryType.BY_NAME);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Position> getOpenFXPositionsByStrategy(final String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        return this.cacheManager.find(Position.class, "Position.findOpenFXPositionsByStrategy", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasOpenPosition(long securityId, String strategyName) {

        Position position = getPositionBySecurityAndStrategy(securityId, strategyName);
        return position != null && position.getDirection() != Direction.FLAT;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Transaction getTransaction(final long id) {

        return this.cacheManager.get(TransactionImpl.class, id);
    }

    @Override
    public Transaction getTransactionByExtId(final String extId) {

        Validate.notEmpty(extId, "ExtId is empty");

        return this.cacheManager.findUnique(TransactionImpl.class, "Transaction.findByExtId", QueryType.BY_NAME,
                new NamedParam("extId", extId));
    }

    @Override
    public List<Transaction> getDailyTransactions(int limit) {

        LocalDate today = LocalDate.now();
        return this.cacheManager.find(Transaction.class, "Transaction.findDailyTransactions", limit,
                QueryType.BY_NAME, new NamedParam("curdate", DateTimeLegacy.toLocalDate(today)));
    }

    @Override
    public List<Transaction> getDailyTransactionsByStrategy(String strategyName, int limit) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        LocalDate today = LocalDate.now();
        return this.cacheManager.find(Transaction.class, "Transaction.findDailyTransactionsByStrategy", limit,
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                new NamedParam("curdate", DateTimeLegacy.toLocalDate(today)));
    }

    @Override
    public List<Transaction> getTradesByMinDateAndMaxDate(final Date minDate, final Date maxDate) {

        Validate.notNull(minDate, "minDate is null");
        Validate.notNull(maxDate, "maxDate is null");

        return this.cacheManager.find(Transaction.class, "Transaction.findTradesByMinDateAndMaxDate",
                QueryType.BY_NAME, new NamedParam("minDate", minDate), new NamedParam("maxDate", maxDate));
    }

    @Override
    public List<Order> getDailyOrders() {

        LocalDate today = LocalDate.now();
        return this.cacheManager.find(Order.class, "Order.findDailyOrders", QueryType.BY_NAME,
                new NamedParam("curdate", DateTimeLegacy.toLocalDate(today)));
    }

    @Override
    public List<Order> getDailyOrdersByStrategy(String strategyName) {

        Validate.notEmpty(strategyName, "Strategy name is empty");

        LocalDate today = LocalDate.now();
        return this.cacheManager.find(Order.class, "Order.findDailyOrdersByStrategy", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName),
                new NamedParam("curdate", DateTimeLegacy.toLocalDate(today)));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Account> getAllAccounts() {

        return this.cacheManager.getAll(Account.class);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Account getAccount(long accountId) {

        return this.cacheManager.get(AccountImpl.class, accountId);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Account getAccountByName(final String accountName) {

        Validate.notEmpty(accountName, "Account name is empty");

        return this.cacheManager.findUnique(Account.class, "Account.findByName", QueryType.BY_NAME,
                new NamedParam("name", accountName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<String> getActiveSessionsByOrderServiceType(final String orderServiceType) {

        Validate.notNull(orderServiceType, "Order service type is null");

        return this.genericDao.find(String.class, "Account.findActiveSessionsByOrderServiceType", QueryType.BY_NAME,
                new NamedParam("orderServiceType", orderServiceType));

    }

    private List<Tick> getTicksByMaxDate(final int limit, final long securityId, final Date maxDate,
            int intervalDays) {

        Validate.notNull(maxDate, "Max date is null");

        LocalDateTime maxLocalDateTime = DateTimeLegacy.toLocalDateTime(maxDate);
        LocalDateTime minLocalDateTime = maxLocalDateTime.minusDays(intervalDays);
        return this.genericDao.find(Tick.class, "Tick.findTicksBySecurityAndMaxDate", limit, QueryType.BY_NAME,
                new NamedParam("securityId", securityId),
                new NamedParam("minDate", DateTimeLegacy.toLocalDateTime(minLocalDateTime)),
                new NamedParam("maxDate", DateTimeLegacy.toLocalDateTime(maxLocalDateTime)));
    }

    private List<Tick> getTicksByMinDate(final int limit, final long securityId, final Date minDate,
            int intervalDays) {

        Validate.notNull(minDate, "Min date is null");

        LocalDateTime minLocalDateTime = DateTimeLegacy.toLocalDateTime(minDate);
        LocalDateTime maxLocalDateTime = minLocalDateTime.plusDays(intervalDays);
        return this.genericDao.find(Tick.class, "Tick.findTicksBySecurityAndMinDate", limit, QueryType.BY_NAME,
                new NamedParam("securityId", securityId),
                new NamedParam("minDate", DateTimeLegacy.toLocalDateTime(minLocalDateTime)),
                new NamedParam("maxDate", DateTimeLegacy.toLocalDateTime(maxLocalDateTime)));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Tick getLastTick(final long securityId, Date dateTime, int intervalDays) {

        return CollectionUtil.getSingleElementOrNull(getTicksByMaxDate(1, securityId, dateTime, intervalDays));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Tick> getTicksByMaxDate(final long securityId, final Date maxDate, int intervalDays) {

        return getTicksByMaxDate(-1, securityId, maxDate, intervalDays);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Tick> getTicksByMinDate(final long securityId, final Date minDate, int intervalDays) {

        return getTicksByMinDate(-1, securityId, minDate, intervalDays);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Tick> getDailyTicksBeforeTime(final long securityId, final Date time) {

        Validate.notNull(time, "Time is null");

        List<Long> ids = this.genericDao.find(Long.class, "Tick.findDailyTickIdsBeforeTime", QueryType.BY_NAME,
                new NamedParam("securityId", securityId), new NamedParam("time", time));

        if (ids.size() > 0) {
            return this.cacheManager.find(Tick.class, "Tick.findByIdsInclSecurityAndUnderlying", QueryType.BY_NAME,
                    new NamedParam("ids", ids));
        } else {
            return new ArrayList<>();
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Tick> getDailyTicksAfterTime(final long securityId, final Date time) {

        Validate.notNull(time, "Time is null");

        List<Long> ids = this.genericDao.find(Long.class, "Tick.findDailyTickIdsAfterTime", QueryType.BY_NAME,
                new NamedParam("securityId", securityId), new NamedParam("time", time));

        if (ids.size() > 0) {
            return this.cacheManager.find(Tick.class, "Tick.findByIdsInclSecurityAndUnderlying", QueryType.BY_NAME,
                    new NamedParam("ids", ids));
        } else {
            return new ArrayList<>();
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Tick> getHourlyTicksBeforeMinutesByMinDate(final long securityId, final int minutes,
            final Date minDate) {

        Validate.notNull(minDate, "Min date is null");

        List<Long> ids = this.genericDao.find(Long.class, "Tick.findHourlyTickIdsBeforeMinutesByMinDate",
                QueryType.BY_NAME, new NamedParam("securityId", securityId), new NamedParam("minutes", minutes),
                new NamedParam("minDate", minDate));

        if (ids.size() > 0) {
            return this.cacheManager.find(Tick.class, "Tick.findByIdsInclSecurityAndUnderlying", QueryType.BY_NAME,
                    new NamedParam("ids", ids));
        } else {
            return new ArrayList<>();
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Tick> getHourlyTicksAfterMinutesByMinDate(final long securityId, final int minutes,
            final Date minDate) {

        Validate.notNull(minDate, "Min date is null");

        List<Long> ids = this.genericDao.find(Long.class, "Tick.findHourlyTickIdsAfterMinutesByMinDate",
                QueryType.BY_NAME, new NamedParam("securityId", securityId), new NamedParam("minutes", minutes),
                new NamedParam("minDate", minDate));

        if (ids.size() > 0) {
            return this.cacheManager.find(Tick.class, "Tick.findByIdsInclSecurityAndUnderlying", QueryType.BY_NAME,
                    new NamedParam("ids", ids));
        } else {
            return new ArrayList<>();
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Tick getTickBySecurityAndMaxDate(final long securityId, final Date maxDate) {

        Validate.notNull(maxDate, "Date is null");

        return this.genericDao.findUnique(Tick.class, "Tick.findBySecurityAndMaxDate", QueryType.BY_NAME,
                new NamedParam("securityId", securityId), new NamedParam("maxDate", maxDate));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Bar> getDailyBarsFromTicks(final long securityId, final Date fromDate, final Date toDate) {

        Validate.notNull(fromDate, "From date is null");
        Validate.notNull(toDate, "To date is null");

        return this.genericDao.find(Bar.class, "Bar.findDailyBarsFromTicks", QueryType.BY_NAME,
                new NamedParam("securityId", securityId), new NamedParam("minDate", fromDate),
                new NamedParam("maxDate", toDate));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Bar> getLastNBarsBySecurityAndBarSize(final int n, final long securityId, final Duration barSize) {

        Validate.notNull(barSize, "Bar size is null");

        return this.genericDao.find(Bar.class, "Bar.findBarsBySecurityAndBarSize", n, QueryType.BY_NAME,
                new NamedParam("securityId", securityId), new NamedParam("barSize", barSize));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Bar> getBarsBySecurityBarSizeAndMinDate(final long securityId, final Duration barSize,
            final Date minDate) {

        Validate.notNull(barSize, "Bar size is null");
        Validate.notNull(minDate, "Min date is null");

        return this.genericDao.find(Bar.class, "Bar.findBarsBySecurityBarSizeAndMinDate", QueryType.BY_NAME,
                new NamedParam("securityId", securityId), new NamedParam("barSize", barSize),
                new NamedParam("minDate", minDate));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Forex getForex(final Currency baseCurrency, final Currency transactionCurrency) {

        Validate.notNull(baseCurrency, "Base currency is null");
        Validate.notNull(transactionCurrency, "Transaction currency is null");

        Forex forex = this.cacheManager.findUnique(Forex.class, "Forex.findByBaseAndTransactionCurrency",
                QueryType.BY_NAME, new NamedParam("baseCurrency", baseCurrency),
                new NamedParam("transactionCurrency", transactionCurrency));

        if (forex == null) {

            // reverse lookup
            forex = this.cacheManager.findUnique(Forex.class, "Forex.findByBaseAndTransactionCurrency",
                    QueryType.BY_NAME, new NamedParam("baseCurrency", transactionCurrency),
                    new NamedParam("transactionCurrency", baseCurrency));
        }

        return forex;

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double getForexRateByDate(final Currency baseCurrency, final Currency transactionCurrency,
            final Date date) {

        Validate.notNull(baseCurrency, "Base currency is null");
        Validate.notNull(transactionCurrency, "Transaction currency is null");
        Validate.notNull(date, "Date is null");

        if (baseCurrency.equals(transactionCurrency)) {
            return 1.0;
        }

        Forex forex = getForex(baseCurrency, transactionCurrency);
        if (forex == null) {
            throw new ForexAvailabilityException(
                    "Forex does not exist: " + baseCurrency + "." + transactionCurrency);
        }

        List<Tick> ticks = getTicksByMaxDate(forex.getId(), date, 1);
        if (ticks.isEmpty()) {
            throw new ForexAvailabilityException(
                    "No exchange rate available for " + baseCurrency + "." + transactionCurrency + " for " + date);
        }

        Tick tick = ticks.get(0);
        if (forex.getBaseCurrency().equals(baseCurrency)) {
            // expected case
            return tick.getCurrentValueDouble();
        } else {
            // reverse case
            return 1.0 / tick.getCurrentValueDouble();
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IntrestRate getInterestRateByCurrencyAndDuration(final Currency currency, final Duration duration) {

        Validate.notNull(currency, "Currency is null");
        Validate.notNull(duration, "Duration is null");

        return this.cacheManager.findUnique(IntrestRate.class, "IntrestRate.findByCurrencyAndDuration",
                QueryType.BY_NAME, new NamedParam("currency", currency), new NamedParam("duration", duration));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double getInterestRateByCurrencyDurationAndDate(final Currency currency, final Duration duration,
            final Date date) {

        Validate.notNull(currency, "Currency is null");
        Validate.notNull(duration, "Duration is null");
        Validate.notNull(date, "Date is null");

        IntrestRate intrestRate = getInterestRateByCurrencyAndDuration(currency, duration);

        List<Tick> ticks = getTicksByMaxDate(intrestRate.getId(), date, 1);
        if (ticks.isEmpty()) {
            throw new ServiceException("Cannot get intrestRate for " + currency + " and duration " + duration
                    + " because no last tick is available for date " + date);
        }

        return CollectionUtil.getFirstElement(ticks).getCurrentValueDouble();

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<Currency> getHeldCurrencies() {

        return this.genericDao.find(Currency.class, "CashBalance.findHeldCurrencies", QueryType.BY_NAME);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<CashBalance> getCashBalancesByStrategy(final String strategyName) {

        Validate.notNull(strategyName, "Strategy name is null");

        return this.cacheManager.find(CashBalance.class, "CashBalance.findCashBalancesByStrategy",
                QueryType.BY_NAME, new NamedParam("strategyName", strategyName));

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<Date, Object> getMeasurementsByMaxDate(final String strategyName, final String name,
            final Date maxDate) {

        Validate.notNull(strategyName, "Strategy name is null");
        Validate.notNull(name, "Name is null");
        Validate.notNull(maxDate, "Max date is null");

        List<Measurement> measurements = this.genericDao.find(Measurement.class,
                "Measurement.findMeasurementsByMaxDate", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName), new NamedParam("name", name),
                new NamedParam("maxDateTime", maxDate));

        return getValuesByDate(measurements);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<Date, Map<String, Object>> getAllMeasurementsByMaxDate(final String strategyName,
            final Date maxDate) {

        Validate.notNull(strategyName, "Strategy name is null");
        Validate.notNull(maxDate, "Max date is null");

        List<Measurement> measurements = this.genericDao.find(Measurement.class,
                "Measurement.findAllMeasurementsByMaxDate", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName), new NamedParam("maxDateTime", maxDate));

        return getNameValuePairsByDate(measurements);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<Date, Object> getMeasurementsByMinDate(final String strategyName, final String name,
            final Date minDate) {

        Validate.notNull(strategyName, "Strategy name is null");
        Validate.notNull(name, "Name is null");
        Validate.notNull(minDate, "Min date is null");

        List<Measurement> measurements = this.genericDao.find(Measurement.class,
                "Measurement.findMeasurementsByMinDate", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName), new NamedParam("name", name),
                new NamedParam("minDateTime", minDate));

        return getValuesByDate(measurements);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<Date, Map<String, Object>> getAllMeasurementsByMinDate(final String strategyName,
            final Date minDate) {

        Validate.notNull(strategyName, "Strategy name is null");
        Validate.notNull(minDate, "Min date is null");

        List<Measurement> measurements = this.genericDao.find(Measurement.class,
                "Measurement.findAllMeasurementsByMinDate", QueryType.BY_NAME,
                new NamedParam("strategyName", strategyName), new NamedParam("minDateTime", minDate));

        return getNameValuePairsByDate(measurements);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getMeasurementByMaxDate(final String strategyName, final String name, final Date maxDate) {

        Validate.notNull(strategyName, "Strategy name is null");
        Validate.notNull(name, "Name is null");
        Validate.notNull(maxDate, "Max date is null");

        Measurement measurement = CollectionUtil.getSingleElementOrNull(
                this.genericDao.find(Measurement.class, "Measurement.findMeasurementsByMaxDate", 1,
                        QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                        new NamedParam("name", name), new NamedParam("maxDateTime", maxDate)));

        return measurement != null ? measurement.getValue() : null;

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getMeasurementByMinDate(final String strategyName, final String name, final Date minDate) {

        Validate.notNull(strategyName, "Strategy name is null");
        Validate.notNull(name, "Name is null");
        Validate.notNull(minDate, "Min date is null");

        Measurement measurement = CollectionUtil.getSingleElementOrNull(
                this.genericDao.find(Measurement.class, "Measurement.findMeasurementsByMinDate", 1,
                        QueryType.BY_NAME, new NamedParam("strategyName", strategyName),
                        new NamedParam("name", name), new NamedParam("minDateTime", minDate)));

        return measurement != null ? measurement.getValue() : null;

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<EasyToBorrow> getEasyToBorrowByDateAndBroker(final Date date, final String broker) {

        Validate.notNull(date, "Date is null");
        Validate.notNull(broker, "Broker is null");

        Date truncatedDate = DateUtils.truncate(date, Calendar.DATE);
        return this.cacheManager.find(EasyToBorrow.class, "EasyToBorrow.findByDateAndBroker", QueryType.BY_NAME,
                new NamedParam("date", truncatedDate), new NamedParam("broker", broker));

    }

    @Override
    public Date getCurrentDBTime() {

        return this.genericDao.findUnique(Date.class, "Strategy.findCurrentDBTime", QueryType.BY_NAME);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T> List<T> find(final Class<T> clazz, final String query, QueryType type, boolean useCache,
            final NamedParam... namedParams) {

        Validate.notEmpty(query, "Query is empty");
        Validate.notNull(namedParams, "Named parameters is null");

        if (useCache) {
            return this.cacheManager.find(clazz, query, type, namedParams);
        } else {
            return this.genericDao.find(clazz, query, type, namedParams);
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T> List<T> find(final Class<T> clazz, final String query, final int maxResults, QueryType type,
            boolean useCache, final NamedParam... namedParams) {

        Validate.notEmpty(query, "Query is empty");
        Validate.notNull(namedParams, "Named parameters is null");

        if (useCache) {
            return this.cacheManager.find(clazz, query, maxResults, type, namedParams);
        } else {
            return this.genericDao.find(clazz, query, maxResults, type, namedParams);
        }

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T> T findUnique(final Class<T> clazz, final String query, QueryType type, boolean useCache,
            final NamedParam... namedParams) {

        Validate.notEmpty(query, "Query is empty");
        Validate.notNull(namedParams, "Named parameters is null");

        if (useCache) {
            return this.cacheManager.findUnique(clazz, query, type, namedParams);
        } else {
            return this.genericDao.findUnique(clazz, query, type, namedParams);
        }

    }

    private Map<Date, Object> getValuesByDate(List<Measurement> measurements) {

        Map<Date, Object> valuesByDate = new HashMap<>();
        for (Measurement measurement : measurements) {
            valuesByDate.put(measurement.getDateTime(), measurement.getValue());
        }

        return valuesByDate;
    }

    @SuppressWarnings("unchecked")
    private Map<Date, Map<String, Object>> getNameValuePairsByDate(List<Measurement> measurements) {

        // group Measurements by date
        MultiValueMap measurementsByDate = new MultiValueMap();
        for (Measurement measurement : measurements) {
            measurementsByDate.put(measurement.getDateTime(), measurement);
        }

        // create a nameValuePair Map per date
        Map<Date, Map<String, Object>> nameValuePairsByDate = new HashMap<>();
        for (Date dt : (Set<Date>) measurementsByDate.keySet()) {

            Map<String, Object> nameValuePairs = new HashMap<>();
            for (Measurement measurement : (Collection<Measurement>) measurementsByDate.get(dt)) {
                nameValuePairs.put(measurement.getName(), measurement.getValue());
            }
            nameValuePairsByDate.put(dt, nameValuePairs);
        }

        return nameValuePairsByDate;
    }

}