浏览代码

相似产品接口

wangzaijun 1 年之前
父节点
当前提交
17c885ffef

+ 3 - 1
src/main/java/com/smppw/analysis/application/dto/BaseReq.java

@@ -10,7 +10,7 @@ import lombok.Setter;
  */
 @Setter
 @Getter
-public abstract class BaseReq {
+public abstract class BaseReq<R> {
     /**
      * 参数签名,防止参数被篡改
      */
@@ -23,4 +23,6 @@ public abstract class BaseReq {
      * 时间戳,防止重放攻击
      */
     private long timestamp;
+
+    public abstract R convert();
 }

+ 6 - 1
src/main/java/com/smppw/analysis/application/dto/info/CommonInfoReq.java

@@ -11,7 +11,7 @@ import lombok.Setter;
  */
 @Setter
 @Getter
-public class CommonInfoReq extends BaseReq {
+public class CommonInfoReq extends BaseReq<Object> {
     /**
      * 标的id
      */
@@ -20,4 +20,9 @@ public class CommonInfoReq extends BaseReq {
      * 策略,核心策略,默认All,基金不传或传All
      */
     private String strategy;
+
+    @Override
+    public Object convert() {
+        return null;
+    }
 }

+ 8 - 1
src/main/java/com/smppw/analysis/application/dto/info/FundSimilarReq.java

@@ -1,6 +1,8 @@
 package com.smppw.analysis.application.dto.info;
 
+import cn.hutool.core.bean.BeanUtil;
 import com.smppw.analysis.application.dto.BaseReq;
+import com.smppw.analysis.domain.dto.info.FundSimilarParams;
 import com.smppw.common.pojo.enums.RaiseType;
 import lombok.Getter;
 import lombok.Setter;
@@ -12,7 +14,7 @@ import lombok.Setter;
  */
 @Setter
 @Getter
-public class FundSimilarReq extends BaseReq {
+public class FundSimilarReq extends BaseReq<FundSimilarParams> {
     public static final String DEFAULT_THRESHOLD = "0.85";
     /**
      * 基金id
@@ -34,4 +36,9 @@ public class FundSimilarReq extends BaseReq {
      * 末级策略,head-info接口返回的
      */
     private String strategy;
+
+    @Override
+    public FundSimilarParams convert() {
+        return BeanUtil.copyProperties(this, FundSimilarParams.class);
+    }
 }

+ 1 - 1
src/main/java/com/smppw/analysis/application/dto/info/HeadIndicatorReq.java

@@ -19,7 +19,7 @@ import java.util.Date;
  * @description 头部成立以来指标实时计算接口请求参数
  */
 @Setter
-public class HeadIndicatorReq extends BaseReq {
+public class HeadIndicatorReq extends BaseReq<IndicatorParams> {
     /**
      * 标的id
      */

+ 6 - 1
src/main/java/com/smppw/analysis/application/dto/info/HeadInfoReq.java

@@ -6,7 +6,7 @@ import lombok.Setter;
 
 @Setter
 @Getter
-public class HeadInfoReq extends BaseReq {
+public class HeadInfoReq extends BaseReq<Object> {
     /**
      * 标的id
      */
@@ -15,4 +15,9 @@ public class HeadInfoReq extends BaseReq {
      * 策略,核心策略,默认All,基金不传或传All
      */
     private String strategy;
+
+    @Override
+    public Object convert() {
+        return null;
+    }
 }

+ 1 - 8
src/main/java/com/smppw/analysis/application/dto/performance/BasePerformanceReq.java

@@ -13,7 +13,7 @@ import java.util.List;
 
 @Setter
 @Getter
-public abstract class BasePerformanceReq<R extends Params> extends BaseReq {
+public abstract class BasePerformanceReq<R extends Params> extends BaseReq<R> {
     /**
      * 标的id,包括基金、机构和经理
      */
@@ -54,11 +54,4 @@ public abstract class BasePerformanceReq<R extends Params> extends BaseReq {
      * 结束日期
      */
     private String endDate;
-
-    /**
-     * 参数转换,必须实现
-     *
-     * @return /
-     */
-    public abstract R convert();
 }

+ 1 - 8
src/main/java/com/smppw/analysis/application/dto/position/BasePositionReq.java

@@ -7,7 +7,7 @@ import lombok.Setter;
 
 @Setter
 @Getter
-public abstract class BasePositionReq<R extends BaseParams> extends BaseReq {
+public abstract class BasePositionReq<R extends BaseParams> extends BaseReq<R> {
     /**
      * 基金id
      */
@@ -20,11 +20,4 @@ public abstract class BasePositionReq<R extends BaseParams> extends BaseReq {
      * 结束时间
      */
     private String endDate;
-
-    /**
-     * 把当前的对象转换为R类型的对象
-     *
-     * @return /
-     */
-    public abstract R convert();
 }

+ 34 - 0
src/main/java/com/smppw/analysis/application/service/info/FundInfoService.java

@@ -1,7 +1,12 @@
 package com.smppw.analysis.application.service.info;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.map.MapUtil;
 import com.smppw.analysis.application.dto.info.*;
+import com.smppw.analysis.domain.dataobject.FundSimilarDo;
+import com.smppw.analysis.domain.dto.info.FundSimilarParams;
+import com.smppw.analysis.domain.dto.info.FundSimilarVO;
 import com.smppw.analysis.domain.dto.performance.IndicatorParams;
 import com.smppw.analysis.domain.manager.performance.Performance;
 import com.smppw.analysis.domain.manager.performance.PerformanceConstants;
@@ -10,7 +15,9 @@ import com.smppw.analysis.domain.service.BaseInfoService;
 import com.smppw.common.pojo.enums.Indicator;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Service
 public class FundInfoService {
@@ -76,4 +83,31 @@ public class FundInfoService {
         vo.setSharpeRatio(MapUtil.getStr(indicatorMap, Indicator.SharpeRatio.name()));
         return vo;
     }
+
+    public List<FundSimilarVO> getFundSimilarList(FundSimilarReq req) {
+        List<String> refIds = ListUtil.toLinkedList(req.getRefId());
+        FundSimilarParams params = req.convert();
+        List<FundSimilarDo> dataList = this.baseInfoService.getFundSimilarList(params);
+        List<String> fundIds = dataList.stream().map(FundSimilarDo::getFundId).collect(Collectors.toList());
+        if (CollUtil.isNotEmpty(fundIds)) {
+            refIds.addAll(fundIds);
+        }
+//        Map<String, List<IndicatorCalcPropertyDto>> multiSecRetListNew = this.baseIndicatorServiceV2.getMultiSecRetListNew(
+//                secIds, ListUtil.empty(), Frequency.Monthly, Frequency.Daily, startDate, endDate, false, Consts.BENCHMARK,
+//                params.getRaiseType(), Strategy.All, Visibility.Visible, NavType.CumulativeNav);
+//        List<Map<String, Object>> initRetList = NavUtil.handleNextStepNew(secIds, ListUtil.empty(), multiSecRetListNew, false);
+//        Map<String, Map<String, Double>> retMap = RateConvertorUtils.transfer2TwoDimensionMap(initRetList, "fund_id", "end_date", "ret_range");
+//        Double[][] corArr = CalcUtils.getCorrelationMatrix(retMap, ListUtil.toList(params.getRefId()), secIds);
+//        for (FundSimilarDo map : dataList) {
+//            FundSimilarVO similarVO = BeanUtil.copyProperties(map, FundSimilarVO.class);
+//            int i = fundIds.indexOf(map.getFundId()) + 1; // 因为第一个基金是当前基金,所以需要 + 1 来取该基金与当前基金的相关性
+//            similarVO.setSimilar(corArr[0][i]);
+//            similarVO.setStrategy(StrategyHandleUtils.getStrategy(map.getStrategy()).getStrategyNameDesc());
+//            similarVO.setSubStrategy(this.getStrategyName(map.getSubStrategy()));
+//            similarVO.setThirdStrategy(this.getStrategyName(map.getThirdStrategy()));
+//            resultList.add(similarVO);
+//        }
+//        resultList.stream().filter(e -> e.getSimilar() != null && e.getSimilar() >= Double.parseDouble(params.getThreshold())).collect(Collectors.toList());
+        return null;
+    }
 }

+ 13 - 0
src/main/java/com/smppw/analysis/domain/dao/FundInformationDao.java

@@ -3,6 +3,7 @@ package com.smppw.analysis.domain.dao;
 import cn.hutool.core.map.MapUtil;
 import com.smppw.analysis.domain.dataobject.FundFrequencyDo;
 import com.smppw.analysis.domain.dataobject.FundInformationDo;
+import com.smppw.analysis.domain.dataobject.FundSimilarDo;
 import com.smppw.analysis.domain.dataobject.MonetaryFundProfitDO;
 import com.smppw.analysis.domain.mapper.FundFrequencyDoMapper;
 import com.smppw.analysis.domain.mapper.FundInformationDoMapper;
@@ -29,6 +30,10 @@ public class FundInformationDao {
         this.monetaryFundProfitMapper = monetaryFundProfitMapper;
     }
 
+    public String getNavFrequencyByFundId(String secId) {
+        return this.fundFrequencyDoMapper.getNavFrequencyByFundId(secId);
+    }
+
     public Map<String, Frequency> getNavFrequency(List<String> secIdList) {
         Map<String, Frequency> secFrequencyMap = new HashMap<>();
         List<FundFrequencyDo> fundFrequencyDos = fundFrequencyDoMapper.getNavFrequencyByFundIdList(secIdList);
@@ -66,4 +71,12 @@ public class FundInformationDao {
         params.put("indicator", indicator.getId());
         return this.fundInformationDoMapper.getFundRankByCall(params);
     }
+
+    public List<FundSimilarDo> getSameCompanyFundIds(Map<String, Object> params) {
+        return null;
+    }
+
+    public List<FundSimilarDo> getSameStrategyFundIds(Map<String, Object> params) {
+        return null;
+    }
 }

+ 21 - 0
src/main/java/com/smppw/analysis/domain/dataobject/FundSimilarDo.java

@@ -0,0 +1,21 @@
+package com.smppw.analysis.domain.dataobject;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class FundSimilarDo {
+    private String fundId;
+    private String fundName;
+    private String strategy;
+    private String subStrategy;
+    private String thirdStrategy;
+    private String retYtd;
+    private String ret1y;
+    private String retIncep;
+    private String annualIncep;
+    private String shapeIncep;
+    private String maxdownIncep;
+    private String stdDevIncep;
+}

+ 38 - 0
src/main/java/com/smppw/analysis/domain/dto/info/FundSimilarParams.java

@@ -0,0 +1,38 @@
+package com.smppw.analysis.domain.dto.info;
+
+import com.smppw.common.pojo.enums.RaiseType;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author wangzaijun
+ * @date 2023/3/22 16:58
+ * @description 相似产品 接口请求参数
+ */
+@Setter
+@Getter
+public class FundSimilarParams {
+    public static final String DEFAULT_THRESHOLD = "0.85";
+    /**
+     * 基金id
+     */
+    private String refId;
+    /**
+     * 管理人id
+     */
+    private String trustId;
+    /**
+     * 1-市场同策略,2-管理人同策略
+     */
+    private Integer calcType = 2;
+    /**
+     * 相关性阈值,小数
+     */
+    private String threshold = DEFAULT_THRESHOLD;
+
+    private RaiseType raiseType;
+    /**
+     * 末级策略,head-info接口返回的
+     */
+    private String strategy;
+}

+ 22 - 0
src/main/java/com/smppw/analysis/domain/dto/info/FundSimilarVO.java

@@ -0,0 +1,22 @@
+package com.smppw.analysis.domain.dto.info;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class FundSimilarVO {
+    private String fundId;
+    private String fundName;
+    private String strategy;
+    private String subStrategy;
+    private String thirdStrategy;
+    private String retYtd;
+    private String ret1y;
+    private String retIncep;
+    private String annualIncep;
+    private String shapeIncep;
+    private String maxdownIncep;
+    private String stdDevIncep;
+    private Double similar;
+}

+ 7 - 0
src/main/java/com/smppw/analysis/domain/service/BaseInfoService.java

@@ -1,6 +1,9 @@
 package com.smppw.analysis.domain.service;
 
+import com.smppw.analysis.domain.dataobject.FundSimilarDo;
 import com.smppw.analysis.domain.dataobject.MonetaryFundProfitDO;
+import com.smppw.analysis.domain.dto.info.FundSimilarParams;
+import com.smppw.common.pojo.enums.Frequency;
 import com.smppw.common.pojo.enums.Indicator;
 
 import java.util.List;
@@ -22,7 +25,11 @@ public interface BaseInfoService {
 
     Map<String, String> querySecName(List<String> allSecIdList);
 
+    Frequency getNavFrequency(String secId);
+
     List<MonetaryFundProfitDO> queryMonetaryFund(String fundId);
 
     List<Map<String, Object>> getFundRank(String rankDate, String fundId, List<String> indexIds, Indicator indicator);
+
+    List<FundSimilarDo> getFundSimilarList(FundSimilarParams params);
 }

+ 59 - 3
src/main/java/com/smppw/analysis/domain/service/impl/BaseInfoServiceImpl.java

@@ -3,11 +3,14 @@ package com.smppw.analysis.domain.service.impl;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.StrUtil;
 import com.smppw.analysis.domain.dao.FundInformationDao;
 import com.smppw.analysis.domain.dao.IndexesProfileDao;
 import com.smppw.analysis.domain.dao.RongzhiIndexNavDao;
+import com.smppw.analysis.domain.dataobject.FundSimilarDo;
 import com.smppw.analysis.domain.dataobject.MonetaryFundProfitDO;
+import com.smppw.analysis.domain.dto.info.FundSimilarParams;
 import com.smppw.analysis.domain.event.SaveCacheEvent;
 import com.smppw.analysis.domain.gateway.CacheFactory;
 import com.smppw.analysis.domain.gateway.CacheGateway;
@@ -15,9 +18,14 @@ import com.smppw.analysis.domain.service.BaseInfoService;
 import com.smppw.analysis.infrastructure.config.AnalysisProperty;
 import com.smppw.analysis.infrastructure.consts.RedisConst;
 import com.smppw.common.cache.CaffeineLocalCache;
+import com.smppw.common.pojo.IStrategy;
+import com.smppw.common.pojo.enums.Frequency;
 import com.smppw.common.pojo.enums.Indicator;
 import com.smppw.common.pojo.enums.strategy.Strategy;
 import com.smppw.constants.SecType;
+import com.smppw.utils.StrategyHandleUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
@@ -45,15 +53,15 @@ public class BaseInfoServiceImpl implements BaseInfoService, ApplicationContextA
     public static final String IN = "IN";
     public static final String AP = "AP";
     private static final Map<String, Boolean> INDEX_EXIST = MapUtil.newConcurrentHashMap();
-
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
     private final CacheGateway<Object> cacheGateway;
     private final IndexesProfileDao indexesProfileDao;
     private final RongzhiIndexNavDao rongzhiIndexNavDao;
     private final FundInformationDao fundInformationDao;
     private ApplicationContext applicationContext;
 
-    public BaseInfoServiceImpl(AnalysisProperty property, CacheFactory factory, IndexesProfileDao indexesProfileDao,
-                               RongzhiIndexNavDao rongzhiIndexNavDao, FundInformationDao fundInformationDao) {
+    public BaseInfoServiceImpl(AnalysisProperty property, CacheFactory factory,
+                               IndexesProfileDao indexesProfileDao, RongzhiIndexNavDao rongzhiIndexNavDao, FundInformationDao fundInformationDao) {
         this.cacheGateway = factory.getCacheGateway(property.getCacheType());
         this.indexesProfileDao = indexesProfileDao;
         this.rongzhiIndexNavDao = rongzhiIndexNavDao;
@@ -147,6 +155,30 @@ public class BaseInfoServiceImpl implements BaseInfoService, ApplicationContextA
     }
 
     @Override
+    public Frequency getNavFrequency(String secId) {
+        Frequency frequency;
+        String fundType = this.getSecType(secId);
+        if (SecType.MANAGER.equals(fundType) || SecType.COMPANY.equals(fundType)) {
+            frequency = Frequency.Monthly;
+        } else if (SecType.PRIVATELY_OFFERED_FUND.equals(fundType) ||
+                SecType.PUBLICLY_OFFERED_FUNDS.equals(fundType) ||
+                SecType.INDEX_FUND.equals(fundType) ||
+                SecType.RONGZHI_INDEX.equals(fundType)) {
+            String freq = this.fundInformationDao.getNavFrequencyByFundId(secId);
+            if ("天".equals(freq)) {
+                frequency = Frequency.Daily;
+            } else if ("周".equals(freq)) {
+                frequency = Frequency.Weekly;
+            } else {
+                frequency = Frequency.Monthly;
+            }
+        } else {
+            frequency = Frequency.Daily;
+        }
+        return frequency;
+    }
+
+    @Override
     public Map<String, String> querySecName(List<String> allSecIdList) {
         if (CollUtil.isEmpty(allSecIdList)) {
             return MapUtil.empty();
@@ -195,6 +227,30 @@ public class BaseInfoServiceImpl implements BaseInfoService, ApplicationContextA
         return this.fundInformationDao.getFundRank(rankDate, fundId, indexIds, indicator);
     }
 
+    @Override
+    public List<FundSimilarDo> getFundSimilarList(FundSimilarParams params) {
+        if (StrUtil.isBlank(params.getThreshold()) || !NumberUtil.isNumber(params.getThreshold())) {
+            logger.warn(String.format("相关性阈值 %s 设置错误,提供默认值:%s", params.getThreshold(), FundSimilarParams.DEFAULT_THRESHOLD));
+            params.setThreshold(FundSimilarParams.DEFAULT_THRESHOLD);
+        }
+        IStrategy strategy = StrategyHandleUtils.getStrategy(params.getStrategy());
+        String rankDate = this.getLatestRankRat();
+        List<FundSimilarDo> tempList = ListUtil.list(true);
+        if (params.getCalcType() == 2) {
+            Map<String, Object> req = MapUtil.<String, Object>builder().put("strategy", strategy.getStrategyId())
+                    .put("tableName", "rz_hfdb_core.nav").put("trustId", params.getTrustId()).put("rankDate", rankDate).build();
+            tempList.addAll(this.fundInformationDao.getSameCompanyFundIds(req));
+        } else {
+            Map<String, Object> req = MapUtil.<String, Object>builder().put("strategy", strategy.getStrategyId()).put("rankNum", 50)
+                    .put("tableName", "rz_hfdb_core.fund_indicator_ranking").put("fundId", params.getRefId()).put("rankDate", rankDate).build();
+            tempList.addAll(this.fundInformationDao.getSameStrategyFundIds(req));
+        }
+        List<FundSimilarDo> dataList = ListUtil.list(true);
+        // 过滤当前基金
+        dataList.addAll(tempList.stream().filter(e -> !params.getRefId().equals(e.getFundId())).collect(Collectors.toList()));
+        return dataList;
+    }
+
     /**
      * 把指定类型的标的的名称映射查询出来
      *