|
@@ -0,0 +1,180 @@
|
|
|
+package com.smppw.analysis.application.service.info;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import cn.hutool.core.collection.ListUtil;
|
|
|
+import cn.hutool.core.map.MapUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.smppw.analysis.application.dto.info.*;
|
|
|
+import com.smppw.analysis.domain.dto.info.HeadInfoParams;
|
|
|
+import com.smppw.analysis.domain.dto.info.HeadInfoVO;
|
|
|
+import com.smppw.analysis.domain.dto.info.PrivatelyFundHeadInfoVO;
|
|
|
+import com.smppw.analysis.domain.dto.info.PubliclyFundHeadInfoVO;
|
|
|
+import com.smppw.analysis.domain.dto.performance.IndicatorParams;
|
|
|
+import com.smppw.analysis.domain.manager.info.HeadInfoFactory;
|
|
|
+import com.smppw.analysis.domain.manager.performance.Performance;
|
|
|
+import com.smppw.analysis.domain.manager.performance.PerformanceConstants;
|
|
|
+import com.smppw.analysis.domain.manager.performance.PerformanceFactory;
|
|
|
+import com.smppw.analysis.domain.service.BaseInfoService;
|
|
|
+import com.smppw.analysis.domain.service.NavService;
|
|
|
+import com.smppw.analysis.infrastructure.exception.APIException;
|
|
|
+import com.smppw.common.pojo.IStrategy;
|
|
|
+import com.smppw.common.pojo.ValueLabelVO;
|
|
|
+import com.smppw.common.pojo.dto.DateValue;
|
|
|
+import com.smppw.common.pojo.dto.calc.IndicatorCalcTimeRangeDto;
|
|
|
+import com.smppw.common.pojo.enums.*;
|
|
|
+import com.smppw.constants.SecType;
|
|
|
+import com.smppw.core.IndicatorService;
|
|
|
+import com.smppw.utils.StrategyHandleUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class GlobalService {
|
|
|
+ private final NavService navService;
|
|
|
+ private final BaseInfoService baseInfoService;
|
|
|
+ private final HeadInfoFactory headInfoFactory;
|
|
|
+ private final PerformanceFactory performanceFactory;
|
|
|
+
|
|
|
+ public GlobalService(NavService navService,
|
|
|
+ BaseInfoService baseInfoService,
|
|
|
+ HeadInfoFactory headInfoFactory,
|
|
|
+ PerformanceFactory performanceFactory) {
|
|
|
+ this.navService = navService;
|
|
|
+ this.baseInfoService = baseInfoService;
|
|
|
+ this.headInfoFactory = headInfoFactory;
|
|
|
+ this.performanceFactory = performanceFactory;
|
|
|
+ }
|
|
|
+
|
|
|
+ public HeadInfoVO headInfo(HeadInfoReq req) {
|
|
|
+ HeadInfoParams params = req.convert();
|
|
|
+ String secType = this.baseInfoService.getSecType(req.getSecId());
|
|
|
+ return this.headInfoFactory.getInstance(secType).get(params);
|
|
|
+ }
|
|
|
+
|
|
|
+ public CommonInfoVO commonInfo(CommonInfoReq params) {
|
|
|
+ String secType = this.baseInfoService.getSecType(params.getSecId());
|
|
|
+ CommonInfoVO res = new CommonInfoVO();
|
|
|
+ String secId = params.getSecId();
|
|
|
+ List<Frequency> result = CollectionUtil.newArrayList();
|
|
|
+ // 获取频率
|
|
|
+ HeadInfoVO fundHeadInfo = this.headInfoFactory.getInstance(secType).get(new HeadInfoParams(secId));
|
|
|
+ if (fundHeadInfo == null) {
|
|
|
+ throw new APIException("");
|
|
|
+ }
|
|
|
+ String raiseType = fundHeadInfo.getRaiseType();
|
|
|
+ result.add(this.baseInfoService.getNavFrequency(secId));
|
|
|
+ // 将频率转换一道 取最小频率
|
|
|
+ List<Frequency> frequencies = this.toFrequencyList(result);
|
|
|
+ if (Objects.equals("2", raiseType)) {
|
|
|
+ frequencies.removeIf(p -> p.getId() == Frequency.Default.getId());
|
|
|
+ }
|
|
|
+ List<ValueLabelVO> frequencyValueLabel = this.trans2ValueLabel(frequencies);
|
|
|
+ res.setFrequency(frequencyValueLabel);
|
|
|
+ // 净值类型
|
|
|
+ List<ValueLabelVO> navType = Arrays.stream(NavType.values())
|
|
|
+ .filter(p -> !NavType.All.equals(p) && !NavType.UnitAndCumulativeNav.equals(p))
|
|
|
+ .map(p -> new ValueLabelVO(p.name(), p.getDesc())).collect(Collectors.toList());
|
|
|
+ res.setNavType(navType);
|
|
|
+ handleTimeRange(res, secId);
|
|
|
+ // 获取常用指数
|
|
|
+ List<ValueLabelVO> benchmarkList = baseInfoService.getCommonIndexList();
|
|
|
+ handleBenchmark(res, secType, benchmarkList, fundHeadInfo);
|
|
|
+ return new CommonInfoVO();
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ public HeadIndicatorVO headIndicator(HeadIndicatorReq req) {
|
|
|
+ IndicatorParams params = req.convert();
|
|
|
+ Performance<IndicatorParams, Map<String, Object>> instance = this.performanceFactory.getInstance(PerformanceConstants.INDICATOR);
|
|
|
+ Map<String, Object> dataset = instance.execute(params);
|
|
|
+ Map<String, Object> indicatorMap = MapUtil.get(dataset, req.getSecId(), Map.class);
|
|
|
+ HeadIndicatorVO vo = new HeadIndicatorVO();
|
|
|
+ vo.setAnnualReturn(MapUtil.getStr(indicatorMap, Indicator.AnnualReturn.name()));
|
|
|
+ vo.setAnnualStdDev(MapUtil.getStr(indicatorMap, Indicator.AnnualStdDev.name()));
|
|
|
+ vo.setMaxDrawdown(MapUtil.getStr(indicatorMap, Indicator.MaxDrawdown.name()));
|
|
|
+ vo.setSharpeRatio(MapUtil.getStr(indicatorMap, Indicator.SharpeRatio.name()));
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Frequency> toFrequencyList(List<Frequency> value) {
|
|
|
+ if (CollectionUtil.isEmpty(value))
|
|
|
+ return CollectionUtil.newArrayList(Frequency.Default);
|
|
|
+ if (value.contains(Frequency.Daily))
|
|
|
+ return CollectionUtil.newArrayList(Frequency.Default, Frequency.Daily, Frequency.Weekly, Frequency.Monthly);
|
|
|
+ if (value.contains(Frequency.Weekly))
|
|
|
+ return CollectionUtil.newArrayList(Frequency.Default, Frequency.Weekly, Frequency.Monthly);
|
|
|
+ if (value.contains(Frequency.Monthly))
|
|
|
+ return CollectionUtil.newArrayList(Frequency.Default, Frequency.Monthly);
|
|
|
+ return CollectionUtil.newArrayList(Frequency.Default);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<ValueLabelVO> trans2ValueLabel(List<Frequency> frequencies) {
|
|
|
+ List<ValueLabelVO> res = CollectionUtil.newArrayList();
|
|
|
+ for (Frequency frequency : frequencies) {
|
|
|
+ res.add(new ValueLabelVO(frequency.name(), frequency.getDesc()));
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleTimeRange(CommonInfoVO vo, String secId) {
|
|
|
+ List<String> refIds = ListUtil.toLinkedList(secId);
|
|
|
+ String endDate = null;
|
|
|
+ String startDate = null;
|
|
|
+ Frequency navFrequency = this.baseInfoService.getNavFrequency(secId);
|
|
|
+ Map<String, List<DateValue>> allNavMap = this.navService.getSecIdDateValueNavListMapByDb(refIds, null, null, Visibility.Both, NavType.CumulativeNav);
|
|
|
+ List<IndicatorCalcTimeRangeDto> secTimeRanges = IndicatorService.getInstance().getSecTimeRange(secId, navFrequency, allNavMap);
|
|
|
+ Map<String, String> timeRangeMap = MapUtil.newHashMap();
|
|
|
+ for (IndicatorCalcTimeRangeDto timeRange : secTimeRanges) {
|
|
|
+ if (StringUtils.isEmpty(endDate)) {
|
|
|
+ endDate = timeRange.getEndDate();
|
|
|
+ }
|
|
|
+ if (TimeRange.FromSetup == timeRange.getTimeRange()) {
|
|
|
+ startDate = timeRange.getStartDate();
|
|
|
+ }
|
|
|
+ timeRangeMap.put(timeRange.getTimeRange().name(), timeRange.getStartDate());
|
|
|
+ }
|
|
|
+ vo.setTimeRangeMap(timeRangeMap);
|
|
|
+ vo.setEndDate(endDate);
|
|
|
+ vo.setStartDate(startDate);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleBenchmark(CommonInfoVO res, String fundType, List<ValueLabelVO> benchmarkList, HeadInfoVO headInfoVO) {
|
|
|
+ String benchmarkId = null;
|
|
|
+ ValueLabelVO valueLabelVO;
|
|
|
+ // 基金有对应策略的指数
|
|
|
+ if (fundType.equals(SecType.PRIVATELY_OFFERED_FUND) || fundType.equals(SecType.PRIVATE_FUND)) {
|
|
|
+ PrivatelyFundHeadInfoVO fundHeadInfo = (PrivatelyFundHeadInfoVO) headInfoVO;
|
|
|
+ benchmarkId = fundHeadInfo.getPrimaryBenchmarkId();
|
|
|
+ valueLabelVO = new ValueLabelVO(benchmarkId, fundHeadInfo.getPrimaryBenchmarkName());
|
|
|
+ } else if (fundType.equals(SecType.PUBLICLY_OFFERED_FUNDS)) {
|
|
|
+ // 公募需要特殊处理
|
|
|
+ PubliclyFundHeadInfoVO fundHeadInfo = (PubliclyFundHeadInfoVO) headInfoVO;
|
|
|
+ Integer subStrategyId = fundHeadInfo.getSubstrategyId();
|
|
|
+ IStrategy iStrategy = StrategyHandleUtils.getStrategyById(subStrategyId);
|
|
|
+ benchmarkId = iStrategy.getBenchmark();
|
|
|
+ if (StrUtil.isBlank(benchmarkId)) {
|
|
|
+ benchmarkId = fundHeadInfo.getPrimaryBenchmarkId();
|
|
|
+ valueLabelVO = new ValueLabelVO(benchmarkId, fundHeadInfo.getPrimaryBenchmarkName());
|
|
|
+ } else {
|
|
|
+ Map<String, String> querySecName = this.baseInfoService.querySecName(ListUtil.of(iStrategy.getBenchmark()));
|
|
|
+ String indexName = querySecName.get(iStrategy.getBenchmark());
|
|
|
+ valueLabelVO = new ValueLabelVO(benchmarkId, indexName);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ valueLabelVO = new ValueLabelVO();
|
|
|
+ }
|
|
|
+ if (CollectionUtil.isNotEmpty(benchmarkList)) {
|
|
|
+ Optional<ValueLabelVO> contains = benchmarkList.stream().filter(p -> p.getValue().equals(valueLabelVO.getValue())).findFirst();
|
|
|
+ if (contains.isEmpty()) {
|
|
|
+ benchmarkList.add(0, valueLabelVO);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ benchmarkList.add(valueLabelVO);
|
|
|
+ }
|
|
|
+ res.setBenchmarkId(benchmarkId);
|
|
|
+ res.setUsefulBenchmark(benchmarkList);
|
|
|
+ }
|
|
|
+}
|