package com.smppw.core;

import com.smppw.common.pojo.dto.CompoundRet;
import com.smppw.common.pojo.dto.DateValue;
import com.smppw.common.pojo.dto.calc.IndicatorCalcPropertyDto;
import com.smppw.common.pojo.dto.calc.IndicatorCalcReqPropertyDto;
import com.smppw.common.pojo.enums.Indicator;
import com.smppw.utils.BigDecimalUtils;
import com.smppw.utils.IndicatorCalc;
import com.smppw.utils.IndicatorCalcUtil;
import com.smppw.utils.NavUtil;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class CalcService {
    private CalcService() {
    }

    public static CalcService getInstance() {
        return CalcServiceBuilder.INSTANCE;
    }

    public IndicatorCalcPropertyDto indicatorCalc(IndicatorCalcReqPropertyDto indicatorCalcReq) {
        IndicatorCalcPropertyDto indicatorCalcPropertyDto = new IndicatorCalcPropertyDto();
        indicatorCalcPropertyDto.setIndicatorCalcReq(indicatorCalcReq);

        List<Indicator> indicatorList = indicatorCalcReq.getIndicatorList();
        List<Indicator> navIndicatorList = new ArrayList<>();
        List<Indicator> retIndicatorList = new ArrayList<>();
        for (Indicator indicator : indicatorList) {
            if (Indicator.TYPES_NEED_NAV.contains(indicator)) {
                navIndicatorList.add(indicator);
            } else {
                retIndicatorList.add(indicator);
            }
        }

        List<Indicator> geoIndicatorList = indicatorCalcReq.getGeoIndicatorList();
        List<Indicator> geoNavIndicatorList = new ArrayList<>();
        List<Indicator> geoRetIndicatorList = new ArrayList<>();
        for (Indicator indicator : geoIndicatorList) {
            if (Indicator.TYPES_NEED_NAV.contains(indicator)) {
                geoNavIndicatorList.add(indicator);
            } else {
                geoRetIndicatorList.add(indicator);
            }
        }

        prepareNavBaseData(indicatorCalcReq, indicatorCalcPropertyDto, false);

        prepareExtraGeoNavBaseData(indicatorCalcReq, indicatorCalcPropertyDto);

        Map<String, String> indicatorValueMap = new HashMap<>();
        Map<String, String> extraIndicatorValueMap = new HashMap<>();
        Map<String, Map<String, String>> indexIndicatorValueMap = new HashMap<>();
        Map<String, Map<String, String>> extraIndexIndicatorValueMap = new HashMap<>();

        calcNavIndicator(navIndicatorList, indicatorCalcReq, indicatorValueMap, indexIndicatorValueMap, indicatorCalcPropertyDto);

        calcExtraGeoNavIndicator(geoNavIndicatorList, extraIndicatorValueMap, extraIndexIndicatorValueMap, indicatorCalcPropertyDto);

        prepareRetBaseData(retIndicatorList, indicatorCalcReq, indicatorCalcPropertyDto);

        prepareExtraGeoRetBaseData(geoRetIndicatorList, indicatorCalcReq, indicatorCalcPropertyDto);

        calcRetIndicator(retIndicatorList, indicatorCalcReq, indicatorValueMap, indexIndicatorValueMap, indicatorCalcPropertyDto);

        calcExtraGeoRetIndicator(geoRetIndicatorList, indicatorCalcReq, extraIndicatorValueMap, extraIndexIndicatorValueMap, indicatorCalcPropertyDto);

        indicatorCalcPropertyDto.getSecData().setIndicatorValueMap(indicatorValueMap);
        indicatorCalcPropertyDto.getSecData().setExtraGeoIndicatorValueMap(extraIndicatorValueMap);
        indicatorCalcPropertyDto.getIndexData().setIndexIndicatorValueMap(indexIndicatorValueMap);
        indicatorCalcPropertyDto.getIndexData().setIndexGeoExtraIndicatorValueMap(extraIndexIndicatorValueMap);
        return indicatorCalcPropertyDto;
    }

    private void calcExtraGeoRetIndicator(List<Indicator> geoRetIndicatorList, IndicatorCalcReqPropertyDto indicatorCalcReq, Map<String, String> ariIndicatorValueMap,
                                                 Map<String, Map<String, String>> extraIndexIndicatorValueMap, IndicatorCalcPropertyDto indicatorCalcPropertyDto) {
        if (geoRetIndicatorList.size() > 0) {
            List<CompoundRet> secRetList = indicatorCalcPropertyDto.getSecData().getExtraRetGeoList();
            Map<String, String> retIndicatorValueMap = IndicatorCalc.calcRetIndicatorValue(secRetList, indicatorCalcReq.getIndicatorCalcTimeRangeDto().getTimeRange(),
                    indicatorCalcReq.getFrequency(), indicatorCalcReq.isIfAnnualize(), geoRetIndicatorList, indicatorCalcReq.isIfConvertPerformanceConsistencyWord(), indicatorCalcReq.getLeastRetNum());
            ariIndicatorValueMap.putAll(retIndicatorValueMap);

            List<String> indexIdList = indicatorCalcPropertyDto.getIndicatorCalcReq().getIndexIdList();
            Map<String, List<CompoundRet>> indexExtraRetGeoListMap = indicatorCalcPropertyDto.getIndexData().getIndexExtraRetGeoListMap();
            for (String indexId : indexIdList) {
                List<CompoundRet> indexExtraRetGeoList = indexExtraRetGeoListMap.get(indexId);
                Map<String, String> indexRetIndicatorValueMap = IndicatorCalc.calcRetIndicatorValue(indexExtraRetGeoList, indicatorCalcReq.getIndicatorCalcTimeRangeDto().getTimeRange(),
                        indicatorCalcReq.getFrequency(), indicatorCalcReq.isIfAnnualize(), geoRetIndicatorList, indicatorCalcReq.isIfConvertPerformanceConsistencyWord(), indicatorCalcReq.getLeastRetNum());

                if (extraIndexIndicatorValueMap.containsKey(indexId)) {
                    Map<String, String> map = extraIndexIndicatorValueMap.get(indexId);
                    if (map == null) {
                        map = new HashMap<>();
                    }
                    map.putAll(indexRetIndicatorValueMap);
                } else {
                    extraIndexIndicatorValueMap.put(indexId, indexRetIndicatorValueMap);
                }
            }
        }
    }

    private void calcRetIndicator(List<Indicator> retIndicatorList, IndicatorCalcReqPropertyDto indicatorCalcReq, Map<String, String> indicatorValueMap,
                                         Map<String, Map<String, String>> indexIndicatorValueMap, IndicatorCalcPropertyDto indicatorCalcPropertyDto) {
        if (retIndicatorList.size() > 0) {
            List<CompoundRet> secRetList = indicatorCalcPropertyDto.getSecData().getRetList();
            Map<String, String> retIndicatorValueMap = IndicatorCalc.calcRetIndicatorValue(secRetList, indicatorCalcReq.getIndicatorCalcTimeRangeDto().getTimeRange(),
                    indicatorCalcReq.getFrequency(), indicatorCalcReq.isIfAnnualize(), retIndicatorList, indicatorCalcReq.isIfConvertPerformanceConsistencyWord(), indicatorCalcReq.getLeastRetNum());
            indicatorValueMap.putAll(retIndicatorValueMap);

            if (indicatorCalcReq.getCalcIndexRetIndicatorValue()) {
                Map<String, List<CompoundRet>> indexRetListMap = indicatorCalcPropertyDto.getIndexData().getIndexRetListMap();
                List<String> indexIdList = indicatorCalcPropertyDto.getIndicatorCalcReq().getIndexIdList();
                for (String indexId : indexIdList) {
                    List<CompoundRet> indexRet = indexRetListMap.get(indexId);
                    Map<String, String> indexRetIndicatorValueMap = IndicatorCalc.calcRetIndicatorValue(indexRet,
                            indicatorCalcReq.getIndicatorCalcTimeRangeDto().getTimeRange(), indicatorCalcReq.getFrequency(),
                            indicatorCalcReq.isIfAnnualize(), retIndicatorList, indicatorCalcReq.isIfConvertPerformanceConsistencyWord(), indicatorCalcReq.getLeastRetNum());
                    if (indexIndicatorValueMap.containsKey(indexId)) {
                        indexIndicatorValueMap.get(indexId).putAll(indexRetIndicatorValueMap);
                    } else {
                        indexIndicatorValueMap.put(indexId, indexRetIndicatorValueMap);
                    }
                }
            }
        }
    }

    private void prepareExtraGeoRetBaseData(List<Indicator> retIndicatorList, IndicatorCalcReqPropertyDto indicatorCalcReq, IndicatorCalcPropertyDto indicatorCalcPropertyDto) {

        if (retIndicatorList.size() > 0 || indicatorCalcReq.getNeedExtraGeoRet()) {
            Map<String, CompoundRet> strategyDateRetMap = indicatorCalcReq.getStrategyDateRetMap();

            List<CompoundRet> benchmarkRetList = indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkRetList();

            Map<String, CompoundRet> riskFreeDateRetMap = new HashMap<>();
            String riskOfFreeId = indicatorCalcReq.getRiskOfFreeId();
            if (StringUtils.isNotEmpty(riskOfFreeId)) {
                List<DateValue> riskFreeNavList = indicatorCalcPropertyDto.getRiskFreeData().getRiskFreeNavList();
                List<CompoundRet> riskFreeRetList = IndicatorCalcUtil.getRet(riskFreeNavList, null, null, null);
                for (CompoundRet riskFreeRet : riskFreeRetList) {
                    riskFreeDateRetMap.put(riskFreeRet.getEndDate(), riskFreeRet);
                }
            } else {
                for (CompoundRet benchmarkRet : benchmarkRetList) {
                    CompoundRet riskFreeRet = new CompoundRet();
                    riskFreeRet.setEndDate(benchmarkRet.getEndDate());
                    Double riskOfFreeValue = indicatorCalcReq.getRiskOfFreeValue();
                    BigDecimal rfValue = BigDecimalUtils.divide(new BigDecimal(riskOfFreeValue), new BigDecimal("100"));
                    double riskOfFreeValueDaily = BigDecimalUtils.divide(rfValue, new BigDecimal(indicatorCalcReq.getFrequency().getNum())).doubleValue();
                    riskFreeRet.setRetOfFund(riskOfFreeValueDaily);
                    riskFreeDateRetMap.put(benchmarkRet.getEndDate(), riskFreeRet);
                }
            }

            List<CompoundRet> secExtraGeoRetList = IndicatorCalcUtil.getRet(indicatorCalcPropertyDto.getSecData().getExtraNavList(), benchmarkRetList, riskFreeDateRetMap, strategyDateRetMap);
            indicatorCalcPropertyDto.getSecData().setExtraRetGeoList(secExtraGeoRetList);

            List<String> indexIdList = indicatorCalcPropertyDto.getIndicatorCalcReq().getIndexIdList();
            Map<String, List<DateValue>> indexExtraNavMap = indicatorCalcPropertyDto.getIndexData().getIndexExtraNavMap();
            for (String index : indexIdList) {
                List<DateValue> indexExtraNav = indexExtraNavMap.get(index);
                List<CompoundRet> indexExtraGeoRetList = IndicatorCalcUtil.getRet(indexExtraNav, benchmarkRetList, riskFreeDateRetMap, strategyDateRetMap);
                Map<String, List<CompoundRet>> indexExtraRetGeoListMap = indicatorCalcPropertyDto.getIndexData().getIndexExtraRetGeoListMap();
                indexExtraRetGeoListMap.put(index, indexExtraGeoRetList);
            }

        }

    }

    private void prepareRetBaseData(List<Indicator> retIndicatorList, IndicatorCalcReqPropertyDto indicatorCalcReq, IndicatorCalcPropertyDto indicatorCalcPropertyDto) {
        if (retIndicatorList.size() > 0 || indicatorCalcReq.getNeedRet()) {
            Map<String, CompoundRet> strategyDateRetMap = indicatorCalcReq.getStrategyDateRetMap();

            List<CompoundRet> benchmarkRetList = IndicatorCalcUtil.getRet(indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList(), null, null, strategyDateRetMap);
            indicatorCalcPropertyDto.getBenchmarkData().setBenchmarkRetList(benchmarkRetList);

            Map<String, CompoundRet> riskFreeDateRetMap = new HashMap<>();
            String riskOfFreeId = indicatorCalcReq.getRiskOfFreeId();
            if (StringUtils.isNotEmpty(riskOfFreeId)) {
                List<DateValue> riskFreeNavList = indicatorCalcPropertyDto.getRiskFreeData().getRiskFreeNavList();
                List<CompoundRet> riskFreeRetList = IndicatorCalcUtil.getRet(riskFreeNavList, null, null, null);
                for (CompoundRet riskFreeRet : riskFreeRetList) {
                    riskFreeDateRetMap.put(riskFreeRet.getEndDate(), riskFreeRet);
                }
            } else {
                for (CompoundRet benchmarkRet : benchmarkRetList) {
                    CompoundRet riskFreeRet = new CompoundRet();
                    riskFreeRet.setEndDate(benchmarkRet.getEndDate());
                    Double riskOfFreeValue = indicatorCalcReq.getRiskOfFreeValue();
                    BigDecimal rfValue = BigDecimalUtils.divide(new BigDecimal(riskOfFreeValue), new BigDecimal("100"));
                    double riskOfFreeValueDaily = BigDecimalUtils.divide(rfValue, new BigDecimal(indicatorCalcReq.getFrequency().getNum())).doubleValue();
                    riskFreeRet.setRetOfFund(riskOfFreeValueDaily);
                    riskFreeDateRetMap.put(benchmarkRet.getEndDate(), riskFreeRet);
                }
            }

            List<CompoundRet> secRetList = IndicatorCalcUtil.getRet(indicatorCalcPropertyDto.getSecData().getNavList(), benchmarkRetList, riskFreeDateRetMap, strategyDateRetMap);
            indicatorCalcPropertyDto.getSecData().setRetList(secRetList);

            Map<String, List<CompoundRet>> indexRetListMap = new HashMap<>();
            List<String> indexIdList = indicatorCalcPropertyDto.getIndicatorCalcReq().getIndexIdList();
            Map<String, List<DateValue>> indexNavMap = indicatorCalcPropertyDto.getIndexData().getIndexNavMap();
            for (String indexId : indexIdList) {
                List<DateValue> indexNav = indexNavMap.get(indexId);
                List<CompoundRet> indexRetList = IndicatorCalcUtil.getRet(indexNav, benchmarkRetList, riskFreeDateRetMap, strategyDateRetMap);
                indexRetListMap.put(indexId, indexRetList);
            }
            indicatorCalcPropertyDto.getIndexData().setIndexRetListMap(indexRetListMap);
        }
    }

    private void calcExtraGeoNavIndicator(List<Indicator> geoNavIndicatorList, Map<String, String> indicatorValueMap, Map<String, Map<String, String>> extraIndexIndicatorValueMap,
                                                 IndicatorCalcPropertyDto indicatorCalcPropertyDto) {
        if (geoNavIndicatorList.size() > 0) {
            List<DateValue> extraNavList = indicatorCalcPropertyDto.getSecData().getExtraNavList();
            Map<String, String> navIndicatorValueMap = IndicatorCalc.calcNavIndicatorValue(extraNavList, geoNavIndicatorList);
            indicatorValueMap.putAll(navIndicatorValueMap);

            List<String> indexIdList = indicatorCalcPropertyDto.getIndicatorCalcReq().getIndexIdList();
            Map<String, List<DateValue>> indexExtraNavMap = indicatorCalcPropertyDto.getIndexData().getIndexExtraNavMap();
            for (String indexId : indexIdList) {
                List<DateValue> indexExtraNav = indexExtraNavMap.get(indexId);
                Map<String, String> indexNavIndicatorValueMap = IndicatorCalc.calcNavIndicatorValue(indexExtraNav, geoNavIndicatorList);
                if (extraIndexIndicatorValueMap.containsKey(indexId)) {
                    Map<String, String> map = extraIndexIndicatorValueMap.get(indexId);
                    if (map == null) {
                        map = new HashMap<>();
                    }
                    map.putAll(indexNavIndicatorValueMap);
                } else {
                    extraIndexIndicatorValueMap.put(indexId, indexNavIndicatorValueMap);
                }
            }
        }
    }

    private void calcNavIndicator(List<Indicator> navIndicatorList, IndicatorCalcReqPropertyDto indicatorCalcReq, Map<String, String> indicatorValueMap,
                                         Map<String, Map<String, String>> indexIndicatorValueMap, IndicatorCalcPropertyDto indicatorCalcPropertyDto) {
        if (navIndicatorList.size() > 0) {
            Map<String, String> navIndicatorValueMap = IndicatorCalc.calcNavIndicatorValue(indicatorCalcPropertyDto.getSecData().getNavList(), navIndicatorList);
            indicatorValueMap.putAll(navIndicatorValueMap);

            List<String> indexIdList = indicatorCalcReq.getIndexIdList();
            Map<String, List<DateValue>> indexNavMap = indicatorCalcPropertyDto.getIndexData().getIndexNavMap();
            for (String indexId : indexIdList) {
                List<DateValue> indexNavList = indexNavMap.get(indexId);
                Map<String, String> indexNavIndicatorValueMap = IndicatorCalc.calcNavIndicatorValue(indexNavList, navIndicatorList);
                if (indexIndicatorValueMap.containsKey(indexId)) {
                    indexIndicatorValueMap.get(indexId).putAll(indexNavIndicatorValueMap);
                } else {
                    indexIndicatorValueMap.put(indexId, indexNavIndicatorValueMap);
                }
            }
        }
    }

    private void prepareExtraGeoNavBaseData(IndicatorCalcReqPropertyDto indicatorCalcReq, IndicatorCalcPropertyDto indicatorCalcPropertyDto) {

        if (indicatorCalcReq.getGeoIndicatorList().size() > 0 || indicatorCalcPropertyDto.getIndicatorCalcReq().getNeedExtraGeoRet()) {
            List<DateValue> secNavList = indicatorCalcPropertyDto.getSecData().getNavList();
            List<DateValue> benchmarkNavList = indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList();

            List<DateValue> secNavNormalizeList = IndicatorCalcUtil.navNormalize(secNavList);
            List<DateValue> benchmarkNavNormalizeList = IndicatorCalcUtil.navNormalize(benchmarkNavList);

            List<DateValue> geoExtraNavList = NavUtil.getGeoExtraNavList(secNavNormalizeList, benchmarkNavNormalizeList);

            indicatorCalcPropertyDto.getSecData().setExtraNavList(geoExtraNavList);

            List<String> indexIdList = indicatorCalcPropertyDto.getIndicatorCalcReq().getIndexIdList();
            Map<String, List<DateValue>> indexNavMap = indicatorCalcPropertyDto.getIndexData().getIndexNavMap();
            for (String index : indexIdList) {
                List<DateValue> indexNav = indexNavMap.get(index);
                List<DateValue> indexNavNormalizeList = IndicatorCalcUtil.navNormalize(indexNav);
                List<DateValue> indexGeoExtraNavList = NavUtil.getGeoExtraNavList(indexNavNormalizeList, benchmarkNavNormalizeList);
                indicatorCalcPropertyDto.getIndexData().getIndexExtraNavMap().put(index, indexGeoExtraNavList);
            }
        }
    }

    private void prepareNavBaseData(IndicatorCalcReqPropertyDto indicatorCalcReq, IndicatorCalcPropertyDto indicatorCalcPropertyDto, boolean isTrend) {
        Map<String, List<DateValue>> allNavMap = indicatorCalcReq.getAllNavMap();
        String mainSecId = indicatorCalcReq.getSecId();
        List<DateValue> secIdValidNavList = IndicatorCalcUtil.getSecIdValidNav(mainSecId, indicatorCalcReq.getIndicatorCalcTimeRangeDto(), allNavMap, isTrend, indicatorCalcReq.getDefaultFrequency());
        indicatorCalcPropertyDto.getSecData().setNavList(secIdValidNavList);

        List<DateValue> oriSecIdValidNavList = new ArrayList<>();
        for (DateValue secIdValidNav : secIdValidNavList) {
            DateValue oriSecIdValidNav = new DateValue();
            oriSecIdValidNav.setValue(secIdValidNav.getValue());
            oriSecIdValidNav.setDate(secIdValidNav.getDate());
            oriSecIdValidNav.setIsvalid(secIdValidNav.getIsvalid());
            oriSecIdValidNavList.add(oriSecIdValidNav);
        }
        indicatorCalcPropertyDto.getSecData().setOriNavList(oriSecIdValidNavList);

        List<String> validSecNavDateList = IndicatorCalcUtil.getValidSecNavDateList(secIdValidNavList);
        indicatorCalcPropertyDto.setDateList(validSecNavDateList);

        String benchmarkId = indicatorCalcReq.getBenchmarkId();
        if (StringUtils.isNotEmpty(benchmarkId)) {
            List<DateValue> benchmarkNavList = allNavMap.get(benchmarkId);
            List<DateValue> validBenchmarkNavList = IndicatorCalcUtil.filterOtherNav(benchmarkNavList, validSecNavDateList, false);
            indicatorCalcPropertyDto.getBenchmarkData().setBenchmarkNavList(validBenchmarkNavList);

            List<DateValue> oriValidBenchmarkNavList = new ArrayList<>();
            for (DateValue validBenchmarkNav : validBenchmarkNavList) {
                DateValue oriValidBenchmarkNav = new DateValue();
                oriValidBenchmarkNav.setValue(validBenchmarkNav.getValue());
                oriValidBenchmarkNav.setDate(validBenchmarkNav.getDate());
                oriValidBenchmarkNav.setIsvalid(validBenchmarkNav.getIsvalid());
                oriValidBenchmarkNavList.add(oriValidBenchmarkNav);
            }
            indicatorCalcPropertyDto.getBenchmarkData().setOriBenchmarkNavList(oriValidBenchmarkNavList);
        }

        List<String> indexIdList = indicatorCalcReq.getIndexIdList();
        Map<String, List<DateValue>> indexNavMap = new HashMap<>();
        Map<String, List<DateValue>> oriIndexNavMap = new HashMap<>();
        for (String index : indexIdList) {
            List<DateValue> indexNavList = allNavMap.get(index);
            List<DateValue> validIndexNavList = IndicatorCalcUtil.filterOtherNav(indexNavList, validSecNavDateList, isTrend);
            indexNavMap.put(index, validIndexNavList);

            List<DateValue> oriValidIndexNavList = new ArrayList<>();
            for (DateValue validIndexNav : validIndexNavList) {
                DateValue oriValidIndexNav = new DateValue();
                oriValidIndexNav.setValue(validIndexNav.getValue());
                oriValidIndexNav.setDate(validIndexNav.getDate());
                oriValidIndexNav.setIsvalid(validIndexNav.getIsvalid());
                oriValidIndexNavList.add(oriValidIndexNav);
            }
            oriIndexNavMap.put(index, oriValidIndexNavList);
        }
        indicatorCalcPropertyDto.getIndexData().setIndexNavMap(indexNavMap);
        indicatorCalcPropertyDto.getIndexData().setOriIndexNavMap(oriIndexNavMap);

        String riskOfFreeId = indicatorCalcReq.getRiskOfFreeId();
        if (StringUtils.isNotEmpty(riskOfFreeId)) {
            List<DateValue> riskOfFreeNavList = allNavMap.get(riskOfFreeId);
            List<DateValue> validRiskOfFreeNavList = IndicatorCalcUtil.filterOtherNav(riskOfFreeNavList, validSecNavDateList, false);
            indicatorCalcPropertyDto.getRiskFreeData().setRiskFreeNavList(validRiskOfFreeNavList);
        }
    }

    public IndicatorCalcPropertyDto getTrend(IndicatorCalcReqPropertyDto indicatorCalcReq) {
        IndicatorCalcPropertyDto indicatorCalcPropertyDto = new IndicatorCalcPropertyDto();
        indicatorCalcPropertyDto.setIndicatorCalcReq(indicatorCalcReq);

        prepareNavBaseData(indicatorCalcReq, indicatorCalcPropertyDto, true);

        initNav(indicatorCalcReq, indicatorCalcPropertyDto);

        prepareTrendRetBaseData(indicatorCalcPropertyDto);

        IndicatorCalcUtil.getTrendData(indicatorCalcPropertyDto);

        return indicatorCalcPropertyDto;
    }

    private void prepareTrendRetBaseData(IndicatorCalcPropertyDto indicatorCalcPropertyDto) {
        List<CompoundRet> benchmarkRetList = IndicatorCalcUtil.getRet(indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList(), null, null, null, true);
        indicatorCalcPropertyDto.getBenchmarkData().setBenchmarkRetList(benchmarkRetList);

        List<CompoundRet> secRetList = IndicatorCalcUtil.getRet(indicatorCalcPropertyDto.getSecData().getNavList(), null, null, null, true);
        indicatorCalcPropertyDto.getSecData().setRetList(secRetList);

        Map<String, List<CompoundRet>> indexRetListMap = new HashMap<>();
        List<String> indexIdList = indicatorCalcPropertyDto.getIndicatorCalcReq().getIndexIdList();
        Map<String, List<DateValue>> indexNavMap = indicatorCalcPropertyDto.getIndexData().getIndexNavMap();
        for (String indexId : indexIdList) {
            List<DateValue> indexNav = indexNavMap.get(indexId);
            List<CompoundRet> indexRetList = IndicatorCalcUtil.getRet(indexNav, null, null, null, true);
            indexRetListMap.put(indexId, indexRetList);
        }
        indicatorCalcPropertyDto.getIndexData().setIndexRetListMap(indexRetListMap);
    }

    private void initNav(IndicatorCalcReqPropertyDto indicatorCalcReq, IndicatorCalcPropertyDto indicatorCalcPropertyDto) {
        BigDecimal initValue = indicatorCalcReq.getInitValue();
        if (initValue != null) {
            NavUtil.initNavValue(indicatorCalcPropertyDto.getSecData().getNavList(), initValue);

            if (StringUtils.isNotEmpty(indicatorCalcReq.getBenchmarkId())) {
                NavUtil.initNavValue(indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList(), initValue);
            }

            List<String> indexIdList = indicatorCalcReq.getIndexIdList();
            for (String indexId : indexIdList) {
                NavUtil.initNavValue(indicatorCalcPropertyDto.getIndexData().getIndexNavMap().get(indexId), initValue);
            }
        }
    }

    private static class CalcServiceBuilder {
        public static final CalcService INSTANCE = new CalcService();
    }
}
