|
@@ -3,6 +3,7 @@ package com.smppw.analysis.application.service.info;
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.collection.ListUtil;
|
|
|
+import cn.hutool.core.date.DateUnit;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.map.MapUtil;
|
|
|
import cn.hutool.core.text.CharSequenceUtil;
|
|
@@ -23,9 +24,15 @@ import com.smppw.common.pojo.IStrategy;
|
|
|
import com.smppw.common.pojo.NewSubStrategy;
|
|
|
import com.smppw.common.pojo.ValueLabelVO;
|
|
|
import com.smppw.common.pojo.dto.DateValue;
|
|
|
+import com.smppw.common.pojo.dto.calc.IndicatorCalcIndexDataDto;
|
|
|
import com.smppw.common.pojo.dto.calc.IndicatorCalcPropertyDto;
|
|
|
+import com.smppw.common.pojo.dto.calc.IndicatorCalcSecDataDto;
|
|
|
import com.smppw.common.pojo.dto.calc.IndicatorCalcTimeRangeDto;
|
|
|
+import com.smppw.common.pojo.dto.indicator.CalcMultipleSecMultipleTimeRangeIndicatorReq;
|
|
|
+import com.smppw.common.pojo.dto.indicator.DateIntervalDto;
|
|
|
import com.smppw.common.pojo.enums.*;
|
|
|
+import com.smppw.common.pojo.enums.strategy.Strategy;
|
|
|
+import com.smppw.constants.Consts;
|
|
|
import com.smppw.constants.DateConst;
|
|
|
import com.smppw.core.IndicatorService;
|
|
|
import com.smppw.utils.BigDecimalUtils;
|
|
@@ -419,4 +426,92 @@ public class FundInfoService {
|
|
|
return resultList;
|
|
|
}
|
|
|
|
|
|
+ public List<ManualFundManagerChangeVO> managerChangeList(ManualFundManagerParams params) {
|
|
|
+ String refId = params.getRefId();
|
|
|
+ String benchmarkId = params.getBenchmarkId();
|
|
|
+ List<ManualFundManagerChangeDo> dataList = this.baseInfoService.listFundManagerChangeHistory(refId);
|
|
|
+
|
|
|
+ dataList = dataList.stream().filter(e -> e.getStartDate() != null).collect(Collectors.toList());
|
|
|
+ // 按基金经理+开始任职时间分组每个经理只取一条数据
|
|
|
+ Map<String, ManualFundManagerChangeDo> managerInfoMap = MapUtil.newHashMap();
|
|
|
+ Map<String, List<ManualFundManagerChangeDo>> collect = dataList.stream().collect(Collectors.groupingBy(e -> e.getManagerId() + e.getStartDate(), Collectors.toList()));
|
|
|
+ collect.forEach((k ,v) -> {
|
|
|
+ ManualFundManagerChangeDo temp = v.stream().findFirst().orElse(null);
|
|
|
+ managerInfoMap.put(k, temp);
|
|
|
+ });
|
|
|
+
|
|
|
+ List<ManualFundManagerChangeVO> resultList = ListUtil.list(true);
|
|
|
+ List<Indicator> indicatorList = ListUtil.of(Indicator.IntervalReturn, Indicator.AnnualReturn, Indicator.MaxDrawdown,
|
|
|
+ Indicator.SortinoRatio, Indicator.CalmarRatio);
|
|
|
+ managerInfoMap.forEach((k, data) -> {
|
|
|
+ ManualFundManagerChangeVO vo = new ManualFundManagerChangeVO();
|
|
|
+ vo.setManagerId(data.getManagerId());
|
|
|
+ vo.setManagerName(data.getManagerName());
|
|
|
+ // 任职日期和天数计算
|
|
|
+ vo.setEmployDate(data.getStartDate() + "~" + (CharSequenceUtil.isBlank(data.getEndDate()) ? "至今" : data.getEndDate()));
|
|
|
+ Date date = new Date();
|
|
|
+ if (CharSequenceUtil.isNotBlank(data.getEndDate())) {
|
|
|
+ date = DateUtil.parseDate(data.getEndDate());
|
|
|
+ }
|
|
|
+ vo.setEmployDayNum(DateUtil.between(DateUtil.parseDate(data.getStartDate()), date, DateUnit.DAY) + "");
|
|
|
+ // 指标计算
|
|
|
+ Map<String, Map<String, String>> indicatorValue =
|
|
|
+ this.getIndicatorValue(refId, benchmarkId, data.getStartDate(), data.getEndDate(), indicatorList);
|
|
|
+ if (indicatorValue.get(refId) != null) {
|
|
|
+ vo.setFundRet(indicatorValue.get(refId).get(Indicator.IntervalReturn.name()));
|
|
|
+ vo.setAnnualRet(indicatorValue.get(refId).get(Indicator.AnnualReturn.name()));
|
|
|
+ vo.setMaxDrawdown(indicatorValue.get(refId).get(Indicator.MaxDrawdown.name()));
|
|
|
+ vo.setCalmar(indicatorValue.get(refId).get(Indicator.CalmarRatio.name()));
|
|
|
+ vo.setSortino(indicatorValue.get(refId).get(Indicator.SortinoRatio.name()));
|
|
|
+ }
|
|
|
+ resultList.add(vo);
|
|
|
+ });
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算公募基金和其基准区间内的指标
|
|
|
+ *
|
|
|
+ * @param refId 公募基金
|
|
|
+ * @param benchmarkId 基准
|
|
|
+ * @param startDate 开始日期
|
|
|
+ * @param endDate 结束日期
|
|
|
+ * @param indicatorList 计算指标
|
|
|
+ * @return /
|
|
|
+ */
|
|
|
+ private Map<String, Map<String, String>> getIndicatorValue(String refId, String benchmarkId, String startDate, String endDate, List<Indicator> indicatorList) {
|
|
|
+ DateIntervalDto dateIntervalDto = DateIntervalDto.builder()
|
|
|
+ .id(DateIntervalType.CustomInterval.name()).startDate(startDate).endDate(endDate)
|
|
|
+ .dateIntervalType(DateIntervalType.CustomInterval).frequency(Frequency.Default).build();
|
|
|
+ Map<String, List<DateIntervalDto>> dateIntervalMap = MapUtil.builder(refId, ListUtil.of(dateIntervalDto)).build();
|
|
|
+ Map<String, String> benchmarkIdMap = MapUtil.builder(refId, benchmarkId).build();
|
|
|
+ CalcMultipleSecMultipleTimeRangeIndicatorReq req = CalcMultipleSecMultipleTimeRangeIndicatorReq.builder()
|
|
|
+ .mainSecIdList(ListUtil.of(refId))
|
|
|
+ .secBenchmarkIdMap(benchmarkIdMap)
|
|
|
+ .indexIdList(ListUtil.of(benchmarkId))
|
|
|
+ .raiseType(RaiseType.Both)
|
|
|
+ .strategy(Strategy.All)
|
|
|
+ .visibility(Visibility.Both)
|
|
|
+ .dataFrequency(Frequency.Default)
|
|
|
+ .navType(NavType.CumulativeNav)
|
|
|
+ .secDateIntervalDtoListMap(dateIntervalMap)
|
|
|
+ .indicatorList(indicatorList)
|
|
|
+ .geoExtraindicatorList(ListUtil.empty())
|
|
|
+ .ifAnnualize(true)
|
|
|
+ .riskOfFreeId(Consts.RISK_OF_FREE)
|
|
|
+ .calcIndexRetIndicatorValue(true)
|
|
|
+ .ifConvertPerformanceConsistencyWord(true).build();
|
|
|
+ Map<String, List<IndicatorCalcPropertyDto>> indicatorValueMap = this.baseIndicatorServiceV2.calcMultipleSecMultipleTimeRangeIndicator(req);
|
|
|
+
|
|
|
+ // DateIntervalType.CustomInterval 类型下每个标的只会返回一个维度下的指标计算结果,所以只获取第一条记录的指标计算结果
|
|
|
+ Map<String, Map<String, String>> result = MapUtil.newHashMap();
|
|
|
+ Map<String, String> valueMap = Optional.ofNullable(indicatorValueMap).map(e -> e.get(refId)).orElse(ListUtil.empty()).stream().findFirst()
|
|
|
+ .map(IndicatorCalcPropertyDto::getSecData).map(IndicatorCalcSecDataDto::getIndicatorValueMap).orElse(MapUtil.empty());
|
|
|
+ Map<String, String> valueBenchmarkMap = Optional.ofNullable(indicatorValueMap).map(e -> e.get(refId)).orElse(ListUtil.empty()).stream().findFirst()
|
|
|
+ .map(IndicatorCalcPropertyDto::getIndexData).map(IndicatorCalcIndexDataDto::getIndexIndicatorValueMap).map(e ->e.get(benchmarkId)).orElse(MapUtil.empty());
|
|
|
+ result.put(refId, valueMap);
|
|
|
+ result.put(benchmarkId, valueBenchmarkMap);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
}
|