123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137 |
- package com.smppw.analysis.application.service.style;
- 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.ObjectUtil;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.http.HttpUtil;
- import cn.hutool.json.JSONUtil;
- import com.smppw.analysis.domain.dataobject.FundStyleStatsDO;
- import com.smppw.analysis.domain.dto.style.*;
- import com.smppw.analysis.domain.dto.style.py.PyReq;
- import com.smppw.analysis.domain.dto.style.py.PyReqBody;
- import com.smppw.analysis.domain.dto.style.py.PyReqParam;
- import com.smppw.analysis.domain.dto.style.py.PyResBody;
- import com.smppw.analysis.domain.service.BaseInfoService;
- import com.smppw.analysis.domain.service.FundStyleService;
- import com.smppw.analysis.infrastructure.config.AnalysisProperty;
- import com.smppw.analysis.infrastructure.consts.*;
- import com.smppw.analysis.infrastructure.exception.APIException;
- import com.smppw.common.pojo.IStrategy;
- import com.smppw.common.pojo.enums.CurveType;
- import com.smppw.common.pojo.enums.Frequency;
- import com.smppw.common.pojo.enums.RaiseType;
- import com.smppw.common.pojo.enums.strategy.Strategy;
- import com.smppw.constants.Consts;
- import com.smppw.utils.StrategyHandleUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
- import java.math.BigDecimal;
- import java.nio.charset.Charset;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Optional;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- import java.util.concurrent.atomic.AtomicReference;
- import java.util.stream.Collectors;
- @Service
- public class StyleServiceImpl implements StyleService {
- private static final Logger logger = LoggerFactory.getLogger(StyleServiceImpl.class);
- private static final Map<Frequency, String> FREQ_MAPPER = MapUtil.newHashMap();
- private static final Map<Object, RBSAIndexType> RBSA_MAPPER = MapUtil.newHashMap();
- private static final Map<RBSAIndexType, Map<String, String>> RBSA_INDEX_PROD_MAPPER = MapUtil.newHashMap();
- private static final Map<String, String> CAL_RANGE_MAPPER = MapUtil.newHashMap();
- static {
- FREQ_MAPPER.put(Frequency.Default, "D");
- FREQ_MAPPER.put(Frequency.Daily, "D");
- FREQ_MAPPER.put(Frequency.Weekly, "W");
- FREQ_MAPPER.put(Frequency.Monthly, "M");
- FREQ_MAPPER.put(Frequency.Quarterly, "Q");
- FREQ_MAPPER.put(Frequency.Annually, "Y");
- RBSA_MAPPER.put(ValueGrowthType.CNI6Style, RBSAIndexType.CNI7Style);
- RBSA_MAPPER.put(ValueGrowthType.CNI2Style, RBSAIndexType.CNI3Style);
- RBSA_MAPPER.put(ValueGrowthType.CNI6Strategy, RBSAIndexType.CNI7Strategy);
- RBSA_MAPPER.put(IndustryType.CITIC5, RBSAIndexType.CITIC6);
- RBSA_MAPPER.put(IndustryType.CSI10, RBSAIndexType.CSI11);
- RBSA_MAPPER.put(IndustryType.ShenWan, RBSAIndexType.ShenWan);
- RBSA_MAPPER.put(AssetStyleType.MultiAsset, RBSAIndexType.Large4Assets);
- RBSA_MAPPER.put(AssetStyleType.RongZhiStrategy, RBSAIndexType.RZ5Strategy);
- RBSA_MAPPER.put(AssetStyleType.SegmentationAsset, RBSAIndexType.SegmentationAsset);
- // 成长价值
- // 巨潮风格
- RBSA_INDEX_PROD_MAPPER.put(RBSAIndexType.CNI7Style, MapUtil.<String, String>builder(MapUtil.newHashMap(true)).put("beta1", "大盘成长")
- .put("beta2", "大盘价值").put("beta3", "中盘成长").put("beta4", "中盘价值")
- .put("beta5", "小盘成长").put("beta6", "小盘价值").build()
- );
- // 国证风格
- RBSA_INDEX_PROD_MAPPER.put(RBSAIndexType.CNI3Style, MapUtil.<String, String>builder(MapUtil.newHashMap(true)).put("beta1", "成长").put("beta2", "价值").build());
- // 国证策略
- RBSA_INDEX_PROD_MAPPER.put(RBSAIndexType.CNI7Strategy, MapUtil.<String, String>builder(MapUtil.newHashMap(true)).put("beta1", "大盘低贝")
- .put("beta2", "大盘高贝").put("beta3", "中盘低贝").put("beta4", "中盘高贝")
- .put("beta5", "小盘低贝").put("beta6", "小盘高贝").build());
- // 行业配置
- // 申万一级行业
- RBSA_INDEX_PROD_MAPPER.put(RBSAIndexType.ShenWan, MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("beta1", "美容护理")
- .put("beta2", "环保")
- .put("beta3", "石油石化")
- .put("beta4", "煤炭")
- .put("beta5", "机械设备")
- .put("beta6", "汽车")
- .put("beta7", "非银金融")
- .put("beta8", "银行")
- .put("beta9", "通信")
- .put("beta10", "传媒")
- .put("beta11", "计算机")
- .put("beta12", "国防军工")
- .put("beta13", "电力设备")
- .put("beta14", "建筑装饰")
- .put("beta15", "建筑材料")
- .put("beta16", "综合")
- .put("beta17", "社会服务")
- .put("beta18", "商贸零售")
- .put("beta19", "房地产")
- .put("beta20", "交通运输")
- .put("beta21", "公用事业")
- .put("beta22", "医药生物")
- .put("beta23", "轻工制造")
- .put("beta24", "纺织服饰")
- .put("beta25", "食品饮料")
- .put("beta26", "家用电器")
- .put("beta27", "电子")
- .put("beta28", "有色金属")
- .put("beta29", "钢铁")
- .put("beta30", "基础化工")
- .put("beta31", "农林牧渔")
- .build());
- // 中证行业
- RBSA_INDEX_PROD_MAPPER.put(RBSAIndexType.CSI11, MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("beta1", "中证材料")
- .put("beta2", "中证电信")
- .put("beta3", "中证工业")
- .put("beta4", "中证公用")
- .put("beta5", "中证金融")
- .put("beta6", "中证可选")
- .put("beta7", "中证能源")
- .put("beta8", "中证消费")
- .put("beta9", "中证信息")
- .put("beta10", "中证医药")
- .build());
- // 中信行业风格
- RBSA_INDEX_PROD_MAPPER.put(RBSAIndexType.CITIC6, MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("beta1", "金融")
- .put("beta2", "周期")
- .put("beta3", "消费")
- .put("beta4", "成长")
- .put("beta5", "稳定")
- .build());
- CAL_RANGE_MAPPER.put("3", "ret_3m");
- CAL_RANGE_MAPPER.put("6", "ret_6m");
- CAL_RANGE_MAPPER.put("12", "ret_1y");
- CAL_RANGE_MAPPER.put("24", "ret_2y");
- CAL_RANGE_MAPPER.put("36", "ret_3y");
- CAL_RANGE_MAPPER.put("60", "ret_5y");
- CAL_RANGE_MAPPER.put("120", "ret_10y");
- }
- private final String pyBaseUrl;
- private final BaseInfoService baseInfoService;
- private final FundStyleService fundStyleService;
- public StyleServiceImpl(AnalysisProperty property, BaseInfoService baseInfoService, FundStyleService fundStyleService) {
- this.pyBaseUrl = property.getPyUrl();
- this.baseInfoService = baseInfoService;
- this.fundStyleService = fundStyleService;
- }
- /**
- * 参数检查
- *
- * @param params 请求参数
- * @param <P> 类型参数
- */
- private <P extends BaseParams> void checkParams(P params) {
- if (StrUtil.isBlank(params.getSecId())) {
- throw new APIException("secId 不能为空!");
- }
- if (StrUtil.isBlank(params.getWinlen()) || !NumberUtil.isInteger(params.getWinlen()) || params.getWinlen().length() > 10) {
- throw new APIException("窗口参数非法!");
- }
- if (StrUtil.isBlank(params.getStep()) || !NumberUtil.isInteger(params.getStep()) || Integer.parseInt(params.getStep()) > 100) {
- throw new APIException("步长参数非法!");
- }
- IStrategy strategy = StrategyHandleUtils.getStrategy(params.getStrategy());
- if (strategy == null) {
- strategy = Strategy.All;
- params.setStrategy(strategy.getStrategyOriginName());
- }
- if (params.getRaiseType() == null) {
- params.setRaiseType(RaiseType.Both);
- }
- // CurveType curveType = CurveType.getCurveType(params.getRaiseType(), strategy);
- // Map<String, List<DateValue>> allNavMap = this.navService.getSecIdDateValueNavListMapFromRedisAndDB(ListUtil.toList(params.getSecId()), ListUtil.empty(), ListUtil.empty(),
- // null, null, NavType.CumulativeNav, Visibility.Both, curveType.getId(), strategy.getStrategyId(),
- // MapUtil.empty(), false, null);
- // Integer navLen = Optional.ofNullable(allNavMap).map(e -> e.get(params.getSecId())).map(List::size).orElse(0);
- // if (Integer.parseInt(params.getWinlen()) > navLen) {
- // throw new DataException("净值数量小于窗口期要求数量,无法计算");
- // }
- }
- /**
- * python 请求异步处理,后续考虑用一个线程池,这里极端情况下可能会导致OOM
- *
- * @param reqs 请求
- * @return /
- */
- private Map<String, List<Object>> parallelReqPy(List<PyReq> reqs) {
- ExecutorService executorService = Executors.newFixedThreadPool(reqs.size());
- List<Future<Map<String, List<Object>>>> futures = ListUtil.list(false);
- for (PyReq req : reqs) {
- String taskId = StrUtil.toString(req.getTaskId());
- Future<Map<String, List<Object>>> future = executorService.submit(() -> {
- String body;
- String url = this.pyBaseUrl + req.getApi();
- if ("get".equalsIgnoreCase(req.getMethod())) {
- String encodeParams = HttpUtil.toParams(req.getParams(), Charset.defaultCharset());
- body = HttpUtil.get(url + "?" + encodeParams);
- } else {
- body = req.getJson() ? HttpUtil.post(url, JSONUtil.toJsonStr(req.getParams())) : HttpUtil.post(url, req.getParams());
- }
- return MapUtil.<String, List<Object>>builder(taskId, JSONUtil.parseArray(body)).build();
- });
- futures.add(future);
- }
- Map<String, List<Object>> result = MapUtil.newHashMap();
- for (Future<Map<String, List<Object>>> future : futures) {
- try {
- result.putAll(future.get());
- } catch (Exception e) {
- logger.warn("当前任务执行异常:" + e.getMessage());
- }
- }
- executorService.shutdown();
- return result;
- }
- /**
- * 基于数据从高到低给因子排序
- *
- * @param mapper 因子名称
- * @param dataset 因子数据
- * @param isDesc 是否倒序
- * @return /
- */
- private Map<String, String> sortMapper(Map<String, String> mapper, Map<String, Object> dataset, boolean isDesc) {
- Map<String, Double> temp = MapUtil.newHashMap();
- List<String> nullKeys = ListUtil.list(false);
- dataset.forEach((k, v) -> {
- if (!"date".equals(k)) {
- if (v != null) {
- temp.put(k, Double.parseDouble(StrUtil.toString(v)));
- } else {
- nullKeys.add(k);
- }
- }
- });
- Map<String, Double> doubleMap = MapUtil.sortByValue(temp, isDesc);
- for (String nullKey : nullKeys) {
- doubleMap.putIfAbsent(nullKey, null);
- }
- Map<String, String> result = MapUtil.newHashMap(true);
- doubleMap.forEach((k, v) -> {
- if (mapper.containsKey(k)) {
- result.put(k, mapper.get(k));
- }
- });
- return result;
- }
- /**
- * 基于数据从高到低给因子排序,默认升序
- *
- * @param mapper 因子名称
- * @param dataset 因子数据
- * @return /
- */
- private Map<String, String> sortMapperAsc(Map<String, String> mapper, Map<String, Object> dataset) {
- return this.sortMapper(mapper, dataset, false);
- }
- /**
- * 发起python请求并处理返回结果
- *
- * @param params 参数
- * @param extParams 扩展参数
- * @param pyReqs /
- * @param <P> 类型参数
- * @return /
- */
- private <P extends BaseParams> PyResBody initiateRequest(P params, Map<String, Object> extParams, List<PyReqParam> pyReqs) {
- PyReqBody body = PyReqBody.builder().fundIds(params.getSecId()).startDate(params.getStartDate()).endDate(params.getEndDate())
- .freq(FREQ_MAPPER.get(params.getFrequency())).step(params.getStep()).winLen(params.getWinlen()).build();
- List<PyReq> reqs = ListUtil.list(false);
- pyReqs.forEach(e -> {
- Map<String, Object> extReq = MapUtil.builder(JSONUtil.parseObj(body)).putAll(extParams).put("control", e.getControl()).putAll(e.getExt()).build();
- PyReq pyReq = PyReq.builder().taskId(e.getTaskId()).json(e.getJson()).api(e.getApi()).method(e.getMethod()).params(extReq).build();
- reqs.add(pyReq);
- });
- Map<String, List<Object>> data = this.parallelReqPy(reqs);
- PyResBody resBody = new PyResBody();
- // 总的区间内模型回归结果
- String holisticKey = pyReqs.stream().filter(e -> ObjectUtil.equals(e.getControl(), 0)).map(PyReqParam::getTaskId).findFirst().orElse(null);
- resBody.setHolistic(Optional.ofNullable(holisticKey).map(data::remove).orElse(ListUtil.list(false)).stream().map(JSONUtil::parseObj).findFirst().orElse(null));
- // 滚动区间内模型回归结果
- String sequentialKey = pyReqs.stream().filter(e -> ObjectUtil.equals(e.getControl(), 1)).map(PyReqParam::getTaskId).findFirst().orElse(null);
- resBody.setSequential(Optional.ofNullable(sequentialKey).map(data::remove).orElse(ListUtil.list(false)).stream().map(JSONUtil::parseObj).collect(Collectors.toList()));
- // 其他
- Map<String, List<Map<String, Object>>> extBody = MapUtil.newHashMap();
- data.forEach((k, v) -> extBody.put(k, v.stream().map(JSONUtil::parseObj).collect(Collectors.toList())));
- resBody.setExtBody(extBody);
- return resBody;
- }
- /**
- * 发起python请求并处理返回结果
- *
- * @param api 接口
- * @param params 公共请求参数
- * @param extParams 接口扩展参数
- * @param <P> 类型参数
- * @return /
- */
- private <P extends BaseParams> PyResBody initiateRequest(String api, P params, Map<String, Object> extParams) {
- Map<Integer, String> controls = MapUtil.builder(0, "holistic").put(1, "sequential").build();
- return this.initiateRequest(api, params, extParams, controls);
- }
- /**
- * 发起python请求并处理返回结果
- *
- * @param api 接口
- * @param params 公共请求参数
- * @param extParams 接口扩展参数
- * @param controls 同一个接口请求的参数,就control参数变化
- * @param <P> 类型参数
- * @return /
- */
- private <P extends BaseParams> PyResBody initiateRequest(String api, P params, Map<String, Object> extParams, Map<Integer, String> controls) {
- List<PyReqParam> pyReqs = ListUtil.list(false);
- controls.forEach((k, v) -> pyReqs.add(PyReqParam.builder().api(api).control(k).taskId(v).build()));
- return this.initiateRequest(params, extParams, pyReqs);
- }
- @Override
- public Map<String, Object> stockAttribution(StockAttributionParams params) {
- this.checkParams(params);
- try {
- // 太丑陋,要优化一下下
- String indexIds = "FA000000MK_FA00000SMB_FA00000VMG_FA000000MT_FA000000RV"; // 五因子
- Map<String, String> chartMapper12 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("beta1", "市场因子").put("beta2", "规模因子").put("beta3", "价值因子").put("beta4", "动量因子").put("beta5", "反转因子").build();
- Map<String, String> chartMapper34 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .putAll(chartMapper12).put("epsi", "残差").put("alpha", "超额收益").build();
- Map<String, String> tableMapper1 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("date", "因子系数(%)").putAll(chartMapper12).put("rSquared", "R2").build();
- Map<String, String> tableMapper3 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("date", "贡献度(%)").putAll(chartMapper34).put("rSquared", "R2").build();
- Map<String, Object> extParams = MapUtil.<String, Object>builder().put("indexIds", indexIds).put("winlen", params.getWinlen())
- .put("strategy", 1).put("curve_type", 2).put("returnNo", "None").build();
- PyResBody resBody = this.initiateRequest("GetPerformanceAttribution", params, extParams);
- List<Map<String, Object>> sequential = resBody.getSequential();
- Map<String, Object> holisticMap = resBody.getHolistic();
- Map<String, Object> betaList = MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", holisticMap.get("end_date"))
- .put("beta1", holisticMap.get("beta1"))
- .put("beta2", holisticMap.get("beta2"))
- .put("beta3", holisticMap.get("beta3"))
- .put("beta4", holisticMap.get("beta4"))
- .put("beta5", holisticMap.get("beta5"))
- .put("rSquared", this.rsquaredConstraint(holisticMap.get("R_squared")))
- .build();
- Map<String, Object> contList = MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", holisticMap.get("end_date"))
- .put("beta1", holisticMap.get("cont1"))
- .put("beta2", holisticMap.get("cont2"))
- .put("beta3", holisticMap.get("cont3"))
- .put("beta4", holisticMap.get("cont4"))
- .put("beta5", holisticMap.get("cont5"))
- .put("epsi", holisticMap.get("tepsi"))
- .put("alpha", holisticMap.get("alpha"))
- .put("rSquared", this.rsquaredConstraint(holisticMap.get("R_squared")))
- .build();
- AtomicReference<Double> intervalYieldRate = new AtomicReference<>((double) 0);
- List<String> rateKeys = ListUtil.toList("cont1", "cont2", "cont3", "cont4", "cont5", "tepsi", "alpha");
- holisticMap.forEach((k, v) -> {
- if (rateKeys.contains(k)) {
- intervalYieldRate.updateAndGet(v1 -> v1 + Double.parseDouble(StrUtil.toString(v)));
- }
- });
- Map<String, Object> chart2 = MapUtil.<String, Object>builder("dataset", betaList)
- .put("chartProductNameMapping", this.sortMapperAsc(chartMapper12, betaList))
- .put("intervalYieldRate", intervalYieldRate).build();
- Map<String, Object> chart4 = MapUtil.<String, Object>builder("dataset", contList)
- .put("chartProductNameMapping", this.sortMapperAsc(chartMapper34, contList)).build();
- List<Map<String, Object>> betaList1 = sequential.stream().map(e ->
- MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", e.get("end_date"))
- .put("beta1", e.get("beta1"))
- .put("beta2", e.get("beta2"))
- .put("beta3", e.get("beta3"))
- .put("beta4", e.get("beta4"))
- .put("beta5", e.get("beta5"))
- .put("rSquared", this.rsquaredConstraint(e.get("R_squared")))
- .build()).collect(Collectors.toList());
- List<Map<String, Object>> contList1 = sequential.stream().map(e ->
- MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", e.get("end_date"))
- .put("beta1", e.get("cont1"))
- .put("beta2", e.get("cont2"))
- .put("beta3", e.get("cont3"))
- .put("beta4", e.get("cont4"))
- .put("beta5", e.get("cont5"))
- .put("rSquared", this.rsquaredConstraint(e.get("R_squared")))
- .put("epsi", e.get("epsi"))
- .put("alpha", e.get("alpha"))
- .build()).collect(Collectors.toList());
- Map<String, Object> chart1 = MapUtil.<String, Object>builder("dataset", betaList1)
- .put("chartProductNameMapping", chartMapper12).put("tableProductNameMapping", tableMapper1).build();
- Map<String, Object> chart3 = MapUtil.<String, Object>builder("dataset", contList1)
- .put("chartProductNameMapping", chartMapper34).put("tableProductNameMapping", tableMapper3).build();
- return MapUtil.<String, Object>builder("chart1", chart1).put("chart2", chart2).put("chart3", chart3).put("chart4", chart4).build();
- } catch (Exception e) {
- logger.error("因子归因计算错误" + e.getMessage());
- return MapUtil.empty();
- }
- }
- @Override
- public Map<String, Object> bondAttribution(BondAttributionParams params) {
- this.checkParams(params);
- try {
- Map<String, String> chartMapper12 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("duration", "久期").put("structure", "期限结构")
- .put("convex", "凸性管理").put("credit", "信用利差").put("hyield", "高收益利差").put("conv", "可转债").build();
- Map<String, String> chartMapper34 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .putAll(chartMapper12).put("epsi", "残差").put("alpha", "超额收益").build();
- Map<String, String> tableMapper1 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("date", "因子系数(%)").putAll(chartMapper12).put("rSquared", "R2").build();
- Map<String, String> tableMapper3 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("date", "贡献度(%)").putAll(chartMapper34).put("rSquared", "R2").build();
- Map<String, Object> extParams = MapUtil.<String, Object>builder().put("winlen", params.getWinlen())
- .put("strategy", 1).put("curve_type", 2).build();
- PyResBody resBody = this.initiateRequest("GetBondAttribution", params, extParams);
- List<Map<String, Object>> sequential = resBody.getSequential();
- Map<String, Object> holisticMap = resBody.getHolistic();
- Map<String, Object> betaList = MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", holisticMap.get("Date"))
- .put("duration", holisticMap.get("TDuration"))
- .put("structure", holisticMap.get("TStructure"))
- .put("convex", holisticMap.get("TConvex"))
- .put("credit", holisticMap.get("TCredit"))
- .put("hyield", holisticMap.get("THYield"))
- .put("conv", holisticMap.get("TConv"))
- .put("rSquared", this.rsquaredConstraint(holisticMap.get("R_squared")))
- .build();
- Map<String, Object> contList = MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", holisticMap.get("Date"))
- .put("duration", holisticMap.get("Duration"))
- .put("structure", holisticMap.get("Structure"))
- .put("convex", holisticMap.get("Convex"))
- .put("credit", holisticMap.get("Credit"))
- .put("hyield", holisticMap.get("HYield"))
- .put("conv", holisticMap.get("Conv"))
- .put("epsi", holisticMap.get("Tepsi"))
- .put("alpha", holisticMap.get("Talpha"))
- .put("rSquared", this.rsquaredConstraint(holisticMap.get("R_squared")))
- .build();
- AtomicReference<Double> intervalYieldRate = new AtomicReference<>(0.);
- List<String> rateKeys = ListUtil.toList("TDuration", "TStructure", "TConvex", "TCredit", "THYield", "TConv", "Tepsi", "Talpha");
- holisticMap.forEach((k, v) -> {
- if (rateKeys.contains(k)) {
- intervalYieldRate.updateAndGet(v1 -> v1 + Double.parseDouble(StrUtil.toString(v)));
- }
- });
- Map<String, Object> chart2 = MapUtil.<String, Object>builder("dataset", betaList)
- .put("chartProductNameMapping", this.sortMapperAsc(chartMapper12, betaList))
- .put("intervalYieldRate", intervalYieldRate).build();
- Map<String, Object> chart4 = MapUtil.<String, Object>builder("dataset", contList)
- .put("chartProductNameMapping", this.sortMapperAsc(chartMapper34, contList)).build();
- List<Map<String, Object>> betaList1 = sequential.stream().map(e ->
- MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", e.get("Date"))
- .put("duration", e.get("TDuration"))
- .put("structure", e.get("TStructure"))
- .put("convex", e.get("TConvex"))
- .put("credit", e.get("TCredit"))
- .put("hyield", e.get("THYield"))
- .put("conv", e.get("TConv"))
- .put("epsi", e.get("epsi"))
- .put("alpha", e.get("Alpha"))
- .put("rSquared", this.rsquaredConstraint(e.get("R_squared")))
- .build()).collect(Collectors.toList());
- List<Map<String, Object>> contList1 = sequential.stream().map(e ->
- MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", e.get("Date"))
- .put("duration", e.get("Duration"))
- .put("structure", e.get("Structure"))
- .put("convex", e.get("Convex"))
- .put("credit", e.get("Credit"))
- .put("hyield", e.get("HYield"))
- .put("conv", e.get("Conv"))
- .put("rSquared", this.rsquaredConstraint(e.get("R_squared")))
- .build()).collect(Collectors.toList());
- Map<String, Object> chart1 = MapUtil.<String, Object>builder("dataset", contList1)
- .put("chartProductNameMapping", chartMapper12).put("tableProductNameMapping", tableMapper1).build();
- Map<String, Object> chart3 = MapUtil.<String, Object>builder("dataset", betaList1)
- .put("chartProductNameMapping", chartMapper34).put("tableProductNameMapping", tableMapper3).build();
- return MapUtil.<String, Object>builder("chart1", chart1).put("chart2", chart2).put("chart3", chart3).put("chart4", chart4).build();
- } catch (Exception e) {
- logger.error("债券业绩归因计算错误" + e.getMessage());
- return MapUtil.empty();
- }
- }
- @Override
- public Map<String, Object> relativeAttribution(RelativeAttributionParams params) {
- this.checkParams(params);
- try {
- Map<String, String> chartMapper2 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("market", "市场").put("size", "市值").put("bookToPriceRatio", "账面市值比")
- .put("growvalue", "成长").put("hedge", "升贴水").build();
- Map<String, String> chartMapper1 = MapUtil.<String, String>builder(MapUtil.newHashMap(true)).putAll(chartMapper2).put("rSquared", "R2").build();
- Map<String, String> chartMapper4 = MapUtil.<String, String>builder(MapUtil.newHashMap(true)).putAll(chartMapper2).put("epsi", "残差").put("alpha", "超额收益").build();
- Map<String, String> chartMapper3 = MapUtil.<String, String>builder(MapUtil.newHashMap(true)).putAll(chartMapper4).put("rSquared", "R2").build();
- Map<String, String> tableMapper1 = MapUtil.<String, String>builder(MapUtil.newHashMap(true)).put("date", "因子系数(%)").putAll(chartMapper1).build();
- Map<String, String> tableMapper2 = MapUtil.<String, String>builder(MapUtil.newHashMap(true)).put("date", "").putAll(chartMapper1).build();
- Map<String, String> tableMapper3 = MapUtil.<String, String>builder(MapUtil.newHashMap(true)).put("date", "贡献度(%)").putAll(chartMapper3).build();
- Map<String, String> tableMapper4 = MapUtil.<String, String>builder(MapUtil.newHashMap(true)).put("date", "").putAll(chartMapper3).build();
- Map<String, Object> extParams = MapUtil.<String, Object>builder().put("winlen", params.getWinlen()).put("rw", 0)
- .put("returnNo", "None").put("strategy", 5).put("curve_type", 2).build();
- PyResBody resBody = this.initiateRequest("GetRelAttribution", params, extParams);
- List<Map<String, Object>> sequential = resBody.getSequential();
- Map<String, Object> holisticMap = resBody.getHolistic();
- Map<String, Object> betaList = MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", holisticMap.get("end_date"))
- .put("market", holisticMap.get("TMarket"))
- .put("size", holisticMap.get("TSize"))
- .put("growvalue", holisticMap.get("TGrowvalue"))
- .put("hedge", holisticMap.get("THedge"))
- .put("bookToPriceRatio", holisticMap.get("TBookToPriceRatio"))
- .put("epsi", holisticMap.get("Tepsi"))
- .put("alpha", holisticMap.get("Talpha"))
- .put("rSquared", this.rsquaredConstraint(holisticMap.get("R_squared")))
- .build();
- Map<String, Object> contList = MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", holisticMap.get("end_date"))
- .put("market", holisticMap.get("Market"))
- .put("size", holisticMap.get("Size"))
- .put("growvalue", holisticMap.get("Growvalue"))
- .put("hedge", holisticMap.get("Hedge"))
- .put("bookToPriceRatio", holisticMap.get("BookToPriceRatio"))
- .build();
- AtomicReference<Double> intervalYieldRate = new AtomicReference<>(0.);
- List<String> rateKeys = ListUtil.toList("TMarket", "TSize", "TGrowvalue", "THedge", "TBookToPriceRatio", "Tepsi", "Talpha");
- holisticMap.forEach((k, v) -> {
- if (rateKeys.contains(k)) {
- intervalYieldRate.updateAndGet(v1 -> v1 + Double.parseDouble(StrUtil.toString(v)));
- }
- });
- tableMapper2.put("date", holisticMap.get("Dateini") + "~" + holisticMap.get("end_date"));
- tableMapper4.put("date", holisticMap.get("Dateini") + "~" + holisticMap.get("end_date"));
- Map<String, Object> chart2 = MapUtil.<String, Object>builder("dataset", betaList)
- .put("chartProductNameMapping", this.sortMapperAsc(chartMapper2, betaList))
- .put("tableProductNameMapping", tableMapper2).put("intervalYieldRate", intervalYieldRate).build();
- Map<String, Object> chart4 = MapUtil.<String, Object>builder("dataset", contList)
- .put("chartProductNameMapping", this.sortMapperAsc(chartMapper4, contList)).put("tableProductNameMapping", tableMapper4).build();
- List<Map<String, Object>> betaList1 = sequential.stream().map(e ->
- MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", e.get("end_date"))
- .put("market", e.get("TMarket"))
- .put("size", e.get("TSize"))
- .put("growvalue", e.get("TGrowvalue"))
- .put("hedge", e.get("THedge"))
- .put("bookToPriceRatio", e.get("TBookToPriceRatio"))
- .put("epsi", e.get("epsi"))
- .put("alpha", e.get("Alpha"))
- .put("rSquared", this.rsquaredConstraint(e.get("R_squared")))
- .put("tmarket", e.get("TMarket"))
- .put("tsize", e.get("TSize"))
- .put("tgrowvalue", e.get("TGrowvalue"))
- .put("thedge", e.get("THedge"))
- .put("tbookToPriceRatio", e.get("TBookToPriceRatio"))
- .put("tepsi", e.get("epsi"))
- .put("talpha", e.get("Alpha"))
- .put("trSquared", this.rsquaredConstraint(e.get("R_squared")))
- .build()).collect(Collectors.toList());
- List<Map<String, Object>> contList1 = sequential.stream().map(e ->
- MapUtil.<String, Object>builder(MapUtil.newHashMap(true))
- .put("date", e.get("end_date"))
- .put("market", e.get("Market"))
- .put("size", e.get("Size"))
- .put("growvalue", e.get("Growvalue"))
- .put("hedge", e.get("Hedge"))
- .put("bookToPriceRatio", e.get("BookToPriceRatio"))
- .put("rSquared", this.rsquaredConstraint(e.get("R_squared")))
- .put("tmarket", e.get("Market"))
- .put("tsize", e.get("Size"))
- .put("tgrowvalue", e.get("Growvalue"))
- .put("thedge", e.get("Hedge"))
- .put("tbookToPriceRatio", e.get("BookToPriceRatio"))
- .put("trSquared", this.rsquaredConstraint(e.get("R_squared")))
- .build()).collect(Collectors.toList());
- Map<String, Object> chart1 = MapUtil.<String, Object>builder("dataset", contList1)
- .put("chartProductNameMapping", chartMapper1).put("tableProductNameMapping", tableMapper1).build();
- Map<String, Object> chart3 = MapUtil.<String, Object>builder("dataset", betaList1)
- .put("chartProductNameMapping", chartMapper3).put("tableProductNameMapping", tableMapper3).build();
- return MapUtil.<String, Object>builder("chart1", chart1).put("chart2", chart2).put("chart3", chart3).put("chart4", chart4).build();
- } catch (Exception e) {
- logger.error("相对价值业绩归因计算错误" + e.getMessage());
- return MapUtil.empty();
- }
- }
- @Override
- public FundStyleVO growthValue(GrowthValueParams params) {
- this.checkParams(params);
- try {
- RBSAIndexType indexType = RBSA_MAPPER.get(params.getAllocationIndex());
- return getFundStyleVO(params, indexType, params.getConstraint().getId());
- } catch (Exception e) {
- logger.error("成长价值风格计算错误" + e.getMessage());
- return null;
- }
- }
- @Override
- public FundStyleVO industryValue(IndustryValueParams params) {
- this.checkParams(params);
- try {
- if (params.getIndustryIndex() == IndustryType.ShenWan && params.getWinlen().compareTo("32") < 0) {
- params.setWinlen("36");
- }
- RBSAIndexType indexType = RBSA_MAPPER.get(params.getIndustryIndex());
- return getFundStyleVO(params, indexType, params.getConstraint().getId());
- } catch (Exception e) {
- logger.error("行业配置风格计算错误" + e.getMessage());
- return null;
- }
- }
- @Override
- public Map<String, Object> futureFactor(FutureFactorParams params) {
- this.checkParams(params);
- try {
- Map<String, String> mapper = MapUtil.newHashMap(true);
- Map<String, String> tableMapper = MapUtil.newHashMap(true);
- Map<String, String> tableMapper2 = MapUtil.newHashMap(true);
- Map<String, String> tableMapper4 = MapUtil.newHashMap(true);
- Map<String, String> tableMapper3 = MapUtil.newHashMap(true);
- Map<String, String> chartMapper4 = MapUtil.newHashMap(true);
- Map<String, String> chartMapper3 = MapUtil.newHashMap(true);
- chartMapper4.put("sp", "特质因子");
- chartMapper3.put("sp", "特质因子");
- mapper.put("date", "日期");
- for (FutureStyleRespEnum value : FutureStyleRespEnum.values()) {
- mapper.put(value.getName(), value.getCName());
- chartMapper4.put(value.getName(), value.getCName());
- chartMapper3.put(value.getName(), value.getCName());
- }
- tableMapper.putAll(mapper);
- tableMapper3.putAll(chartMapper3);
- tableMapper.put("r2", "R2");
- tableMapper3.put("r2", "R2");
- tableMapper2.putAll(mapper);
- tableMapper4.put("date", "日期");
- tableMapper4.putAll(chartMapper4);
- tableMapper4.put("r2", "R2");
- Map<String, Object> extParams = MapUtil.<String, Object>builder().put("winlen", params.getWinlen())
- .put("indexIds", BarrConstant.FUTURE_INDEXS).build();
- PyResBody resBody = this.initiateRequest("futures/style", params, extParams);
- List<Map<String, Object>> sequential = resBody.getSequential();
- Map<String, Object> holisticMap = resBody.getHolistic();
- List<Map<String, Object>> dataset1 = sequential.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap();
- for (FutureStyleRespEnum value : FutureStyleRespEnum.values()) {
- temp.put("date", e.get("date"));
- temp.put(value.getName(), e.get("beta" + value.getNum()));
- temp.put("r2", this.rsquaredConstraint(e.get("nav_r_squared")));
- }
- return temp;
- }).collect(Collectors.toList());
- Map<String, Object> chart1 = MapUtil.<String, Object>builder("dataset", dataset1)
- .put("chartProductNameMapping", mapper).put("tableProductNameMapping", tableMapper).build();
- Map<String, Object> dataset20 = MapUtil.newHashMap();
- Map<String, Object> dataset41 = MapUtil.newHashMap();
- Map<String, Object> dataset42 = MapUtil.newHashMap();
- for (FutureStyleRespEnum value : FutureStyleRespEnum.values()) {
- dataset41.put(value.getName(), holisticMap.get("nav_coef" + value.getNum()));
- dataset42.put(value.getName(), holisticMap.get("vol_coef" + value.getNum()));
- dataset20.put(value.getName(), holisticMap.get("beta" + value.getNum()));
- }
- dataset41.put("r2", this.rsquaredConstraint(holisticMap.get("nav_r_squared")));
- dataset41.put("sp", holisticMap.get("nav_sp"));
- dataset42.put("r2", this.rsquaredConstraint(holisticMap.get("vol_r_squared")));
- dataset42.put("sp", holisticMap.get("vol_sp"));
- dataset20.put("date", holisticMap.get("dateini") + "~" + holisticMap.get("end_date"));
- dataset41.put("date", holisticMap.get("dateini") + "~" + holisticMap.get("end_date"));
- dataset42.put("date", holisticMap.get("dateini") + "~" + holisticMap.get("end_date"));
- tableMapper2.put("date", "统计区间");
- tableMapper4.put("date", "统计区间");
- Map<String, Object> profit4 = MapUtil.<String, Object>builder("dataset", dataset41)
- .put("chartProductNameMapping", this.sortMapper(chartMapper4, dataset41, true))
- .put("tableProductNameMapping", tableMapper4).build();
- Map<String, Object> risk4 = MapUtil.<String, Object>builder("dataset", dataset42)
- .put("chartProductNameMapping", this.sortMapper(chartMapper4, dataset42, true))
- .put("tableProductNameMapping", tableMapper4).build();
- Map<String, Object> chart4 = MapUtil.<String, Object>builder("profit", profit4).put("risk", risk4).build();
- Map<String, Object> chart2 = MapUtil.<String, Object>builder("dataset", dataset20)
- .put("chartProductNameMapping", this.sortMapper(mapper, dataset20, true))
- .put("tableProductNameMapping", tableMapper2).put("r2", this.rsquaredConstraint(holisticMap.get("nav_r_squared"))).build();
- List<Map<String, Object>> dataset31 = sequential.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap();
- temp.put("date", e.get("date"));
- temp.put("sp", e.get("nav_sp"));
- temp.put("r2", this.rsquaredConstraint(e.get("nav_r_squared")));
- for (FutureStyleRespEnum value : FutureStyleRespEnum.values()) {
- temp.put(value.getName(), e.get("nav_coef" + value.getNum()));
- }
- return temp;
- }).collect(Collectors.toList());
- List<Map<String, Object>> dataset32 = sequential.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap();
- temp.put("date", e.get("date"));
- temp.put("sp", e.get("vol_sp"));
- temp.put("r2", this.rsquaredConstraint(e.get("vol_r_squared")));
- for (FutureStyleRespEnum value : FutureStyleRespEnum.values()) {
- temp.put(value.getName(), e.get("vol_coef" + value.getNum()));
- }
- return temp;
- }).collect(Collectors.toList());
- Map<String, Object> profit3 = MapUtil.<String, Object>builder("dataset", dataset31)
- .put("chartProductNameMapping", chartMapper3).put("tableProductNameMapping", tableMapper3).build();
- Map<String, Object> risk3 = MapUtil.<String, Object>builder("dataset", dataset32)
- .put("chartProductNameMapping", chartMapper3).put("tableProductNameMapping", tableMapper3).build();
- Map<String, Object> chart3 = MapUtil.<String, Object>builder("profit", profit3).put("risk", risk3).build();
- return MapUtil.<String, Object>builder("chart1", chart1).put("chart2", chart2).put("chart4", chart4).put("chart3", chart3).build();
- } catch (Exception e) {
- logger.error("期货风格归因计算错误" + e.getMessage());
- return MapUtil.empty();
- }
- }
- @Override
- public CustomRbsaVO customRbsa(CustomRbsaParams params) {
- this.checkParams(params);
- try {
- List<String> ids = params.getIndexIds();
- String rfIndex = params.getExcess() == 0 ? "None" : Consts.RISK_OF_FREE;
- String indexIds = String.join("_", ids);
- String up = ids.stream().map(e -> "1").collect(Collectors.joining("_"));
- String down = ids.stream().map(e -> "0").collect(Collectors.joining("_"));
- Map<String, Object> extParams = MapUtil.<String, Object>builder()
- .put("indexIds", indexIds)
- .put("upbounds", up)
- .put("downbounds", down)
- .put("boundswitch", params.getConstraint().getId())
- .put("rfIndex", rfIndex)
- .put("rfValue", "None")
- .put("constraintvalue", params.getConstraintType() == 1 ? up : up.replaceAll("1", "0"))
- .put("constrainttype", params.getConstraintType())
- .put("alphacontrol", 0)
- .put("style", "F0")
- .put("winlen", params.getWinlen())
- .put("rw", 0)
- .put("dataType", 1)
- .put("returnNo", "None")
- .put("strategy", 1)
- .put("curve_type", 2)
- .put("freq", FREQ_MAPPER.get(params.getFrequency()))
- .build();
- PyReqParam holisticExt = PyReqParam.builder().api("GetCustomRbsa").control(0).taskId("holistic")
- .ext(MapUtil.<String, Object>builder("freq", FREQ_MAPPER.get(Frequency.Weekly)).build()).build();
- PyReqParam sequentialExt = PyReqParam.builder().api("GetCustomRbsa").control(1).taskId("sequential").build();
- List<PyReqParam> pyReqs = ListUtil.of(holisticExt, sequentialExt);
- PyResBody resBody = this.initiateRequest(params, extParams, pyReqs);
- Map<String, Object> holisticMap = resBody.getHolistic();
- List<Map<String, Object>> sequential = resBody.getSequential();
- Map<String, String> indexProMap = this.baseInfoService.querySecName(ids);
- Map<String, Object> risk = MapUtil.newHashMap(true);
- Map<String, Object> profit = MapUtil.newHashMap(true);
- indexProMap.forEach((k, v) -> {
- int i = ids.indexOf(k) + 1;
- risk.put("date", holisticMap.get("date"));
- profit.put("date", holisticMap.get("date"));
- risk.put(k, MapUtil.getStr(holisticMap, "beta" + i));
- profit.put(k, MapUtil.getStr(holisticMap, "cont" + i));
- });
- CustomRbsaVO.DataSet dataset = new CustomRbsaVO.DataSet(risk, profit);
- CustomRbsaVO.Chart2 chart2 = CustomRbsaVO.Chart2.builder().dataset(dataset).chartProductNameMapping(indexProMap)
- .r2(this.rsquaredConstraint(MapUtil.getStr(holisticMap, "r_squared"))).build();
- List<Map<String, Object>> dataset1 = sequential.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap(true);
- temp.put("date", e.get("date"));
- temp.put("r2", this.rsquaredConstraint(e.get("r_squared")));
- indexProMap.forEach((k, v) -> {
- int i = ids.indexOf(k) + 1;
- temp.put(k, MapUtil.getStr(e, "beta" + i));
- });
- return temp;
- }).collect(Collectors.toList());
- CustomRbsaVO.Chart1 chart1 = CustomRbsaVO.Chart1.builder().dataset(dataset1).chartProductNameMapping(indexProMap).build();
- return CustomRbsaVO.builder().chart1(chart1).chart2(chart2).build();
- } catch (Exception e) {
- logger.error("自定义风格计算错误" + e.getMessage());
- return null;
- }
- }
- @Override
- public Map<String, Object> barraOverview(BarraStyleParams params) {
- this.checkParams(params);
- try {
- Map<String, String> mapper = MapUtil.newHashMap(true);
- for (BarraStyleRespEnum value : BarraStyleRespEnum.values()) {
- mapper.put(value.getName(), value.getYName());
- }
- Map<String, Object> extParams = MapUtil.<String, Object>builder().put("winlen", params.getWinlen()).put("benchmarkId", params.getBenchmarkId())
- .put("indexIds", BarrConstant.BARRA_FACTOR_INDEXS).put("poolCode", BarrConstant.POOL_CACHE_ALL).put("excess", params.getExcess()).build();
- PyReqParam holisticExt = PyReqParam.builder().api("GetBarraSensitivity").control(0).taskId("holistic").build();
- PyReqParam sequentialExt = PyReqParam.builder().api("GetBarraSensitivity").control(1).taskId("sequential").build();
- PyReqParam factorTrendExt = PyReqParam.builder().api("GetBarraSensitivity").control(2).taskId("factorTrend").build();
- List<PyReqParam> pyReqs = ListUtil.of(holisticExt, sequentialExt, factorTrendExt);
- PyResBody resBody = this.initiateRequest(params, extParams, pyReqs);
- Map<String, Object> holisticMap = resBody.getHolistic();
- List<Map<String, Object>> sequential = resBody.getSequential();
- List<Map<String, Object>> factorTrend = resBody.getExtBody().get("factorTrend");
- List<Map<String, Object>> dataset1 = ListUtil.list(true);
- for (BarraStyleRespEnum value : BarraStyleRespEnum.values()) {
- Map<String, Object> temp = MapUtil.newHashMap();
- temp.put("name", value.getCName());
- temp.put("product", holisticMap.get("coef" + value.getNum()));
- temp.put("standardError", holisticMap.get("std_err" + value.getNum()));
- temp.put("t", holisticMap.get("t" + value.getNum()));
- temp.put("pt", holisticMap.get("pt" + value.getNum()));
- dataset1.add(temp);
- }
- dataset1.sort((o1, o2) -> MapUtil.getDouble(o2, "product").compareTo(MapUtil.getDouble(o1, "product")));
- Map<String, String> mapper1 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("name", "名称")
- .put("product", "产品敏感度")
- .put("standardError", "标准误差")
- .put("t", "t")
- .put("pt", "p>|t|")
- .build();
- Map<String, Object> chart1 = MapUtil.<String, Object>builder("dataset", dataset1).put("tableProductNameMapping", mapper1)
- .put("r2", this.rsquaredConstraint(holisticMap.get("r_squared"))).build();
- Map<String, Object> tableMapper23 = new LinkedHashMap<>();
- tableMapper23.put("date", "时段");
- tableMapper23.putAll(mapper);
- tableMapper23.put("r2", "R2");
- List<Map<String, Object>> dataset2 = factorTrend.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap();
- temp.put("date", "custom".equals(e.get("dateini")) ? "当前区间" : e.get("dateini") + "年");
- for (BarraStyleRespEnum value : BarraStyleRespEnum.values()) {
- temp.put(value.getName(), e.get("coef" + value.getNum()));
- }
- temp.put("r2", this.rsquaredConstraint(e.get(BarrConstant.R_SQUARED)));
- return temp;
- }).collect(Collectors.toList());
- Map<String, Object> chart2 = MapUtil.<String, Object>builder("dataset", dataset2).put("tableProductNameMapping", tableMapper23)
- .put("chartProductNameMapping", mapper).build();
- List<Map<String, Object>> dataset3 = sequential.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap();
- temp.put("date", e.get("end_date"));
- for (BarraStyleRespEnum value : BarraStyleRespEnum.values()) {
- temp.put(value.getName(), e.get("coef" + value.getNum()));
- }
- temp.put("r2", this.rsquaredConstraint(e.get("r_squared")));
- return temp;
- }).collect(Collectors.toList());
- Map<String, Object> chart3 = MapUtil.<String, Object>builder("dataset", dataset3).put("tableProductNameMapping", tableMapper23)
- .put("chartProductNameMapping", mapper).build();
- return MapUtil.<String, Object>builder().put("chart1", chart1).put("chart2", chart2).put("chart3", chart3).build();
- } catch (Exception e) {
- logger.error("barra概览计算错误" + e.getMessage());
- return MapUtil.empty();
- }
- }
- @Override
- public Map<String, Object> barraRiskProfit(BarraStyleParams params) {
- this.checkParams(params);
- try {
- Map<String, String> mapper = MapUtil.newHashMap(true);
- Map<String, String> mapperForTable = MapUtil.newHashMap(true);
- mapperForTable.put("r2", "R2值");
- for (BarraStyleRespEnum value : BarraStyleRespEnum.values()) {
- mapper.put(value.getName(), value.getCName());
- mapperForTable.put(value.getName(), value.getCName());
- }
- Map<String, String> tableMapper1 = MapUtil.newHashMap(true);
- for (BarraRiskProfitEnum value : BarraRiskProfitEnum.values()) {
- tableMapper1.put(value.getKey(), value.getProfit());
- }
- Map<String, String> chartMapper1 = new LinkedHashMap<>(tableMapper1);
- chartMapper1.remove("r2");
- Map<String, String> tableMapper3 = MapUtil.newHashMap(true);
- tableMapper3.put("date", "时段");
- for (BarraRiskProfitEnum value : BarraRiskProfitEnum.values()) {
- tableMapper3.put(value.getKey(), value.getRisk());
- }
- Map<String, String> chartMapper3 = new LinkedHashMap<>(tableMapper3);
- chartMapper3.remove("r2");
- Map<String, Object> extParams = MapUtil.<String, Object>builder().put("winlen", params.getWinlen()).put("benchmarkId", params.getBenchmarkId())
- .put("indexIds", BarrConstant.BARRA_FACTOR_INDEXS).put("poolCode", BarrConstant.POOL_CACHE_ALL).put("excess", params.getExcess()).build();
- PyResBody resBody = this.initiateRequest("GetBarraNavAttribution", params, extParams);
- List<Map<String, Object>> sequential = resBody.getSequential();
- Map<String, Object> holisticMap = resBody.getHolistic();
- // chart1
- List<Map<String, Object>> dataset1 = sequential.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap();
- temp.put("date", e.get("end_date"));
- temp.put("r2", this.rsquaredConstraint(e.get("r_squared")));
- for (BarraRiskProfitEnum value : BarraRiskProfitEnum.values()) {
- temp.put(value.getKey(), e.get("nav_" + value.getCode()));
- }
- return temp;
- }).collect(Collectors.toList());
- Map<String, Object> chart1 = MapUtil.<String, Object>builder("dataset", dataset1).put("chartProductNameMapping", chartMapper1).put("tableProductNameMapping", tableMapper1).build();
- // chart2
- List<Map<String, Object>> dataset2 = ListUtil.list(true);
- Map<String, Object> temp2 = MapUtil.newHashMap();
- for (BarraStyleRespEnum value : BarraStyleRespEnum.values()) {
- temp2.put(value.getName(), holisticMap.get("nav_cont" + value.getNum()));
- }
- dataset2.add(temp2);
- Map<String, Object> chart2 = MapUtil.<String, Object>builder("dataset", dataset2).put("chartProductNameMapping", this.sortMapperAsc(mapper, dataset2.get(0)))
- .put("tableProductNameMapping", mapperForTable).put("r2", this.rsquaredConstraint(holisticMap.get("nav_r_squared"))).build();
- // chart3
- List<Map<String, Object>> dataset3 = sequential.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap();
- temp.put("date", e.get("end_date"));
- temp.put("r2", this.rsquaredConstraint(e.get("r_squared")));
- for (BarraRiskProfitEnum value : BarraRiskProfitEnum.values()) {
- temp.put(value.getKey(), e.get("vol_" + value.getCode()));
- }
- return temp;
- }).collect(Collectors.toList());
- Map<String, Object> chart3 = MapUtil.<String, Object>builder("dataset", dataset3).put("chartProductNameMapping", chartMapper3).put("tableProductNameMapping", tableMapper3).build();
- // chart4
- List<Map<String, Object>> dataset4 = ListUtil.list(true);
- Map<String, Object> temp4 = MapUtil.newHashMap();
- for (BarraStyleRespEnum value : BarraStyleRespEnum.values()) {
- temp4.put(value.getName(), holisticMap.get("vol_cont" + value.getNum()));
- }
- dataset4.add(temp4);
- Map<String, Object> chart4 = MapUtil.<String, Object>builder("dataset", dataset4).put("chartProductNameMapping", this.sortMapperAsc(mapper, dataset4.get(0)))
- .put("tableProductNameMapping", mapperForTable).build();
- return MapUtil.<String, Object>builder().put("chart1", chart1).put("chart2", chart2).put("chart3", chart3).put("chart4", chart4).build();
- } catch (Exception e) {
- logger.error("barra风格计算错误" + e.getMessage());
- return MapUtil.empty();
- }
- }
- @Override
- public Map<String, Object> selectionTiming(SelectionTimingParams params) {
- try {
- if (!CAL_RANGE_MAPPER.containsKey(params.getWinlen())) throw new APIException("窗口参数非法");
- Map<String, String> mapper = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("alpha", "选股能力").put("beta", "择时能力").build();
- Map<String, String> mapper1 = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("range", "统计周期")
- .put("alpha", "Alpha(%)")
- .put("testAlpha", "T检验(Alpha)")
- .put("selectionAlpha", "选股能力(Alpha)")
- .put("beta2", "Beta2")
- .put("testBeta2", "T检验(Beta2)")
- .put("timingBeta2", "择时能力(Beta2)")
- .build();
- Map<String, Object> extParams = MapUtil.<String, Object>builder().put("model", params.getModel()).put("benchmarkId", params.getBenchmarkId())
- .put("calRange", CAL_RANGE_MAPPER.get(params.getWinlen())).build();
- PyReqParam holisticExt = PyReqParam.builder().api("GetIndicatorStatsLine").method("get").taskId("holistic").build();
- PyReqParam sequentialExt = PyReqParam.builder().api("GetIndicatorStatsTable").method("get").taskId("sequential").control(1).build();
- List<PyReqParam> pyReqs = ListUtil.of(holisticExt, sequentialExt);
- PyResBody resBody = this.initiateRequest(params, extParams, pyReqs);
- List<Map<String, Object>> sequential = resBody.getSequential();
- List<Map<String, Object>> holistic = resBody.getExtBody().get("holistic");
- List<Map<String, Object>> dataset = holistic.stream().map(e -> MapUtil.builder("date", e.get("range_perid"))
- .put("alpha", e.get("alpha_value")).put("beta", e.get("beta2_value")).build()).collect(Collectors.toList());
- List<Map<Object, Object>> dataset1 = sequential.stream().filter(e -> !"成立以来".equals(e.get("range_perid"))).map(e ->
- MapUtil.builder(MapUtil.newHashMap(true))
- .put("range", e.get("range_perid"))
- .put("alpha", e.get("alpha"))
- .put("testAlpha", e.get("alpha_pvalue"))
- .put("selectionAlpha", e.get("stock_selection_ability"))
- .put("beta2", e.get("beta2"))
- .put("testBeta2", e.get("beta2_pvalue"))
- .put("timingBeta2", e.get("market_timing_ability"))
- .build()).collect(Collectors.toList());
- Map<String, Object> chart = MapUtil.<String, Object>builder().put("dataset", dataset).put("productNameMapping", mapper).build();
- Map<String, Object> table = MapUtil.<String, Object>builder().put("dataset", dataset1).put("productNameMapping", mapper1).build();
- return MapUtil.<String, Object>builder().put("chart", chart).put("table", table).build();
- } catch (Exception e) {
- logger.error("选股择时能力计算错误" + e.getMessage());
- return MapUtil.empty();
- }
- }
- @Override
- @SuppressWarnings("unchecked")
- public Map<String, Object> rzStyle(RzStyleParams params) {
- try {
- List<FundStyleStatsDO> fundStyleStatsList = fundStyleService.listFundStyleOverview(params.getSecId());
- List<Map<String, Object>> dataset = ListUtil.list(true);
- for (FundStyleStatsDO fundStyleStatsDO : fundStyleStatsList) {
- Map<String, Object> tempMap = MapUtil.newHashMap();
- tempMap.put("date", fundStyleStatsDO.getEndDate());
- tempMap.put("upside", fundStyleStatsDO.getUpsideCaptureRatio1y());
- tempMap.put("downside",fundStyleStatsDO.getDownsideCaptureRatio1y());
- tempMap.put("style", handleFundStyle(fundStyleStatsDO.getUpsideCaptureRatio1y(),fundStyleStatsDO.getDownsideCaptureRatio1y()));
- dataset.add(tempMap);
- }
- Map<String, String> mapper = MapUtil.<String, String>builder(MapUtil.newHashMap(true))
- .put("date", "时间").put("upside", "进攻能力").put("downside", "防御能力").put("style", "风格").build();
- Map<String, Object> chart1 = MapUtil.<String, Object>builder().put("dataset", dataset)
- .put("chartProductNameMapping", mapper).put("tableProductNameMapping", mapper).build();
- List<String> secIdList = ListUtil.list(true);
- List<String> fundBenchmarkList = ListUtil.toList(params.getSecId(), params.getBenchmarkId());
- List<String> unionIds = CollUtil.addAllIfNotContains(fundBenchmarkList, secIdList);
- return MapUtil.<String, Object>builder().put("chart1", chart1).build();
- } catch (Exception e) {
- logger.error("风格总览计算错误" + e.getMessage());
- return MapUtil.empty();
- }
- }
- private String handleFundStyle(BigDecimal upside, BigDecimal downside) {
- String style;
- BigDecimal standardLevel = BigDecimal.valueOf(0.5);
- if (standardLevel.compareTo(upside) <= 0 && standardLevel.compareTo(downside) >= 0) {
- style = "攻守兼备型";
- } else if (standardLevel.compareTo(upside) > 0 && standardLevel.compareTo(downside) > 0) {
- style = "防御型";
- } else if (standardLevel.compareTo(upside) < 0 && standardLevel.compareTo(downside) < 0) {
- style = "进攻型";
- } else {
- style = "风格不明显";
- }
- return style;
- }
- /**
- * 成长价值和行业配置接口重构,支持基金、机构、经理、组合等
- *
- * @param params 请求参数
- * @param indexType 因子
- * @param boundSwitch 多空或多头
- * @param <P> 类型参数
- * @return /
- */
- private <P extends BaseParams> FundStyleVO getFundStyleVO(P params, RBSAIndexType indexType, Integer boundSwitch) {
- CurveType curveType = CurveType.getCurveType(params.getRaiseType(), StrategyHandleUtils.getStrategy(params.getStrategy()));
- List<CurveType> strategyList = ListUtil.of(CurveType.PrivateSubstratgy, CurveType.PublicSubstrategy, CurveType.BothSubstratgy);
- int curveTypeId = strategyList.contains(curveType) ? curveType.getId() : 2;
- String indexIds = String.join("_", RBSAIndexTypeMap.getInstance().getIndexIds(indexType));
- Map<String, Object> extParams = MapUtil.<String, Object>builder().put("boundSwitch", boundSwitch)
- .put("indexIds", indexIds).put("strategy", 1).put("curveType", curveTypeId).build();
- PyResBody resBody = this.initiateRequest("fund/style", params, extParams);
- List<Map<String, Object>> sequential = resBody.getSequential();
- Map<String, Object> holisticMap = resBody.getHolistic();
- Map<String, String> indexProMap = RBSA_INDEX_PROD_MAPPER.get(indexType);
- Map<String, Object> risk = MapUtil.newHashMap(true);
- Map<String, Object> profit = MapUtil.newHashMap(true);
- indexProMap.forEach((k, v) -> {
- risk.put("date", holisticMap.get("date"));
- risk.put(k, MapUtil.getStr(holisticMap, k));
- });
- for (int i = 0; i < indexProMap.size(); i++) {
- profit.put("date", holisticMap.get("date"));
- profit.put("beta" + (i + 1), MapUtil.getStr(holisticMap, "cont" + (i + 1)));
- }
- FundStyleVO.DataSet dataset = new FundStyleVO.DataSet(risk, profit);
- FundStyleVO.Chart2 chart2 = FundStyleVO.Chart2.builder().dataset(dataset).chartProductNameMapping(indexProMap)
- .r2(this.rsquaredConstraint(MapUtil.getStr(holisticMap, "r_squared"))).build();
- List<Map<String, Object>> dataset1 = sequential.stream().map(e -> {
- Map<String, Object> temp = MapUtil.newHashMap(true);
- temp.put("date", e.get("date"));
- temp.put("r2", this.rsquaredConstraint(e.get("r_squared")));
- indexProMap.forEach((k, v) -> temp.put(k, MapUtil.getStr(e, k)));
- return temp;
- }).collect(Collectors.toList());
- FundStyleVO.Chart1 chart1 = FundStyleVO.Chart1.builder().dataset(dataset1).chartProductNameMapping(indexProMap).build();
- return FundStyleVO.builder().chart1(chart1).chart2(chart2).build();
- }
- /**
- * 对r2做一个简单的约束,[-1, 1] 之间
- *
- * @param r2 /
- * @return /
- */
- private String rsquaredConstraint(Object r2) {
- if (r2 == null) {
- return null;
- }
- double v = Double.parseDouble(StrUtil.toString(r2));
- if (v < -1d) {
- v = -1d;
- } else if (v > 1d) {
- v = 1d;
- }
- return String.valueOf(v);
- }
- }
|