package com.smppw.utils;

import com.smppw.common.cache.CaffeineLocalCache;
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.IndicatorCalcTimeRangeDto;
import com.smppw.common.pojo.enums.Frequency;
import com.smppw.common.pojo.enums.TimeRange;
import com.smppw.common.pojo.enums.TrendType;
import com.smppw.core.trend.Trend;
import com.smppw.core.trend.TrendFactory;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author lzj
 */
public class IndicatorCalcUtil {

    /**
     * 获取标的的有效净值序列
     * 截取规则 :
     *  开始日期 : 1, timeRange == TimeRange.FromSetup - 开始日期直接用入参的开始日期, 其他timeRange根据下方规则截取
     *              2. 如果入参的开始日期有净值, 则开始日期直接用入参的开始日期. 否则先往前找四个交易日, 找不到就往后截
     * @param secId 标的ID
     * @param indicatorCalcTimeRangeDto 时间区间
     * @param allNavMap 净值map
     */
    public static List<DateValue> getSecIdValidNav(String secId, IndicatorCalcTimeRangeDto indicatorCalcTimeRangeDto, Map<String, List<DateValue>> allNavMap, boolean isTrend, Frequency frequency) {
        //标的的净值序列
        List<DateValue> secNavList = allNavMap.get(secId);

        //标的的净值map key-日期  value-净值
        Map<String,Double> secNavMap = new HashMap<>();
        //全部的日期序列
        List<String> dateList = new ArrayList<>();
        for (DateValue dv : secNavList) {
            secNavMap.put(dv.getDate(),dv.getValue());
            dateList.add(dv.getDate());
        }

        boolean isValidIndicatorCalcTimeRangeDto = (null != indicatorCalcTimeRangeDto && !StringUtils.isEmpty(indicatorCalcTimeRangeDto.getStartDate()) &&
                !StringUtils.isEmpty(indicatorCalcTimeRangeDto.getEndDate()));
        if (isValidIndicatorCalcTimeRangeDto) {
            TimeRange timeRange = indicatorCalcTimeRangeDto.getTimeRange();
            String startDate = indicatorCalcTimeRangeDto.getStartDate();
            String endDate = indicatorCalcTimeRangeDto.getEndDate();

            //推开始日期
            String resultStartDate = null;
            if (timeRange == TimeRange.FromSetup || timeRange == TimeRange.Custom) {
                resultStartDate = startDate;
            } else {
                //判断startDate是否有净值
                Double startNav = secNavMap.get(startDate);
                if (startNav != null) {
                    resultStartDate = startDate;
                } else {
                    if (frequency == Frequency.Monthly) {
                        List<String> monthPreDays = indicatorCalcTimeRangeDto.getMonthPreDays();
                        List<String> monthLaterDays = indicatorCalcTimeRangeDto.getMonthLaterDays();
                        String preDays = null;
                        String laterDays = null;
                        for (String monthPreDay : monthPreDays) {
                            Double monthPreDayNav = secNavMap.get(monthPreDay);
                            if (monthPreDayNav != null) {
                                preDays = monthPreDay;
                                break;
                            }
                        }
                        for (String monthLaterDay : monthLaterDays) {
                            Double monthLaterDayNav = secNavMap.get(monthLaterDay);
                            if (monthLaterDayNav != null) {
                                laterDays = monthLaterDay;
                                break;
                            }
                        }
                        if (null != preDays || null != laterDays) {
                            if (null == preDays) {
                                resultStartDate = laterDays;
                            } else if (null == laterDays) {
                                resultStartDate = preDays;
                            } else {
                                String monthLastDate = monthPreDays.get(0);
                                //获取距离(剔除交易日)  谁近取谁, 同样近取前面的
                                int laterMonthDateDistance = 1;
                                for (String monthLaterDay : monthLaterDays) {
                                    if (laterDays.equals(monthLaterDay)) {
                                        break;
                                    } else {
                                        boolean isTradingDay = CaffeineLocalCache.getIsTradingDay(monthLaterDay);
                                        if (isTradingDay) {
                                            laterMonthDateDistance ++;
                                        }
                                    }
                                }
                                int thisMonthDateDistance = 0;
                                for (String monthPreDay : monthPreDays) {
                                    if (preDays.equals(monthPreDay)) {
                                        break;
                                    } else {
                                        boolean isTradingDay = CaffeineLocalCache.getIsTradingDay(monthPreDay);
                                        if (isTradingDay) {
                                            thisMonthDateDistance ++;
                                        }
                                    }
                                }
                                if (thisMonthDateDistance <= laterMonthDateDistance) {
                                    resultStartDate = preDays;
                                } else {
                                    resultStartDate = laterDays;
                                }
                            }
                        }
                    } else {
                        // 获取前四个交易日的集合 从大到小排序
                        List<String> tradingDayList = indicatorCalcTimeRangeDto.getPreDays();
                        for (String tradingDay : tradingDayList) {
                            startNav = secNavMap.get(tradingDay);
                            if (startNav != null) {
                                resultStartDate = tradingDay;
                                break;
                            }
                        }
                    }

                    if (resultStartDate == null) {
                        //startDate没有净值, 而且前四天的交易日都没有净值
                        String firstDate = null;
                        if (secNavList != null && secNavList.size() > 0) {
                            firstDate = secNavList.get(0).getDate();
                        }
                        if (isTrend || (timeRange == TimeRange.FromThisYear && StringUtils.isNotEmpty(firstDate) && firstDate.compareTo(startDate) >= 0)) {
                            resultStartDate = startDate;
                        } else {
                            return new ArrayList<>();
                        }
                    }
                }
            }

            indicatorCalcTimeRangeDto.setStartDate(resultStartDate);

            List<DateValue> validSecNavList = new ArrayList<>();
            //截取净值序列  [resultStartDate,endDate]

            //二分法找净值
            Integer endIndex = getMostLeftLessNav(dateList, endDate);
            Integer startIndex = -1;

            if (timeRange != TimeRange.Custom) {
                startIndex = getMostRightThanNav(dateList, resultStartDate);
            } else {
                startIndex = getMostLeftLessNav(dateList, resultStartDate);
            }

            if (startIndex == -1 || endIndex == -1 || startIndex >= endIndex) {
                return new ArrayList<>();
            }
            List<DateValue> dateValues = secNavList.subList(startIndex, endIndex + 1);

            if (dateValues.size() == 0) {
                return dateValues;
            }

            if ( dateValues.get(0).getIsvalid() == null || dateValues.get(0).getIsvalid() == 0 ) {
                dateValues.get(0).setIsvalid(1);
            }

            if (dateValues.get(dateValues.size() - 1).getIsvalid() == null || dateValues.get(dateValues.size() - 1).getIsvalid() == 0) {
                dateValues.get(dateValues.size() - 1).setIsvalid(1);
            }

            for (DateValue dateValue : dateValues) {
                if (dateValue.getIsvalid() != null && dateValue.getIsvalid() == 1) {
                    DateValue validSecNav = new DateValue();
                    validSecNav.setIsvalid(dateValue.getIsvalid());
                    validSecNav.setValue(dateValue.getValue());
                    validSecNav.setDate(dateValue.getDate());
                    validSecNavList.add(validSecNav);
                }
            }
            return validSecNavList;
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * 循环净值序列, 拿出日期序列  排序, 从小到大
     * @param navList   净值序列
     * @return  日期序列
     */
    public static List<String> getValidSecNavDateList(List<DateValue> navList) {
        List<String> validSecNavDateList = new ArrayList<>();
        for (DateValue dateValue : navList) {
            validSecNavDateList.add(dateValue.getDate());
        }

        //排序, 从小到大
        Collections.sort(validSecNavDateList);
        return validSecNavDateList;
    }

    /**
     * 更近入参的时间序列筛选净值序列
     * @param navList   净值序列
     * @param dateList  时间序列
     * @return  有效净值序列
     */
    public static List<DateValue> filterOtherNav(List<DateValue> navList, List<String> dateList, boolean isTrendIndex) {
        if (null != navList && navList.size() > 0) {
            Map<String, DateValue> dateNavMap = new HashMap<>();
            for (DateValue nav : navList) {
                dateNavMap.put(nav.getDate(), nav);
            }

            List<DateValue> validNavList = new ArrayList<>();
            for (int i = 0 ; i < dateList.size() ; i++) {
                DateValue dateValue = new DateValue();
                dateValue.setDate(dateList.get(i));
                Double value = null;
                if (dateNavMap.containsKey(dateList.get(i))) {
                    value = dateNavMap.get(dateList.get(i)).getValue();
                } else if (!isTrendIndex || i == 0) {
                    //二分法获取小于等于的最接近这个日期的净值
                    DateValue lessDateValue = getMostLeftNoLessNav(navList, dateList.get(i));
                    value = lessDateValue.getValue();
                }
                dateValue.setValue(value);
                dateValue.setIsvalid(1);
                validNavList.add(dateValue);
            }
            return validNavList;
        }
        return new ArrayList<>();
    }

    /**
     *
     * @param navList   从小到大的净值序列
     * @param date  日期
     * @return  小于等于 date 的 日期最大的净值
     */
    private static DateValue getMostLeftNoLessNav(List<DateValue> navList, String date) {
        if (navList == null || navList.size() == 0) {
            return new DateValue();
        }
        int L = 0;
        int R = navList.size() - 1;
        int ans = -1;
        while (L <= R) {
            int mid = (L + R) / 2;
            if (navList.get(mid).getDate() !=null && navList.get(mid).getDate().compareTo(date) <= 0) {
                ans = mid;
                L = mid + 1;
            } else {
                R = mid - 1;
            }
        }
        return ans == -1 ? new DateValue(date, null) : navList.get(ans);
    }

    /**
     *
     * @param dateList   从小到大的净值序列
     * @param date  日期
     * @return  小于等于 date 的 日期最大的净值
     */
    public static Integer getMostLeftLessNav(List<String> dateList, String date) {
        if (dateList == null || dateList.size() == 0) {
            return -1;
        }
        int L = 0;
        int R = dateList.size() - 1;
        int ans = -1;
        while (L <= R) {
            int mid = (L + R) / 2;
            if (dateList.get(mid) !=null && dateList.get(mid).compareTo(date) <= 0) {
                ans = mid;
                L = mid + 1;
            } else {
                R = mid - 1;
            }
        }
        return ans;
    }

    /**
     *
     * @param dateList   从小到大的净值序列
     * @param date  日期
     * @return  大于等于 date 的 日期最小的净值
     */
    public static Integer getMostRightThanNav(List<String> dateList, String date) {
        if(dateList == null || Objects.requireNonNull(dateList).size() == 0){
            return -1;
        }else if(dateList.get(dateList.size()-1).compareTo(date) < 0){
            return dateList.size() - 1;
        }
        int low = 0;
        int high = dateList.size() - 1;
        while(low < high){
            //防止溢出
            int mid = low + (high-low)/2;
            if(dateList.get(mid).compareTo(date) < 0){
                low = mid + 1;
            }else{
                high = mid;
            }
        }
        return low;
    }

    /**
     *  获取收益
     * @param navList
     * @param benchmarkRetList
     * @param riskFreeDateRetMap
     * @param strategyDateRetMap
     * @return
     */
    public static List<CompoundRet> getRet(List<DateValue> navList, List<CompoundRet> benchmarkRetList, Map<String, CompoundRet> riskFreeDateRetMap, Map<String, CompoundRet> strategyDateRetMap) {
        return getRet(navList, benchmarkRetList, riskFreeDateRetMap, strategyDateRetMap, false);
    }

    /**
     *  获取收益
     * @param navList
     * @param benchmarkRetList
     * @param riskFreeDateRetMap
     * @param strategyDateRetMap
     * @return
     */
    public static List<CompoundRet> getRet(List<DateValue> navList, List<CompoundRet> benchmarkRetList, Map<String, CompoundRet> riskFreeDateRetMap, Map<String, CompoundRet> strategyDateRetMap, Boolean isTrend) {
        List<CompoundRet> retList = new ArrayList<>();

        if (navList == null || navList.size() == 0) {
            return retList;
        }

        //排序 从小到大
        Collections.sort(navList, new Comparator<DateValue>() {
            @Override
            public int compare(DateValue o1, DateValue o2) {
                return o1.getDate().compareTo(o2.getDate());
            }
        });

        Map<String, CompoundRet> benchmarkRetMap = new HashMap<>();
        if (benchmarkRetList != null) {
            for (CompoundRet benchmarkRet : benchmarkRetList) {
                benchmarkRetMap.put(benchmarkRet.getEndDate(), benchmarkRet);
            }
        }

        Double preNav = 0.0;
        for (int i = 0 ; i < navList.size() ; i++) {
            CompoundRet compoundRet = new CompoundRet();
            Double ret = null;
            if (i == 0 && isTrend && navList.get(0).getValue() != null) {
                ret = 0.0;
            }
            String date = navList.get(i).getDate();
            compoundRet.setEndDate(date);
            if ( i != 0 ) {
                Double nav = navList.get(i).getValue();
                if (preNav != null && nav!= null) {
                    BigDecimal preNavBigDecimal = new BigDecimal(preNav.toString());
                    BigDecimal navBigDecimal = new BigDecimal(nav.toString());
                    BigDecimal bigDecimalRet = BigDecimalUtils.subtract(BigDecimalUtils.divide(navBigDecimal, preNavBigDecimal), new BigDecimal("1"));
                    if (null != bigDecimalRet) {
                        ret = bigDecimalRet.doubleValue();
                    }
                    if (null != riskFreeDateRetMap) {
                        compoundRet.setRetOfRf(riskFreeDateRetMap.get(date) != null ? riskFreeDateRetMap.get(date).getRetOfFund() : null);
                    }
                    if (null != strategyDateRetMap) {
                        compoundRet.setRetOfStg(strategyDateRetMap.get(date) != null ? strategyDateRetMap.get(date).getRetOfFund() : null);
                    }
                    if (benchmarkRetList != null) {
                        compoundRet.setRetOfBmk(benchmarkRetMap.get(date) != null ? benchmarkRetMap.get(date).getRetOfFund() : null);
                    }
                }
            }
            compoundRet.setRetOfFund(ret);

            retList.add(compoundRet);
            if (isTrend) {
                if (preNav == null || preNav.compareTo(0.0) == 0) {
                    preNav = navList.get(i).getValue();
                }
            } else {
                preNav = navList.get(i).getValue();
            }
        }
        return retList;
    }

    public static List<CompoundRet> calcExtraRetGeo(List<CompoundRet> secRetList, List<CompoundRet> benchmarkRetList) {
        List<CompoundRet> extraRetAriList = new ArrayList<>();

        Map<String, CompoundRet> benchmarkRetMap = new HashMap<>();
        for (CompoundRet compoundRet : benchmarkRetList) {
            benchmarkRetMap.put(compoundRet.getEndDate(), compoundRet);
        }
        for (CompoundRet compoundRet : secRetList) {
            CompoundRet extraRetAri = new CompoundRet();
            Double secRet = compoundRet.getRetOfFund();
            CompoundRet benchmarkRetDto = benchmarkRetMap.get(compoundRet.getEndDate());
            if (null == benchmarkRetDto || null ==secRet || benchmarkRetDto.getRetOfFund() == null ) {
                extraRetAri.setEndDate(compoundRet.getEndDate());
                extraRetAri.setRetOfFund(null);
            } else if (benchmarkRetDto.getRetOfFund().compareTo(0.0) == 0) {
                extraRetAri.setEndDate(compoundRet.getEndDate());
                extraRetAri.setRetOfFund(0.0);
            } else {
                Double molecule = secRet + 1;
                Double denominator = benchmarkRetDto.getRetOfFund() + 1;
                Double benchmarkRet = BigDecimalUtils.subtract(BigDecimalUtils.divide(new BigDecimal(molecule), new BigDecimal(denominator)), new BigDecimal("1")).doubleValue();
                extraRetAri.setEndDate(compoundRet.getEndDate());
                extraRetAri.setRetOfFund(benchmarkRet);
            }
            extraRetAriList.add(extraRetAri);
        }

        return extraRetAriList;
    }

    public static void getTrendData(IndicatorCalcPropertyDto indicatorCalcPropertyDto) {
        List<TrendType> trendTypeList = indicatorCalcPropertyDto.getIndicatorCalcReq().getTrendTypeList();

        List<CompoundRet> benchmarkRetList = null;
        if (indicatorCalcPropertyDto.getIndicatorCalcReq().getFixedIncome() != null) {
            benchmarkRetList = new ArrayList<>();
            List<CompoundRet> retList = indicatorCalcPropertyDto.getSecData().getRetList();
            for (CompoundRet ret : retList) {
                CompoundRet bRet = new CompoundRet();
                bRet.setEndDate(ret.getEndDate());
                bRet.setRetOfFund(BigDecimalUtils.divide(indicatorCalcPropertyDto.getIndicatorCalcReq().getFixedIncome(), new BigDecimal("100")).doubleValue());
                benchmarkRetList.add(bRet);
            }
        } else {
            benchmarkRetList = indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkRetList();
        }

        for (TrendType trendType : trendTypeList) {
            TrendFactory trendFactory = TrendFactory.getInstance();
            Trend trend = trendFactory.get(trendType);
            //标的的走势数据 - start
            if (TrendType.Nav == trendType) {
                List<DateValue> navList = trend.getDateValueTrend(null, indicatorCalcPropertyDto.getSecData().getNavList(), null);
                indicatorCalcPropertyDto.getSecData().setNavList(navList);

                List<Double> trendList = datevalueToDouble(navList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);

            } else if (TrendType.Ret == trendType) {
                List<CompoundRet> retList = trend.getCompoundRetTrend(indicatorCalcPropertyDto.getSecData().getNavList(), null, null);
                indicatorCalcPropertyDto.getSecData().setRetList(retList);

                List<Double> trendList = compoundRetToDouble(retList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);

            } else if (TrendType.ExtraNav == trendType) {
                List<DateValue> extraNavList = trend.getDateValueTrend(null, indicatorCalcPropertyDto.getSecData().getNavList(), indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList());
                indicatorCalcPropertyDto.getSecData().setExtraNavList(extraNavList);

                List<Double> trendList = datevalueToDouble(extraNavList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);

            } else if (TrendType.ExtraRetAri == trendType ) {

                List<CompoundRet> extraRetList = trend.getCompoundRetTrend(null, indicatorCalcPropertyDto.getSecData().getRetList(), benchmarkRetList);
                indicatorCalcPropertyDto.getSecData().setExtraRetAriList(extraRetList);
                List<Double> trendList = compoundRetToDouble(extraRetList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);

            } else if (TrendType.ExtraRetGeo == trendType ) {
                List<CompoundRet> extraRetList = trend.getCompoundRetTrend(null, indicatorCalcPropertyDto.getSecData().getRetList(), benchmarkRetList);
                indicatorCalcPropertyDto.getSecData().setExtraRetGeoList(extraRetList);
                List<Double> trendList = compoundRetToDouble(extraRetList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);

            } else if (TrendType.DrawdownTrend == trendType) {
                List<DateValue> drawDownValueList = trend.getDateValueTrend(indicatorCalcPropertyDto.getDateList(), indicatorCalcPropertyDto.getSecData().getNavList(), null);
                indicatorCalcPropertyDto.getSecData().setDrawdownList(drawDownValueList);

                List<Double> trendList = datevalueToDouble(drawDownValueList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);

            } else if (TrendType.ExtraDrawdownTrend == trendType) {
                List<DateValue> extraDrawDownValueList = trend.getDateValueTrend(indicatorCalcPropertyDto.getDateList(),
                        indicatorCalcPropertyDto.getSecData().getNavList(), indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList());
                indicatorCalcPropertyDto.getSecData().setDrawdownList(extraDrawDownValueList);

                List<Double> trendList = datevalueToDouble(extraDrawDownValueList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);

            } else if (TrendType.NetValueChange == trendType) {
                List<CompoundRet> netValueChangeList = trend.getCompoundRetTrend(indicatorCalcPropertyDto.getSecData().getNavList(), null, null);
                List<Double> trendList = compoundRetToDouble(netValueChangeList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);
            } else if (TrendType.OrigNav == trendType) {
                List<DateValue> navList = trend.getDateValueTrend(null, indicatorCalcPropertyDto.getSecData().getOriNavList(), null);
                indicatorCalcPropertyDto.getSecData().setNavList(navList);

                List<Double> trendList = datevalueToDouble(navList);
                indicatorCalcPropertyDto.getSecData().getTrendValueMap().put(trendType, trendList);
            }
            //标的的走势数据 - end

            //基准 和 指数 的走势数据 - start
            List<String> indexIdList = indicatorCalcPropertyDto.getIndicatorCalcReq().getIndexIdList();
            if (TrendType.Nav == trendType || TrendType.ExtraNav == trendType) {
                Trend navTrend = trendFactory.get(TrendType.Nav);
                List<DateValue> benchmarkNavList = navTrend.getDateValueTrend(null, indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList(), null);
                indicatorCalcPropertyDto.getBenchmarkData().setBenchmarkNavList(benchmarkNavList);

                List<Double> benchmarkTrendList = datevalueToDouble(benchmarkNavList);
                indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkTrendValueMap().put(TrendType.Nav, benchmarkTrendList);

                Map<String, List<DateValue>> indexNavMap = new HashMap<>();
                for (String index : indexIdList) {
                    List<DateValue> indexNavList = navTrend.getDateValueTrend(null, indicatorCalcPropertyDto.getIndexData().getIndexNavMap().get(index), null);
                    indexNavMap.put(index, indexNavList);

                    List<Double> indexTrendList = datevalueToDouble(indexNavList);
                    Map<String, Map<TrendType, List<Double>>> indexTrendValueMapMap = indicatorCalcPropertyDto.getIndexData().getIndexTrendValueMap();
                    if (indexTrendValueMapMap.containsKey(index)) {
                        indexTrendValueMapMap.get(index).put(TrendType.Nav,indexTrendList);
                    } else {
                        Map<TrendType, List<Double>> indexTrendValueMap = new HashMap<>();
                        indexTrendValueMap.put(TrendType.Nav, indexTrendList);
                        indexTrendValueMapMap.put(index, indexTrendValueMap);
                    }
                }
                indicatorCalcPropertyDto.getIndexData().setIndexNavMap(indexNavMap);

            } else if (TrendType.Ret == trendType || TrendType.ExtraRetAri == trendType || TrendType.ExtraRetGeo == trendType) {
                Trend retTrend = trendFactory.get(TrendType.Ret);
                List<CompoundRet> retList = retTrend.getCompoundRetTrend(indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList(), null, null);
                indicatorCalcPropertyDto.getBenchmarkData().setBenchmarkRetList(retList);

                List<Double> benchmarkTrendList = compoundRetToDouble(retList);
                indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkTrendValueMap().put(TrendType.Ret, benchmarkTrendList);

                Map<String, List<CompoundRet>> indexRetListMap = new HashMap<>();
                for (String index : indexIdList) {
                    List<CompoundRet> indexRetList = retTrend.getCompoundRetTrend(indicatorCalcPropertyDto.getIndexData().getIndexNavMap().get(index), null, null);
                    indexRetListMap.put(index, indexRetList);

                    List<Double> indexTrendList = compoundRetToDouble(indexRetList);
                    Map<String, Map<TrendType, List<Double>>> indexTrendValueMapMap = indicatorCalcPropertyDto.getIndexData().getIndexTrendValueMap();
                    if (indexTrendValueMapMap.containsKey(index)) {
                        indexTrendValueMapMap.get(index).put(TrendType.Ret,indexTrendList);
                    } else {
                        Map<TrendType, List<Double>> indexTrendValueMap = new HashMap<>();
                        indexTrendValueMap.put(TrendType.Ret, indexTrendList);
                        indexTrendValueMapMap.put(index, indexTrendValueMap);
                    }

                }
                indicatorCalcPropertyDto.getIndexData().setIndexRetListMap(indexRetListMap);

            } else if (TrendType.DrawdownTrend == trendType || TrendType.ExtraDrawdownTrend == trendType) {
                Trend drawdownTrendTrend = trendFactory.get(TrendType.DrawdownTrend);
                List<DateValue> benchmarkDrawDownValueList = drawdownTrendTrend.getDateValueTrend(indicatorCalcPropertyDto.getDateList(), indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkNavList(), null);
                indicatorCalcPropertyDto.getBenchmarkData().setBenchmarkDrawdown(benchmarkDrawDownValueList);

                List<Double> benchmarkTrendList = datevalueToDouble(benchmarkDrawDownValueList);
                indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkTrendValueMap().put(TrendType.DrawdownTrend, benchmarkTrendList);

                Map<String, List<DateValue>> indexDrawdownMap = new HashMap<>();
                for (String index : indexIdList) {
                    List<DateValue> indexDrawDownValueList = drawdownTrendTrend.getDateValueTrend(indicatorCalcPropertyDto.getDateList(), indicatorCalcPropertyDto.getIndexData().getIndexNavMap().get(index), null);
                    indexDrawdownMap.put(index, indexDrawDownValueList);

                    List<Double> indexTrendList = datevalueToDouble(indexDrawDownValueList);
                    Map<String, Map<TrendType, List<Double>>> indexTrendValueMapMap = indicatorCalcPropertyDto.getIndexData().getIndexTrendValueMap();
                    if (indexTrendValueMapMap.containsKey(index)) {
                        indexTrendValueMapMap.get(index).put(TrendType.DrawdownTrend,indexTrendList);
                    } else {
                        Map<TrendType, List<Double>> indexTrendValueMap = new HashMap<>();
                        indexTrendValueMap.put(TrendType.DrawdownTrend, indexTrendList);
                        indexTrendValueMapMap.put(index, indexTrendValueMap);
                    }

                }
                indicatorCalcPropertyDto.getIndexData().setIndexDrawdownMap(indexDrawdownMap);
            } else if (TrendType.OrigNav == trendType) {
                Trend navTrend = trendFactory.get(TrendType.Nav);
                List<DateValue> benchmarkNavList = navTrend.getDateValueTrend(null, indicatorCalcPropertyDto.getBenchmarkData().getOriBenchmarkNavList(), null);
                indicatorCalcPropertyDto.getBenchmarkData().setOriBenchmarkNavList(benchmarkNavList);

                List<Double> benchmarkTrendList = datevalueToDouble(benchmarkNavList);
                indicatorCalcPropertyDto.getBenchmarkData().getBenchmarkTrendValueMap().put(TrendType.OrigNav, benchmarkTrendList);

                Map<String, List<DateValue>> indexNavMap = new HashMap<>();
                for (String index : indexIdList) {
                    List<DateValue> indexNavList = navTrend.getDateValueTrend(null, indicatorCalcPropertyDto.getIndexData().getOriIndexNavMap().get(index), null);
                    indexNavMap.put(index, indexNavList);

                    List<Double> indexTrendList = datevalueToDouble(indexNavList);
                    Map<String, Map<TrendType, List<Double>>> indexTrendValueMapMap = indicatorCalcPropertyDto.getIndexData().getIndexTrendValueMap();
                    if (indexTrendValueMapMap.containsKey(index)) {
                        indexTrendValueMapMap.get(index).put(TrendType.OrigNav,indexTrendList);
                    } else {
                        Map<TrendType, List<Double>> indexTrendValueMap = new HashMap<>();
                        indexTrendValueMap.put(TrendType.OrigNav, indexTrendList);
                        indexTrendValueMapMap.put(index, indexTrendValueMap);
                    }
                }
                indicatorCalcPropertyDto.getIndexData().setOriIndexNavMap(indexNavMap);
            }
            //基准 和 指数 的走势数据 - end
        }
    }

    public static List<DateValue> navNormalize(List<DateValue> dateValueList) {
        Double firstValue = null;
        List<DateValue> navNormalizeList = new ArrayList<>();
        for (DateValue dateValue : dateValueList) {
            DateValue navNormalize = new DateValue();
            navNormalize.setDate(dateValue.getDate());

            navNormalize.setIsvalid(dateValue.getIsvalid());
            if (dateValue.getValue() == null || dateValue.getValue().compareTo(0.0) == 0) {
                navNormalize.setValue(0.0);
            } else {
                if (firstValue == null) {
                    firstValue = dateValue.getValue();
                }
                navNormalize.setValue(dateValue.getValue() / firstValue);
            }
            navNormalizeList.add(navNormalize);

        }
        return navNormalizeList;
    }

    private static List<Double> datevalueToDouble(List<DateValue> dateValueList) {
        List<Double> doubles = new ArrayList<>();
        for (DateValue dateValue : dateValueList) {
            doubles.add(dateValue.getValue());
        }
        return doubles;
    }

    private static List<Double> compoundRetToDouble(List<CompoundRet> list) {
        List<Double> doubles = new ArrayList<>();
        for (CompoundRet compoundRet : list) {
            doubles.add(compoundRet.getRetOfFund());
        }
        return doubles;
    }
}
