package name.abuchen.portfolio.snapshot; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; import name.abuchen.portfolio.Messages; import name.abuchen.portfolio.model.Account; import name.abuchen.portfolio.model.Client; import name.abuchen.portfolio.model.InvestmentVehicle; import name.abuchen.portfolio.model.Portfolio; import name.abuchen.portfolio.model.Taxonomy; import name.abuchen.portfolio.money.CurrencyConverter; import name.abuchen.portfolio.money.Money; import name.abuchen.portfolio.money.MutableMoney; import name.abuchen.portfolio.snapshot.filter.ReadOnlyClient; public class ClientSnapshot { private final Client client; private final CurrencyConverter converter; private final LocalDate date; private List<AccountSnapshot> accounts = new ArrayList<>(); private List<PortfolioSnapshot> portfolios = new ArrayList<>(); private PortfolioSnapshot jointPortfolio; private Money assets; public static ClientSnapshot create(Client client, CurrencyConverter converter, LocalDate date) { ClientSnapshot snapshot = new ClientSnapshot( client instanceof ReadOnlyClient ? ((ReadOnlyClient) client).getSource() : client, converter, date); for (Account account : client.getAccounts()) snapshot.accounts.add(AccountSnapshot.create(account, converter, date)); for (Portfolio portfolio : client.getPortfolios()) snapshot.portfolios.add(PortfolioSnapshot.create(portfolio, converter, date)); return snapshot; } private ClientSnapshot(Client client, CurrencyConverter converter, LocalDate date) { this.client = client; this.converter = converter; this.date = date; } public Client getClient() { return client; } public String getCurrencyCode() { return converter.getTermCurrency(); } public CurrencyConverter getCurrencyConverter() { return converter; } public LocalDate getTime() { return date; } public List<AccountSnapshot> getAccounts() { return accounts; } public List<PortfolioSnapshot> getPortfolios() { return portfolios; } public PortfolioSnapshot getJointPortfolio() { if (this.jointPortfolio == null) { if (portfolios.isEmpty()) { Portfolio portfolio = new Portfolio(); portfolio.setName(Messages.LabelJointPortfolio); portfolio.setReferenceAccount(new Account(Messages.LabelJointPortfolio)); this.jointPortfolio = PortfolioSnapshot.create(portfolio, converter, date); } else if (portfolios.size() == 1) { this.jointPortfolio = portfolios.get(0); } else { this.jointPortfolio = PortfolioSnapshot.merge(portfolios, converter); } } return this.jointPortfolio; } public Money getMonetaryAssets() { if (this.assets == null) { MutableMoney sum = MutableMoney.of(getCurrencyCode()); for (AccountSnapshot account : accounts) sum.add(account.getFunds()); // use joint portfolio to reduce rounding errors if a security is // split across multiple portfolio sum.add(getJointPortfolio().getValue()); this.assets = sum.toMoney(); } return this.assets; } public GroupByTaxonomy groupByTaxonomy(Taxonomy taxonomy) { return new GroupByTaxonomy(taxonomy, this); } public Map<InvestmentVehicle, AssetPosition> getPositionsByVehicle() { return getAssetPositions().collect(Collectors.toMap(AssetPosition::getInvestmentVehicle, v -> v)); } public Stream<AssetPosition> getAssetPositions() { List<AssetPosition> answer = new ArrayList<>(); Money monetaryAssets = getMonetaryAssets(); for (SecurityPosition p : getJointPortfolio().getPositions()) answer.add(new AssetPosition(p, converter, date, monetaryAssets)); for (AccountSnapshot a : accounts) answer.add(new AssetPosition(new SecurityPosition(a), converter, date, monetaryAssets)); return answer.stream(); } }