123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206 |
- package com.simuwang.base.common.util;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.map.MapUtil;
- import cn.hutool.core.util.StrUtil;
- import com.simuwang.base.common.conts.AccountingItems;
- import com.simuwang.base.common.conts.AccountingNewItems;
- import com.simuwang.base.common.conts.HoldingType;
- import com.simuwang.base.common.enums.MarketTradIngCodeEnum;
- import com.simuwang.base.pojo.dos.FundPositionDetailDO;
- import com.simuwang.base.pojo.dos.ValuationTableDO;
- import com.simuwang.base.pojo.valuation.AssetsValuationInfo;
- import com.simuwang.base.pojo.valuation.CmValuationTableAttribute;
- import com.smppw.utils.BigDecimalUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.math.BigDecimal;
- import java.util.*;
- import java.util.stream.Collectors;
- public final class ValuationTableParseUtil {
- private static final Logger log = LoggerFactory.getLogger(ValuationTableParseUtil.class);
- /**
- * 多头
- */
- public final static Integer BULL_LONG_SHORT = 1;
- /**
- * 空头
- */
- public final static Integer BEAR_LONG_SHORT = 2;
- private final static Map<String, Integer> CURRENCY_CODE_MAP = MapUtil.newHashMap();
- static {
- // 1-人民币,2-美元,3-港元
- CURRENCY_CODE_MAP.put("CNY", 1);
- CURRENCY_CODE_MAP.put("USD", 2);
- CURRENCY_CODE_MAP.put("HKD", 3);
- }
- /**
- * 特殊连接符(用户证券名称的识别剔除)
- */
- private final static List<String> SPECIAL_CODE = CollUtil.toList("-", "_", ".");
- public static List<FundPositionDetailDO> parseDataNew(List<CmValuationTableAttribute> attrList, ValuationTableDO file,
- List<String> marketCodeList) {
- // 汇总类数据map
- Map<String, Integer> tailCode = new HashMap<>();
- // 区分"科目代码"列为明细类和汇总类数据
- boolean isFooterRow;
- // 返回结果(持仓明细对象)
- List<FundPositionDetailDO> dataList = new ArrayList<>();
- // 识别科目代码层级关系
- handleSubjectCodeLevel(attrList);
- // 兼容存在重复的数据(兼容updateValuationPositionDetailType任务)
- Map<String, String> originalCodePreOriginalCodeMap = attrList.stream().filter(e -> StrUtil.isNotBlank(e.getPreOriginalSubjectCode()))
- .collect(Collectors.toMap(CmValuationTableAttribute::getOriginalSubjectCode, CmValuationTableAttribute::getPreOriginalSubjectCode,
- (oldValue, newValue) -> newValue));
- for (int i = 0; i < attrList.size(); i++) {
- CmValuationTableAttribute attr = attrList.get(i);
- if (attr.getSubjectCode() == null) {
- continue;
- }
- // 估值表解析到的数据 -> 持仓明细对象
- FundPositionDetailDO data = toDetail(attr, file);
- // 判断数据为明细类 or 汇总类数据(给字段isFooterRow赋值)
- isFooterRow = dealDetailOrSummary(data);
- if (data.getSubjectCode() == null) {
- continue;
- }
- // 汇总类数据("基金投资合计","实收资本"等字段)
- if (isFooterRow) {
- handleSummaryData(data, tailCode);
- }
- // 持仓明细类数据
- if (!isFooterRow) {
- // 从科目代码识别出明细证券代码securitiesCode
- String securitiesCode = dealSecuritiesCode(attr.getSubjectCode(), attr.getPreOriginalSubjectCode(), attr.getLevel());
- data.setSecuritiesCode(securitiesCode);
- // 处理证券名称(剔除上一科目名称)
- String preOriginalSubjectCode = originalCodePreOriginalCodeMap.get(attr.getOriginalSubjectCode());
- String preSecuritiesName = attrList.stream().filter(e -> e.getOriginalSubjectCode().equals(preOriginalSubjectCode))
- .findFirst().map(CmValuationTableAttribute::getSubjectName).orElse(null);
- String securitiesName = handleSecuritiesName(data.getLevel(), data.getSecuritiesName(), preSecuritiesName);
- data.setSecuritiesName(securitiesName);
- // data.subjectCode字段保存估值表中的原始科目代码
- data.setSubjectCode(attr.getOriginalSubjectCode());
- // 资产类型,1资产类,2负债类,3共同类,4所有者权益类,6损益类(根据科目代码编码规则可得)
- data.setSubjectType(Integer.valueOf(data.getSubjectCode().substring(0, 1)));
- }
- data.setIsvalid(1);
- data.setCreateTime(new Date());
- dataList.add(data);
- }
- // 推断持仓明细类型
- dealAssetTypeNew(dataList, originalCodePreOriginalCodeMap, marketCodeList);
- return dataList;
- }
- /**
- * 初步处理证券名称(剔除上一科目名称)
- * 如:场外_已上市_开放式_货币_成本-平安财富宝货币A
- * 准确的证券名称应该为:平安财富宝货币A
- *
- * @param level 持仓明细层级
- * @param originalSecuritiesName 当前明细的证券名称
- * @param preSecuritiesName 上一级的证券名称
- * @return 处理后的证券名称
- */
- private static String handleSecuritiesName(Integer level, String originalSecuritiesName, String preSecuritiesName) {
- if (StrUtil.isBlank(preSecuritiesName) || StrUtil.isBlank(originalSecuritiesName) || !originalSecuritiesName.contains(preSecuritiesName) || level == null || level < 4) {
- return originalSecuritiesName;
- }
- String securitiesName = originalSecuritiesName.replace(preSecuritiesName, "");
- for (String specialCode : SPECIAL_CODE) {
- if (securitiesName.startsWith(specialCode)) {
- securitiesName = securitiesName.substring(1);
- }
- }
- return securitiesName;
- }
- /**
- * 获取明细证券代码
- *
- * @param subjectCode 估值表科目代码(去掉".","_")
- * @param preOriginalSubjectCode 上一级科目代码
- * @param level 层级
- * @return 明细证券代码
- */
- private static String dealSecuritiesCode(String subjectCode, String preOriginalSubjectCode, Integer level) {
- String securitiesCode = null;
- // 一级科目的证券代码 等于 估值表原始科目代码
- if (level == null) {
- return null;
- }
- if (level == 1) {
- securitiesCode = subjectCode;
- return securitiesCode;
- }
- // 二级或三级科目的证券代码为空
- if (level == 2 || level == 3) {
- return null;
- }
- if (StrUtil.isNotBlank(preOriginalSubjectCode) && level >= 4) {
- String preSubjectCode = preOriginalSubjectCode.replaceAll("[\\.\\s_-]", "");
- securitiesCode = subjectCode.substring(preSubjectCode.length());
- }
- return securitiesCode;
- }
- private static void handleSummaryData(FundPositionDetailDO data, Map<String, Integer> tailCode) {
- data.setSecType(100);
- String subjectName = data.getSecuritiesName();
- if (StringUtils.isNotEmpty(subjectName)) {
- if (subjectName.startsWith("-") || Character.isDigit(subjectName.toCharArray()[0])) {
- //如果科目名称是数字
- data.setSecuritiesAmount(BigDecimalUtils.toBigDecimal((subjectName.replace("%", "").replace(",", ""))));
- data.setSecuritiesName(data.getSubjectCode());
- } else {
- data.setSecuritiesName(data.getSubjectCode() + subjectName);
- }
- } else {
- data.setSecuritiesName(data.getSubjectCode());
- }
- String subjectCode = getTypeNo(data.getSubjectCode());
- if (subjectCode == null) {
- subjectCode = "1000";
- } else {
- if (tailCode.containsKey(subjectCode)) {
- int num = tailCode.get(subjectCode);
- tailCode.put(subjectCode, num + 1);
- subjectCode = subjectCode + ":" + num;
- } else {
- tailCode.put(subjectCode, 1);
- }
- }
- data.setSecuritiesCode(subjectCode);
- data.setSubjectCode(subjectCode);
- data.setLevel(0);
- }
- private static boolean dealDetailOrSummary(FundPositionDetailDO data) {
- boolean isFooterRow = false;
- if (!Character.isDigit(data.getSubjectCode().toCharArray()[0])) {
- isFooterRow = true;
- }
- if (!isFooterRow && ValuationDataUtils.hasChinese(data.getSubjectCode(), false)) {
- String code = data.getSubjectCode();
- if (data.getSecuritiesName() != null) {
- code = code.replace(data.getSecuritiesName(), "");
- }
- if (ValuationDataUtils.hasChinese(code, false)) {
- int endIndex = getSubjectCodeEndIndex(data.getSubjectCode());
- String subCode = code.substring(0, endIndex);
- if (subCode.length() < 4 && data.getSecuritiesName() == null) {
- isFooterRow = true;
- } else {
- data.setSubjectCode(subCode);
- if (data.getSecuritiesName() == null) {
- data.setSecuritiesName(code.substring(endIndex));
- }
- }
- } else {
- data.setSubjectCode(code);
- }
- }
- return isFooterRow;
- }
- /**
- * 识别科目代码的层级
- *
- * @param valuationDataList 估值表解析到的数据
- */
- private static void handleSubjectCodeLevel(List<CmValuationTableAttribute> valuationDataList) {
- // 先过滤出一级科目(一级科目长度一定是4位)
- List<CmValuationTableAttribute> levelOneCodeList = valuationDataList.stream()
- .filter(e -> StrUtil.isNotBlank(e.getOriginalSubjectCode()) && e.getOriginalSubjectCode().length() == 4
- && StrUtil.isNumeric(e.getOriginalSubjectCode()))
- .sorted(Comparator.comparing(CmValuationTableAttribute::getOriginalSubjectCode)).collect(Collectors.toList());
- if (CollUtil.isEmpty(levelOneCodeList)) {
- return;
- }
- levelOneCodeList.forEach(levelOneCodeData -> {
- String parentCode = levelOneCodeData.getOriginalSubjectCode();
- levelOneCodeData.setLevel(1);
- List<CmValuationTableAttribute> subSubjectList = valuationDataList.stream()
- .filter(e -> StrUtil.isNotBlank(e.getOriginalSubjectCode()) && e.getOriginalSubjectCode().startsWith(parentCode) && e.getLevel() == null)
- .sorted(Comparator.comparing(e -> e.getOriginalSubjectCode().length())).collect(Collectors.toList());
- handSubSubjectLevel(subSubjectList, parentCode, 1);
- });
- }
- /**
- * 递归找出子类科目的层级
- *
- * @param subjectList 子类科目数据
- * @param parentLevel 父类层级
- */
- private static void handSubSubjectLevel(List<CmValuationTableAttribute> subjectList, String parentCode, Integer parentLevel) {
- if (CollUtil.isEmpty(subjectList)) {
- return;
- }
- subjectList.forEach(e -> e.setPreOriginalSubjectCode(parentCode));
- for (CmValuationTableAttribute parentData : subjectList) {
- if (parentData.getLevel() != null) {
- continue;
- }
- String subParentCode = parentData.getOriginalSubjectCode();
- parentData.setLevel(parentLevel + 1);
- parentData.setPreOriginalSubjectCode(parentCode);
- List<CmValuationTableAttribute> subSubjectList = subjectList.stream()
- .filter(e -> StrUtil.isNotBlank(e.getOriginalSubjectCode()) && e.getOriginalSubjectCode().startsWith(subParentCode)
- && !e.getOriginalSubjectCode().equals(subParentCode) && e.getLevel() == null)
- .sorted(Comparator.comparing(e -> e.getOriginalSubjectCode().length())).collect(Collectors.toList());
- handSubSubjectLevel(subSubjectList, subParentCode, parentLevel + 1);
- }
- }
- private static FundPositionDetailDO toDetail(CmValuationTableAttribute attr, ValuationTableDO userValuationTableDo) {
- FundPositionDetailDO detail = new FundPositionDetailDO();
- detail.setFundId(userValuationTableDo.getFundId());
- detail.setValuationDate(userValuationTableDo.getValuationDate());
- detail.setCurrency(getCurrencyCode(attr.getCurrency()));
- detail.setExchangeRate(attr.getExchangeRate());
- detail.setSecuritiesName(attr.getSubjectName());
- detail.setSecuritiesAmount(attr.getSecuritiesAmount());
- detail.setMarketValue(attr.getMarketValue());
- // [权重](市值占净值比)如果不能从估值表中读取时,市值占净值比=市值/资产净值
- BigDecimal marketValueRatio = attr.getMarketValueRatio();
- if (marketValueRatio == null || marketValueRatio.compareTo(BigDecimal.ZERO) == 0) {
- BigDecimal netAssetMarketValue = userValuationTableDo.getNetAssetsValue();
- if (attr.getMarketValue() != null && netAssetMarketValue != null && netAssetMarketValue.compareTo(BigDecimal.ZERO) != 0) {
- marketValueRatio = BigDecimalUtils.divide(attr.getMarketValue(), netAssetMarketValue);
- }
- }
- detail.setMarketValueRatio(marketValueRatio);
- detail.setNetCost(attr.getNetCost());
- detail.setNetCostRatio(attr.getNetCostRatio());
- BigDecimal increment = attr.getIncrement();
- detail.setIncrement(increment);
- // [估值增值]如果不能从估值表中读取时,估值增值=市值-成本
- if (increment != null && increment.compareTo(BigDecimal.ZERO) == 0) {
- increment = BigDecimalUtils.subtract(attr.getMarketValue(), attr.getNetCost());
- }
- detail.setIncrement(increment);
- detail.setHaltInfo(attr.getHaltInfo());
- detail.setNature(1);// 默认为多
- detail.setSubjectCode(attr.getSubjectCode());
- detail.setLevel(attr.getLevel());
- detail.setMarketPrice(attr.getMarketPrice());
- detail.setUnitCost(attr.getUnitCost());
- return detail;
- }
- private static Integer getCurrencyCode(String currency) {
- if (StrUtil.isBlank(currency)) {
- return null;
- }
- for (Map.Entry<String, Integer> entry : CURRENCY_CODE_MAP.entrySet()) {
- if (entry.getKey().equals(currency)) {
- return entry.getValue();
- }
- }
- return null;
- }
- private static String getTypeNo(String name) {
- if (name.contains("合计") && name.contains("证券")) {
- return "100";
- }
- if (name.startsWith("其中")) {
- if (name.contains("股票")) {
- return "101";
- }
- if (name.contains("债券")) {
- return "102";
- }
- if (name.contains("基金")) {
- return "103";
- }
- if (name.contains("权证")) {
- return "104";
- }
- if (name.contains("衍生")) {
- return "105";
- }
- return null;
- }
- if (name.contains("头寸")) {
- return "106";
- }
- boolean isPaidInCapital = isPaidInCapital(name);
- if (isPaidInCapital) {
- return "107";
- }
- if (name.contains("损益平准金")) {
- if (name.contains("未")) {
- return "109";
- }
- return "108";
- }
- if (name.contains("合计") && name.contains("资产")) {
- return "110";
- }
- if (name.contains("合计") && name.contains("负债")) {
- return "111";
- }
- if (name.contains("资产") && name.contains("净值")) {
- return "112";
- }
- if (name.contains("单位") && name.contains("净值")) {
- String trimName = name.trim();
- if (trimName.length() == 5) {
- // 去掉末尾的符号
- trimName = trimName.substring(0, 4);
- }
- if ("单位净值".equals(trimName) || name.contains("今日") || name.contains("基金")) {
- return "201";
- }
- if (name.contains("累计")) {
- return "202";
- }
- if (name.contains("期初")) {
- return "203";
- }
- if (name.contains("昨日")) {
- return "204";
- }
- if (name.contains("年初")) {
- return "205";
- }
- if (name.contains("期初")) {
- return "206";
- }
- if (name.contains("周初")) {
- return "207";
- }
- if (name.contains("月初")) {
- return "208";
- }
- return null;
- }
- if (name.contains("可分配") && (name.contains("收益") || name.contains("利润"))) {
- if (name.contains("单位")) {
- return "212";
- }
- return "213";
- }
- if (name.contains("现金类占")) {
- return "210";
- }
- if (name.contains("累计派现")) {
- return "211";
- }
- return null;
- }
- private static boolean isPaidInCapital(String name) {
- return name.contains("实收") && name.contains("资本")
- || name.contains("实收") && name.contains("信托");
- }
- /**
- * 识别证券类型,多头空头,交易场所
- *
- * @param dataList 估值表数据对象
- * @param originalCodePreOriginalCodeMap 当前科目代码 -上一级科目代码映射关系
- * @param marketCodeList 交易场所code列表
- */
- public static void dealAssetTypeNew(List<FundPositionDetailDO> dataList, Map<String, String> originalCodePreOriginalCodeMap, List<String> marketCodeList) {
- if (CollUtil.isEmpty(dataList)) {
- return;
- }
- Map<String, String> securitiesCodeNameMap = MapUtil.newHashMap();
- // 查询交易场所code
- for (int i = 0; i < dataList.size(); i++) {
- FundPositionDetailDO fundPositionDetail = dataList.get(i);
- // 汇总类数据("基金投资合计","实收资本"等字段)不需要处理
- if (fundPositionDetail.getSecType() != null && fundPositionDetail.getSecType() == 100) {
- continue;
- }
- // 获取二级、三级、四级科目名称
- List<String> securitiesNameList = CollUtil.toList("", "", "");
- getPreSecuritiesName(fundPositionDetail, dataList, originalCodePreOriginalCodeMap, securitiesNameList);
- String secondSecuritiesName = securitiesNameList.get(0);
- String thirdSecuritiesName = securitiesNameList.get(1);
- String fourSecuritiesName = fundPositionDetail.getLevel() != null && fundPositionDetail.getLevel() > 4 ? securitiesNameList.get(2) : "";
- // 标识证券类型
- addStockTypeNew(fundPositionDetail, secondSecuritiesName, thirdSecuritiesName, fourSecuritiesName);
- // 识别空头多头(识别过程中已经默认为 1-多头)
- addLongShort(fundPositionDetail);
- // 空头类或正回购的市值入库时应该为负数
- if (fundPositionDetail.getNature() == 2 && fundPositionDetail.getMarketValue() != null
- && fundPositionDetail.getMarketValue().compareTo(BigDecimal.ZERO) > 0
- || (fundPositionDetail.getSubType() != null && fundPositionDetail.getSubType().equals(HoldingType.BondBackRepo.getId()))) {
- fundPositionDetail.setMarketValue(BigDecimalUtils.multiply(fundPositionDetail.getMarketValue(), BigDecimalUtils.toBigDecimal("-1")));
- }
- // 识别交易场所
- addMarketIdNew(fundPositionDetail, secondSecuritiesName + thirdSecuritiesName + fourSecuritiesName);
- // 识别证券代码(过滤掉交易场所code)
- filterSecuritiesCode(fundPositionDetail, marketCodeList);
- // 用于后面识别估值增值和应计利息子类
- if (fundPositionDetail.getLevel() != null && fundPositionDetail.getLevel() >= 4) {
- securitiesCodeNameMap.put(fundPositionDetail.getSubjectCode(), securitiesNameList.get(1));
- }
- }
- // 划分估值增值和应计利息明细数据的sub_type
- for (int i = 0; i < dataList.size(); i++) {
- FundPositionDetailDO info = dataList.get(i);
- Integer secType = info.getSecType();
- if (secType == null || secType == 100 || (info.getLevel() != null && info.getLevel() == 0)) {
- continue;
- }
- // 二级,三级期货,期权,其他衍生品的子类 -> sub_type=20
- if (info.getLevel() > 1 && info.getLevel() < 4) {
- if ((secType == HoldingType.Derivatives.getId() || secType == HoldingType.Future.getId() || secType == HoldingType.Option.getId())) {
- info.setSubType(HoldingType.CostCash.getId());
- }
- }
- // 四级以上的明细,如果成本或数量为空或为0
- if (info.getLevel() >= 4) {
- if (((info.getNetCost() == null || info.getNetCost().compareTo(BigDecimal.ZERO) == 0.0)
- || (info.getSecuritiesAmount() == null || info.getSecuritiesAmount().compareTo(BigDecimal.ZERO) == 0.0))) {
- String thirdSecuritiesName = securitiesCodeNameMap.get(info.getSubjectCode());
- // 正逆回购(目前存在应计利息,不存在估值增值)
- if (info.getSecType() == HoldingType.BondBack.getId()) {
- if (StrUtil.isNotBlank(thirdSecuritiesName) && thirdSecuritiesName.contains("利息")) {
- info.setSubType(HoldingType.Interest.getId());
- }
- continue;
- }
- // 其他衍生品不做这个限制
- if (info.getSecType() == HoldingType.Derivatives.getId()) {
- continue;
- }
- // 三级科目名称包含"利息" -> sub_type=22
- if (StrUtil.isNotBlank(thirdSecuritiesName) && thirdSecuritiesName.contains("利息")) {
- info.setSubType(HoldingType.Interest.getId());
- continue;
- }
- info.setSubType(HoldingType.CostCash.getId());
- }
- }
- }
- }
- /**
- * 识别证券代码
- *
- * @param fundPositionDetail 持仓明细数据
- * @param marketCodeList 交易场所code列表
- */
- public static void filterSecuritiesCode(FundPositionDetailDO fundPositionDetail, List<String> marketCodeList) {
- if (fundPositionDetail.getLevel() == null || fundPositionDetail.getLevel() < 4) {
- return;
- }
- // 识别证券代码
- String securitiesCode = getSecuritiesCode(fundPositionDetail.getSecuritiesCode(), marketCodeList);
- fundPositionDetail.setSecuritiesCode(securitiesCode);
- }
- /**
- * 识别证券代码(去掉交易场所code)
- *
- * @param originalSecuritiesCode 原始证券代码
- * @param marketCodeList 交易场所code列表
- * @return 去掉交易场所code的证券代码
- */
- private static String getSecuritiesCode(String originalSecuritiesCode, List<String> marketCodeList) {
- String securitiesCode = originalSecuritiesCode;
- if (StrUtil.isBlank(originalSecuritiesCode)) {
- return securitiesCode;
- }
- for (String marketCode : marketCodeList) {
- if (originalSecuritiesCode.endsWith(marketCode)) {
- int length = originalSecuritiesCode.length();
- if (length > marketCode.length()) {
- securitiesCode = originalSecuritiesCode.substring(0, length - marketCode.length());
- break;
- }
- }
- }
- return securitiesCode;
- }
- /**
- * 标识证券类型
- *
- * @param info 持仓明细对象
- * @param secondSecuritiesName 二级证券名称
- * @param thirdSecuritiesName 三级证券名称
- * @param fourSecuritiesName 四级证券名称
- */
- public static void addStockTypeNew(FundPositionDetailDO info, String secondSecuritiesName, String thirdSecuritiesName, String fourSecuritiesName) {
- // 无证券名称或市值的数据不识别证券类型
- if (info.getSecuritiesName() == null || info.getMarketValue() == null) {
- return;
- }
- Integer level = info.getLevel();
- String subjectCode = info.getSubjectCode();
- // 一.现金类
- if (startWith(AccountingNewItems.CASH, subjectCode)) {
- info.setSecType(HoldingType.Cash.getId());
- info.setSubType(HoldingType.Cash.getId());
- return;
- }
- // 二.股票类
- if (startWith(AccountingNewItems.EQUITY_LIST, subjectCode)) {
- // 1."1102"开头
- if (subjectCode.startsWith("1102") || level < 4) {
- info.setSecType(HoldingType.Stock.getId());
- Integer subType = dealStockSubType(secondSecuritiesName, thirdSecuritiesName);
- info.setSubType(subType);
- return;
- }
- // 2."2101"开头 并且 二级或三级或四级科目有"存托凭证"or"股票"的 四级及以上科目
- boolean is2101StockType = subjectCode.startsWith("2101") && (secondSecuritiesName.contains("存托凭证") || secondSecuritiesName.contains("股票")
- || thirdSecuritiesName.contains("存托凭证") || thirdSecuritiesName.contains("股票")
- || fourSecuritiesName.contains("存托凭证") || fourSecuritiesName.contains("股票"));
- if (is2101StockType) {
- info.setSecType(HoldingType.Stock.getId());
- Integer subType = dealStockSubType(secondSecuritiesName, thirdSecuritiesName);
- info.setSubType(subType);
- return;
- }
- }
- // 3."1101"开头并且层级 >=4 并且二级科目或三级或四级科目含有"股票"
- boolean is1101StockType = subjectCode.startsWith("1101") && level >= 4 &&
- (secondSecuritiesName.contains("股票") || thirdSecuritiesName.contains("股票") || fourSecuritiesName.contains("股票"));
- if (is1101StockType) {
- info.setSecType(HoldingType.Stock.getId());
- Integer subType = dealStockSubType(secondSecuritiesName, thirdSecuritiesName);
- info.setSubType(subType);
- return;
- }
- // 三.债券类
- if (startWith(AccountingNewItems.BOND_LIST, subjectCode)) {
- // 1."1103","1104"开头
- if (subjectCode.startsWith("1103") || subjectCode.startsWith("1104") || level < 4) {
- info.setSecType(HoldingType.Bond.getId());
- info.setSubType(HoldingType.Bond.getId());
- return;
- }
- // 2.子类"正逆回购" -> 证券名称以"GC"开头 或 证券名称包含"-0"
- if (info.getSecuritiesName().startsWith("GC") || info.getSecuritiesName().contains("-0")) {
- info.setSecType(HoldingType.Bond.getId());
- info.setSubType(HoldingType.BondBack.getId());
- return;
- }
- }
- // 3."2101"开头并且层级 >=4 并且二级或三级或四级科目含有"债券"
- boolean is2101BondType = subjectCode.startsWith("2101") && level >= 4 &&
- (secondSecuritiesName.contains("债券") || thirdSecuritiesName.contains("债券") || fourSecuritiesName.contains("债券"));
- if (is2101BondType) {
- info.setSecType(HoldingType.Bond.getId());
- info.setSubType(HoldingType.Bond.getId());
- return;
- }
- // 4."1101"开头并且层级 >=4 并且二级或三级或四级科目含有"债券"或"债"
- boolean is1101BondType = subjectCode.startsWith("1101") && level >= 4 &&
- (secondSecuritiesName.contains("债券") || secondSecuritiesName.contains("债")
- || thirdSecuritiesName.contains("债券") || thirdSecuritiesName.contains("债")
- || fourSecuritiesName.contains("债券") || fourSecuritiesName.contains("债"));
- if (is1101BondType) {
- info.setSecType(HoldingType.Bond.getId());
- info.setSubType(HoldingType.Bond.getId());
- return;
- }
- // 5.1108开头并且层级 >=4 并且二级或三级或四级科目带有“债”
- boolean is1108BondType = subjectCode.startsWith("1108") && level >= 4
- && (secondSecuritiesName.contains("债") || thirdSecuritiesName.contains("债") || fourSecuritiesName.contains("债"));
- if (is1108BondType) {
- info.setSecType(HoldingType.Bond.getId());
- info.setSubType(HoldingType.Bond.getId());
- return;
- }
- // 正逆回购类
- if (startWith(AccountingNewItems.BOND_BACK_LIST, subjectCode)) {
- info.setSecType(HoldingType.BondBack.getId());
- // 2202-正回购
- if (subjectCode.startsWith("2202")) {
- info.setSubType(HoldingType.BondBackRepo.getId());
- }
- // 1202-逆回购
- if (subjectCode.startsWith("1202")) {
- info.setSubType(HoldingType.BondBackReverseRepo.getId());
- }
- return;
- }
- // 四.基金类
- if (startWith(AccountingNewItems.FUND_LIST, subjectCode)) {
- // "1108"开头并且非“债券类型”才归为基金(先识别债券再识别基金)
- // 1."1105","1107","1109","1110"开头
- info.setSecType(HoldingType.Fund.getId());
- info.setSubType(HoldingType.Fund.getId());
- return;
- }
- // 2."1101"开头并且层级<4 或 "1101"开头并且二级或三级或四级科目含有"基金"或"理财"
- boolean is1101FundType = subjectCode.startsWith("1101") && level < 4 || (subjectCode.startsWith("1101") &&
- (secondSecuritiesName.contains("基金") || secondSecuritiesName.contains("理财")
- || thirdSecuritiesName.contains("基金") || thirdSecuritiesName.contains("理财")
- || fourSecuritiesName.contains("基金") || fourSecuritiesName.contains("理财")));
- if (is1101FundType) {
- info.setSecType(HoldingType.Fund.getId());
- info.setSubType(HoldingType.Fund.getId());
- return;
- }
- // 3.2101开头并且层级>=4,二级或三级科目名称包含“ETF”
- boolean is2101FundType = subjectCode.startsWith("2101") && level >= 4
- && (secondSecuritiesName.contains("ETF") || thirdSecuritiesName.contains("ETF") || fourSecuritiesName.contains("ETF"));
- if (is2101FundType) {
- info.setSecType(HoldingType.Fund.getId());
- info.setSubType(HoldingType.Fund.getId());
- return;
- }
- // 五.期货、期权类
- if (startWith(AccountingNewItems.DERIVATIVES, subjectCode)) {
- // 其他衍生品
- boolean isDerivatives = secondSecuritiesName.contains("收益互换") || thirdSecuritiesName.contains("收益互换") || fourSecuritiesName.contains("收益互换");
- boolean isOptionType = secondSecuritiesName.contains("期权") || thirdSecuritiesName.contains("期权") || fourSecuritiesName.contains("期权");
- if (level < 4) {
- // 层级小于4,并且二级或三级科目包含“期权” -> 期权
- if (isOptionType) {
- info.setSecType(HoldingType.Option.getId());
- info.setSubType(HoldingType.Option.getId());
- return;
- }
- // 层级小于4,并且非期权非其他衍生品 -> 期货
- if (!isDerivatives) {
- info.setSecType(HoldingType.Future.getId());
- info.setSubType(HoldingType.Future.getId());
- return;
- }
- // 层级小于4,并且二级或三级科目包含“收益互换” -> 其他衍生品
- info.setSecType(HoldingType.Derivatives.getId());
- info.setSubType(HoldingType.Derivatives.getId());
- return;
- }
- // 标识子类类型
- String securitiesName = info.getSecuritiesName();
- if (isOptionType) {
- info.setSecType(HoldingType.Option.getId());
- // 期权通用判断
- boolean isCmdtOption = securitiesName.contains("购") || securitiesName.contains("沽") || securitiesName.contains("C") || securitiesName.contains("P");
- // ETF期权
- boolean isETFOption = (securitiesName.contains("ETF") || securitiesName.contains("科创50") || securitiesName.contains("科创板50"))
- && isCmdtOption;
- // 股指期权
- boolean isIndexOption = (securitiesName.contains("上证50") || securitiesName.contains("沪深300") || securitiesName.contains("中证1000"))
- && isCmdtOption;
- if (isETFOption) {
- info.setSubType(HoldingType.ETFOption.getId());
- return;
- }
- if (isIndexOption) {
- info.setSubType(HoldingType.IndexOption.getId());
- return;
- }
- if (isCmdtOption) {
- info.setSubType(HoldingType.CmdtOption.getId());
- return;
- }
- // 归为其他期权
- info.setSubType(HoldingType.Other.getId());
- return;
- }
- // 非期权和非其他衍生品 -> 期货类
- if (!isDerivatives) {
- String stockCode = info.getSecuritiesCode();
- info.setSecuritiesCode(stockCode);
- info.setSecType(HoldingType.Future.getId());
- if (startWith(AccountingNewItems.INDEX_FUTRUE, stockCode)) {
- // 股指期货
- info.setSubType(HoldingType.IndexFuture.getId());
- return;
- }
- if (startWith(AccountingItems.BOND_FUTRUE, stockCode) || info.getSecuritiesName().contains("国债")) {
- if (stockCode.startsWith("TA")) {
- // 国债期货(T),商品期货(TA)存在冲突,先识别商品期货,再识别国债期货
- info.setSubType(HoldingType.CmdtFuture.getId());
- return;
- }
- // 国债期货
- info.setSubType(HoldingType.BondFuture.getId());
- return;
- }
- if (startWith(AccountingItems.CMDT_FUTRUE, stockCode)) {
- // 商品期货
- info.setSubType(HoldingType.CmdtFuture.getId());
- return;
- }
- // 归为其他期货
- info.setSubType(HoldingType.Other.getId());
- return;
- }
- // 其他衍生品
- info.setSecType(HoldingType.Derivatives.getId());
- // 二三四级科目是否包含"冲抵" -> 冲抵现金
- if (secondSecuritiesName.contains("冲抵") || thirdSecuritiesName.contains("冲抵") || fourSecuritiesName.contains("冲抵")) {
- info.setSubType(HoldingType.CostCash.getId());
- } else {
- info.setSubType(HoldingType.Derivatives.getId());
- }
- return;
- }
- // 以3199开头 -> 其他衍生品
- if (subjectCode.startsWith("3199")) {
- info.setSecType(HoldingType.Derivatives.getId());
- info.setSubType(HoldingType.Derivatives.getId());
- return;
- }
- // 七.其他类
- if (startWith(AccountingNewItems.OTHER, subjectCode)) {
- info.setSecType(HoldingType.Other.getId());
- info.setSubType(HoldingType.Other.getId());
- return;
- }
- // 其他资产类
- if (startWith(AccountingNewItems.OTHER_ASSET, subjectCode)) {
- info.setSecType(HoldingType.Other.getId());
- info.setSubType(HoldingType.OTHER_ASSET.getId());
- return;
- }
- // 其他负债类
- if (startWith(AccountingNewItems.OTHER_DEBT, subjectCode)) {
- info.setSecType(HoldingType.Other.getId());
- info.setSubType(HoldingType.OTHER_DEBT.getId());
- return;
- }
- // 八.兜底策略
- if (info.getSecType() == null && StrUtil.isNotBlank(secondSecuritiesName) && StrUtil.isNotBlank(thirdSecuritiesName)) {
- if (secondSecuritiesName.contains("资产") || thirdSecuritiesName.contains("资产")) {
- info.setSecType(HoldingType.Cash.getId());
- info.setSubType(HoldingType.Cash.getId());
- return;
- }
- if (secondSecuritiesName.contains("股票") || thirdSecuritiesName.contains("股")) {
- info.setSecType(HoldingType.Stock.getId());
- info.setSubType(HoldingType.Stock.getId());
- return;
- }
- if (secondSecuritiesName.contains("基金") || thirdSecuritiesName.contains("基金")) {
- info.setSecType(HoldingType.Other.getId());
- info.setSubType(HoldingType.Other.getId());
- return;
- }
- if ((secondSecuritiesName.contains("理财") || thirdSecuritiesName.contains("理财"))
- && (info.getSubjectCode().startsWith("1101.08") || info.getSubjectCode().startsWith("1101.09"))) {
- info.setSecType(HoldingType.Other.getId());
- info.setSubType(HoldingType.Other.getId());
- return;
- }
- if (secondSecuritiesName.contains("债") || thirdSecuritiesName.contains("债")) {
- if (!secondSecuritiesName.contains("负债") && !thirdSecuritiesName.contains("负债")) {
- info.setSecType(HoldingType.Bond.getId());
- info.setSubType(HoldingType.Bond.getId());
- } else {
- info.setSecType(HoldingType.Other.getId());
- info.setSubType(HoldingType.Other.getId());
- }
- }
- }
- }
- /**
- * 股票类子类识别:沪港通,深港通,港股通
- *
- * @param secondSecuritiesName 二级证券名称
- * @param thirdSecuritiesName 三级证券名称
- * @return 股票子类
- */
- private static Integer dealStockSubType(String secondSecuritiesName, String thirdSecuritiesName) {
- if (secondSecuritiesName.contains("沪港通") || thirdSecuritiesName.contains("沪港通")) {
- return HoldingType.StockSHH.getId();
- }
- if ((secondSecuritiesName.contains("深港通") || thirdSecuritiesName.contains("深港通"))) {
- return HoldingType.StockSZH.getId();
- }
- if ((secondSecuritiesName.contains("港股通") || thirdSecuritiesName.contains("港股通"))) {
- return HoldingType.StockHGT.getId();
- }
- return HoldingType.Stock.getId();
- }
- /**
- * 多头、空头识别
- *
- * @param fundPositionDetail 持仓明细对象
- */
- public static void addLongShort(FundPositionDetailDO fundPositionDetail) {
- Integer secType = fundPositionDetail.getSecType();
- if (secType == null) {
- return;
- }
- String subjectCode = fundPositionDetail.getSubjectCode();
- // 股票类:归属于1102,1101下的股票为多头;归属于2101下的股票为空头
- if (secType == HoldingType.Stock.getId()) {
- if (subjectCode.startsWith("1102") || subjectCode.startsWith("1101")) {
- fundPositionDetail.setNature(BULL_LONG_SHORT);
- return;
- }
- if (subjectCode.startsWith("2101")) {
- fundPositionDetail.setNature(BEAR_LONG_SHORT);
- return;
- }
- }
- // 债券类:归属于1101,1103,1104下的债券为多头;归属于2101下的债券为空头
- if (secType == HoldingType.Bond.getId()) {
- if (subjectCode.startsWith("110") || subjectCode.startsWith("1102") || subjectCode.startsWith("1104")) {
- fundPositionDetail.setNature(BULL_LONG_SHORT);
- return;
- }
- if (subjectCode.startsWith("2101")) {
- fundPositionDetail.setNature(BEAR_LONG_SHORT);
- return;
- }
- }
- // 期货,期权,衍生品类
- if (secType == HoldingType.Future.getId() || secType == HoldingType.Option.getId() || secType == HoldingType.Derivatives.getId()) {
- BigDecimal netCost = fundPositionDetail.getNetCost();
- Integer longShort = inferFutureOptionLongShort(netCost, fundPositionDetail.getLevel(), fundPositionDetail.getMarketValue());
- fundPositionDetail.setNature(longShort);
- }
- // 正回购 -> 空头
- if (secType == HoldingType.Bond.getId() && fundPositionDetail.getSubjectCode().startsWith("2202")) {
- fundPositionDetail.setNature(BEAR_LONG_SHORT);
- }
- // 2101下的基金 -> 空头
- if (secType == HoldingType.Fund.getId() && fundPositionDetail.getSubjectCode().startsWith("2101")) {
- fundPositionDetail.setNature(BEAR_LONG_SHORT);
- }
- // 其他资产 -> 多头, 其他负债 -> 空头
- if (secType == HoldingType.Other.getId() && fundPositionDetail.getSubType() != null && fundPositionDetail.getSubType().equals(HoldingType.OTHER_DEBT.getId())) {
- fundPositionDetail.setNature(BEAR_LONG_SHORT);
- }
- }
- /**
- * 获取持仓明细的二、三级、四级证券名称
- *
- * @param fundPositionDetail 持仓明细
- * @param dataList 估值表持仓明细数据
- * @param originalCodePreOriginalCodeMap 科目代码-上一级科目代码映射关系
- * @param securitiesNameList
- * @return 持仓明细的二、三级、四级证券名称
- */
- private static void getPreSecuritiesName(FundPositionDetailDO fundPositionDetail, List<FundPositionDetailDO> dataList,
- Map<String, String> originalCodePreOriginalCodeMap, List<String> securitiesNameList) {
- Integer level = fundPositionDetail.getLevel();
- String preOriginalCode = originalCodePreOriginalCodeMap.get(fundPositionDetail.getSubjectCode());
- if (StrUtil.isBlank(preOriginalCode) || level == null || level == 1) {
- return;
- }
- if (level == 2) {
- securitiesNameList.set(0, fundPositionDetail.getSecuritiesName());
- }
- if (level == 3) {
- String secondSecuritiesName = dataList.stream().filter(e -> e.getSubjectCode().equals(preOriginalCode))
- .findFirst().map(FundPositionDetailDO::getSecuritiesName).orElse("");
- securitiesNameList.set(0, secondSecuritiesName);
- securitiesNameList.set(1, fundPositionDetail.getSecuritiesName());
- }
- if (level == 4) {
- securitiesNameList.set(2, fundPositionDetail.getSecuritiesName());
- }
- if (level >= 4) {
- FundPositionDetailDO preFundPositionDetail = dataList.stream().filter(e -> e.getSubjectCode().equals(preOriginalCode))
- .findFirst().orElse(null);
- if (preFundPositionDetail != null) {
- getPreSecuritiesName(preFundPositionDetail, dataList, originalCodePreOriginalCodeMap, securitiesNameList);
- }
- }
- }
- /**
- * 识别交易场所
- * MarketTradIngCodeEnum
- *
- * @param info 持仓明细对象数据
- * @param marketName 二级、三级证券名称
- */
- public static void addMarketIdNew(FundPositionDetailDO info, String marketName) {
- if (info.getSecType() == null) {
- return;
- }
- // 股票交易场所
- if (info.getSecType() == HoldingType.Stock.getId()) {
- addStockMarketId(info, marketName);
- }
- // 债券交易场所
- if (info.getSecType() == HoldingType.Bond.getId() || info.getSecType() == HoldingType.BondBack.getId()) {
- addBondMarketId(info, marketName);
- }
- // 期货、期权交易场所
- if (info.getSecType() == HoldingType.Future.getId() || info.getSecType() == HoldingType.Option.getId()) {
- addFutureOptionMarketId(info, marketName);
- }
- }
- private static void addBondMarketId(FundPositionDetailDO info, String marketName) {
- if (marketName.contains("上交") || marketName.contains("上海")) {
- // 二级或三级科目包含"上交"或"上海" -> 上交所
- info.setMarketId(MarketTradIngCodeEnum.SSE.getMarketId());
- return;
- }
- if (marketName.contains("深交") || marketName.contains("深圳")) {
- // 二级或三级科目包含"深交"或"深圳" -> 深交所
- info.setMarketId(MarketTradIngCodeEnum.SZSE.getMarketId());
- return;
- }
- if (marketName.contains("北交") || marketName.contains("北京")) {
- // 二级或三级科目包含“北交”或“北京”-> 北交所
- info.setMarketId(MarketTradIngCodeEnum.NEEQ.getMarketId());
- return;
- }
- if (marketName.contains("银行间")) {
- // 二级或三级科目包含“银行间”-> 银行间
- info.setMarketId(MarketTradIngCodeEnum.IBM.getMarketId());
- return;
- }
- // 兜底策略:交易场所为场外(OTC)
- if (info.getMarketId() == null) {
- info.setMarketId(MarketTradIngCodeEnum.OTC.getMarketId());
- }
- }
- /**
- * 识别期货、期权交易场所
- *
- * @param info 持仓明细对象数据
- * @param marketName 二级、三级证券名称
- */
- private static void addFutureOptionMarketId(FundPositionDetailDO info, String marketName) {
- if (marketName.contains("上交") || (marketName.contains("上海")
- && !marketName.contains("上海能源") && !marketName.contains("上海商品") && !marketName.contains("上海期货"))) {
- // 二级或三级科目包含"上交"或"上海"并且不包含"上海能源"和"上海商品"和"上海期货" -> 上交所
- info.setMarketId(MarketTradIngCodeEnum.SSE.getMarketId());
- return;
- }
- if (marketName.contains("深交") || marketName.contains("深圳")) {
- // 二级或三级科目包含"深交"或"深圳" -> 深交所
- info.setMarketId(MarketTradIngCodeEnum.SZSE.getMarketId());
- return;
- }
- if (marketName.contains("中金所") && info.getSecType() != null && info.getSecType().equals(HoldingType.Future.getId())) {
- // 二级或三级科目包含"中金所" -> 中国金融期货交易所(期货-20,期权-51)
- info.setMarketId(MarketTradIngCodeEnum.CFFEX_FUTURE.getMarketId());
- return;
- }
- if (marketName.contains("中金所") && info.getSecType() != null && info.getSecType().equals(HoldingType.Option.getId())) {
- // 二级或三级科目包含"中金所" -> 中国金融期货交易所(期货-20,期权-51)
- info.setMarketId(MarketTradIngCodeEnum.CFFEX_OPTION.getMarketId());
- return;
- }
- if (marketName.contains("广州商品") || marketName.contains("广期所") || marketName.contains("广州期货")) {
- // 二级或三级科目包含"广州商品"或"广期所"或"广州期货”-> 广州期货交易所
- info.setMarketId(MarketTradIngCodeEnum.GZFE.getMarketId());
- return;
- }
- if (marketName.contains("郑州商品") || marketName.contains("郑商所") || marketName.contains("郑州期货")) {
- // 二级或三级科目包含"郑州商品"或"郑商所"或"郑州期货”-> 郑州期货交易所
- info.setMarketId(MarketTradIngCodeEnum.CZC.getMarketId());
- return;
- }
- if (marketName.contains("大连商品") || marketName.contains("大商所") || marketName.contains("大连期货")) {
- // 二级或三级科目包含"大连商品"或"大商所"或"大连期货”-> 大连期货交易所
- info.setMarketId(MarketTradIngCodeEnum.DCE.getMarketId());
- return;
- }
- if (marketName.contains("上海能源")) {
- // 二级或三级科目包含"上海能源" -> 上海国际能源交易中心
- info.setMarketId(MarketTradIngCodeEnum.INE.getMarketId());
- return;
- }
- if (marketName.contains("上海商品") || marketName.contains("上期所") || marketName.contains("上海期货")) {
- // 二级或三级科目包含"上海商品"或"上期所"或"上海期货”-> 上海期货交易所
- info.setMarketId(MarketTradIngCodeEnum.SHFE.getMarketId());
- return;
- }
- // 兜底策略:交易场所为场外(OTC)
- if (info.getMarketId() == null) {
- info.setMarketId(MarketTradIngCodeEnum.OTC.getMarketId());
- }
- }
- /**
- * 识别股票交易场所
- *
- * @param info 持仓明细对象数据
- * @param marketName 二级、三级证券名称
- */
- private static void addStockMarketId(FundPositionDetailDO info, String marketName) {
- if (marketName.contains("场外") || marketName.contains("新三板")) {
- // 二级或三级科目包含“场外“或”新三板 -> 新三板
- info.setMarketId(MarketTradIngCodeEnum.NTBC.getMarketId());
- return;
- }
- if (marketName.contains("上交") || marketName.contains("上海")) {
- // 二级或三级科目包含"上交"或"上海" -> 上交所
- info.setMarketId(MarketTradIngCodeEnum.SSE.getMarketId());
- return;
- }
- if (marketName.contains("深交") || marketName.contains("深圳")) {
- // 二级或三级科目包含"深交"或"深圳" -> 深交所
- info.setMarketId(MarketTradIngCodeEnum.SZSE.getMarketId());
- return;
- }
- if (marketName.contains("北交") || marketName.contains("北京")) {
- // 二级或三级科目包含“北交”或“北京”-> 北交所
- info.setMarketId(MarketTradIngCodeEnum.NEEQ.getMarketId());
- return;
- }
- if (marketName.contains("港") || marketName.contains("港股通")) {
- // 二级或三级科目包含"港"或"港股通" -> 港交所
- info.setMarketId(MarketTradIngCodeEnum.HKEX.getMarketId());
- if (info.getSecuritiesCode() != null && info.getSecuritiesCode().startsWith("H")) {
- info.setSecuritiesCode(info.getSecuritiesCode().replace("H", ""));
- }
- }
- if (marketName.contains("沪港通")) {
- if (info.getSecuritiesCode() != null) {
- if (info.getSecuritiesCode().startsWith("6")) {
- info.setMarketId(MarketTradIngCodeEnum.SSE.getMarketId());
- } else if (info.getSecuritiesCode().startsWith("H")) {
- info.setSecuritiesCode(info.getSecuritiesCode().replace("H", ""));
- }
- }
- } else if (marketName.contains("深港通")) {
- if (info.getSecuritiesCode() != null) {
- if (!info.getSecuritiesCode().startsWith("H")) {
- info.setMarketId(MarketTradIngCodeEnum.SZSE.getMarketId());
- } else {
- info.setSecuritiesCode(info.getSecuritiesCode().replace("H", ""));
- }
- }
- }
- // 兜底策略:交易场所为场外(OTC)
- if (info.getMarketId() == null) {
- info.setMarketId(MarketTradIngCodeEnum.OTC.getMarketId());
- }
- }
- /**
- * 期货及衍生品空头、多头识别逻辑
- *
- * @param netCost 成本
- * @param level 层级
- * @param marketValue 市值
- * @return 1-多头 或 2-空头
- */
- private static Integer inferFutureOptionLongShort(BigDecimal netCost, int level, BigDecimal marketValue) {
- //1.期货及衍生品的一级,二级,三级科目的多头空头识别逻辑:通过市值正负确认,正则为多头,反之空头
- Integer inferByMarketValue = marketValue != null && marketValue.compareTo(BigDecimal.ZERO) > 0 ? BULL_LONG_SHORT : BEAR_LONG_SHORT;
- if (level <= 3) {
- return inferByMarketValue;
- }
- //成本为空时,识别为多头(在持仓分析的时候,会过滤掉成本为空的数据,因此无意义的,但为了防止空指针,默认为多头)
- if (netCost == null) {
- return BULL_LONG_SHORT;
- }
- //2.期货及衍生品的四级以上科目:1-如果成本小于0为空头;2-等于0时,市值为正则为多头,反之空头;3-成本大于0为多头
- if (netCost.compareTo(BigDecimal.ZERO) < 0) {
- return BEAR_LONG_SHORT;
- }
- if (netCost.compareTo(BigDecimal.ZERO) == 0) {
- return inferByMarketValue;
- }
- return BULL_LONG_SHORT;
- }
- private static boolean startWith(Collection<String> codeSet, String subCode) {
- for (String code : codeSet) {
- if (subCode.startsWith(code)) {
- return true;
- }
- }
- return false;
- }
- public static int getSubjectCodeEndIndex(String str) {
- char[] cArr = str.toCharArray();
- if (!Character.isDigit(cArr[0])) {
- return 0;
- }
- int startIndex = 0;
- for (int i = 0; i < cArr.length; i++) {
- int index = cArr[i];
- if ((index >= 48 && index <= 57) || (index >= 65 && index <= 90) || (index >= 97 && index <= 122)) {
- continue;
- }
- startIndex = i;
- break;
- }
- return startIndex;
- }
- public static List<CmValuationTableAttribute> getAttrList(List<AssetsValuationInfo> dataList) {
- List<CmValuationTableAttribute> attrList = new ArrayList<>(dataList.size());
- for (AssetsValuationInfo info : dataList) {
- CmValuationTableAttribute attr = new CmValuationTableAttribute();
- attr.setUserid(info.getUserId());
- attr.setSubjectCode(info.getSubjectCode());
- attr.setOriginalSubjectCode(info.getOriginalSubjectCode());
- attr.setSubjectName(info.getSubjectName());
- attr.setSecuritiesAmount(BigDecimalUtils.toBigDecimal(info.getSecuritiesAmount()));
- attr.setUnitCost(BigDecimalUtils.toBigDecimal(info.getUnitCost()));
- attr.setNetCost(BigDecimalUtils.toBigDecimal(info.getNetCost()));
- attr.setNetCostRatio(BigDecimalUtils.toBigDecimal(info.getNetCostRatio()));
- attr.setMarketValue(BigDecimalUtils.toBigDecimal(info.getMarketValue()));
- attr.setMarketValueRatio(BigDecimalUtils.toBigDecimal(info.getMarketValueRatio()));
- attr.setIncrement(BigDecimalUtils.toBigDecimal(info.getIncrement()));
- attr.setHaltInfo(info.getHaltInfo());
- attr.setRightsInterestsInfo(info.getRightsInterestsInfo());
- attr.setMarketPrice(BigDecimalUtils.toBigDecimal(info.getMarketPrice()));
- attr.setCurrency(info.getCurrency());
- if (info.getExchangeRate() != null) {
- attr.setExchangeRate(BigDecimalUtils.toBigDecimal(info.getExchangeRate()));
- }
- attr.setOCurrencyCost(BigDecimalUtils.toBigDecimal(info.getOriCurrencyCost()));
- attr.setOCurrencyMarketValue(BigDecimalUtils.toBigDecimal(info.getOriCurrencyMarketValue()));
- attr.setOCurrencyValueAdded(BigDecimalUtils.toBigDecimal(info.getOriCurrencyValueAdded()));
- attrList.add(attr);
- }
- return attrList;
- }
- }
|