EvaluationState.java

package com.tdmconsult.ete.evaluation;

import static com.tdmconsult.ete.accounting.BalanceRecords.ZERO_AMOUNT;

import com.tdmconsult.ete.masterdata.Security;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
@RequiredArgsConstructor
public class EvaluationState {

    private final Security security;
    private final int fiscalYear;
    private List<EvaluationPosition> positions = new ArrayList<>();

    public long getTotalQuantity() {
        return positions.stream()
                .mapToLong(p -> {
                    final var factor = p.isSell() ? -1 : p.isLikeBuy() ? 1 : 0;
                    return p.getQuantity() * factor;
                })
                .sum();
    }

    public BigDecimal getTotalBuyCost() {
        return positions.stream()
                .filter(p -> p.getTradingDate().getYear() == fiscalYear)
                .filter(EvaluationPosition::isBuy)
                .map(EvaluationPosition::getTotalCost)
                .reduce(BigDecimal::add).orElse(ZERO_AMOUNT);
    }

    public BigDecimal getTotalSellCost() {
        return positions.stream()
                .filter(p -> p.getTradingDate().getYear() == fiscalYear)
                .filter(EvaluationPosition::isSell)
                .map(EvaluationPosition::getTotalCost)
                .reduce(BigDecimal::add).orElse(ZERO_AMOUNT);
    }

    public BigDecimal getTotalProfit() {
        return positions.stream()
                .filter(p -> p.getTradingDate().getYear() == fiscalYear)
                .filter(EvaluationPosition::isSell)
                .filter(p -> p.getProfitLoss().signum() > 0)
                .map(EvaluationPosition::getProfitLoss)
                .reduce(BigDecimal::add).orElse(ZERO_AMOUNT);
    }

    public BigDecimal getTotalLoss() {
        return positions.stream()
                .filter(p -> p.getTradingDate().getYear() == fiscalYear)
                .filter(EvaluationPosition::isSell)
                .filter(p -> p.getProfitLoss().signum() < 0)
                .map(EvaluationPosition::getProfitLoss)
                .reduce(BigDecimal::add).orElse(ZERO_AMOUNT).abs();
    }

    public BigDecimal getEvaluationTotalDelta(final int forFiscalYear) {
        return getPositions().stream()
                .map(x -> x.getEvaluationDelta(forFiscalYear))
                .reduce(BigDecimal::add)
                .orElse(BigDecimal.ZERO);
    }

    public Optional<EvaluationPosition.Rate> getEvaluationRate(final int fiscalYear) {
        return positions.stream()
                .filter(p -> fiscalYear >= p.getTradingDate().getYear())
                .map(p -> p.getEvaluationRate(fiscalYear))
                .findFirst();
    }

    public BigDecimal getEvaluationTotal(final int fiscalYear) {
        return positions.stream()
                .map(p -> p.getEvaluationAmount(fiscalYear))
                .reduce(BigDecimal::add).orElse(ZERO_AMOUNT);
    }

    public BigDecimal getEvaluationGap(final int fiscalYear) {
        return positions.stream()
                .map(p -> p.getEvaluationDelta(fiscalYear))
                .reduce(BigDecimal::add).orElse(ZERO_AMOUNT);
    }

    public BigDecimal getProfitLoss() {
        return positions.stream()
                .map(EvaluationPosition::getProfitLoss)
                .reduce(BigDecimal::add).orElse(ZERO_AMOUNT);
    }
}