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.HeadInfoConstants; 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) { String secType = this.baseInfoService.getSecType(req.getSecId()); String type = HeadInfoConstants.SEC_TYPE_HEAD_MAP.get(secType); HeadInfoParams params = req.convert(); params.setSecType(secType); return this.headInfoFactory.getInstance(type).get(params); } public CommonInfoVO commonInfo(CommonInfoReq params) { String secType = this.baseInfoService.getSecType(params.getSecId()); CommonInfoVO res = new CommonInfoVO(); String secId = params.getSecId(); List result = CollectionUtil.newArrayList(); String type = HeadInfoConstants.SEC_TYPE_HEAD_MAP.get(secType); HeadInfoVO fundHeadInfo = this.headInfoFactory.getInstance(type).get(new HeadInfoParams(secId, type)); if (fundHeadInfo == null) { throw new APIException(""); } String raiseType = fundHeadInfo.getRaiseType(); result.add(this.baseInfoService.getNavFrequency(secId)); // 将频率转换一道 取最小频率 List frequencies = this.toFrequencyList(result); if (Objects.equals("2", raiseType)) { frequencies.removeIf(p -> p.getId() == Frequency.Default.getId()); } List frequencyValueLabel = this.trans2ValueLabel(frequencies); res.setFrequency(frequencyValueLabel); // 净值类型 List 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 benchmarkList = baseInfoService.getCommonIndexList(); handleBenchmark(res, secType, benchmarkList, fundHeadInfo); return res; } @SuppressWarnings("unchecked") public HeadIndicatorVO headIndicator(HeadIndicatorReq req) { IndicatorParams params = req.convert(); Performance> instance = this.performanceFactory.getInstance(PerformanceConstants.INDICATOR); Map dataset = instance.execute(params); Map 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 toFrequencyList(List 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 trans2ValueLabel(List frequencies) { List 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 refIds = ListUtil.toLinkedList(secId); String endDate = null; String startDate = null; Frequency navFrequency = this.baseInfoService.getNavFrequency(secId); Map> allNavMap = this.navService.getSecIdDateValueNavListMapByDb(refIds, null, null, Visibility.Both, NavType.CumulativeNav); List secTimeRanges = IndicatorService.getInstance().getSecTimeRange(secId, navFrequency, allNavMap); Map 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 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 querySecName = this.baseInfoService.querySecName(ListUtil.of(benchmarkId)); String indexName = querySecName.get(benchmarkId); valueLabelVO = new ValueLabelVO(benchmarkId, indexName); } } else { valueLabelVO = new ValueLabelVO(); } if (CollectionUtil.isNotEmpty(benchmarkList)) { // 如果常用指数里面没有基准,则把基准放在常用指数的第一位 Optional 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); } }